Page 97 - The Art of Designing Embedded Systems
P. 97
84 THE ART OF DESIGNING EMBEDDED SYSTEMS
“Safely” is important, as global variables, the old standby of the des-
perate programmer, are generally a Bad Idea and are deadly in any inter-
rupt-driven system. We all know how globals promote bugs by being
available to every function in the code; with multitasking systems they lead
to worse conflicts as several tasks may attempt to modify a global all at the
same time.
Instead, the operating system’s communications resources let you
cleanly pass a message without fear of its corruption by other tasks. Prop-
erly implemented code lets you generate the real-time analogy of OOP’s
first tenet: encapsulation. Keep all of the task’s data local, bound to the
code itself, and hidden from the rest of the system.
For instance, one challenge faced by many embedded systems is
managing system status info. Generally, lots and lots of different inputs,
from door switches to the results of operator commands, affect total status.
Maintain the status in a global data structure and you’ll surely find it ham-
mered by multiple tasks. Instead, bind the data to a task, and let other tasks
set and query it via requests sent through queues or mailboxes.
Is this slower than using a global? Sure. It uses more memory, too.
Just as we make some compromises in selecting a compiler over an as-
sembler, proper use of an RTOS trades off a bit of raw CPU horsepower
for better code that’s easier to understand and maintain.
Most operating systems give you tools to manage resources. Surely
it’s a bad idea for multiple tasks to communicate with a UART or similar
device simultaneously. One way to control this is to lock the resource-
often using a semaphore or other RTOS-supplied mechanism-so only
one task at a time can access the device.
Resource locking and priority systems lead to one of the perils of
real-time systems: priority inversion. This is the deadly condition where a
low-priority task blocks a ready and willing high-priority task.
Suppose the system is more or less idle. A background, perhaps
unimportant, task asks for and gets exclusive access to a comm port. It’s
locked now, dedicated to the task until released. Suddenly an oh-my-god
interrupt occurs that starts off the system’s highest priority and most criti-
cal task. It, too, asks for exclusive comm port access, only to be denied that
by the OS since the resource is already in use. The high-priority task is in
control; the lower one can’t run, and can’t complete its activity and thus re-
lease the comm port. The least important activity of all has blocked the
most important!
Most operating systems recognize the problem and provide a work-
around. For example in VxWorks you can use their mutual exclusion sem-
aphores to enable “priority inheritance.” The task that locks the resource

