TriCore架构寄存器
了解TriCore架构,我们首先得知道TriCore架构会用到哪些寄存器,TriCore架构寄存器包括:16个通用的地址寄存器A[0]A[15],16个通用的数据寄存器D[0]D[15],1个PC(Program Counter)寄存器,1个程序状态字寄存器PSW(Program Status Word),1个上下文信息寄存器PCXI( Previous Context Information register)。除了这些,还有Core Special Function Registers (CSFRs),这里不一一展开。上述寄存器均是32 Bit寄存器,TriCore架构寄存器如下所示:

通用寄存器中,编号0~7对应的[地址寄存器|数据寄存器]称为低位寄存器(Lower Registers),编号8~15对应的[地址寄存器|数据寄存器]称为高位寄存器(Upper Registers)。

PSW、PCXI不仅记录着程序运行的状态信息,而且与PC寄存器一样,是程序切换过程中,存储(Save)和恢复(Restore)上下文的重要组成部分A[10]、A[11]、A[15]、D[15]这4个通用寄存器还有特殊功能:

A[10]:栈指针寄存器Stack Pointer (SP) register
A[11]:返回地址寄存器Return Address (RA) register
A[15]:隐式基地址寄存器Implicit Address register
D[15]:隐式数据寄存器Implicit Data register
A[0]、A[1]、A[8]、A[9]是系统全局寄存器,也就是说在函数调用、中断发生过程中,上下文的Save和Restore不会存储这4个寄存器中的信息。

这里需要着重关注一下A[11]和D[15]寄存器。这两个寄存器对于Bug问题的排查非常有用,为什么这样说呢?因为当程序异常时,D[15]寄存器存储记录TIN(Trap Identification Number),A[11]记录Trap的入口地址。如果能获取这两个信息,很多问题可被快速定位。注意,如果Bug问题是异步的(Asynchronous),A[11]寄存器最近捕获的地址并不一定是问题发生点的入口地址。

D[15]寄存器很有用,在Tricore架构中,Trap分为8个等级:MMU (Memory Management Unit)、 Internal Protection、 Instruction Error、Context Management、System Bus and Peripherals、Assertion Trap、System Call、Non-Maskable Interrupt (NMI)。通过D[15]记录的TIN号即可确认Trap的Class,因此,可以在Trap程序中,将D[15]和A[11]寄存器的信息存储到NVM中,以便于Bug问题的排查。

Tasks和Context
在TriCore架构中,Tasks分为两种: Software Managed Tasks (SMTs) 和 Interrupt Service Routines (ISRs)。ISR 由硬件触发,直接响应中断;SMT任务由OS创建和调度,因此称为User Tasks。

每个Task会关联对应地模式(Mode):

User-0 Mode: 用于不访问外设的Tasks,不能由中断操作
User-1 Mode:用于访问一些不受保护的外设Tasks,比如:定时器(TIM)访问任务,此类型任务可以短时间关中断。
Supervisor Mode:可访问系统所有寄存器和外设,且可以关闭中断。
一个Tasks执行过程中,会关联多个元素,也就是我们常说的任务上下文(Context)。而这些任务上下文信息是处理器(processor)工作所必须的输入,不然,岂不是“巧妇难为无米之炊”?

任务上下文信息都包括啥呢?任务使用的一些通用寄存器(General Registers)、PC寄存器、程序状态信息寄存器(PSW、PCXI)。Tasks的有效运行和维护由硬件直接操作。

TriCore架构中,Context分为Upper context 和Lower context,Upper context 由硬件自动存储,速度快;Lower context需要手动维护。

1、CSA(Context Save Areas)
上下文存储区(CSA)不知道你是否有留意。在链接文件中,会分配一定大小的CSA区间,如下所示:

上述3个栈的空间分配如下所示:

如何理解上述的空间分配参数呢?结合tc397,这里做一个分析:

LCF_DSPR0_START:DSPR0的起始地址,LCF_DSPR0_SIZE:DSPR0的空间大小。这些值的大小不能随便设定,需要根据Datasheet设置,如下所示:

LCF_CSA0_SIZE:设置CSA0的大小(本例:8k),一般放在DSPR空间;
LCF_USTACK0_SIZE:设置用户栈大小(本例:2k);
LCF_ISTACK1_SIZE:设置中断栈大小(本例:1k)。这三个参数的设置根据项目使用情况预估。
TriCore架构中,CSA是由固定大小(64 bytes)组成的连续存储空间,64 bytes边界对齐。且每个CSA只能保存upper context 或者lower context。

upper context / lower context是什么?upper context 或者lower context均对应16个32 bit寄存器,所以upper context 或者lower context会占用64 bytes空间,保存的内容就是这16个寄存器存储的内容。upper context /lower context示例如下所示:

上图示意中,upper context /lower context放到了Cached区间(Segment 8),启动Cached功能,CPU访问数据或者指令的效率更高(DCached/PCached属于high-speed RAM)。对于Cache功能,可以参考前文Aurix:初识Cached和Non-Cached。

2、CSA作用
铺叙了这么多,需要聊一下CSA(Context Save Area),CSA干什么用的呢?程序在执行的过程中,会有Interrupt、Trap、Function Call发生,而这些事件的执行均需要保存对应的upper context 或者lower context,以便于知道程序应从哪里返回,以及返回时对应的上下文信息等。示例:Function_A()在执行的过程中需要调用Function_B()。

t0时刻,Function_A()调用Function_B()之前需要将对应的upper context 或者lower context信息存储(Save)到CSA中;
t1时刻,开始执行Function_B();
t2时刻,返回Function_A()之前,需要将CSA中的信息恢复(Restore);
t3时刻,返回Function_A()继续执行。
上述流程如下所示:

注意:

当Interrupt、Trap、Function Call发生时,upper context自动保存;
每个CSA实体16 Word对齐(64 byte)。