基于 ARM 的设备上预取中止错误的常见原因是什么?

What are the common causes of Prefetch Abort errors on ARM-based devices?

我的 C 程序是 运行 在裸机上 Raspberry Pi 3B+。它工作正常,除了我得到随机冻结,这些冻结被 CPU 本身报告为 Prefetch Abort。该设备可能可以正常工作数小时,然后突然崩溃。它在崩溃之前没有做任何特别的事情,所以它是不可预测的。

发生此错误时,FS 寄存器 (FSR) 设置为 0xD,表明这是一个权限错误:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0087e/Cihhhged.html

其他寄存器:FAR为0xE80000B6,LR为0xFFFFFFFF,PC为0xE80000B6,PSR为0x200001F1

我的程序使用 FIQ 和 IRQ 中断,并使用所有四个 cpu 内核。

我在这里不要求具体的调试,因为深入了解细节太复杂了,但是您知道发生预取错误的常见原因吗?

鉴于您的代码是多线程的(实际上是多核)并且崩溃是不可预测的,我想说预取中止几乎肯定是由竞争引起的内存损坏引起的。

如果您能找出生成中止的位置,可能会有所帮助。但是,像这样的错误可能非常难以追踪;如果代码总是在同一个地方崩溃,那可能会有所帮助,但即使它崩溃了,您也可以找出哪个地址正在遭受损坏,监控该地址是否存在恶意写入,而不会影响程序的时间(以及因此的表现形式)错误)基本上是不可能的。

根本原因很可能是缓冲区溢出,尤其是考虑到您上面的评论。实际上,您应该事先知道您的缓冲区需要多大,然后再将它们设置为该大小。如果您使用的任何算法都不能保证它使用的缓冲区数量的限制,您应该添加对缓冲区执行运行时检查并适当响应的代码(可能是一个很好地报告的错误,以便您知道哪个缓冲区溢出) .使用堆是可以的,但是将大缓冲区声明为 static 更快且无泄漏,前提是包含缓冲区的函数是不可重入的。

如果混合中也存在数据访问竞争,请注意您需要的不仅仅是数据屏障指令来解决这些问题。数据屏障指令仅解决与未决内存事务相关的一致性问题。它们不会阻止共享数据的寄存器缓存(你需要 volatile 关键字)或同步读-修改-写竞争(你需要互斥机制,无论你使用的是什么框架或在 armv7 上使用 STREXLDREX 指令自制)。