再上一篇:附录C
上一篇:附录D
主页
下一篇:E.2 设计 Fault 服务例程
再下一篇:E.3 在 C 中上报入栈的寄存器和各 fault 状态寄存器
文章列表

附录E

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

Cortex-M3疑难解答

E.1 简介

使用 CM3,一大令人闹心之处就是会有那么多的 faults,不知什么时候就会来一个。来的是哪 个,为什么来,如何避免?这连珠炮一般的问题简直成了学习的拦路虎了。
其实,只要我们掌握和理解得深入,不粗心,规范设计和编程,这些 faults 就成了纸老虎。 如果善加利用,甚至还能变害为利——在系统出现故障时由它们为我们提供有用的诊断信息——这 才是 CM3设计这些 faults的初衷。
当 fault发生时,首先要弄清楚的就是 fault源,下表列出了相关的寄存器
表 E.1 CM3 中的 fault 状态寄存器组

地址

寄存器

全名

尺寸

0xE000_ED28

MMSR

MemManagefault状态寄存器

字节

0xE000_ED29

BFSR

总线 fault状态寄存器

字节

0xE000_ED2A

UFSR

用法 fault状态寄存器

半字

0xE000_ED2C

HFSR

硬 fault状态寄存器

0xE000_ED30

DFSR

调试 fault状态寄存器

0xE000_ED3C

AFSR

辅助 fault状态寄存器

上表的另一可视化视图如下图所示:

图 E.1 各 fulat状态寄存器的地址组织
因为 MMSR,BFSR和 UFSR的地址是相连的,所以可以使用按字加载指令一次性地全部读进来。 在这种情况下,这个三合一的 fault状态亦有一个名字:可配置 fault状态寄存器(CFSR)。
另一个提供重要信息的寄存器是什么?它远在天边,近在眼前——人尽皆知的程序计数器 PC! 进入 fault服务例程后,当时的 PC值在(SP-0x24)处。因为 CM3中有两个堆栈指针,fault服务 例程还要判定发生 fault时使用的是哪一个堆栈——MSP还是 PSP。
进一步地,对于总线 fault 和存储器管理 fault,有时还能精确定位肇事指令的地址——当 MMAVALID/BFARVALID位被置位时,即是精确 fault。此时,存储器管理 fault的地址存储在 MMAR 中,总线 fault的地址则存储在 BFAR中。在物理实现上,MMAR与 BFAR其实是同一个寄存器,因
此同一时刻只能用一个——这是因为同一时刻只能出现一个 fault(但是访问地址还是不同的), 如表 E.2所示。
表 E.2 CM3 中的 fault 地址寄存器

地址

寄存器

全名

尺寸

0xE000_ED34

MMAR

MemManagefault地址寄存器

0xE000_ED38

BFAR

总线 fault地址寄存器

最后,在执行 fault 服务例程时,LR 寄存器的值也常常是一个线索,间接反映了发生 fault
时的情景。如果 fault是由无效的 EXC_RETURN值导致的,则进入 fault时,LR的值则是上次异 常返回时使用的 EXC_RETURN 值。Fault 服务例程可以据此上报有问题的 LR 值,从而使开发人员 可以检查为何会使用非法的 EXC_RETURN(常常是粗心造成的)。