HardFault routine for the ARM Cortex-M family

viatorus wrote on Tuesday, October 23, 2018:


while implementing a hard fault handler for your embedded device, I looked up the documentation from here:

I have some questions about the code posted there:

/* The prototype shows it is a naked function - in effect this is just an
assembly function. */
static void HardFault_Handler( void ) __attribute__( ( naked ) );

/* The fault handler implementation calls a function called
prvGetRegistersFromStack(). */
static void HardFault_Handler(void)
    __asm volatile
        " tst lr, #4                                                \n"
        " ite eq                                                    \n"
        " mrseq r0, msp                                             \n"
        " mrsne r0, psp                                             \n"
        " ldr r1, [r0, #24]                                         \n"
        " ldr r2, handler2_address_const                            \n"
        " bx r2                                                     \n"
        " handler2_address_const: .word prvGetRegistersFromStack    \n"

void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
   // ....
  1. Why do we move the stackpointer by 0x24 bytes?
  2. The function prvGetRegistersFromStack only has one parameter. Register r1 is ignored, isn’t it?

rtel wrote on Wednesday, October 24, 2018:

  1. Why do we move the stackpointer by 24 bytes?

Don’t think the stack pointer is moved, although there is a read from an
offset of 24 from the stack pointer.

  1. The function /prvGetRegistersFromStack/ only has one parameter.
    Register R1 is ignored. Am I right?

It looks like R1 is pre-loaded with a value that can be observed (using
the debugger) from inside the C function - looks like the exception
return address, but not sure, also not sure why that is handled specially.