The example bellow was made for GCC compiler where you can easily specify local variable as register. This is unnecessary for local pointer variable but must be done for LR which holds information about exception context. Notice the naked attribute to handler function. It is needed so that the handler has no function prologue which could change SP. SP (main or process) actually holds the address of the exception context.
For easier debugging the software breakpoint is added at the end of handler and automatic handler catch functionality can be disabled so that CPU stops at breakpoint (not on handler entry).
typedef struct { unsigned long m_dwExR0; unsigned long m_dwExR1; unsigned long m_dwExR2; unsigned long m_dwExR3; unsigned long m_dwExR12; unsigned long m_dwExLR; unsigned long m_dwExPC; unsigned long m_dwExPSR; }SCortexM3ExContext; __attribute__( ( naked ) ) void HardFaultHandler() { register SCortexM3ExContext * psCortexM3ExContext __asm("r0"); register unsigned long dwLR __asm("lr"); if ( dwLR & 4 ) asm(" mrs r0, psp"); else asm(" mrs r0, msp"); asm(" BKPT"); while ( 1 ); }