Page 81 - The Art of Designing Embedded Systems
P. 81
68 THE ART OF DESIGNING EMBEDDED SYSTEMS
mov ax, [j+ll
adc ax, 0 ; prop carry to high part of j
mov [j+ll ,ax
An interrupt in the middle of this code will leave j just partially
changed: if the ISR is reincarnated with j in transition, its value will surely
be corrupt. Or, if other routines use the variable, the ISR may change its
value at the same time other code tries to make sensible use of it.
The first solution is to avoid global variables! Globals are an abomi-
nation, a sure source of problems in any system, and an utter nightmare in
real-time code. Never, ever pass data between routines in globals unless
the following three conditions are fulfilled:
Reentrancy issues are dealt with via some method, such as dis-
abling interrupts around their use-though I do not recommend
disabling interrupts cavalierly, since that affects latency.
The globals are absolutely needed because of a clear performance
issue. Most alternatives do impose some penalty in execution time.
The global use is limited and well documented.
Inside of an ISR, be wary of any variable declared as a static. Though
statics have their uses, the ISR that reenables interrupts, and then is inter-
rupted before it completes, will destroy any statics declared within.
In 1997, on a dare, I examined firmware embedded in 23 completed
products, all of which were shipping to customers. Every one had this par-
ticular problem! Interestingly, the developers of 70% of the projects ad-
mitted to infrequent, unexplainable crashes or other odd behavior. One
frustrated engineer revealed that his product burped almost hourly, a symp-
tom “corrected” (perhaps “masked” would be a better term) by adding a
very robust watchdog timer circuit. This particularly bad system, which
had the reentrancy problem inside an ISR, also had the fastest interrupt rate
of any of the products examined.
This suggests using a stress test to reveal latent reentrancy defects.
Crank up the interrupt rates! If the timer comes once per second, try driv-
ing it every millisecond and see how the system responds. Assuming per-
formance issues don’t crash the code, this simple test often shows a horde
of hidden flaws.
Even the perfectly coded reentrant ISR leads to problems. If such a
routine runs so slowly that interrupts keep giving birth to additional copies
of it, eventually the stack will fill. Once the stack bangs into your variables,
the program is on its way to oblivion. You must ensure that the average in-

