[Tricore][TC1.6.2][架构手册] - 5.中断系统
[Tricore][TC1.6.2][架构手册] - 5.中断系统
TriCore系统中,外部中断可以向CPU或DMA等发起中断请求,本章介绍CPU的中断处理功能,包括中断优先级规则和中断向量表访问。
5.1. 概览
每个中断源都分配了唯一的中断优先级编号SRPN(Service Request Priority Number),接收到中断源发出的中断请求后,中断控制单元ICU(Interrupt Control Unit)根据SRPN对多个并发的中断请求进行投票,从而确定处理优先级。获胜中断请求的SRPN会作为PIPN(Pending Interrupt Priority Number),和触发信号一起发送给CPU,CPU比较PIPN和CCPN(Current CPU Priority Number),进而决定是否接收该中断请求。如果CPU决定接收该中断请求,则会发送中断应答并返回当前中断的优先级编号,然后ICU会清除发出请求的中断源。
5.1.1. ICU中断控制寄存器 - ICR
ICU Interrupt Control Register(ICR)保存当前CPU优先级编号CCPN、全局中断禁用/使能位IE以及当前挂起中断的优先级编号PIPN。
5.1.2. 收到中断请求时CPU的操作
CPU检查全局中断使能位ICR.IE并比较CCPN和PIPN,仅当ICR.IE == 1且PIPN > CCPN时允许中断。条件满足时CPU会执行中断服务程序,同时向中断源发送确认信息。
下面几种情况会导致CPU无法及时响应ICU的中断请求:
- 全局中断被禁用:ICR.IE == 0
- CCPN大于等于PIPN
- CPU正在执行进入中断/Trap服务程序的流程
- CPU正在执行不可中断的Trap
- CPU正在执行multi-cycle指令
- CPU正在执行会修改ICR寄存器的指令
仅当上述情况没有发生时CPU才会响应中断。
5.1.3. 进入中断服务例程
当执行中断的条件满足时,执行如下步骤进入中断服务例程:
- 保存当前任务的Upper Context
- 将返回地址A[11]设置为当前PC指针:A[11] = PC
- 如果程序之前未使用中断栈(PSW.IS = 0),则将A[10]设置为中断栈指针ISP:A[10] = ISP,然后设置栈指针标志:PSW.IS = 1
- I/O模式设置为Supervisor,即使能所有权限:PSW.IO = 10B
- 将当前的保护寄存器组设置为0:PSW.PRS = 000B
- 清空调用深度计数器(PSW.CDC),同时将调用深度限制为64:PSW.CDC = 0000000B
- 使能调用深度计数器:PSW.CDE = 1
- 将PSW安全位设置为SYSCON寄存器中预设的值:PSW.S = SYSCON.IS
- 禁用全局寄存器A[0]、A[1]、A[8]、A[9]的写入权限:PSW.GW = 0
- 禁用中断系统:ICR.IE = 0,将ICR.IE的值保存至PCXI.PIE
- 将当前CPU优先级编号(ICR.CCPN)保存至先前CPU优先级编号域(PCXI.PCPN)
- 将挂起中断优先级编号(ICR.PIPN)保存至当前CPU优先级编号域(ICR.CCPN)
- 访问中断向量表,获取ISR的第一条指令
注意:无论是否进入中断/Trap服务例程,都会禁用全局寄存器的写入权限(PSW.GW = 0),确保所有中断/Trap都没有受PSW控制的寄存器的访问权限。
进入中断服务例程会禁用全局中断并将当前CPU优先级CCPN设置为挂起中断的优先级PIPN,用户可以重新使能全局中断并修改CCPN从而处理某些特殊情况。
ENABLE指令可以使能中断系统,该指令会将ICR.IE置1,BISR(Begin Interrupt Service Routine)指令也可以使能中断系统,该指令会将ICR.CCPN设置为新的值,并且保存当前任务的Lower Context,MTCR(Move To Core Register)指令也可以修改ICR.IE和CCPN。
ENABLE、BISR、DISABLE三个指令会阻塞CPU执行中断,直到这三个指令执行完毕,这样可以避免产生错误,并且不需要在这些指令执行后再执行一条ISYNC(Synchronize Instruction Stream)指令,但MTCR指令执行完之后必须再执行一条ISYNC指令。
5.2. 退出中断服务例程
RFE(Return From Exception)指令退出中断服务例程,硬件会自动恢复Upper Context,Upper Context包含了PCXI寄存器,而PCXI寄存器中保存了之前CPU优先级编号PCPN和之前全局中断使能位PIE,这两个值有如下作用:
- 将PCXI.PCPN写入ICR.CCPN,恢复中断前CPU的优先级
- 将PCXI.PIE写入ICR.IE,恢复中断禁用/使能状态
完成上述步骤后继续执行原来的程序。
5.3. 中断向量表
中断服务例程ISR通过中断向量表与特定优先级的中断关联,中断向量表保存了中断服务例程的入口,中断向量表存储在内存中。
CPU执行中断时根据中断优先级(ICR.PIPN)计算中断向量的地址,然后将该地址加载至PC指针,程序从该地址执行对应的中断服务程序,该地址为对应中断服务例程首条指令的位置。受内存所限,中断向量表一般只存储中断服务例程的部分代码,例如只存储一条跳转指令,进而引导CPU去对应的地址执行后续的中断程序(存放在内存其他位置)。
Base of Interrupt Vector Table register(BIV)存储中断向量表的基地址,中断向量按优先级升序存储,系统预初始化阶段,使能全局中断前使用MTCR指令初始化BIV寄存器(该寄存器受ENDINIT保护),系统可以存在多个中断向量表,通过修改BIV寄存器进行切换。
执行中断时,CPU根据PIPN和BIV基地址计算对应中断服务例程的入口地址,中断向量表可以在32-byte或者8-byte两种模式间切换(通过BIV寄存器的Vector Size Select(VSS)位设置)。
将PIPN左移5位(VSS=0)或者左移3位(VSS=1),加上BIV的基地址得到对应中断向量的地址,为了实现这种计算方式,需要将BIV寄存器的14:5位或12:3位置0。
if (BIV.VSS == 0)
ISR_Entry_PC = {BIV[31:1],1'b0} | {PIPN<<5};
else
ISR_Entry_PC = {BIV[31:1],1'b0} | {PIPN<<3};
注意:这里官方手册的图存在错误
如果ISR很短,则可能完全被中断向量表的代码段包含,如果ISR代码较多则可能占用多个向量空间,为了避免这种情况可以将其拆分为跳转指令和后续代码,中断向量表中的代码为一条跳转指令,具体执行逻辑存放在其他位置。
因为BIV寄存器的存在,中断向量表可以存放在可用代码段的任何位置,上电时的默认值依具体平台而定,预初始化阶段可以使用MTCR指令修改BIV,允许存在多个中断向量表,通过BIV寄存器进行切换。
5.4. 使用TriCore中断系统
本小节展示了如何使用TriCore的中断系统。
5.4.1. 跨多个优先级的中断服务例程
由于中断向量和中断源并非密切相关,因此中断向量可以横跨多个优先级(如图22所示),如果ISR较大导致8个字空间无法存储,则其可以横跨多个节点,而不是使用跳转指令去其他位置执行。如果使用这种方式,则被覆盖的若干节点无法被使用(对于同一个Service Provider)。
图22中,优先级编号3和4对应的两个向量被占用,因此不能使用这两个优先级编号(针对同一Service Provider),如果Service Provider为其他(如DMA或CPU2),则对于同一个中断源,仍然可以使用这两个优先级编号。
这种方式会增加系统提供的优先级编号的范围,同时中断向量表的大小也需要进行对应的调整。
5.4.2. 中断优先级组
中断优先级组用于描述一组无法互相中断的ISR。
CPU执行中断时会禁用全局中断并将CCPN设置为PIPN,这会阻止后续的中断,直至使用软件再次打开中断或使用RFE指令返回。
注意:RFE指令自动恢复ICR.IE之前的值,该值应该为1,否则全局中断为禁用状态。
如果ISR使能全局中断(ICR.IE=1)但未修改CCPN,则优先级小于CCPN的中断还是会被阻塞,包括当前正在执行的中断(无法再次执行),高优先级的中断仍然可以执行。
程序通常需要将具有相似重要性的中断请求组合在一起,以便该组中的任何中断都不能互相中断。
定义中断优先级组时,可以在重新使能中断前,由中断服务例程将CCPN设置为该组中最大的SRPN,如图23所示。
在图23中,优先级1112的中断请求组成一个中断优先级组,优先级1417的中断请求组成一个中断优先级组。
优先级组中的任一中断执行时,都会将CCPN设置为最大值(12或17),只有优先级大于该值的中断才能执行(如13或18)。
在该示例中,中断优先级为13的中断请求其实也相当于一个中断优先级组,将CCPN设置为255等同于禁用全局中断(所有中断可视为一个组)。
中断优先级的灵活性很高:所有中断都为一个组、每个中断形成单独的组、介于两者之间所有可能的组合。
5.4.3. 利用优先级拆分ISR
可以使用优先级将ISR拆分为多个部分,例如,ISR的前半部分需要快速响应,则该部分的中断优先级可以较高,后半部分的优先级可以设置的较低,从而将中断服务例程拆分为两个部分。
中断请求的优先级首先设置为较高的值,在中断服务例程执行的过程中,软件再次发送相同的中断并将优先级设置为较低的值,从而回到原来的用户程序(只修改了刚才执行中断的优先级),当CPU优先级小于第二次设置的中断优先级后,再次执行刚才被挂起的中断,从而完成刚才中断程序剩余的部分。
在某些情况下,中断自身的优先级较低,但是一旦该中断被执行就不能被中断,系统允许在该中断执行时,由ISR修改中断优先级,同样的,也允许彻底结束ISR的执行。
5.4.4. 具有多个优先级的中断源
某些中断的优先级不是固定的,而是取决于系统当前的情况,同一中断源可以在不同的时间,由程序设置不同的SRPN,ISR根据优先级可以执行不同的代码。
传统的中断系统中,ISR必须检查中断的当前优先级并执行对应的代码,这会导致响应延迟,TriCore系统中,中断可以有多个优先级,从而在中断向量表中存在多个程序入口,因此不需要再次检查中断优先级,从而减少延迟。
如果ISR独立于中断优先级,则相应的服务程序需要放在通用的ISR向量表中,该向量表中的每个节点都与该中断关联。
注意:创建中断向量表时,必须考虑一个中断拥有多个优先级的情况。
5.4.5. 中断控制寄存器
中断处理需要用到两个内核特殊功能寄存器:
- ICR:中断控制寄存器
- BIV:中断向量表基指针
ICU中断控制寄存器ICR保存当前CPU优先级编号CCPN、全局中断使能/禁用位IE、挂起中断优先级PIPN,根据平台的不同还会包含一个中断仲裁方案,BIV寄存器保存了中断向量表的基地址,可以使用特定的指令使能/禁用中断系统。
ICU中断控制寄存器 - ICR
- PIPN:Pending Interrupt Priority Number,挂起中断请求编号,该位为只读模式,其值在中断仲裁结束后由ICU寄存器设置,标识当前挂起中断的优先级编号,若没有挂起的中断或开始执行新的中断仲裁时,设置ICR.PIPN=0
- 00:没有挂起的中断请求
- 01:中断挂起,优先级最低
- ...
- FF:中断挂起,优先级最高
- IE:Global Interrupt Enable Bit,全局中断使能位,硬件在进入/退出ISR时自动更新该位,执行中断时将该位置0,中断使用RFE指令返回时将该位置1,ENABLE、DISABLE、MTCR和BISR指令也会修改该位
- 0:禁用全局中断
- 1:使能全局中断
- CCPN:Current CPU Priority Number,当前CPU优先级编号,硬件在进入/退出ISR时自动更新该位,也可以使用BISR或MTCR指令修改该位
中断向量表基指针 - BIV
BIV寄存器包含中断向量表的基地址,将PIPN左移3位或5位再和BIV进行或操作得到中断向量地址,VSS位控制左移的长度,该值决定了向量空间是8-Byte还是32-Byte。
- BIV:Base Address of Interrupt Vector Table,中断向量表基地址,中断向量按2的幂对齐
- VSS:Vector Spacing Select,向量大小,设置一个中断向量占用的空间(8-Byte/32-Byte)
- 0:32-Byte
- 1:8-Byte