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

时间:2018-09-08 10:01:04

标签: debugging exception arm stm32f4

我正在STM32F429 ARM Cortex M4设备上处理以太网代码,遇到遇到MemManage异常的情况,事实证明原因很难追查。据我了解,MemManage异常是由某些违反MPU的行为引起的,例如试图在0xE0000000及更高版本的受保护寄存器空间中执行代码。我阅读的Cortex M4文档指出,应在MMSFR寄存器位中捕获异常的原因,并且在某些情况下可以在MMFAR寄存器中捕获错误的地址。

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

有人对为什么在未设置MMSFR位的情况下可能发生MemManage异常有一些想法吗?或者,提供一些技巧的建议,以更好地了解异常发生之前代码中发生的情况。

3 个答案:

答案 0 :(得分:3)

我的直觉(不一定准确!)是这里不正确。没有理由说MemManage异常不能准确地记录其调用原因,并且您提到PC不应存在的地方,这表明在异常输入之前,出了什么问题。在此基础上,我认为通过识别在何处发生而不是尝试从异常类型中推断出原因,您将学到更多。

我首先在您确定发生异常的那一刻检查LR中的值。这不一定会告诉您PC损坏的发生位置,但会告诉您最后一个BL在问题发生之前的位置,因此它可能有助于确定问题的出处。您可能还会发现检查PSR([8-0])中的异常状态位以确认故障的类型很有帮助。 (MemManage为0x004。)

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

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

  

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

     

...

     

在上面的示例中,通过设置   辅助控制寄存器中的DISDEFWBUF位(位1)(或   ACTLR)将导致不精确的错误变成精确的错误,   这使故障更易于调试,尽管代价是速度较慢   程序执行。