rtel wrote on Friday, July 20, 2012:
I think the next thing to try is working out which instruction was executing (or attempting to execute) when the hard fault occurs. When the hard fault occurs the stack frame of the fault handler includes the CPU registers as they were when the fault occurred, and the fist thing of interest in the program counter (PC). That tells you the instruction. The other registers will then give you the operand values, which can help track down things like null pointer use as a source of the fault.
To decode the stack frame, provide the following hard fault handler (the function name needs to be correct for the fault handler in your system, and you may need to write it all in assembler depending on how your system is currently set up).
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 pop_registers_from_fault_stack \n"
);
}
This code just sets up everything ready, then jumps to a function called pop_registers_from_fault_stack - which is defined below:
void pop_registers_from_fault_stack(unsigned int * hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
unsigned int stacked_psr;
stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
/* Inspect stacked_pc to locate the offending instruction. */
for( ;; );
}
Put a break point in the for(;
loop in this function, then when the break point is hit, look at the value of stacked_pc to find the instruction that caused the fault.
Once you know the address of the instruction, open up the assembly view in your debugger, go to that address, and put a break point there. Next reset your system so it runs from the start again, and when the break point is hit, you should be able to see the line of C code that is executing.
Regards.