C语言 当恢复的堆栈帧不包含合理信息时,如何在STM32H743上调试HardFault?

x33g5p2x  于 2023-03-22  发布在  其他
关注(0)|答案(1)|浏览(93)

我目前正在尝试查找STM32 H743上有时会出现的HardFault的原因。我能够将问题缩小到大约200行的代码段。现在,我当然想确定它的确切位置。
一些可能相关或不相关的信息:我用C语言编程芯片,使用ST HAL。我通过VSCode的ST-Linkv 3使用GDB调试。
调试因以下几个因素而变得复杂:

  • 错误发生得很少。我已经找到了复制故障的可靠方法,但可能需要几分钟到一个小时才能发生错误。
  • 这个错误取决于一些硬件时序(它涉及UART外设)。我不能在它发生之前单步执行代码,因为当单步执行时,它不会发生。
  • 错误似乎没有留下有意义的堆栈帧(见下图)。这实际上是我问题的主要主题。

为了找到错误的原因,我按照这里的说明进行操作:https://interrupt.memfault.com/blog/cortex-m-hardfault-debug
我的CFSR(0xE000ED28)的值是0x1。所以是IACCVIOL。嗯...在这一点上,我想有必要提到我没有启用任何MPU。所以如果我理解正确,这意味着有东西试图将代码执行跳转到现在允许执行代码的内存位置。这可能是什么原因?
我的HFSR(0xE000ED2C)的值是0x40000000。那么一个FORCED错误,这对我有任何帮助吗?
我的lr寄存器的值是0xFFFFFFE9lr & (1<<2)0x0,所以这意味着msp应该是活动堆栈指针。从msp阅读堆栈帧(运行p/a *(uint32_t[8] *)$msp)得到:

0x672,        // r0
0x40,         // r1
0x631090,     // r2
0x20001800,   // r3
0xff          // r12
0xfc006e3f    // LR
0xfc006e3e    // pc
0x81000000    // xPSR

所以如果我理解正确的话,LR应该是HardFault处理程序之前最后一次跳转的返回地址。但是0xfc006e3f是什么样的返回地址呢?我猜这是HardFault首先发生的部分原因,但是我如何从这些信息中找到问题实际上是在哪里引起的呢?

mznpcxlj

mznpcxlj1#

我能够找到我的问题,感谢所有的建议,在评论!
最后@Ilya的评论几乎是正确的:在我的代码中我使用了一个通过UART外设实现OneWire协议的库。这个库在堆栈上声明了一个UART接收缓冲区,并使用它在中断模式下接收数据。如果OneWire事务由于某种原因超时,它会返回一个错误代码,但是它不取消UART接收操作。有时,UART接收事务将在一段时间后完成,并覆盖堆栈中UART接收缓冲器使用的存储器位置处的任何内容在我不幸的情况下,这意味着我留下了一个硬故障,没有线索,究竟是什么造成的。
我通过在OneWire超时的情况下取消UART接收操作解决了这个问题。

相关问题