目录
1.R52+ AArch32通用寄存器描述
2.Abort模式是什么
3.实例详解
1.R52+ AArch32通用寄存器描述
上篇文章我们阐述了关于R52+异常如何定位,其中详细说明了发生异常后应该在什么模式下去观察寄存器。
今天就以Abort异常为例,详解下如何精准定位Abort异常。
首先回顾下,在AArch32执行态下有哪些寄存器是模式私有,如下图:
左侧Appliaction层级视角表示当前模式的状态,右侧系统层级视角则表示不同模式下的寄存器名;我们在调试器可以清晰看到SP_svc、SP_abt这些寄存器的名字。
那么我们如何判断当前处于什么模式呢?我们可以看APSR或者CPSR寄存器,AArch32下位域定义如下:
我们可以通过M位域看到当前处于什么模式,如下图:
一般来说,R52+上电起来运行在EL2,对应Hyp模式;在完成各种初始化后,会进入到EL1模式,即Supervisor;一旦发生异常,会有相应的SPSR(Saved Program Status Register)在进入异常前保存当前状态。
那么我们如何判断是否进入Abort模式?只需要在异常函数while(1)找CPSR.M即可。
2.Abort模式是什么
之前我们讲过,当我们触发了MPU保护时,R52+会进入到Abort_Hanlder,包括Prefetch_Abort和Data_Abort。
个人理解,所谓Abort就是处理器的内存系统没办法成功完成一个内存的访问,这个时候就会产生Abort。
举个例子,CPU发送指令给memory,告诉它到哪个位置写入或者读取数据,在memory这一层肯定会判断CPU发的这个地址是不是对的呀,如果发现了异常,它就会告诉CPU:你这个不对嗷,你自己看着吧。
因此,在R52+里,会造成Abort异常一般都有如下几种原因:
- 接受到芯片内部总线(例如AMAB总线)系统返回的错误响应;
- 触发了MPU的保护;
- TCM内部出现了ECC错误等等
具体来讲,如果是CPU进行指令预取发生了错误,就会产生prefetch abort,我们可以通过系统寄存器IFSR找到错误类型,通过IFAR找到是哪条指令出的问题;
如果是数据访问,就会产生data abort,同样的,我们可以通过DFSR找到错误状态,通过DFAR到错误地址,
刚好这个也对应了R52+ 的两个异常向量:PrefetchAbort_Hanlder和DataAbort_Handler。
其实,在这里突然想到了,如果TCM里面出现了ECC错误,那么DataAbort就会一直发生,那到底在DataAbort_Handler,我们看到的LR和SPSR是否是最开始发生错误的值?这要打个大大问号。
除了按指令、数据进行分类,Abort也按照同步或者异步进行分类;
同步Abort:Synchronous,指的是这个Abort异常就是在当前指令发生的,我们可以通过LR_abt来查看触发该异常的指令,通过SPSR_abt来查看异常发生时的状态;
异步Abort:Asynchronous,指的是已经产生Abort异常,但是代码还继续跑了一会,这个时候就很难定位到问题,往往异步Abort是最致命的。基本还没遇到过异常Abort这种情况。
3.实例详解
说了这么多,我们还是拿个具体例子来说说。
假设现在进了Prefetch Abort Handler里面,按照规矩,我们首先查看IFSR、IFAR,具体如下:
假设现在出现了Synchronous parity error on memory access,并且是memory(slave)回的错误响应,那么这个值就为0x218;进一步,如果我们想知道具体是哪个slave的问题,我们就需要看辅助寄存器AIFSR:
如果是ECC错误,并且是ATCM发生了,这个寄存器的值就是0x12;
再进一步,如果我们想知道ECC发生的错误位置,我们可以看寄存器 IMP_TCMERR0\1、IMP_TCMSYNDR0\1,具体如下:
IMP_TCMERRx.RAMID会告知是TCM哪个bank发生的错误,以及访问的地址。
IMP_TCMSYNDR0\1则表示具体的错误,从而可以计算出哪一个bit发生的错误。