Summary
A Real-Time Operating System (RTOS) is software that manages the time of a microprocessor or
microcontroller. This application note is a reprint from an article I published in Electronic Design
Magazine, June 1994 issue.
Introduction
Real-time systems are characterized by the fact that severe consequences can result if logical as well as
timing correctness properties of the system are not met. A real-time multitasking application is a system
in which several time critical activities must be processed simultaneously. A real-time multitasking
kernel (also called a real-time operating system, RTOS) is software which ensures that time critical
events are processed as efficiently as possible. The use of a RTOS generally simplifies the design
process of a system by allowing the application to be divided into multiple independent elements called
tasks.
Foreground/Background.
Systems which do not use a RTOS are generally designed as shown in figure 1. These systems are
called foreground/background. An application consist of an infinite loop which calls application modules
to perform the desired operations. The modules are executed sequentially (background) with interrupt
service routines (ISRs) handling asynchronous events (foreground). Critical operations must be
performed by the ISRs to ensure that they are dealt with in a timely fashion. Because of this, ISRs have
a tendency to take longer than they should. Information for a background module made available by an
ISR is not processed until the background routine gets its turn to execute. The latency in this case
depends on how long the background loop takes to execute.
REAL-TIME KERNELS
Multitasking.
Multitasking is the process of scheduling and switching the CPU between several tasks; a single CPU
switches its attention between several sequential tasks. Multitasking provides the ability to structure your
application into a set of small, dedicated tasks that share the processor. One of the most important
aspects of multitasking is that it allows the application programmer to manage complexity which is
inherent in real-time applications. Real-time kernels can make application programs easier to design
and maintain. A task is a simple program which thinks it has the CPU all to itself. The design process
for a real-time application involves splitting the work to be done into tasks which are responsible for a
portion of the problem.
Kernel.
The kernel is the part of the multitasking system responsible for the management of tasks and
communication between tasks. When the kernel decides to run a different task, it simply saves the
current task's context (CPU registers) onto the current task's stack; each task is assigned its own stack
area in memory. Once this operation is performed, the new task's context is restored from its stack area
and then, execution of the new task's code is resumed. This process is called a context switch or a task
switch. The current top of stack for each task, along with other information, is stored in a data structure
called the Task Control Block (TCB). A TCB is assigned to each task when the task is created and is
managed by the RTOS.
Interrupts.
An important issue in real-time systems is the time required to respond to an interrupt and to actually
start executing user code to handle the interrupt. All RTOSs disable interrupts when manipulating critical
sections of code. The longer a RTOS disables interrupts, the higher the interrupt latency. RTOSs
generally disable interrupts for less than about 50 uS but obviously, the lower the better. The code that
services an interrupt is called an Interrupt Service Routine (ISR).
Scheduler.
The scheduler, also called the dispatcher, is the part of the kernel which is responsible for determining
which task will run next and when. Most real-time kernels are priority based; each task is assigned a
priority based on its importance. Establishing the priority for each task is application specific. In a
priority based kernel, control of the CPU will always be given to the highest priority task ready to run.
When the highest priority task gets the CPU, however, depends on the type of scheduler used. There
are two types of schedulers: non-preemptive and preemptive.
Non-preemptive scheduling.
Non-preemptive schedulers require that each task does something to explicitly give up control of the
CPU. To maintain the illusion of concurrency, this process must be done frequently. Non-preemptive
scheduling is also called cooperative multitasking; tasks cooperate with each other to gain control of the
CPU. When a task relinquishes the CPU, the kernel executes the code of the next most important task
that is ready to run. Asynchronous events are still handled by ISRs. An ISR can make a higher priority
task ready to run but the ISR always return to the interrupted task. The new higher priority task will gain
control of the CPU only when the current task voluntarily gives up the CPU. This is illustrated in figure 2.
Latency of a non-preemptive scheduler is much lower than with Foreground/Background; latency is now
given by the time of the longest task.
Preemptive scheduling.
In a preemptive kernel, when an event makes a higher priority task ready to run, the current task is
immediately suspended and the higher priority task is given control of the CPU. If an ISR makes a
higher priority task ready to run, the interrupted task is suspended and the new higher priority task is
resumed. Most real-time systems employ preemptive schedulers because they are more responsive.
Preemptive scheduling is illustrated in figure 3.
Reentrancy.
A reentrant function is a function which can be used by more than one task without fear of data
corruption. Conversely, a non-reentrant function is a function which cannot be shared by more than one
task unless mutual exclusion to the function is ensured by either using a semaphore (described later) or,
by disabling interrupts during critical sections of code. A reentrant function can be interrupted at any
time and resumed at a later time without loss of data. Reentrant functions either use local variables
(CPU registers or variables on the stack) or protect their data when global variables are used. Compilers
specifically designed for embedded software will generally provide reentrant run-time libraries. Nonpreemptive
schedulers do not require reentrant functions unless a function is shared between a task and
an ISR. Preemptive schedulers requires you to have reentrant functions if the functions are shared by
more than one task.
这里面好多东西不全:原文请看:http://www.ucos-ii.com/downloads/appnotes/an1004.pdf
这个不错,是讲UC/OS_II.