徽州骆驼 · 5 天前

MCU进异常调试小技巧--以ARM内核为例

目录

1.Cortex-M7异常处理

2.Cortex-R52+异常处理

3.小结

调试板子总遇到莫名其妙进异常的情况,我们可以有哪些手段来定位现场?

今天就接着前几天介绍内核单元的文章继续聊聊ARM内核的异常以及错误处理。

1.Cortex-M7异常处理

Cortex-M7架构是Armv7-M,内核自带异常包括NMI、HardFault、MemManage等等,具体如下图:

image.png

这些异常处理函数,我们都可以在代码中找到,以S32K344为例,它的中断向量表长这样:

image.png

基本上每个函数的实现都是While(1),如下图:

image.png

那在这个函数里,我们可以做哪些事情呢?很明显,找到错误引发现场是首要目标。

在Armv7-M架构里有一块名为System Control Block的空间,里面设计有不同的寄存器用于记录上述不同异常发生时的信息。

image.png

我们以常见的触发MPU保护异常为例,看如何定位数组越界等错误。

当错误发生时,MMFAR(MemManage Fault Address Register)会保存触发MPU错误的memory地址。

image.png

为啥会触发呢?很有可能就是内核LSU去对MPU保护外的地址进行了load或者store访问操作,进一步的,如果我们想知道具体是什么操作导致触发了MPU,我们就需要查看MMFSR(MemManage Fault Status Register)的详细信息。

MMFSR这个虽然名叫寄存器,但其实它本身是CFSR(Configurable Fault Status Register)中的位域:

image.png

可以看到,MMFSR在CFSR的低8位, 它提供了MemManage的状态信息,具体如下:

image.png

  • MMARVALID:置1表示MMFAR中的地址有效;
  • MLSPERR:置1表示浮点lazy context保存时发生MemManage Fault;
  • MSTKERR:置1表示在进入异常里再次触发;
  • MUNSTKERR:置1表示在退出异常里再次触发;
  • DACCVIOL:置1表示数据访问触发该异常,MMFAR保存了准备load\store数据的地址;
  • IACCVIOL:置1表示取指时访问了MPU或者XN的地址,MMFAR保存了取指的地址。

通过上述两个寄存器的联合分析,我们就可以定位到问题现场,并判断出到底是取指的问题,还是读写数据的问题。

M核相对来说要简单一些,但最近玩R核的时候发生了很多好玩的事情。

2.Cortex-R52+异常处理

Cortex-R52+是ArmV8-R的架构,仅有AArch32一个执行态。
在这个状态下,R52又可以执行在8种不同模式下,分别为User、System、FIQ、IRQ、Supervisor、Abort、Undefined以及Hyp。这些模式都关联有不同异常等级,在R52里异常等级分为了3种:EL0-EL2,推荐用法如下:

image.png

而模式与异常等级关联如下:

image.png

当异常发生时会内核会切换至不同模式,由于每种模式都有私有通用寄存器,因此很多信息在当前模式下的通用寄存器了就看不到了。

例如如果我们运行在SVC模式下,当发生了DataAbort异常时,内核会切换至Abort模式,同时把当前模式下的SP、LR、SPSR展示就是Abort模式下的数据,我们要看发生异常,只能先了解自己程序运行在哪个模式,然后去看对应模式的SP、LR,即可看到进异常之前的现场。

我们可以从R52+SVD描述发现这些端倪:

image.png

进一步的,如果我们想进一步搞明白是什么问题造成的异常,可以继续看如下寄存器。

R52+同样也有系统控制模块,其中第5、6组描述的是关于故障的一些寄存器,如下:

image.png

从上述字面意思,我们可以发现其实和M核还是比较类似的,区别在于R52需要使用原子指令才能读出数据。

以访问DFAR(Data Fault Address Register),需要的指令为:

image.png

老规矩,R52有如下几个异常处理函数:

image.png

当发生异常时,我们可以读取DFSR、DFAR、IFSR和IFAR。

以DFSR和DFAR为例,DFSR包含了最近一次数据错误的状态信息,如下:

image.png

其中,最关键的是bit5-0,记录了错误状态位,具体如下:

image.png

进一步,如果我们想知道它是读或者写造成的异常,可以观察Bit11, WnR:

image.png

然后我们根据DFAR记录的地址,就可以发现具体是在哪个位置出现的错误。

值得一提的是,在C5组里提供了两个辅助寄存器ADFSR、AIFSR可用于进一步定位问题,

image.png

当我们从DFSR获取到具体问题时,我们来看ADFSR,可以获取到具体是哪一个接口发生的什么错误,然后我们就可以去找FAE支持啦。

例如,如果我们发现PORT定位为BTCM、TYPE为ECC error on data,那么我们就可以考虑是否TCM开启了ECC保护,我们没有初始化ECC造成这些异常。

3.小结

简单聊聊最近调试的收获,还不是特别深入,后续将继续研究,争取打造成属于自己的debug调试小流程。

作者:快乐的肌肉
来源:汽车MCU软件设计

推荐阅读:

更多汽车电子干货请关注汽车电子与软件专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
5681
内容数
415
汽车电子与软件行业的相关技术报道及解读。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息