Page 83 - The Art of Designing Embedded Systems
P. 83
70 THE ART OF DESIGNING EMBEDDED SYSTEMS
to the human-speed debugging that gives interrupting hardware a chance to
issue yet another request while the code’s stopped at the breakpoint.
In the case of NMI, though, disaster strikes immediately, since there
is no interrupt-safe state. The NMI is free to reoccur at any time, even in
the most critical non-reentrant parts of the code, wreaking havoc and
despair.
A lot of applications now just can’t survive the problems inherent in
using breakpoints. After all, stopping the code stops everything; your en-
tire system shuts down. If your code controls a moving robot arm, for ex-
ample, and you stop the code as the arm starts moving, it will keeping
going and going and going . . . until something breaks or a limit switch is
actuated. Years ago I worked on a 14-ton steel gauge; a 280 controlled the
motion of this monster on railroad tracks. Hit a breakpoint and the system
ran off the end of the tracks!
Datacomm is another problem area. Stop the code via a breakpoint,
with data packets still streaming in, and there’s a good chance the receiv-
ing device will time out and start transmitting retry requests.
Though breakpoints are truly wonderful debugging aids, they are like
Heisenberg’s uncertainty principle: the act of looking at the system
changes it. You can cheat Heisenberg-at least in debugging embedded
code!-by using real-time trace, a feature available on all emulators and
some smart logic analyzers.
Trace collects the execution stream of the code in real time, without
slowing or altering the flow. It’s a completely nonintrusive way of view-
ing what happens.
Trace changes the philosophy of debugging. No longer does one stop
the code, examine various registers and variables, and then timidly step
along. With trace your program is running at full tilt, a breakneck pace that
trace does nothing to alter. You capture program flow, and then examine
what happened, essentially looking into the past as the code continues on
(Figure 4-6).
Trace shows only what happens on the bus. You can view neither reg-
isters nor variables unless an instruction reads or writes them to memory.
Worse, C’s stack-based design often makes it impossible to view variables
that were captured. You may see the transactions (pushes and pops), but the
tool may display neither the variable name nor the data in its native type.
With millions of instructions every second, it’s clearly impossible to
capture your program’s entire execution stream. Nor is it desirable, as a
trace buffer a hundred million frames deep is simply too much data to
plow through. Pick an emulator that offers flexible triggers-breakpoint-
like resources that start and stop trace collection.

