The following is an excerpt from µC/OS-III: The Real-Time Kernel by Jean J. Labrosse.
A real-time kernel is software that manages the time and resources of a microprocessor, microcontroller or Digital Signal Processor (DSP), and provides indispensable services to your applications.
A Real Time Operating System (RTOS) generally contains a real-time kernel and other higher-level services such as file management, protocol stacks, a Graphical User Interface (GUI), and other components. Most additional services revolve around I/O devices.
Micriμm offers a complete suite of RTOS components including: an embedded file system, a TCP/IP stack, a graphical user interface, USB device and host stacks, and more. You can pick and choose only the components required for your application. Contact us for additional details and pricing.
The following is a list of features provided by μC/OS-III:
μC/OS-III is provided in ANSI-C source form. The source code for μC/OS-III is arguably the cleanest and most consistent kernel code available. Clean source is part of the corporate culture at Micriμm. Although many commercial kernel vendors provide source code for their products, unless the code follows strict coding standards and is accompanied by complete documentation with examples to show how the code works, these products may be cumbersome and difficult to harness. With this book, you will gain a deep understanding of the inner workings of μC/OS-III, which will protect your investment.
μC/OS-III is highly intuitive. Once familiar with the consistent coding conventions used, it is simple to predict the functions to call for the services required, and even predict which arguments are needed. For example, a pointer to an object is always the first argument, and a pointer to an error code is always the last one.
μC/OS-III is a preemptive multi-tasking kernel and therefore, μC/OS-III always runs the most important ready-to-run task.
μC/OS-III allows multiple tasks to run at the same priority level. When multiple tasks at the same priority are ready-to-run, and that priority level is the most important level, μC/OS-III runs each task for a user-specified time called a time quanta. Each task can define its own time quanta, and a task can also give up the CPU to another task at the same priority if it does not require the full time quanta.
μC/OS-III has a number of internal data structures and variables that it needs to access atomically. To ensure this, μC/OS-III is able to protect these critical regions by locking the scheduler instead of disabling interrupts. Interrupts are therefore disabled for very little time. This ensures that μC/OS-III is able to respond to some of the fastest interrupt sources.
Interrupt response with μC/OS-III is deterministic. Also, execution times of most services provided by μC/OS-III are deterministic.
The footprint (both code and data) can be adjusted based on the requirements of the application. Adding and removing features (i.e., services) is performed at compile time through approximately 40 #defines (see os_cfg.h). μC/OS-III also performs a number of run-time checks on arguments passed to μC/OS-III services. Specifically, μC/OS-III verifies that the user is not passing NULL pointers, not calling task level services from ISRs, that arguments are within allowable range, and options specified are valid, etc.. These checks can be disabled (at compile time) to further reduce the code footprint and improve performance. The fact that μC/OS-III is scalable allows it to be used in a wide range of applications and projects.
μC/OS-III can be ported to a large number of CPU architectures. Most μC/OS-II ports are easily converted to work on μC/OS-III with minimal changes in just a matter of minutes and therefore benefit from more than 45 CPU architectures already supported by μC/OS-II.
μC/OS-III was designed especially for embedded systems and can be ROMed along with the application code.
μC/OS-III allows the user to configure the kernel at run time. Specifically, all kernel objects such as tasks, stacks, semaphores, event-flag groups, message queues, number of messages, mutual exclusion semaphores, memory partitions and timers, are allocated by the user at run time. This prevents over-allocating resources at compile time.
μC/OS-III supports an unlimited number of tasks. From a practical standpoint, however, the number of tasks is actually limited by the amount of memory (both code and data space) that the processor has access to. Each task requires its own stack space and, μC/OS-III provides features to allow stack growth of the tasks to be monitored at run-time.
μC/OS-III does not impose any limitations on the size of each task, except that there be a minimum size based on the CPU used.
μC/OS-III supports an unlimited number of priority levels. However, configuring μC/OS-III for between 32 and 256 different priority levels is more than adequate for most applications.
μC/OS-III allows for any number of tasks, semaphores, mutual exclusion semaphores, event flags, message queues, timers, and memory partitions. The user allocates all kernel objects at run-time.
μC/OS-III provides all the services expected from a high-end real-time kernel, such as task management, time management, semaphores, event flags, mutexes, message queues, software timers, fixed-size memory pools, etc.
Mutexes are provided for resource management. Mutexes are special types of semaphores that have built-in priority inheritance, which eliminate unbounded priority inversions. Accesses to a mutex can be nested and therefore, a task can acquire the same mutex up to 250 times. Of course, the mutex owner needs to release the mutex an equal number of times.
μC/OS-III allows a task to suspend itself or another task. Suspending a task means that the task will not be allowed to execute until the task is resumed by another task. Suspension can be nested up to 250 levels deep. In other words, a task can suspend another task up to 250 times. Of course, the task must be resumed an equal number of times for it to become eligible to run on the CPU.
You can define any number of “one-shot” and/or “periodic” timers. Timers are countdown counters that perform a user-definable action upon counting down to 0. Each timer can have its own action and, if a timer is periodic, the timer is automatically reloaded and the action is executed every time the countdown reaches zero.
Pend on multiple objects: μC/OS-III allows an application to wait (i.e., pend) on multiple events at the same time. Specifically, a task can wait on multiple semaphores and/or message queues to be posted. The waiting task wakes up as soon as one of the events occurs.
μC/OS-III allows an ISR or task to directly signal a task. This avoids having to create an intermediate kernel object such as a semaphore or event flag just to signal a task, and results in better performance.
μC/OS-III allows an ISR or a task to send messages directly to a task. This avoids having to create and use a message queue, and also results in better performance.
Each task can have a user-definable number of “task registers.” Task registers are different than CPU registers. Task registers can be used to hold “errno” type variable, IDs, interrupt disable time measurement on a per-task basis, and more.
μC/OS-III verifies that NULL pointers are not passed, that the user is not calling task-level services from ISRs, that arguments are within allowable range, that options specified are valid, that a pointer to the proper object is passed as part of the arguments to services that manipulate the desired object, and more. Each μC/OS-III API function returns an error code concerning the outcome of the function call.
μC/OS-III has built-in features to measure the execution time of each task, stack usage of each task, number of times a task executes, CPU usage, ISR-to-task and task-to-task response time, peak number of entries in certain lists, interrupt disable and scheduler lock time on a per-task basis, and more.
μC/OS-III was designed so that it could easily be optimized based on the CPU architecture. Most data types used in μC/OS-III can be changed to make better use of the CPU’s natural word size. Also, the priority resolution algorithm can easily be written in assembly language to benefit from special instructions such as bit set and clear, as well as count-leading-zeros (CLZ), or find-first-one (FF1) instructions.
All of the μC/OS-III “pend” services include timeouts, which help avoid deadlocks.
The clock tick manager in μC/OS-III is accomplished by a task that receives a trigger from an ISR. Handling delays and timeouts by a task greatly reduces interrupt latency. Also, μC/OS-III uses a hashed delta list mechanism, which further reduces the amount of overhead in processing delays and timeouts of tasks.
μC/OS-III allows the port and application programmer to define “hook” functions, which are called by μC/OS-III. A hook is simply a defined function that allows the user to extend the functionality of μC/OS-III. One such hook is called during a context switch, another when a task is created, yet another when a task is deleted, etc.
For time measurements, μC/OS-III requires that a 16-bit or 32-bit free running counter be made available. This counter can be read at run time to make time measurements of certain events. For example, when an ISR posts a message to a task, the timestamp counter is automatically read and saved as part of the message posted. When the recipient receives the message, the timestamp is provided to the recipient, and by reading the current timestamp, the time it took for the message to be received can be determined.
This feature allows kernel awareness debuggers to examine and display μC/OS-III variables and data structures in a user-friendly way. The kernel awareness support in μC/OS-III can be used by μC/Probe to display this information at run-time.
Each μC/OS-III kernel object can have a name associated with it. This makes it easy to recognize what the object is assigned to. You can thus assign an ASCII name to a task, a semaphore, a mutex, an event flag group, a message queue, a memory partition, and a timer. The object name can have any length, but must be NUL terminated.