Debugging Embedded C
Debug probes, breakpoints, logging over UART, and how to find the instruction that caused a HardFault.
There is no console and no core dump on a microcontroller, but there are powerful tools: a debug probe gives you breakpoints, single-stepping and live memory views on the real hardware, and the CPU itself records why it crashed.
Finding the cause of a HardFault
The naked HardFault_Handler checks bit 2 of LR to find which stack (MSP or PSP) holds the frame.
hardfault_c copies the frame and the fault status registers (CFSR, HFSR, BFAR, MMFAR) into globals.
bkpt halts in the debugger; read g_fault_frame.pc and look it up in the .map/.elf file.
Adding printf calls to find a timing bug Toggle a GPIO and measure with a logic analyzer printf changes the timing so much that timing bugs often disappear while you watch (a 'heisenbug').
Which stacked register tells you where a HardFault happened?
The stacked PC (program counter) — the address of the instruction that was executing when the fault occurred.
What is the difference between a breakpoint and a watchpoint?
A breakpoint stops when execution reaches an address; a watchpoint stops when a memory location is read or written.