cortex-minstruction-setfaultthumb

STM32 sometimes hardfault on reboot (thumb instruction issue?)


STM32L496 micro is hard faulting when power is cycled, but only on some builds of firmware, others are ok. I've been able to track it down to a specific path in the assembly, what looks like is happening is a vector table address is loaded into R3 with and LDR command, and then a branch is done to that address with a BX. Sometimes, it seems to grab the address in the vector table but off by a byte. Here's a brief summary:

How it should work:

LDR R3, [R0] ---> R3 = [0x20001188] = 0x080422F0

LDR R3, [R3, #8] ---> R3 = [0x080422F8] = 0x0801E421

BX R3 ---> branch to addr 0x0801E421

Vector Table data:

[0x080422F8] = 0x0801E421

[0x080422FC] = 0x0801E441

But what I see sometimes on reboot with a hardfault and the core dump shows:

R3 = 0x410801E4

Which is actually the proper data but as if it was read off by one byte (that is, reading from 0x080422F9 not ...F8). NOTE the MSB is the LSB of the next address from above in the vector table. When changing the code, that byte (41 here) will change but always shows up like that in the fault, so I'm pretty confident it's referencing the address but off by a byte. (That is, if the LSB at 0x080422FC was 'B1', R3 would equal 0xB10801E4, this is very repeatable) NOTE: This never happens in debug mode, stepping through the code, but is quite repeatable just cycling power.

I know the cortex m4 uses Thumb instructions, and the thumb uses bit[0] set to '1'. Seems to make sense this could be why it seems to access the address + 1, but why only in this instance, and why only certain builds?

I've attempted adding stack size to my thread (shouldn't be a problem), lot's of code changes and modifications in tracking this down.


Solution

  • I have since figured this one out. It was not related to thumb instructions. Essentially the bootloader had an interrupt that incremented a tick, and that interrupt was not being disabled before jumping to the application, so some occasions that tick would get incremented once, which actually incremented the flash address stored at that same RAM address in the application. Always disable interrupts when leaving the bootloader!