Freertos uses the code section below for fault handlers, to get information out of the current stack pointer (the task-stack which caused the crash). unfortunately this works only based on exceptions, and if the the causing function is the last call in the stack.
"tst lr, #4 \n"
"ite eq \n"
"mrseq r0, msp \n"
"mrsne r0, psp \n"
"ldr r1, ADDRESS \n"
"bx r1 \n"
"ADDRESS: .word stackdump_printf \n"
I am looking for the same idea of implementation as above, but with the ability to give me the stack info if the function causing the error was not the last caller, as in the example below
lumos_c_mangling void getRegistersFromStack( uint32_t *pulFaultStackAddress )
{
uint32_t dummy;
/* These are volatile to try and prevent the compiler/linker optimising them
away as the variables never actually get used. If the debugger won't show the
values of the variables, make them global my moving their declaration outside
of this function. */
volatile uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; /* Link register. */
volatile uint32_t pc; /* Program counter. */
volatile uint32_t psr;/* Program status register. */
r0 = pulFaultStackAddress[ 0 ];
r1 = pulFaultStackAddress[ 1 ];
r2 = pulFaultStackAddress[ 2 ];
r3 = pulFaultStackAddress[ 3 ];
r12 = pulFaultStackAddress[ 4 ];
lr = pulFaultStackAddress[ 5 ];
pc = pulFaultStackAddress[ 6 ];
psr = pulFaultStackAddress[ 7 ];
/* When the following line is hit, the variables contain the register values. */
for(;;);
}
void Hardfault_Handler()
{
__asm__
(
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" ldr r1, [r0, #24] \n"
" ldr r2, SP_ADDRESS_CONST \n"
" bx r2 \n"
" SP_ADDRESS_CONST: .word getRegistersFromStack \n"
);
}
void my_assert(int exp) {
if(!exp) {
// here set exception (for debug purposes, i will set here hardfault active (ignore this please in the current discussion)
NVIC_SetPendingIRQ(HardFault_IRQn);
}
}
void main() {
my_assert(0);
}
So here, it would show me that the function "my_assert()" is causing the issue, but this is not true, its the caller of "my_assert()".
Questions:
Based on the link (https://www.silabs.com/content/usergenerated/asi/cloud/content/siliconlabs/en/community/mcu/32-bit/knowledge-base/jcr:content/content/primary/blog/debug_a_hardfault-78gc.social.0.10.html) i could correct the SP by "0x1C + sizeof(uint32_t)", is this correct?
Is there a solution i can refactor this call from ASM to C? I am really not familiar with ASM and would strongly prefer a C implementation.