[Engineering Essentials]
The RTOS Motto: On Time And On Budget
Scheduling and resource allocation are the dominant factors in determining what real-time operating system fits best.
William Wong
ED Online ID #20212
December 11, 2008
Copyright © 2006 Penton Media, Inc., All rights reserved. Printing of this document is for personal use only.
Reprints
Real-time operating systems (RTOSs) tend to be a checkbox
item for many embedded projects. But is an RTOS
always necessary? The answer is application-specific, so understanding
what one will deliver is key to determining whether it
becomes a requirement or an extravagance.
In general, an RTOS can be used anywhere a non-RTOS is
employed. However, it’s rare to find an operating system with a
matching RTOS that has exactly the same application programming
interface (API). Many of them, though, embed an RTOS
within a conventional operating system. For example, Lynux-
Works LynxOS and Bluecat Linux share a Linux API. LynxOS
is a hard RTOS, while Bluecat inherits its base from Linux.
Linux continues to improve its real-time performance, but
its worst-case interrupt latency still doesn’t meet what would
be considered hard real time for an RTOS. It all comes down
to quality of service (QoS). Platforms like RTLinux Free augment
Linux, providing hard real-time class QoS.
It’s important to note that this type of addition often incorporates
an RTOS programming environment that’s distinct
from the original operating system. An RTOS is typically
small compared to a conventional desktop or server OS. They often target more smaller, resource-constrained microcontrollers.
For instance, CMX’s CMX-RTX and CMX-Tiny+
can run on 8-bit MCUs up through 64-bit processors.
The increased power and memory capacity of 8-bit processors
is making an RTOS more desirable for these platforms. But,
an OS or RTOS is usually a requirement in 16-bit platforms
and up with RTOS products like Express Logic’s ThreadX,
Wind River’s VxWorks, Micrium’s uCOS-II, and Green Hills
Software’s velOSity being common selections. Depending on
requirements, MontaVista’s Linux meets 16- and 32-bit platform
requirements in the low microsecond range.
THE RTOS CORE: SCHEDULING AND PARTITIONING
Most programmers aren’t familiar with RTOS constraints
and requirements. Most usually opt for an RTOS due to its
performance. Most RTOS products are small and fast, yet an
RTOS also adds consistency. Beyond the fact that an RTOS
gets the job done quickly, it can guarantee a job will get done.
In many applications, a late result can be catastrophic. Thus,
a poor result within the proper timeframe is preferable. These
applications are generally called hard real-time systems. Hard
real time doesn’t indicate how fast
the system may be or how quickly
a system may respond. Rather, it
refers to how reliably a system can
meet the specified requirements.
A hard real-time system may
have a fixed cycle time of one minute
with a response time of one
second. In theory, it’s something
almost any operating system could
handle. This isn’t always the case,
though, as anyone can attest to
when waiting for a desktop application
to respond within a minute.
Hard real-time systems typically
have shorter cycle times and tighter
response requirements. Faster processors
always help, and multicore
platforms can improve response
time, too. The trick for developers
is to match system requirements to
the hardware and software, hence
the importance of an RTOS in
embedded applications.
An RTOS can implement a range of
scheduling policies, and the application will
often restrict a programmer’s choices (see the
table). Non-preemptive scheduling is trivial
to implement but useful in some applications.
On the other hand, non-preemptive
scheduling within a task can be implemented
on top of a preemptive system.
Non-preemptive should not be overlooked,
especially in light of new multicore
processors. Here, hardware may be tuned to
handle an event-based operation in which
a thread will wait for an external event to
occur. This approach is usually unsuitable
for a single-core processor handling multiple
threads. On multicore systems with many cores, though, it’s often typical to
dedicate one core to handle one peripheral.
It then makes sense to have that core idle
while waiting for an event to occur.
As a result, preemptive, interrupt-driven
RTOS architectures make up the majority
of platforms deployed. These platforms
have a range of requirements, issues, and
solutions
(see the figure). Interrupt latency
is always an issue, although hardware—
multiple register sets, hardware scheduling
and task switching, and hierarchical priority
interrupt systems—can significantly
reduce this overhead.
Several issues coincide with preemption.
Most are timing-related, like race conditions,
deadlock, starvation, and priority
inversion, which occurs when a low-priority
task A owns a synchronization resource of
a higher-priority task B, and a task C with
priority higher than A is running.
Without a feature like priority ceilings,
task C can prevent task A and C from running.
A priority-ceiling feature changes the
priority of task A to that of task C, allowing
it to run and eventually release the resource
needed by C. At this point, task A’s priority
returns to normal and task C can run.
The other timing-related issues, which
the programmer must address, are often the
sources of bugs that are difficult to locate
and correct. Trace tools become valuable
assets in locating these kinds of bugs, since
symptoms such as blocked tasks are the
only indication of the problem.
Continue to page 2
Of the required features for an operating
system, one is optional in an RTOS
environment—reentrant libraries. In a typical
operating system, this is a requirement
because the tasks and programs tend to be
arbitrary and changing, as well as prone to
sharing libraries.
In an embedded environment, there’s
usually more control over the programs
and tasks running in the system. Often,
tasks never share any code except for the
operating-system interface, which may or
may not be reentrant. Programmers, especially
those dealing with device drivers,
need to be aware of reentrancy issues.
A plethora of task synchronization
mechanisms is out there, from mutexes to
messaging systems. From an RTOS perspective,
no difference exists between them
with respect to synchronization issues,
such as race conditions.
The timer tends to be common among
microcontrollers and operating systems.
Minimally, a timer will be used as a timeof-
day clock. But because they’re so useful,
they tend to be implemented in a special
fashion. The POSIX specification even
defines timers as a component. Timers can
also provide watchdog support.
In many microcontrollers, a timer can be
set up to wake up the system when it’s in
sleep mode. Some implementations allow
operating systems to use it as a general
timer, even though this wakeup feature is
independent of the operating system.
Some systems have different types of
timers with different characteristics to
meet various requirements. Some timers
can be synchronized to deliver simultaneous
pulse-width-modulation (PWM)
streams for motor-control applications.
For an RTOS, a single timer will usually
provide the necessary support to implement
a time-of-day clock as well as providing
time-slice support.
Timers also support time slicing. Usually
found on time-sharing systems, it gives
applications a “fair” amount of time to execute.
This type of round-robin scheduling
can be implemented for any interrupt level.
Normally, the interval provided by a clock
“tick” will be fixed and tasks will be given
the same amount of time to execute before
being preempted. Of course, this policy is
arbitrary and a variety of implementations
is possible. For instance, variable time-slice
durations would allow time to be allocated
on a per task basis, with some tasks receiving
more time than others, versus a task
priority scheme that would potentially lock
out lower-priority tasks.
Many RTOSs feature a fixed scheduler.
Others permit replacement or customization,
while another segment of RTOSs
supports a variety of policies. This flexible
approach is what enables operating systems
such as Linux to provide real-time support
at the same time they’re running a mix of
applications in a time-sliced environment.
Real-time tasks have a high priority and
run before the typical user tasks.
Linux actually has a more complex
scheduling system that specifies a task on
whether it will relinquish control to another
task of the same priority in a roundrobin
methodology or continue to run to
completion. (For more, see “Hypervisors And
Separation Kernels”) Virtualization
RTOS platforms like Open Kernel Labs’
OKL4 address this issue.
BASIC COMMUNICATIONS
Some texts separate task synchronization
and communication, but generally they’re
the same thing. It’s just a matter of what
information is exchanged. Nowhere is
this more apparent than with messagepassing-
based RTOS. Here, the messaging
system handles all communication with no
distinction between communication and
synchronization.
Minimally, an RTOS must provide a
mutual exclusion primitive, such as a
mutex. Everything else can be built upon
this primitive. In many cases, as with a
message-passing system, the mutual exclusion
support is hidden within the operating
system. Only higher-level messaging
functions are exposed.
Messaging systems have a range of
names, from pipes to queues, and their
implementations can span from singleprocessor,
single-memory models to multicore
clustering systems. Enea’s OSE RTOS
and QNX’s Neutrino are two mainline
RTOSs based on message passing.
Regardless of the approach or API chosen,
the communication system must be
integrated into the operating system’s scheduler
at some level. Therefore, a task can be
removed from the active queue if it must wait
for an event. Likewise, a task that initiates an
event, causing another task to become active,
will result in a scheduling action.
Communication, events, and scheduling
may be tied to the hardware, something
that the RTOS must also handle. Texas
Instruments’ DSP/BIOS is an RTOS
designed to run on the DSP side of a dualcore
system like TI’s DaVinci line. Among
other things, DSP/BIOS handles communication
between the ARM core and
the DSP core.
Continue to page 3
The move to multicore with larger cores
will likely retain the RTOS or an OS.
However, smaller cores obviate or limit the
possibility of an RTOS. Intellasys’ SEAforth
40C18 chip contains 40 small 18-bit
cores that run Forth (see “Are You Migrating
To Massive Multicore Yet?” at www.electronicdesign.com, ED Online 19976). The
instructions are compact, so each word
holds four instructions.
Each core has 64 words of ROM and
RAM, and the chip has space for only
10,000 instructions. That’s barely enough
to fit a program, let alone an RTOS. Still,
enough space exists to place dedicated parts
of an operating environment throughout
the chip. Likewise, the applications for
this platform are often dedicated. Thus,
RTOS-style support isn’t required since
the hardware is handling core-to-core
communication and task dispatch.
MANAGING RESOURCES
What distinguishes an RTOS is its ability
to manage resources, including time and
memory. Timing issues are associated with
interrupt response time, but resource-management
timing issues occur, too. Though
interrupts address a number of timing issues,
applications must still utilize resources.
Consider memory allocation. Many
real-time applications forego dynamic
memory allocation to make sure it doesn’t
become an issue because of the variance
that can occur due to allocation and deallocation.
Applications that need dynamic
memory allocation often split them into
real-time and non-real-time portions. The
latter handles dynamic memory allocation.
Typically, the real-time portion must have
enough memory allocated before it’s used.
C and C++ are used in real-time embedded
applications because memory and
other resource usage is explicit. Real-time
tasks need to avoid C and C++. In particular,
it’s more difficult with C++, where
allocation and deallocation are more easily
hidden but the process is still manageable.
The challenge is greater with languages
such as Java and C#, which inherently use
dynamic memory allocation. The programmer
can control memory allocation
and deallocation. In some instances, the
programming environment can enforce
memory allocation and deallocation.
The Real Time Specification for Java
(RTSJ) defines ways to create Java applications
that do not need garbage collection.
RTSJ does so within the Java framework,
enabling programmers to gain the advantages
of Java without the memory-allocation
limitations.
Both Sun an DDC-I have implementations
of RTSJ. DDC-I’s supports x86
and PowerPC platforms. Aonix has a similar
real-time platform called PERC. These platforms feature real-time, concurrent
garbage collectors that make it possible to
write real-time applications in Java without
the memory-allocation limitations.
However, the real-time requirements
aren’t as tight because the system must
allow thread switches for the garbage collector.
On the other hand, the garbage
collector will consume timing resources,
though only when real-time tasks can guarantee
that certain deadlines are met. Fast is
good, but on time is the RTOS credo.
One consideration when looking at realtime
platforms is the overall impact memory
allocation will have on a system. Many
systems can operate with a static allocation
that never changes, but more dynamic systems
could benefit from real-time garbage
collection instead. Studies show that efficiency
of garbage collection versus explicit
memory allocation is comparable.
Another issue surrounding virtualmachine-
style platforms such as Java and
C# is the use of a just-in-time (JIT) compiler.
Real-time systems based on these
types of systems must employ ahead-oftime
(AOT) compilers like C and C++.
Designers may choose Java or C# for
their improved productivity, lower susceptibility
to bugs, and safety. It should come
as no surprise, then, that a safety-critical
Java specification dubbed JSR-302 is in the
works (see “Critical Java,” ED Online 8116).
SECURING AN RTOS
An RTOS is limited by the hardware it
runs on. Hardware that lacks memory
protection can be secured, but the level of
security will be limited. Memory and virtual-
machine support usher in a higher level
of security, though. Security policies like
those in SE Linux, Green Hills Integrity,
and LynuxWorks LynxSecure Embedded
Hypervisor and LynxOS-SE RTOS offer
much more security than a typical RTOS.
Cost is higher, however, so developers need
to weigh the tradeoff.
Real-time developers will have to contend
with policy implementation and boundaries.
Security support can take lots of time,
depending on where information is coming
from and going. This is where partitioned
systems step in, so security can be applied at
the boundaries and with non-real-time portions
of the application in that space.
OS AWARE DEBUGGERS
Debugger support is a key factor to consider
when looking at any operating system. This
support shows up in two areas: kernel and
device driver debugging, and OS awareness.
Kernel debugging is critical to the creation
and support of device drivers and
kernel enhancements. In many cases, a
special debugger is required to handle an
RTOS’s kernel. In others, the debugging
understands the kernel environment as
well as the application environment.
OS awareness provides insights into the
operating system. Support can vary from
providing information about OS service
state to the ability to adjust task scheduling.
Likewise, an OS-aware debugger typically
lets other applications or threads run while
the debugger stops another.
|