3 Gordon Drive, P.O.Box 1347 Rockland, Maine 04841 U.S.A.
Find Tools for Your Chip


 

© 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.