[Part 1 introduces the RTOS, and explains the special features a DSP-oriented RTOS. Part 3 introduces the RTOS kernel and shows how it prioritizes tasks. It also explains dynamic memory allocation, system calls, and hardware interrupts.]
Concepts of RTOS
Real-time operating systems require a set of functionality to effectively perform their function, which is to be able to execute all of their tasks without violating specified timing constraints. This section describes the major functions that real-time operating systems perform.
A task is a basic unit of programming that an operating system controls. Each different operating system may define a task slightly differently. A task implements a computation job and is the basic unit of work handled by the scheduler. The kernel creates the task, allocates memory space to the task and brings the code to be executed by the task into memory. A structure called a task control block (TCB) is created and used to manage the schedule of the task. A task is placeholder information associated with a single use of a program that can handle multiple concurrent users. From the program's point-of-view, a task is the information needed to serve one individual user or a particular service request.
Types of real-time tasks:
- Periodic – Executes regularly according to a precomputed schedule.
- Sporadic – Triggered by external events or conditions, with a predetermined maximum execution frequency.
- Spontaneous – Optional real-time tasks that are executed in response to external events (or opportunities), if resources are available.
- Ongoing tasks – Fair-share threads.
Today's microprocessors can only execute one program instruction at a time. But because they operate so fast, they can be made to appear to run many programs and serve many users simultaneously. This illusion is created by rapidly multiplexing
the processor over the set of active tasks. The processor operates at speeds that make it seem as though all of the user's tasks are being performed at the same time.
While all multitasking depends on some time of processor multiplexing, there are many strategies for "scheduling" the processor. In systems with priority-based scheduling, each task is assigned a priority depending on its relative importance, the amount of resources it is consuming, and other factors. The operating system preempts tasks having a lower priority value so that a higher priority task is given a chance to run. I'll have much more to say about scheduling later in this series.
Forms of Multitasking
There are three important multitasking algorithms:
Rapid Response to Interrupts
- Preemptive – With this algorithm, if a high-priority task becomes ready for execution it can immediately pre-empt the execution of a lower-priority task and acquire the processor without having to wait for the next regular rescheduling. In this context, "immediately" means after the scheduling latency period. This latency is one of the most important characteristics of a real-time kernel and largely defines the system responsiveness to external stimuli.
- Cooperative – With this algorithm, if a task is not ready to execute it voluntarily relinquishes the control of the processor so that other tasks can run. This algorithm does not require much scheduling and generally is not suited for real-time applications.
- Time-sharing – A pure time sharing algorithm has obvious low responsiveness (limited by the length of scheduling interval). Nevertheless, a time sharing algorithm is always implemented in real-time operating systems. The reason for this is that there is almost always more than one nonreal-time task in the real-time system (interaction with user, logging of accounting information, various other bookkeeping tasks). These tasks have low priority and are scheduled with a timesharing policy in the time when no tasks of higher priority are ready for execution.
An interrupt is a signal from a device attached to a computer or from a program within the computer that causes the RTOS to stop and figure out what to do next. Almost all DSPs and general-purpose processors are interrupt-driven. The processor will begin executing a list of computer instructions in one program and keep executing the instructions until either the task is complete or cannot go any further (waiting on a system resource for example) or an interrupt signal is sensed. After the interrupt signal is sensed, the processor either resumes running the program it was running or begins running another program.
An RTOS has code that is called an interrupt handler. The interrupt handler prioritizes the interrupts and saves them in a queue if more than one is waiting to be handled. The scheduler program in the RTOS then determines which program to give control to next.
An interrupt request (IRQ) will have a value associated with it that identifies it as a particular device. The IRQ value is an assigned location where the processor can expect a particular device to interrupt it when the device sends the processor signals about its operation. The signal momentarily interrupts the processor so that it can decide what processing to do next. Since multiple signals to the processor on the same interrupt line might not be understood by the processor, a unique value must be specified for each device and its path to the processor.
In many ways, interrupts provide the "energy" for embedded real-time systems. The energy is consumed by the tasks executing in the system. Typically, in DSP systems, interrupts are generated on buffer boundaries by the DMA or other equivalent hardware. In this way, every interrupt occurrence will ready a DSP RTOS task that iterated on full/empty buffers. Interrupts come from many sources (Figure 1) and the DSP RTOS must effectively manage multiple interruptions from both inside and outside the DSP system.
Figure 1. An RTOS must respond to and manage multiple interruptions from inside and outside the application.