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.
   78   79   80   81   82   83   84   85   86   87   88