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);
    }
}
Committer:
rgrover1
Date:
Wed Jan 29 18:47:15 2014 +0000
Revision:
1:c325619800b2
Parent:
0:68900ac9bc4b
removing un-necessary duplicated tail of the assembly code.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:68900ac9bc4b 1 ; Reference: http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html
rgrover1 0:68900ac9bc4b 2
rgrover1 0:68900ac9bc4b 3 ; On the Cortex-M3, the processor core automatically saves some interesting
rgrover1 0:68900ac9bc4b 4 ; registers to the stack on initial exception entry. The following
rgrover1 0:68900ac9bc4b 5 ; HardFault_Handler is a short assembly function to determine which stack (MSP
rgrover1 0:68900ac9bc4b 6 ; or PSP) was being used when the fault occurred; once this is done, the fault
rgrover1 0:68900ac9bc4b 7 ; handler assembly code passes a pointer to the stack frame into a C function
rgrover1 0:68900ac9bc4b 8 ; called prvGetRegistersFromStack() which then aids user-debugging.
rgrover1 0:68900ac9bc4b 9
rgrover1 0:68900ac9bc4b 10 AREA asm_func, CODE, READONLY
rgrover1 0:68900ac9bc4b 11
rgrover1 0:68900ac9bc4b 12 ; Export HardFault_Handler function location so that linker can find it
rgrover1 0:68900ac9bc4b 13 EXPORT HardFault_Handler
rgrover1 0:68900ac9bc4b 14 HardFault_Handler
rgrover1 0:68900ac9bc4b 15
rgrover1 0:68900ac9bc4b 16 TST LR, #4 ; test bit 2 of the EXC_RETURN placed in LR to determine which
rgrover1 0:68900ac9bc4b 17 ; stack was in use before entering the handler
rgrover1 0:68900ac9bc4b 18
rgrover1 0:68900ac9bc4b 19 ; move the appropriate stack pointer value into R0
rgrover1 0:68900ac9bc4b 20 ITE EQ
rgrover1 0:68900ac9bc4b 21 MRSEQ R0, MSP
rgrover1 0:68900ac9bc4b 22 MRSNE R0, PSP
rgrover1 0:68900ac9bc4b 23
rgrover1 0:68900ac9bc4b 24 LDR R1, [R0, #24] ; get stacked PC
rgrover1 0:68900ac9bc4b 25
rgrover1 0:68900ac9bc4b 26 ; call prvGetRegistersFromStack() with R0 set as the stack pointer at the
rgrover1 0:68900ac9bc4b 27 ; time of exception entry.
rgrover1 0:68900ac9bc4b 28 LDR R2, HANDLER2_ADDRESS_CONST
rgrover1 0:68900ac9bc4b 29 BX R2
rgrover1 0:68900ac9bc4b 30 IMPORT prvGetRegistersFromStack
rgrover1 0:68900ac9bc4b 31 ALIGN 4
rgrover1 0:68900ac9bc4b 32 HANDLER2_ADDRESS_CONST DCD prvGetRegistersFromStack
rgrover1 0:68900ac9bc4b 33
rgrover1 1:c325619800b2 34 END