|
3
Gordon Drive, P.O.Box 1347 Rockland, Maine 04841 U.S.A.
|
|
© 2004 Avocet Systems, Inc.
|
Call
Us Today at 207-596-7766 ("Picton Press")
|
|
Avocet Systems, Inc. : The Complete Solution for Embedded Systems
Development Tools
|
|
|
Hints
Hardware Breakpoints
Abstract
Modern debugging tools offer a wide range of features, but all have some sort
of breakpointing mechanism. Lots of vendors tout their reasons for saving a
few bucks with software breakpoints... we wonder if it's really such a good
idea.
What is the big deal about hardware and software breakpoints? Why does the firmware
engineer care about the industry's breakpoint hype? With the current wide selection
in emulators, breakpoints are a source of confusion as never before.
Most emulators support two different kinds of breakpoints. Event breakpoints
let you match complex conditions. For example, if you'd like to break after
the 50,000th write of a 12 to address char_ptr, then you'll use the emulator's
event system.
Execution breakpoints stop the target code when you get to a particular address.
If you click on a line of source code to set a breakpoint you are using an execution
breakpoint. Most debugging takes place using this resource, so it's important
that it be implemented carefully.
How Breakpoints Work
A hardware breakpoint stops your target code from running using external emulator-mounted
electronics that is completely independent of your hardware. Logic circuits
(often implemented as RAM arrays) watch every bus cycle, stopping execution
when the address at which you've set the breakpoint occurs. A hardware breakpoint
never alters your code, stack, or any other target resource; it is completely
non-intrusive.
A software breakpoint, by contrast, always modifies your code. Typically the
source level debugger inserts an INT3 instruction in your code at each breakpoint
address. (INT3 does a call through location 0000C). When properly implemented
the debugger remembers the instruction that was at the breakpoint address, replacing
it after the code hits any breakpoint.
The emulator detects the software breakpoint by watching the system execute
the INT3 - specifically, by catching the INT3's read from location 0000C. It
then switches to its own internal operation, stopping your code and running
its own.
Forbidden ROM
The problems inherent in software breakpoints really gave birth to the emulator
business. Since software breakpoints must modify your code, you cannot debug
ROMed code with software breakpoints.
Yes, you can copy the ROM to emulator RAM and set the breakpoints in RAM, but
this changes the non-intrusive nature of your tool. With the code running on
the emulator itself, not on your target, it impossible to isolate many hardware/software
interaction problems. For example: code that uses initialized data which has
incorrectly been placed in ROM will work properly when running from emulation
RAM, but will always fail from ROM.
In contrast, hardware breakpoints have no downside. You can step and breakpoint
on code in ROM or in RAM; you can run the code exactly as it will in the delivered
system, finding obscure timing, reentrancy, and other problems.
Though self-modifying code is finally falling out of favor, software breakpoints
cannot be used in self modifying code (for the same reasons listed above) -
despite the fact that such code always runs from RAM
Chip Select Blues
Since software breakpoints work by modifying the contents of RAM (i.e.,. by
replacing an instruction with an INT3 or other breakpoint instruction), they
often will not work if the processor's chip selects are not programmed. Think
about it: on reset the chip selects are partially disabled; with no access to
memory, there's no way the unit can replace an instruction with the INT3. You'll
have to single step through the startup code first, before attempting to set
breakpoints on, say, main().
Note that some emulators get around these problems by allowing breakpoints to
run only in the emulator's overlay RAM, which usually does not require chip
selects to operate.
Don't Read from 0000C!
Another problem arises from the way most software breakpoints work. The emulator
typically watches for reads from location 0000C (the INT3 vector address). Any
read from this address causes the unit to immediately breakpoint _ even if no
breakpoints were set.
Sometimes the firmware reads from low memory as part of an initial memory test.
These reads will crash the emulator, since they signal a breakpoint, even when
none was specified.
This also implies that you may not use the INT3 instruction in your code. The
emulator will erroneously take it as a breakpoint.
If you use software breakpoints, be sure to turn off all memory tests and other
low memory reads before debugging!
Spurious Interrupts
Since software breakpoints modify your code, any time the debugger gets out
of sync with the emulator it may leave INT3s lying around, like hidden time
bombs.
On any sort of unusual exit from the debugger be very, very sure to redownload
your code! It's not a bad practice to redownload every time you exit the debugger,
just to be sure these unwanted INT3s don't cause trouble. Clearly, fast downloads
are essential with software breakpoints.
Why Take Chances?
In the days of $20,000 emulators developers often bought cheap ROM monitors,
which cost little largely since they used software breakpoints. That day is
long gone. High quality emulators with hardware breakpoints now carry no price
penalty over other units. Why compromise... especially where there is no cost
to do it right?
Breakpoints in ISRs
Did you know that many emulators can neither breakpoint nor single step inside
of an interrupt service routine? Link to our application note that discusses
this problem.
Event breakpoints break on complete bus matches; you can mix these with other
sorts of breakpoints to create complex IF- THEN conditions.
Copyright 1994, Softaid, Inc.
|
|
|