MMSFR寄存器中的所有位为零会导致ARM MemManage异常的原因是什么?

问题描述 投票:2回答:3

我正在研究STM32F429 ARM Cortex M4设备上的以太网代码,并遇到一种情况,我正在收到一个MemManage异常,原因很难找到原因。根据我的理解,MemManage异常是由于某些违反MPU的行为引起的,例如试图在0xE0000000及以上的受保护寄存器空间中执行代码。我读过的Cortex M4文档指出应该在MMSFR寄存器位中捕获异常的原因,并且在某些情况下可以在MMFAR寄存器中捕获错误的地址。

让我感到沮丧的是,MMSFR寄存器中的所有位都为零,正在生成MemManage异常。我正在执行断点指令,就像输入异常处理程序一样,所以我很确定MMSFR没有被意外清除。此外,我的代码中没有任何地方我甚至使用MPU,它应该在上电时处于默认状态。最后,我可以故意在我的代码中的其他地方创建一个MemManage异常,并且MMSFR位正确地识别我触发的问题。从异常中展开堆栈,关于PC的唯一不寻常的事情是它位于初始化RTOS的早期调用的代码中间,但是在发生异常时不应该执行。我正在试图确定PC如何达到它所做的价值,但事实证明它很难被隔离。

有没有人有一些想法,为什么没有设置MMSFR位可能会发生MemManage异常?或者,建议使用技术来更好地了解异常发生之前我的代码中出现的情况。

debugging exception arm stm32f4
3个回答
3
投票

我的直觉(不一定准确!)就是这里的东西不对。 MemManage异常没有理由不能准确地记录其调用的原因,并且你提到的PC本来就不应该表明在异常进入之前出错了。在此基础上,我认为通过识别异常发生的位置,而不是尝试从异常类型中推断出原因,您将学到更多。

我首先检查LR中您确定发生异常的点的值。这不一定会告诉你PC腐败发生在哪里,但它会告诉你问题发生前最后一次发布BL的位置,所以它可能有助于解决问题所在。您可能还会发现检查PSR([8-0])中的异常状态位以确认故障类型很有帮助。 (MemManage是0x004。)


2
投票

我终于找到了这个问题。它是在结构中执行回调函数的代码,但结构指针是空指针。结构中回调函数的偏移量对应于向量表中的MemManager异常处理程序与地址零的偏移量。因此,MemManager处理程序不是通过异常调用的,而是一个简单的函数调用。这就是为什么堆栈让我感到困惑的原因 - 我期待看到一个异常堆栈帧而不是一个简单的函数调用堆栈帧。

我的线索是PSR([8-0])中的异常状态位全为零(感谢suggestion from cooperised),这表明我的MemManager异常实际上并未被调用为异常。然后我从那里回溯以了解哪些代码负责将函数调用作为函数调用。我有缺陷的假设是,MemManager处理程序可以到达的唯一方法是通过异常 - PSR值和非异常堆栈框架是我忽略的主要线索。


0
投票

仔细检查您获得的异常实际上是MemManage而不是其他内容(例如,如果您使用多个异常类型的共享处理程序)。另一种可能性是你得到了一个不精确的故障,并且丢弃了有关原始故障的信息。来自FreeRTOS debugging guide

ARM Cortex-M故障可能是精确的或不精确的。如果在BusFault状态寄存器(或IMPRECISERR,可在地址BFSR中访问字节)中设置0xE000ED29位(位2),则故障不准确。

...

在上面的例子中,通过设置辅助控制寄存器(或DISDEFWBUF)中的ACTLR位(位1)来关闭写缓冲将导致不精确的故障成为精确的故障,这使得故障更容易调试,尽管代价是程序执行速度较慢。

© www.soinside.com 2019 - 2024. All rights reserved.