倒数第三篇:E.2 设计 Fault 服务例程
倒数第二篇:E.3 在 C 中上报入栈的寄存器和各 fault 状态寄存器
主页
第一篇:第1章
第二篇:1.2 ARM 的各种架构版本
文章列表

E.4 理解发生 fault 的原因

《Cortex-M3 权威指南》,嵌入式处理器开发教程。

在收集到所需的信息后,就需要分析问题了。表 E.3-表 E.7列出了导致 faults的典型原因。

表E.3 MemManage fault 状态寄存器提供的讯息

可能的原因

MSTKERR

入栈时发生错误(异常响应序列开始时)

1)堆栈指针的值被破坏

2)堆栈容易过大,已经超出 MPU允许的 region范围

MUNSTKERR

出栈时发生错误(异常响应序列终止时)。入栈时没有发生错误,出栈时却出

错,总令人有些匪夷所思,可能的原因是

1. 异常服务例程破坏了堆栈指针

2. 异常服务例程更改了 MPU配置

DACCVIOL

内存访问保护违例。这是 MPU发挥作用的体现。常常是用户应用程序企图访

问特权级 region所致

IACCVIOL

1. 内存访问保护违例。常常是用户应用程序企图访问特权级 region。在这种情

况下,入栈的 PC给出的地址,就是产生问题的代码之所在

2. 跳转到不可执行指令的 regions

3. 异常返回时,使用了无效的 EXC_RETURN值

4. 向量表中有无效的向量。例如,异常在向量建立之前就发生了,或者加载的 是用于传统 ARM内核的可执行映像

5. 在异常处理期间,入栈的 PC值被破坏了

表E.4 总线fault 状态寄存器提供的讯息

可能的原因

STKERR

(自动)入栈期间出错

1. 堆栈指针的值被破坏

2. 堆栈用量太大,到达了未定义存储器的区域

3. PSP未经初始化就使用

UNSTKERR

(自动)出栈期间出错。如果没有发生过 STKERR,则最可能的就是在异常

处理期间把 SP的值破坏了

IMPRECISERR

与设备之间传送数据的过程中发生总线错误。可能是因为设备未经初始化而

引起;或者在用户级访问了特权级的设备,或者传送的数据单位尺寸不能为 设备所接受。此时,有可能是 LDM/STM指令造成了非精确总线 fault。

PRECISERR

在数据访问期间的总线错误。通过 BFAR 可以获取具体的地址。发生 fault

的原因同上。

IBUSERR

同 MemManage fault中的 IACCVIOL

表E.5 用法fault 状态寄存器提供的讯息

可能的原因

DIVBYZERO

当 DIV_0_TRP置位时则发生了除数为零的情况。引发此 fault的指令可以从入栈

的 PC读取

UNALIGNED

当 UNALIGN_TRP 置位时发生未对齐访问。引发此 fault 的指令可以从入栈的 PC

读取

NOCP

企图执行一个协处理器指令。引发此 fault的指令可以从入栈的 PC读取

INVPC

1. 异常返回时使用了无效的 EXC_RETURN,例如

1) 当 EXC_RETURN=0xFFFF_FFF1时却要返回线程模式

2) 当 EXC_RETURN=0xFFFF_FFF9时却要返回 handler模式

2. 无效的异常活动状态,例如

1) 当前异常的活动状态已经清除了,却在此时执行异常返回。往往是因为滥 用 VECTCLRACTIVE或清除了 SHCSR中活动状态所致

2) 在尚有异常的活动位置位时,却要返回线程模式

3. 由于堆栈指针错误导致了 IPSR 的值不正确。对于 INVPC fault,入栈的 PC 指出了该 fault服务例程在何处抢占了其它代码。这个问题往往是由比较隐晦 的程序错误造成的,欲详细调查该问题的原因,最好使用 ITM的跟踪功能。

4. ICI/IT位对当前指令无效。当 LDM/STM指令被异常打断后,在异常服务例程 中又更改了入栈的 PC。结果在中断返回时,非零的 ICI 位段作用到了不使用 ICI位段的指令上。如果是其它原因破坏了 PSR的值,也可能导致此 fault。

INVSTATE

1. 加载到 PC 中的跳转地址值是偶数(LSB=0)。通过检查入栈 PC 的值,一下子

就可以查出该问题。

2. 向量地址的 LSB=0,诊断方法同上。

3. 入栈的 PSR在异常处理过程中被破坏,使得在返回时内核尝试进入 ARM状态。

UNDEFINSTR

1. 使用了 CM3不支持的指令

2. 代码段中的数据被破坏

3. 连接时加载了 ARM目标码。请检查编译阶段的设置

4. 指令对齐的问题。例如,在使用GNU工具链时,忘记了在.ascii后使用.align, 就有可能导致下一条指令没有对齐

表E.6 硬fault 状态寄存器提供的讯息

可能的原因

DEBUGEVF

因调试事件导致的 fault

1. 断点/观察点事件

2. 在硬 fault服务例程的执行过程中,没有使能监视器异常(MON_EN=0)也 没有使能停机调试(C_DEBUGEN=0),却执行了 BKPT指令。缺省时,有些 C编译器可能会在半主机代码中使用 BKPT指令。

FORCED

这是 fault“上访”的情况

1. 试图在 SVC/监视器服务例程中执行 SVC/BKPT,或者在其它拥有相同或更 高优先级的服务例程中执行 SVC/BKPT。

2. 发生了 fault,但是它的服务例程被除能

3. 发生了 fault,但是当前处理器在响应同级或更高优先级的异常

4. 发生了 fault,但是它被掩蔽了

VECTBL

取向量失败,

1. 在取向量过程中发生总线 fault

2. 向量表偏移量设置有误

表E.7 调试fault 状态寄存器提供的讯息

可能的原因

EXTERNAL

EDBGREQ信号置为有效

VCATCH

发生了向量抓捕事件

DWTTRAP

发生了 DWT观察点事件

BKPT

1. 执行了 BKPT指令

2. FPB单元产生了断点事件