1. 模块简介
对于嵌入式系统来说,实时性是一个非常重要的特性,相比较于桌面端系统,嵌入式系统往往部署在各种硬件设备上,这些硬件设备的控制往往都要求毫秒甚至微秒级的反馈。而在车规级控制器中,有些硬件功能的实时性要求就更为严苛。
而提到实时性,就不得不提中断,在计算机原理中,中断是一种用于打破正常程序执行流程的机制。中断允许计算机在执行程序的过程中临时暂停当前任务,转而处理其他优先级更高或需要立即处理的事件。这些事件可能来自系统的外部输入(如键盘、鼠标、定时器)或系统内部(如除零错误、内存访问错误等)。
广义的中断概念包括以下几个关键要素:
中断请求(Interrupt Request,IRQ): 外部设备或系统内部产生中断时,会向计算机发送中断请求。每个中断源通常有一个唯一的IRQ号。
中断向量表(Interrupt Vector Table,IVT): 计算机维护一个中断向量表,其中存储了每个可能中断的处理程序的地址。当中断发生时,计算机通过查找中断向量表找到相应中断的处理程序。
中断服务程序(Interrupt Service Routine,ISR): 中断服务程序是一段特定的代码,用于处理特定中断类型。当中断发生时,控制权会转移到相应中断的ISR,执行相关操作。
中断控制器(Interrupt Controller): 中断控制器负责管理和协调各个中断源,确保按照优先级处理中断。常见的中断控制器包括 PIC(Programmable Interrupt Controller)和 APIC(Advanced Programmable Interrupt Controller)。
中断的引入提高了计算机系统的响应性和并发性,允许系统在处理一些紧急事件时快速做出响应。中断机制是操作系统和硬件之间协调的重要手段,确保系统能够高效地处理各种事件。
TC3XX系列中断采用中断路由的方式,将硬件中断源和CPU、DMA进行灵活的连接,并且有着稳定可靠高效的硬件上下文保存机制,具有较高的中断实时性。
这里补充一点,中断虽然称为中断,但并不是在任意时刻都可以打断普通程序的运行,在计算机系统微观视角中,一般是每条指令执行之后(一条指令一般包括取指、译码、执行、访存等步骤)由硬件查询是否有中断需要执行,如果有就执行中断响应步骤,如果没有则继续下一条指令。
2. 功能介绍
2.1 中断系统
TC3XX系列的中断系统涉及到外设、中断控制器、CPU、DMA等的交互,每个模块内部都有与中断相关的控制寄存器,因而这里称其为中断系统,下面我们将从整体上,先阐述TC3XX系列芯片中断系统的交互逻辑。
熟悉ARM的朋友都知道,在ARM系统中,中断向量表中存放了每个中断服务例程(也就是中断函数)的地址,当出现中断信号时,由向量中断控制器VIC接收该信号,然后进入统一的中断枢纽例程中,在中断枢纽例程中查询向量表然后进行中断服务例程**的跳转。(下图为ARM PL190 VIC框图)
TC3XX系列的中断响应路线其实和这个类似,不同的是TC3XX中没有中断枢纽例程,CPU接收中断信号后直接跳转到中断向量表,在中断向量表中每个中断有最多32字节的代码空间,一般是在向量表中放跳转指令,跳转到实际执行的中断服务例程中。下图是TC3XX中断系统的硬件框图:
从图中我们可以看到整个中断系统包含来自软硬件的中断源,一个中断路由器IR,和对应的服务提供者,服务提供者可以是CPU或者是DMA,所以在这里中断请求的术语称之为Service Request,服务请求,因为它可能触发一个CPU中断,也可能是触发一个DMA转换。
它的大体响应流程是这样的:当外部中断源如ADC等模块产生了服务请求信号,会发送给IR,IR根据配置的优先级进行仲裁,并将胜出的服务请求路由至对应的服务提供者,如果服务提供者是CPU则是中断服务,如果是DMA则是某路DMA通道的转换使能信号。
下面我们展开介绍各个模块在中断系统中的运行逻辑。
2.2 中断源
中断源是由外设模块、软件模块等进行的服务请求,每个外设模块都有不同的请求事件,比如ADC模块当某个Group的转换完成之后会发出对应的服务请求,CAN或Eth模块在收到外部数据时会发出接收服务请求。具体的资源情况是硬件固定的,使用时需要查询对应模块的说明。
一般情况下,外设的中断信号没有开关,对应的事件发生之后就会向IR发送请求,而中断的控制逻辑由后续的IR模块和CPU来负责处理。
2.3 中断路由器IR
中断路由器IR负责接收系统的服务请求,然后进行优先级仲裁,并将仲裁胜出的请求路由至对应的服务提供者。它的输入是各个外设模块,输出则是CPU或DMA模块。IR模块主要包括服务请求节点(Service Request Node, SRN)、中断控制单元(Interrupt Control Unit,ICU)和外设总线接口(Bus Peripheral Interface,BPI)。IR有很多的SRN,每个SRN对应一个硬件的服务请求,比如ADC0有4个服务请求,则在IR中就有与其对应的4个SRN。中断控制单元负责与对应的服务提供者进行连接。外设总线接口则负责外设总线的连接。
2.3.1 服务请求节点SRN
每个SRN对应一个硬件的服务请求,外设模块的服务请求信号在硬件上一般是直接连接到其对应的SRN的,具体的中断控制如优先级、使能、状态查询等都是在SRN中进行的。每个SRN有一个服务请求控制寄存器(Service Request Control Register,SRC),如SRC_VADC_G3_SR0表示ADC3的SRC寄存器。
SRC寄存器中包含了这个服务请求的控制和状态量,下面我们详细介绍其中的每个成员。
Service Request Priority Number (SRPN):服务请求优先级,也就是我们常说的中断优先级,它决定了服务请求在IR中仲裁的结果;同时它也是和CPU中断向量表对应,这个稍后在CPU中断逻辑中会介绍;另外当路由对象是DMA时,它指示对应的DMA通道
Enable Bit (SRE):也就是中断使能位,如果使用中断则需要打开,决定IR是否将该请求路由到对应的服务提供者,如果使能位没有打开,也可以通过软件轮询SRR中断状态位来执行对应服务例程
Type-Of-Service Control (TOS):服务类型,也就是选择将服务路由到哪个ICU中,CPU0、CPU1或者DMA,
Service Request Flag (SRR):中断标志位,该位在服务提供者响应服务的时候会自动清除,所以TC3XX中不需要软件去清除中断标志位,但如果没有打开SRE使用的轮询,则需要每次执行后用CLRR清除中断标志位
Clear Bits(CLRR):中断标志清除位,用来清除SRR,读的话一直是0
Set Bits(CLRR):软件中断请求位,可以通过软件来请求一次中断
Interrupt Trigger Overflow Bit (IOV):中断溢出标志位,如果一个中断没有被接收或者清除,又进行了一次触发,则该位会置位
Interrupt Trigger Overflow Clear Bit (IOVCLR):中断溢出标志清除位,清除中断溢出标志,读的话一直是0
SW Sticky Bit (SWS):软请求粘滞位,如果调用过SETR接口进行过软触发,则该位会置位直到清除
SW Sticky Clear Bit (SWSCLR):软请求粘滞清除位,用来清除软请求粘滞位,读的话一直是0
SRC是中断系统中非常重要的寄存器,比如我们要判断硬件是否发出服务请求,就看SRR位。查看是否路由到CPU,就看SRE使能位,当然CPU中也有中断的使能和仲裁逻辑,我们下面会介绍。
2.3.2 Interrupt Control Unit (ICU)
每个SRN的服务请求会路由到一个ICU中,一个ICU连接一个CPU或者DMA,每个ICU内部进行服务请求的仲裁,并将仲裁的结果发送到连接的服务提供者。ICU中一般不需要配置,与CPU和DMA的连接相对比较固定。我们可以通过查询ICU的寄存器查看仲裁或路由情况,包括LASRx、ECRx等,这些寄存器一般是只读的,不需要用户配置,这里就不展开介绍了。
2.4 CPU as Interrupt Service Provider
当服务请求被路由到CPU的时候,CPU会接收IR的信号并作应答,然后执行对应的服务例程,也就是我们常说的中断。接下来我们从CPU的角度介绍中断的处理流程。在此之前,我们先介绍两个重要的寄存器,中断向量表基址指针(Base Interrupt Vector Table Pointer,BIV)和ICU中断控制寄存器(ICU Interrupt Control Register,ICR)。这里需要注意的是,这两个寄存器属于CPU寄存器,在多核系统中,每个核都有一套自己的CPU寄存器,所以会存在CPU0_ICR,CPU1_ICR,而前文提到的IR模块寄存器属于外设寄存器,一个系统里只有一套。CPU寄存器不能直接读写,要通过ENABLE、DISABLE、MTCR、MFCR等内核指令访问。
如上图是中断向量表基址指针寄存器,包括中断向量表基址BIV和向量空间选择位VSS。
BIV:Base Address of Interrupt Vector Table,中断向量表基址,TC3XX的中断向量表是存放在Flash中的连续地址,因此需要该寄存器来表示向量表基地址;
VSS:Vector Spacing Select,向量空间选择位,该位表征每个中断向量所占的内存空间,0表示每个中断向量占据32字节,1表示8字节,默认为32字节;
ICR是CPU主要的中断控制寄存器,其中包括全局中断使能位IE,当前CPU中断优先级位CCPN和等待中断优先级位PIPN。
IE:Global Interrupt Enable Bit,全局中断使能位,我们所使用的关闭所有中断操作,就是将该位置0,因为每个CPU是独立的,也有自己的ICR控制器,所以IE只控制当前核的中断开关;
CCPN:Current CPU Priority Number,当前CPU中断优先级,在非中断程序执行时,该位为0,进入中断时,该位会被硬件设置为所触发中断的优先级;
PIPN:Pending Interrupt Priority Number,等待中断优先级,表征当前CPU收到IR路由但还未处理的中断优先级;
2.4.1 中断向量列表
众所周知,早期的单片机系统中,硬件触发中断后,进入同一的中断入口函数,在入口函数中查找中断源,然后选择对应的中断服务例程。这样的系统结构中断的响应效率较低,后面才出现了向量中断。向量中断的核心亮点在于由硬件进行中断入口的查找和跳转,这样可以大大降低中断的响应时间,达到真正的高实时性。
TC3XX的中断向量表存放在PFlash(代码段)中的一段连续地址中,默认一个向量的存储空间是8 word(32字节),通过BIV指向其基地址。这里有一个非常巧妙的逻辑,中断向量的位置是和中断优先级绑定的,也就是前文IR模块中的SRC.SRPN,比如优先级为80的中断,它的向量地址就是基址加上偏移为BIV+80*32,CPU在接收该中断信号后第一行运行的代码也就是这个位置。这样设计省去了从中断源到中断入口地址的链接开销,只需要在编译过程中对中断向量表进行编址,CPU在接收到IR的中断信号之后直接按照对应的优先级进行跳转。中断向量表在内存中的结构如下图:
如图我们还可以看到,向量表是支持跨优先级占用的。因为一般情况下32字节放不下中断服务例程,只能放跳转指令,但是如果代码量不那么大,可以通过占有多优先级的方式,省去一次跳转。上图中优先级25放置了一个中断,通过优先级2的中断源触发,这里35因为被占据,所以要注意不能再给其他中断使用了。
2.4.2 CPU中断控制策略
前面我们提到,IR模块中有SRC.SRE位表征到达IR的服务请求信号是否会被路由,但是路由到CPU之后也并非能够直接执行,还需要判断相关的条件。
我们都知道,系统在运行过程中有时需要进入临界区时,防止中断程序或者OS调度程序破坏数据一致性。而根据数据的保护需求,对于临界区的实现可能是关闭所有中断,或者关闭OS中断(也就是关闭某一优先级以下中断)。
对于TC3XX来说,如果要关闭所有中断,那么操作方法就是将ICR.IE置0,此时所有路由到该CPU的中断都处于Pending状态,不会被接收。而如果要关闭OS中断,将所有OS优先级以下的中断全部屏蔽,则可将ICR.CCPN设置为目标门槛优先级,小于或等于该优先级的中断都将被屏蔽。
所以当中断信号到达CPU的时候,如果ICR.IE为1,且该中断优先级大于ICR.CCPN中指示的当前CPU中断优先级,CPU会接收该中断,向IR发出ACK信号,则IR中的中断标志位SRC.SRR会被硬件清除,然后CPU开始执行中断响应步骤。
2.5 DMA as Interrupt Server Provider
除了CPU接收IR的服务请求信号执行中断响应程序以外,TC3XX的中断系统还有一个亮点,那就是将服务请求信号路由到DMA中,硬件触发一次DMA转换。这种连接,我们只需要将SRC.TOS设置为DMA,然后将SRC.SRPN设置为目标DMA通道号,即可实现路由。
我们都知道,根据摩尔定律,计算机的计算能力每18个月能翻一倍,而存储器的性能每年只能提升7%,所以经过这么多年的发展,内存已经成为了计算机计数的瓶颈,现在CPU的Cache不断增大,也就是为了照顾这一短板。
而DMA的主要目的是承担CPU数据读写的任务,从而解放CPU的算力。TC3XX中实现了将外设的中断信号连接到DMA中,我们就可以通过设计外设触发链路,不经过CPU就能完成外设数据的处理。比如通过ADC中断触发DMA,能够直接将ADC采样数据取到RAM中;通过将SPI的中断信号路由到DMA,就能完成后台异步SPI发送。
2.6 CPU中断处理流程
当所有条件满足,CPU就要开始响应中断了,下面我们将介绍CPU对于中断的响应和退出流程。
在CPU决定响应中断时,并不是直接去按向量表执行其中断服务例程,而是先由硬件执行一系列操作进行上下文保存,也就是保护现场,而在退出中断之后也需要加载上下文,也就是恢复现场。下面我们先详细介绍CPU对于中断的硬件响应步骤:
第一步是保存上部分上下文,TC3XX系列芯片中存在硬件CSA机制,分为上、下两部分上下文,主要包括通用寄存器和链接地址等信息,其中上部分是由中断或者异常时由硬件自动保存,并在退出时使用RFE指令加载回来,下图为CSA结构图,关于CSA的机制本文就不展开讨论了,后续会出专题进行介绍;
保存返回地址寄存器A[11],也就是我们常说的链接寄存器;
如果此时CPU的中断栈使能开关PSW.IS没有打开,则硬件会将栈寄存器A[10](SP指针)指向中断栈指针ISP,以使用中断的栈,同时将PSW.IS置位;
将I/O模式(外设访问权限)设置为Supervisor模式;
将当前保护寄存器集设置为PSW.PRS=000B,TC3XX每个核有6套内存保护的设置集,如果使用了内存保护则这里表示会切换到PSW.PRS=000指向的保护策略;
调用深度计数器PSW.CDC清零,并且调用深度限制被设置为64;
调用深度检查打开:PSW.CDE=1;
PSW安全位被设置为SYSCON中的值:PSW.S = SYSCON.IS;
全局地址寄存器A[0], A[1], A[8], A[9]的写入会被禁用:PSW.GW=0;
当前全局中断使能位ICR.IE被保存到PCXI链接字寄存器中的先前全局中断使能位PCXI.PIE中,然后将ICR.IE置0,关闭所有中断;
当前中断优先级ICR.CCPN被保存到PCXI链接字寄存器中的先前中断优先级位PCXI.PCPN(这里顺便一提,PCXI在上部分上下文中,第一步已经保存到CSA中了,因此在嵌套处理时,此处PCXI可以写入,以实现中断嵌套);
等待中断优先级位ICR.PIPN被写入到当前CPU中断优先级位ICR.CCPN;
从中断向量表中取第一条指令,然后开始执行中断服务函数,至此硬件的处理流程结束。
回看整个中断响应流程,其实CPU在响应中断的时候,主要做的事情就是保护上下文、切换系统模式、切换中断环境,这在任何一个系统中都是必需的,而TC3XX得益于其独特的硬件上下文自动保存机制,省去了软件压栈的时间,对中断的实时性有较好的优化作用。
中断执行完毕之后自然需要退出中断,退出中断需要使用RFE指令,然后硬件会执行相应的步骤:
将链接字寄存器中的先前中断优先级位PCXI.PCPN写入到ICR.CCPN中,这样就恢复了中断进入之前的系统中断优先级门槛;
将链接字寄存器中的PCXI.PIE被恢复到ICR.IE中;
从CSA中加载进入中断时保存的上部分上下文。
从中断退出流程我们可以看到,其实主要的硬件处理是还是处理上下文和中断环境。TC3XX的中断是可以直接嵌套的,我们可以直接在中断服务例程中使能全局中断,打开嵌套,得益于其完善的硬件上下文保存机制,软件不需要像ARM一样执行系统模式切换和额外的上下文保存工作,从而提升了系统执行效率。
2.7 不可屏蔽中断NMI
TC3XX还提供了一种不可屏蔽中断机制(Non-Maskable Interrupt,NMI) ,一般是SMU模块或者外部ESR0/ESR1引脚触发,用于响应紧急事件。这种机制虽然叫不可屏蔽中断,但是它的本质走的是Trap系统,而不是本文中的中断系统,因此IR模块或CPU的中断控制位都不会对其响应产生影响,从而实现不可屏蔽中断的响应逻辑。关于不可屏蔽中断,本文就不展开介绍了,后续在TC3XX Trap系统中再进行讨论。
3. 使用示例
讲完了中断的内部逻辑,下面我们就进行实操。本文实现的一个示例是利用Aurix2G的MCAL,在EB Tresos中进行配置,实现一个ADC的采样中断配置。ADC这里我们使用ADC3的Source0,关于ADC内部的配置这里就不展开说了,Demo配置中也有实现,以后介绍到ADC我们再讨论。
3.1 配置及代码
首先我们来到EB工具中的Irq模块中,找到IrqAdcConfig页面进行Adc的中断配置(注意TC3XX中有DSADC模块,用于Delta-Sigma转换,本文用的是EVADC),这里我们来到Adc3,将Catogary配置为CAT1(CAT2为OS中断),然后设置中断优先级,这里使用120,然后TOS选CPU0,由CPU0执行中断函数;
然后需要在代码中进行中断使能和初始化,这里IrqAdc_Init是MCAL中定义好的函数,主要目的将我们配置的优先级和路由目的地写入到SRC寄存器中;
IrqAdc_Init();
SRC_VADCG3SR0.B.SRE = 1; /* Enable EVADC Group3 Source0 INT */
void IrqAdc_Init(void)
{
#if (IRQ_ADC3_EXIST == STD_ON)
IRQ_SFR_MODIFY32 (SRC_VADCG3SR0.U, IRQ_CLEAR_MASK, \
((uint32)IRQ_ADC3_SR0_TOS | (uint32) IRQ_ADC3_SR0_PRIO));
IRQ_SFR_MODIFY32 (SRC_VADCG3SR1.U, IRQ_CLEAR_MASK, \
((uint32)IRQ_ADC3_SR1_TOS | (uint32) IRQ_ADC3_SR1_PRIO));
IRQ_SFR_MODIFY32 (SRC_VADCG3SR2.U, IRQ_CLEAR_MASK, \
((uint32)IRQ_ADC3_SR2_TOS | (uint32) IRQ_ADC3_SR2_PRIO));
IRQ_SFR_MODIFY32 (SRC_VADCG3SR3.U, IRQ_CLEAR_MASK, \
((uint32)IRQ_ADC3_SR3_TOS | (uint32) IRQ_ADC3_SR3_PRIO));
#endif/*End of IRQ_ADC3_EXIST*/
}
这里再介绍以下中断函数的编址,因为TC3XX中中断向量表的位置是和中断优先级一一对应的,因此需要在编译链接过程中进行编址,不同的编译器有不同的指令(本文使用Tasking编译器),这里MCAL中有中断实现,如果要手动定义中断函数,可以参考格式;
#define IFX_INTERRUPT(isr, vectabNum, prio) \
void __interrupt(prio) __vector_table(vectabNum) isr(void)
IFX_INTERRUPT(ADC3SR0_ISR, 0, IRQ_ADC3_SR0_PRIO)
{
/* Enable Global Interrupts */
ENABLE();
/* Call Adc Interrupt function*/
Adc_RS0EventInterruptHandler(3U);
}
到这里一个ADC Group3 Source0的中断就配置完毕了,然后我们编译烧录运行。
3.2 调试运行
前文说到,中断向量表的向量地址就是基址加上偏移(BIV.VSS=0,向量宽度32字节),这里我们优先级为120,向量地址就是BIV+120*32,我们查看寄存器得知BIV=0x802FE000,则目标中断向量地址为0x802FEF00。
然后我们来到这个地方查看汇编,并在开头打上断点,系统停在了这里,就说明我们的中断成功触发了,并且CPU响应了该中断。然后我们观察汇编代码,发现这里是一个跳转指令,跳转到0x80007DDE。
然后我们来到Map中查询发现这个地址就是Adc3中断函数的地址,也就是正如前文所说,向量表32字节的空间一般是存放跳转指令,用于向中断服务例程跳转。
然后我们继续单步执行,就来到了我们的ADC中断函数中,我们的示例到此就演示完成了。
3.3 问题排查
我们在配置中断过程中,难免会遇到一些问题,这里介绍下排查的思路。
首先就是中断没有进的情况,这时候我们需要排查硬件中断源是否触发了,需要查看SRC.SRR寄存器,如果这里不是1,则表示硬件配置有问题,要向前排查外设模块是否配置无误,这也是最常遇到的情况;
其次就是SRE没有在代码里使能,这个是配置代码中没有的,用户除了调用初始化函数以外,每个中断是需要自己手动打开的,打开之后IR模块才会进行路由;
还有就是中断优先级是否配置正确,可以用前面的计算方法根据BIV的值和SRC.SRPN的值查询中断向量地址,查看向量表中对应代码是否正确;
然后就是SRC.TOS是否配置正确,如果配置为DMA的话这里是要在配置中修改为DMA的;
4. 小结
本文介绍了Infineon Aurix2G TC3XX系列芯片的中断系统,描述了包括外设、中断路由器IR和CPU在内的中断交互逻辑,并从IR模块内部描述了中断路由和控制机制,从CPU角度描述了中断的响应流程、开关逻辑,并结合示例对配置和代码进行了调试,能够帮助读者完整地了解该芯片中断系统的原理。TC3XX的中断系统采用了完善的硬件机制,保证了其高实施性,同时具有灵活的路由连接,可以实现复杂触发链路,解放CPU的算力。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_44000419/article/details/135586224
|
-
15917674d548db719a.png
(48.08 KB )
-
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE3ODU0NjYx,size_16,color_FFFFFF,t_70.jpg
(73.32 KB )
-
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE3ODU0NjYx,size_16,color_FFFFFF,t_70.jpg
(45.79 KB )
-
20190614093537543.jpg
(18.74 KB )
-
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwNjkyNjI5,size_16,color_FFFFFF,t_70.jpg
(32.63 KB )
-
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwNjkyNjI5,size_16,color_FFFFFF,t_70.jpg
(40.09 KB )
-
4970260e52a3607c54.png
(132.55 KB )
-
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1pDU2hvdUNTRE4=,size_16,color_FFFFFF,t_70.jpg
(315.15 KB )
|