Page 227 - The Art of Designing Embedded Systems
P. 227
214 THE ART OF DESIGNING EMBEDDED SYSTEMS
Functions
Regardless of language, keep functions small! The ideal size is less
than a page; in no case should a function ever exceed two pages. Break
large functions into several smaller ones.
The only exception to this rule is the very rare case where real time
constraints (or sometimes stack limitations) mandate long sequences of in-
line code. The project manager must approve all such code. . . but first
look hard for a more structured alternative!
Explicitly declare every parameter passed to each function. Clearly
document the meaning of the parameter in the comments.
Define a prototype for every called function, with the exception of
those in the compiler’s runtime library. Prototypes let the compiler catch
the all-too-common errors of incorrect argument types and improper num-
bers of arguments. They are cheap insurance.
In general, function names should follow the variable naming proto-
col. Remember that functions are the “verbs” in programs-they do things.
Incorporate the concept of “action words” into the variables’ names. For
example, use “read-A/D” instead of “A/D-data,” or “send-to-LCD’ in-
stead of “LCD-out.”
Interrupt Sewice Routines
ISRs, though usually a small percentage of the code, are often the
hardest bits of firmware to design and debug. Crummy ISRs will destroy
the project schedule!
Decent interrupt routines, though, require properly designed hard-
ware. Sometimes it’s tempting to save a few gates by letting the external
device just toggle the interrupt line for a few microseconds. This is unac-
ceptable. Every interrupt must be latched until acknowledged, either by
the processor’s interrupt-acknowledge cycle (be sure the hardware acks
the proper interrupt source), or via a handshake between the code and the
hardware.
Use the non-maskable interrupt only for catastrophic events, like the
apocalypse or imminent power failure. Many tools cannot properly debug
NMI code. Worse, NMI is guaranteed to break non-reentrant code.
If at all possible, design a few spare I/O bits in the system. These are
tremendously useful for measuring ISR performance.
Keep ISRs short! Long (too many lines of code) and slow are the
twins of ISR disaster. Remember that long and slow may be disjoint; a five-
line ISR with a loop can be as much of a problem as a loop-free 500-line

