Working on a STM32G0B0 (Cortex M0+), recently I have a problem with IWDG (independent watch dog).
Despite I never made it work properly as windowed one, it works decently as normal watchdog.
I set it quite hard at 10mS just to observe any glitches during development.
Never triggered, code works properly until today :))))
So I would like to know if my code execution was the problem (hard to believe)
Or just a bug hit me and landed to HarwareFault()
Finally, could be a non implemented vector, but shouldn't be unless a bug occured.
Similar to this thread
How do I debug unexpected resets in a STM32 device?
And this implementation for Cortex M3, M4
https://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/
I would like to know if there is a good way for M0+ to save at least address that caused jumping to HardwareFault.
Would be nice to save more for debug purposes. I want to print that info after next reset.
Thanks for hints!
Note: I use bare metal C without any SDK except for definitions and ARM low level code.
EDIT
Following some guidance from here
https://community.silabs.com/s/article/debug-a-hardfault?language=en_US
There is a handler that they say is working on M0 but it isn't
void debugHardfault(uint32_t *sp)
{
uint32_t r0 = sp[0];
uint32_t r1 = sp[1];
uint32_t r2 = sp[2];
uint32_t r3 = sp[3];
uint32_t r12 = sp[4];
uint32_t lr = sp[5];
uint32_t pc = sp[6];
uint32_t psr = sp[7];
while(1);
}
__attribute__( (naked) )
void HardFault_Handler(void)
{
__asm volatile
(
"mrs r0, msp \n"
"mov r1, #4 \n"
"mov r2, lr \n"
"tst r2, r1 \n"
"beq jump_debugHardfault \n"
"mrs r0, psp \n"
"jump_debugHardfault: \n"
"ldr r1, debugHardfault_address \n"
"bx r1 \n"
"debugHardfault_address: .word debugHardfault \n"
);
}
Error: selected processor does not support `mrs r0,msp' in Thumb mode
EDIT2
Found a handler for M0 at Segger
https://wiki.segger.com/Cortex-M_Fault
Implemented like this for M0
.syntax unified
.cpu cortex-m0plus
.fpu softvfp
.thumb
.global HardFault_Handler
.global NMI_Handler
.global PendSV_Handler
.global SVC_Handler
HardFault_Handler:
BusFault_Handler:
UsageFault_Handler:
MemManage_Handler:
PendSV_Handler:
SVC_Handler:
NMI_Handler:
;// This version is for Cortex M0
movs R0, #4
mov R1, LR
tst R0, R1 ;// Check EXC_RETURN in Link register bit 2.
bne Uses_PSP
mrs R0, MSP ;// Stacking was using MSP.
b Pass_StackPtr
Uses_PSP:
mrs R0, PSP ;// Stacking was using PSP.
Pass_StackPtr:
ldr R2,=HardFaultHandler
bx R2 ;// Stack pointer passed through R0.
.end
IWDG (watchdog) was disabled and I triggered a HF manually like this
int _UnalignedAccess(void) {
int r;
volatile unsigned int* p;
p = (unsigned int*)0x20000001; // not aligned
r = *p;
return r;
}
Collecting function
void HardFaultHandler(unsigned int* pStack) {
HardFaultRegs.SavedRegs.r0 = pStack[0]; // Register R0
HardFaultRegs.SavedRegs.r1 = pStack[1]; // Register R1
HardFaultRegs.SavedRegs.r2 = pStack[2]; // Register R2
HardFaultRegs.SavedRegs.r3 = pStack[3]; // Register R3
HardFaultRegs.SavedRegs.r12 = pStack[4]; // Register R12
HardFaultRegs.SavedRegs.lr = pStack[5]; // Link register LR
HardFaultRegs.SavedRegs.pc = pStack[6]; // Program counter PC
HardFaultRegs.SavedRegs.psr.byte = pStack[7]; // Program status word PSR
}
Still not working properly. Hardware fault is triggered but my function is not called at all. Instead, big crash and reset (no watchdog)
Any help appreciated!