Page 211 - Embedded Microprocessor Systems Real World Design
P. 211

wherever practical. When testing unknown code on unknown hardware, minimiz-
                   ing the size of the unknown speeds debugging. If using a monitor program or an
                   emulator, the key debugging tool usually is the breakpoint. The code is run with a
                   breakpoint set in the area where a problem is thought to be. When the breakpoint
                   occurs, registers and memory are examined to determine the problem. The catch,
                   in a real-time system, is that interrupts keep coming, motors keep turning, and, in
                   general, the real world keeps happening while the software engineer is trying to
                   figure out what went wrong with the code. If regular edge-sensitive interrupts occur,
                   all of them may be stacked up and waiting to execute when the code is resumed.
                   While there is no silver bullet for this characteristic of real-time debugging, a few
                   tricks can make this part of the task a bit easier:

                     If  the  system will  run this way,  turn  off  all interrupts except those  absolutely
                     necessary to  make the  problem  show up.  If  the  system runs but  the  bug dis
                     appears,  turn  the  interrupts back  on  one at a  time until  the  problem  comes
                     back.
                     If a timer interrupt is used, slow it down enough that you can actually see what
                     is happening.
                     If using debug trace outputs or a circular trace buffer, as described in Chapter
                     6, pay careful attention to the trace values when an error occurs, looking for pat-
                     terns. You may find that a problem occurs only when a particular interrupt code
                     appears in the table twice in a row, indicating a possible problem with reentrancy.
                     Or you may find that a particular  interrupt always occurs between  two polling
                     loop  trace  points,  indicating  a  potential  “shared  memory  or  1/0  trap,” as
                     described in Chapter 5.
                     Ask yourself, “Did it work before the last software change?” I spent a long time
                     one day asking a software engineer if‘ she had changed the code since everything
                     quit working. She kept telling me that she had not changed the code, then finally
                     admitted to making changes, but insisted that the changes were not in the area
                     that was not working. I finally convinced her to try the previous version and every-
                     thing worked again. She had not realized that the new version required  more
                     stack space then she had allowed for.
                     Determine whether the problem goes away when the emulator is connected. If
                     so, this nearly always points to a hardware setup/hold-time  problem or a race
                     condition-but  not always. I once worked on a problem that disappeared every
                     time the emulator was  connected. The problem  turned out to be the “shared
                     memory or 1/0 trap,” described in Chapter 5. For some reason, the emulator
                     timing kept the interrupt from occurring between the two critical instructions.
                     If you can, determine what specific condition causes the software to fail. This may
                     be difficult without an emulator. If the exact hardware condition that caused the
                     problem can be isolated, a pattern may  emerge. Or a logic analyzer may  shed
                     light on the conditions surrounding the fault.


                   192                                             Embedded MicrOpocessor System
   206   207   208   209   210   211   212   213   214   215   216