A hardfault handler to dump useful registers to aid debugging of program exceptions. Often knowing the ProgramCounter (PC) at fault time is enough to find a useful location in source code.

The library installs an alternate version of the HardFault_Handler to replace the system default. The replaced handler is able to emit useful registers on the system console to aid debugging. You can enhance the handler to emit more useful information.

How would one test this..

Here's how one might produce an exception to trigger a hard-fault. You would not want to do this in your project, but the snippet helps demonstrate the function of this library. The snippet comes from a shared project: PointerError.

// Example of hanging when reading a bad pointer
/* Refer to http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html */

#include "mbed.h"

DigitalOut myled(LED1);

unsigned x[10] = {0};

int main() {
    unsigned *ok_ptr = x;
    unsigned *bad_ptr = (unsigned*)0xe600b0; // not in RAM!
    printf("ok_ptr = 0x%08X, bad_ptr = 0x%08X\n", (unsigned)ok_ptr, (unsigned)bad_ptr);

    unsigned ok_read = ok_ptr[0];
    printf("ok_read = %d\n", ok_read);

    unsigned bad_read = bad_ptr[0];
    printf("bad_read = %d\n", bad_read);

    while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }
}

hardfault.s

Committer:
rgrover1
Date:
2014-01-29
Revision:
1:c325619800b2
Parent:
0:68900ac9bc4b

File content as of revision 1:c325619800b2:

; Reference: http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

; On the Cortex-M3, the processor core automatically saves some interesting
; registers to the stack on initial exception entry. The following
; HardFault_Handler is a short assembly function to determine which stack (MSP
; or PSP) was being used when the fault occurred; once this is done, the fault
; handler assembly code passes a pointer to the stack frame into a C function
; called prvGetRegistersFromStack() which then aids user-debugging.

    AREA asm_func, CODE, READONLY

; Export HardFault_Handler function location so that linker can find it
    EXPORT HardFault_Handler
HardFault_Handler

    TST LR, #4 ; test bit 2 of the EXC_RETURN placed in LR to determine which
               ; stack was in use before entering the handler

    ; move the appropriate stack pointer value into R0
    ITE EQ
    MRSEQ R0, MSP
    MRSNE R0, PSP

    LDR R1, [R0, #24] ; get stacked PC

    ; call prvGetRegistersFromStack() with R0 set as the stack pointer at the
    ; time of exception entry.
    LDR R2, HANDLER2_ADDRESS_CONST
    BX R2
    IMPORT prvGetRegistersFromStack
    ALIGN 4
HANDLER2_ADDRESS_CONST DCD prvGetRegistersFromStack

    END