前言:本文先对英飞凌TC3xx系列芯片TriCore架构的Trap机制进行介绍,然后通过实操对发生Trap后进行分析,以便在软件开发过程中遇到此类问题能快速定位。
1、Trap简介
对于TriCore架构芯片,当发生不可屏蔽中断(NMI)、指令异常、内存管理异常或非法访问等事件时,系统会产生Trap。大致流程是异常发生后,先进行硬件现场保护,然后通过异常向量表查找入口地址并执行Trap处理程序,最后通过RFE指令返回(可恢复Trap)。
2、Trap类型
TriCore架构将异常分成了8大类(Class)。每个类都有自己的Trap处理程序,通过每个条目32字节的Trap向量进行访问,并根据硬件定义的trap类号进行索引。在每个大类中,又下分了异常识别号(TIN),在执行异常处理程序的第一条指令之前,TIN由硬件加载到通用寄存器D[15]中。异常可以进一步分为同步或异步,以及硬件或软件生成。下面的表格列出了异常类别,并对每个类别中预先定义的特定异常进行了总结和分类。
同步Trap和异步Trap
顾名思义,同步Trap就是异常发生与处理在同一时刻。异步Trap就是异常发生与处理在不同时刻。比如如果我们打开了数据缓存(Data Cache),在没有使用内存屏障的前提下,我们对数据的写入其实只是往Cache里写,然后程序继续执行后续指令,由Cache负责把数据写入到内存中。而Trap只有在Cache把数据往内存里写的时候才会被检测到,此时我们的程序已经执行到后面某个位置了,所以是异步的。对于异步Trap,因为其返回地址已经没有参考性了,所以此时最好的办法是关闭Cache,使Trap变为同步Trap。(CPU_PCONx.PCBYP控制Cache的使能)。
3、异常向量表
异常处理是使用异常向量表来进行管理的,用户需要在PFlash中分配8*32字节的内存空间(开头需256字节对齐,即BTV的值能整除256),用来存放异常向量表,每个Class占据32字节的空间。向量表中用来存放跳转指令,用来跳转到用户定义的异常处理程序中。例如发生了Class 4,TIN 2的Trap那么Trap入口地址为BTV + 32*Class
4、Trap处理流程
Trap发生后,如果系统能够处理该类型的Trap,并且返回后系统能够继续运行,则属于可恢复的Trap。如果发生该Trap后系统后续已经无法继续运行了,则属于不可恢复的Trap。绝大多数的Trap都属于可恢复Trap。
Trap响应
可恢复Trap发生后,内核会执行如下响应步骤:
-
Trap发生后的第一个动作是保存上部分上下文;
-
返回地址寄存器A[11]会更新为导致该Trap的指令位置;
-
Trap的子类TIN值被保存到通用寄存器D[15];
-
如果中断栈寄存器没有被使用,则栈寄存器A[10]会被设置为中断栈指针地址ISP,并将PSW.IS置1;
-
I/O模式被切换到Supervisor Mode,也就是最高级的特权模式;
-
保护寄存器集被设置为0:PWS.PRS=0;
-
调用深度计数器(CDC)被清零,并设置调用深度限值为64,PSW.CDC=0000000B;
-
调用深度检查使能:PSW.CDE=1;
-
PSW的安全位被设置为SYSCON寄存器中的值PSW.S=SYSCON.TS;
-
A[0], A[1], A[8], A[9]的访问被禁止:PSW.GW=0;
-
全局中断位被关闭:ICR.IE=0;
-
按照Trap类在异常向量表中查询入口地址,并开始执行。
对于不可恢复Trap,执行响应步骤如下:
-
Trap的子类TIN值被保存到通用寄存器D[15];
-
如果中断栈寄存器没有被使用,则栈寄存器A[10]会被设置为中断栈指针地址ISP,并将PSW.IS置1;
-
I/O模式被切换到Supervisor Mode,也就是最高级的特权模式;
-
保护寄存器集被设置为0:PWS.PRS=0;
-
PSW的安全位被设置为SYSCON寄存器中的值PSW.S=SYSCON.TS;
-
全局中断被关闭:ICR.IE=0;
-
按照Trap类查询异常向量表并开始执行。
上下文使用超限(FCU)就属于不可恢复Trap。
Trap处理程序
Trap处理程序是由用户自定的,用户可以在其中编写中断处理代码,进行异常修复、记录等事务。一种处理方法是将Trap的相关信息进行保存,然后执行复位,以尝试最大限度地恢复系统。
比如下面是ETAS官方提供的Trap处理程序:
; # --------------------------------------------------------------------------
; # MMU (Virtual memory)
; # --------------------------------------------------------------------------
.sdecl '.text.traptab0.trapvec.000',CODE
.sect '.text.traptab0.trapvec.000'
.align 32
.global Os_TrapVectorTable
.align 256 ; The vector table must be aligned such that the lowest 8 bits of its address are zero
Os_TrapVectorTable: ; [$Satisfies $TgtCore 112]
.global Os_memory_trap
Os_memory_trap:
mov d5, # 0
mov d4, #14
j Os_trap_fault
; # --------------------------------------------------------------------------
; # Internal Protection
; # --------------------------------------------------------------------------
.sdecl '.text.traptab0.trapvec.001',CODE
.sect '.text.traptab0.trapvec.001'
.align 32
.global Os_protection_trap
Os_protection_trap:
mov d5, # 1
mov d4, #14
j Os_trap_fault
这里列举了两个Class处理程序,其他类似。不过它的处理程序仅仅是报错,并没有进行软件复位。
Trap退出
Trap的退出仅仅是通过一条RFE指令实现的。
-
将返回地址加载到PC中,注意此时仍指向发生Trap的那条指令,所以如果问题没有修复,仍然会重新进Trap,这也是为什么一般都采取复位的Trap处理方式;
-
恢复全局中断使能位:ICR.IE = PCXI.PIE;
-
恢复中断优先级位:ICR.CCPN = PCXI.PCPN;
-
将保存的高上下文恢复。
5、相关寄存器
Trap向量表指针寄存器BTV
程序同步错误寄存器PSTR
数据同步错误寄存器DSTR
数据异步错误寄存器DATR
数据错误地址寄存器DEADD
具体的各寄存器bit位代表的含义可以查看手册《AURIXTC3XX_um_part1_v1.4》
6、实践操作
1. 暂停程序运行,调用Call Stack,发现进入ShutdownOS,从这就可以看出是Core2 10ms任务函数出问题了。
2. 观察结构体Os_const_coreconfiguration中Trap相关的信息,结构体中的TrapInfo会记录Trap发生时的Class,TIN以及返回地址。
从上图可以看出发生了Class4 TIN2的Trap,查表可知是数据访问同步错误。发生Trap的返回地址是0x8014151A,查看Core2 10ms任务函数找到地址0x8014151A,从这可知在语句TrapTest = *(uint32*)0xF0A3D900出问题了
观察Memory发现0xF0A3D900是无效地址,至此找出问题所在
当然也可以通过外设寄存器来观察,如下图指明了Trap返回的地址0xF0A3D900以及Trap类型Class4 TIN2
关于Trap入口地址
观察BTV地址为0x800D4000,和程序中地址一致
Trap地址为BTV+32*4,为0x800D4080
7、参考文档
1. 《Infineon-AURIX_TC3xx_Architecture_vol1-UserManual-v01_00-EN》
2. 《AURIXTC3XX_um_part1_v1.4》