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