STM32 有时在重新启动时发生硬错误(Thumb 指令问题?)

huangapple go评论54阅读模式
英文:

STM32 sometimes hardfault on reboot (thumb instruction issue?)

问题

STM32L496微控制器在重新上电时出现硬件故障,但只在某些固件版本上发生,其他版本正常。我已经追踪到问题出现在汇编代码的特定路径,看起来发生的情况是通过LDR命令将矢量表地址加载到R3中,然后通过BX跳转到该地址。有时候,似乎获取到了矢量表中的地址,但偏移了一个字节。以下是简要总结:

正常工作原理:

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

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

BX R3 ---> 跳转到地址0x0801E421

矢量表数据:

[0x080422F8] = 0x0801E421

[0x080422FC] = 0x0801E441

但在重新启动时,硬件故障和核心转储显示:

R3 = 0x410801E4

这实际上是正确的数据,但好像是多读了一个字节(也就是,从0x080422F9而不是...F8读取)。请注意,MSB是上面矢量表中下一个地址的LSB。当更改代码时,该字节(这里是41)会更改,但在故障中总是显示为这种方式,因此我相当确信它引用的是地址,只是偏了一个字节。注意:在调试模式下永远不会发生这种情况,通过代码进行单步调试,但重新上电后会重复出现。

我知道Cortex M4使用Thumb指令,Thumb使用位[0]设置为'1'。这似乎能解释为什么它似乎访问地址+1,但为什么只在这种情况下,为什么只有某些版本会发生这种情况?

我已尝试为线程添加堆栈大小(不应该是问题),并在追踪问题时进行了大量代码更改和修改。

英文:

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.

答案1

得分: 2

我已经弄清楚了这一点。这与指令无关。基本上,引导加载程序有一个增加计时器的中断,而在跳转到应用程序之前未禁用该中断,因此有时该计时器会增加一次,实际上增加了应用程序中相同RAM地址中存储的闪存地址。离开引导加载程序时,始终禁用中断!

英文:

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!

答案2

得分: 1

The cortex-m doesn't not support arm mode. Only thumb mode is supported. So if your code switches probably you're compiling for the wrong platform.

英文:

The cortex-m doesn't not support arm mode. Only thumb mode is supported. So if your code switches probably you're compiling for the wrong platform

huangapple
  • 本文由 发表于 2023年4月4日 08:32:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75924658.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定