我目前正在努力寻找我的STM32H743上有时发生硬件故障的原因. 我能够将罪魁祸首缩小到一段大约200行的代码.现在,我当然想确定它的确切位置.

一些可能相关也可能不相关的信息: 我正在使用C语言对芯片进行编程,使用ST HAL.我通过VSCode的ST-Linkv3使用GDB进行调试.

调试因以下几个因素而变得复杂:

  • 该错误很少发生.我已经找到了复制故障的可靠方法,但可能需要几分钟到一个小时才会出现错误.
  • 该误差取决于某些硬件时序(它涉及UART外设).我不能只是单步执行代码,直到它发生,因为当单步执行时,它就不会发生.
  • 该错误似乎没有留下有意义的堆栈帧(见下文).这其实是我质询的主要题目.

为了找到错误的原因,我按照下面的说明进行操作:https://interrupt.memfault.com/blog/cortex-m-hardfault-debug

我的CFSR(0xE000ED28)的值是0x1.所以是IACCVIOL.嗯..在这一点上,我想提到我没有启用任何MPU是有意义的. 因此,如果我理解正确的话,这意味着有什么东西试图将代码执行跳到现在允许执行代码的内存位置.造成这种情况的可能原因是什么?

我的HFSR(0xE000ED2C)的价值是0x40000000.那么FORCED故障,这对我有什么帮助吗?

我的lr寄存器的值是0xFFFFFFE9.lr & (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应该是Harderror处理程序之前的最后一次跳转的返回地址.但是0xfc006e3f是一个什么样的寄信人地址呢?我想这是硬件故障最初发生的部分原因,但我如何才能从这些信息中找到问题的实际原因?

推荐答案

我找到了我的问题,谢谢 comments 中的所有建议!

最后,@Ilya的 comments 几乎是一针见血: 在我的代码中,我使用了一个通过UART外围设备实现OneWire协议的库.该库在堆栈上声明一个UART接收缓冲区,并使用它在中断模式下接收数据.如果OneWire事务由于某种原因超时,它会返回错误代码,但不会取消UART接收操作. 有时,显然,UART接收事务将在一段时间后完成,并覆盖堆栈中UART接收缓冲区曾经所在的内存位置中的任何内容.在我的不幸 case 中,这意味着我被留下了一个硬件故障,对真正导致它的原因一无所知.

我通过在OneWire超时的情况下取消UART接收操作解决了这个问题.

C++相关问答推荐

uintPtr_t上的算术

int_leastX_t与intX_t不同吗?

有关字符数组指针和次指针以及qsort函数中的cmp函数的问题

为什么这个C程序代码会产生以下结果?

InetPton()函数无效的IP地址

如果我释放其他内容,返回值就会出错

如何使用[BTStack]BLE发送大型(>;2kb)信息包

For循环中的变量行为不符合预期.[C17]

如何读取文件并将内容保存在字符串中?(在C语言中,没有崩溃或核心转储错误)

在编写代码时,Clion比vscode有更多的问题指示器

Tic-tac-toe:从文件加载存储

这个空指针类型的转换是有效代码还是恶意代码?

如何将C中的两个字符串与从文件接收的字符串中的字符数进行比较

如何组合两个宏来初始化C语言中的字符串数组?

STM32 FATFS用户手册(Um1721)中的代码正确吗?

&stdbool.h&q;在嵌入式系统中的使用

我的代码可以与一个编译器一起使用,但不能与其他编译器一起使用

如何在Rust中处理C的longjmp情况?

gdb - 你能找到持有内部 glibc 锁的线程吗?

从管道读取数据时丢失