Search code examples
debuggingembeddedinterruptbreakpointsjtag

Hardware breakpoints vs Software breakpoints in embedded systems


My understanding is that inserting software breakpoints involves replacing the next instruction in code to be executed by a software interrupt instruction which will cause the CPU to halt when it reaches that instruction.

Hardware breakpoints involve putting the address of the next instruction after the breakpoint to be executed into a register and when the addresses match, via the use of a hardware comparator, this then causes the CPU to halt (Correct me if i'm wrong).

What i'm confused about is, do we only use hardware breakpoints when using a hardware debugger to debug a board via JTAG for example? Or can JTAG use software breakpoints also?

Is GDB only used with software breakpoints, or can it be used also in conjunction with JTAG? Sorry if the question is a bit broad.


Solution

  • "correct me if I'm wrong"

    A breakpoint is set on the instruction, not after it - the break occurs before the instruction is executed, not after - otherwise setting a breakpoint on a jump, call or branch instruction would fail.

    "do we only use hardware breakpoints when using a hardware debugger to debug a board via JTAG for example?"

    JTAG is a simple communication interface to the on-chip debug (and is used for other purposes such as in-circuit memory and FPGA programming and boundary-scan for example).

    While it may vary between architectures on ARM Cortex-M for example, you can access the on-chip debug registers from the target code and set hardware breakpoints. Yoiu can also place software break points in your code using the BKPT instruction (as opposed to a SWI as you suggest).

    Or can JTAG use software breakpoints also?

    As I said, JTAG is just a communication interface to the on-chip debug, however through the on-chip debug, you can directly set any RAM content, so the JTAG connected debugger software running on the development host can temporarily modify code in RAM to set a software breakpoint (by replacing the target instruction with a BKPT, then when the breakpoint is hit, reverting back to the original instruction so it can be executed. Software breakpoints are not so straightforward for code running from ROM, though some debuggers support unlimited ROM breakpoints (for a price) - the manufacturers of such hardware do not necessarily publicise the methods they use to do that.

    Before JTAG and on-chip debug became widely available on evebnlow-end parts, technologies such as In-Circuit Emulation and ROM emulators were used. These were generally expensive and complex solutions.

    Is GDB only used with software breakpoints, or can it be used also in conjunction with JTAG?

    GDB can be used in a number of ways. It requires a "debug stub" - a software layer mapping the debugger software to the available hardware - the nature of which will depend on the debug interface and target device used. When using a UART or Ethernet port for example, the stub is actually code running on the target itself (such as Linux's gdbserver). In that case it is less reliable since software errors may prevent the debug port driver from actually running especially in targets lacking MMU protection. Simpler JTAG devices interface with GDB through a stub running on the development host, for example the commonly used OpenOCD software. More expensive JTAG debug hardware may run the stub on the JTAG hardware itself - such as Abatron's bdi2000 for example. Either way the debug stub will be able to use hardware and software breakpoints depending on the target capabilities.