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 #include "mbed.h"
rgrover1 0:68900ac9bc4b 2 #include <stdint.h>
rgrover1 0:68900ac9bc4b 3
rgrover1 0:68900ac9bc4b 4 /* Reference: http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html */
rgrover1 0:68900ac9bc4b 5
rgrover1 0:68900ac9bc4b 6 /*
rgrover1 0:68900ac9bc4b 7 * The stack frame of the fault handler contains the state of the ARM Cortex-M
rgrover1 0:68900ac9bc4b 8 * registers at the time that the fault occurred. The code below shows how to
rgrover1 0:68900ac9bc4b 9 * read the register values from the stack into C variables. Once this is done,
rgrover1 0:68900ac9bc4b 10 * the values of the variables can be inspected or written to the console just
rgrover1 0:68900ac9bc4b 11 * as an other variable.
rgrover1 0:68900ac9bc4b 12 */
rgrover1 0:68900ac9bc4b 13 extern "C" void
rgrover1 0:68900ac9bc4b 14 prvGetRegistersFromStack(uint32_t *pulFaultStackAddress)
rgrover1 0:68900ac9bc4b 15 {
rgrover1 0:68900ac9bc4b 16 /* These are volatile to try and prevent the compiler/linker optimising them
rgrover1 0:68900ac9bc4b 17 * away as the variables never actually get used. If the debugger won't
rgrover1 0:68900ac9bc4b 18 * show the values of the variables, make them global my moving their
rgrover1 0:68900ac9bc4b 19 * declaration outside of this function.*/
rgrover1 0:68900ac9bc4b 20
rgrover1 0:68900ac9bc4b 21 /*
rgrover1 0:68900ac9bc4b 22 * Only the ProgramCounter (PC) is useful in this particular case.
rgrover1 0:68900ac9bc4b 23 */
rgrover1 0:68900ac9bc4b 24 // volatile uint32_t r0;
rgrover1 0:68900ac9bc4b 25 // volatile uint32_t r1;
rgrover1 0:68900ac9bc4b 26 // volatile uint32_t r2;
rgrover1 0:68900ac9bc4b 27 // volatile uint32_t r3;
rgrover1 0:68900ac9bc4b 28 // volatile uint32_t r12;
rgrover1 0:68900ac9bc4b 29 // volatile uint32_t lr; /* Link register. */
rgrover1 0:68900ac9bc4b 30 volatile uint32_t pc; /* Program counter. */
rgrover1 0:68900ac9bc4b 31 // volatile uint32_t psr;/* Program status register. */
rgrover1 0:68900ac9bc4b 32
rgrover1 0:68900ac9bc4b 33 // r0 = pulFaultStackAddress[ 0 ];
rgrover1 0:68900ac9bc4b 34 // r1 = pulFaultStackAddress[ 1 ];
rgrover1 0:68900ac9bc4b 35 // r2 = pulFaultStackAddress[ 2 ];
rgrover1 0:68900ac9bc4b 36 // r3 = pulFaultStackAddress[ 3 ];
rgrover1 0:68900ac9bc4b 37 // r12 = pulFaultStackAddress[ 4 ];
rgrover1 0:68900ac9bc4b 38 // lr = pulFaultStackAddress[ 5 ];
rgrover1 0:68900ac9bc4b 39 pc = pulFaultStackAddress[ 6 ];
rgrover1 0:68900ac9bc4b 40 // psr = pulFaultStackAddress[ 7 ];
rgrover1 0:68900ac9bc4b 41
rgrover1 0:68900ac9bc4b 42 error("\r\nHardFault_Handler: from pc = 0x%08x\r\n", (unsigned)pc);
rgrover1 0:68900ac9bc4b 43 }