Debugging a HardFault on a Cortex-M: from a mystery to a line of code
Every embedded developer knows the moment: the firmware has been running, and then it does not. The debugger shows that the program sits in an infinite loop with a name like HardFault_Handler or Default_Handler, and the call stack is a few meaningless frames. That loop is the default handler of the startup code, and it says exactly nothing about what happened. The fault has a cause, and the processor has already written it down: in eight registers on the stack and in four status registers. It is only necessary to read them.
This article shows how to turn the loop into a line of source code, in two real examples that I ran in QEMU (a model of an STM32F4 board) and examined with GDB: a call of a NULL function pointer and a write to an address where nothing is. All outputs are real.