【研发日记】嵌入式处理器技能解锁(五)——TI C2000 DSP的中断系统

文章目录

前言

背景介绍

中断框架

外设中断

ePIE模块

CPU中断

中断嵌套

应用实例

总结

参考资料


前言

        见《【研发日记】嵌入式处理器技能解锁(一)——多任务异步执行调度的三种方法

        见《【研发日记】嵌入式处理器技能解锁(二)——TI C2000 DSP的SCI(串口)通信

        见《【研发日记】嵌入式处理器技能解锁(三)——TI C2000 DSP的C28x内核》        

        见《【研发日记】嵌入式处理器技能解锁(四)——TI C2000 DSP的Memory

背景介绍

        本文要讲的中断系统是TI C2000 DSP的一种多任务处理机制。其在整体软件架构中发挥的作用如下图所示:

        Tips:中断任务调度不同于User软件调度,这里是芯片硬件层面的机制,切换速度快到系统时钟周期的级别。

中断框架

        TI C2000 DSP的中断路径分为三级外设、ePIE和CPU,如下图所示:

        C28x CPU有14条对外中断line,其中前12条(INT1到INT12)通过ePIE(增强型外设中断扩展)模块连接到各种外设中断,最后两条(INT13和INT14)直接连到Timer1和Timer2。

        ePIE有多达16*12个对外的中断Channel,每16个Channel组成一个Group,总共12个Group。每个Group的16Channel个由一个Mux(多路复用)连接到CPU的1条对外中断line。

        每个外设中一般都有多个中断,例如INT_ADCA1(ADC的A模块的通道1中断)、INT_ADCA2(ADC的A模块的通道2中断)等等,每个中断都连接到ePIE对外的中断Channel。每个中断也都对应一个ISR(中断服务程序),两种通过Vector Table(中断向量表)映射在一起。如下图所示:

        TI C2000 DSP的这种三级中断架构设计,使得CPU能够处理大量的外设中断。每一级都有其自身的使能和标志寄存器,这些寄存器的灵活配置,可以允许CPU处理一个中断ISR时让其他中断挂起,或者让其他中断的ISR嵌套在当前ISR中间。前者可以用于某些关键ISR期间禁用Other中断,后者可以用在软件修改中断的硬件优先级

外设中断

        TI C2000 DSP的外设子系统非常多,功能各不相同。每个外设也都有多个中断,主要用于调度跟本外设相关的任务。例如,外设SCI(serial communication interface)的中断系统,可以用于提取/填充FIFO、处理通信故障等,SCI的几个接收中断如下图所示:

        Tips:在ePIE的Vector Table中可以看到单个SCI通道的RX中断只有一个,例如ITN9.1的SCIA_RX中断,但是上面的框图中SCI接收的相关中断有那么多,这就是外设级的Mux(多路复用)在发挥作用。每条中断Line上都有Enable和Flag寄存器,当ITN9.1的SCIA_RX传递到CPU中的ISR时,再读取相应的Flag寄存器就可以判断具体是什么中断,然后再switch到子代码中。

ePIE模块

        TI C2000 DSP的ePIE模块为每个外围中断信号提供了一个通道,每个通道上都有单独的Flag位和Enable位寄存器,如下图所示:

        ePIE模块的这些通道根据相关的CPU中断进行分组,每个组内的16个通道组成一个16位Enable寄存器(PIEIERx)、一个16位Flag寄存器(PIEIFRx)和一个ACK寄存器(PIEACKx)。PIEACKx寄存器位充当该组的公共中断掩码。

        当外设中有多个中断同时发生,或者ePIE中挂着多个中断时,Mux模块就会去仲裁出优先级highest(通道号lowest)的送到CPU。当CPU接收到中断时,还要从ePIE的Vector Table中获取对应ISR的地址。

        ePIE模块中的优先级仲裁就是一个比大小的过程,也是芯片硬件层面的一个行为机制,User Code在这个阶段干涉不了优先级仲裁的结果。而且TI C2000 DSP的一百多个外设中断,每一个的优先级位置都是在芯片硬件层面定义好的,第一组和第二组的32个中断,优先级示例如下:

CPU中断

        CPU中断与ePIE模块一样,也是为每条连接到CPU的中断Line提供Flag位和Enable位寄存器,如下图所示:

        CPU中断涉及的有一个Enable寄存器(IER)和一个Flag寄存器(IFR),这两个寄存器都是CPU内部寄存器。此外还有一个全局中断掩码(INTM),位于ST1寄存器,可以使用CPU的EINT指令(Clear INTM掩码,置为0,允许全局中断)和DINT指令(Set INTM掩码,置为1,禁止全局中断)进行配置。

        中断传播到CPU Interrupt Logic模块时,CPU要做的事情包括四部分:

        1、自动将IFR和IER置为0,将INTM置为1,这是芯片硬件层面的动作机制,目的是阻止再有中断进来。对于中断嵌套的应用后面再讲。

        2、保存现场,把堆栈和PC指针中的数据都保存起来。

        3、从Vector Table中抓取相应ISR的地址,执行中断服务程序。

        4、等ISR 执行Complete后,再回到前面保存的程序现场,回到主程序,并把各级中断Enable。

        当CPU阶段有多个中断同时发生,IFR寄存器中挂着多个中断时,Mux模块就会去仲裁出优先级highes的送到CPU Interrupt Logic模块。这里的优先级仲裁也是一个比大小的过程(芯片硬件层面的一个行为机制),但是不同于ePIM中的编号那么规则。在CPU阶段总共有32个中断,每一个的优先级位置也都是在芯片硬件层面定义好的,如下图所示:

        Tips:上图中的系统中断比较特殊,User能设计开发的空间很小,只需了解即可,无需过多关注。

中断嵌套

        默认情况下,TI C2000 DSP芯片内部的硬件机制是不对中断进行嵌套。也就是前文所讲述的,所有的中断都按照TI在芯片硬件层面设定好的优先级进行仲裁,等着高优先级的ISR先执行完,然后再执行低优先级的ISR。如果低优先级的ISR已经在执行过程中,高优先级的中断来了也要等前面的ISR执行完。这种方式是最保守,也最安全的一种应用方式

        但是在一些应用场景中,就是要求高优先级的ISR无条件地优先执行,甚至User需要改变TI在芯片硬件中定义的优先级顺序,重新设计一套Software优先级,这时候就需要用到中断嵌套了。例如,User设计的软件中用到INT1.5和INT2.4两个中断,要求INT2.4的优先级最高,无条件地优先执行,示例如下:

        上图中断的Software优先级设计和中断嵌套是User Code通过控制IER和PIEIERx等寄存器来实现的,具体过程如下图所示:

        1、开中断,User Code把INT1.5和INT2.4两条线路上的使能寄存器都Enable,用不到的线路都Disable;

        2、外设中断事件A发生,中断信号被PIEIFR1.5寄存器捕捉到;

        3、中断信号穿过PIEIER1.5之后,芯片硬件机制自动把PIEIER1.5 Disable;

        4、中断信号穿过PIEACK.1之后,芯片硬件机制自动把PIEACK.1 Disable;

        5、中断信号穿过INTM之后,芯片硬件机制自动把INTM Disable;

        6、中断信号到达CPU Interrupt Logic后,从Vector Table中抓取INT1.5的ISR的地址,开始执行该ISR;

        7 、User在INT1.5 ISR头部写入的Code重新把INTM Enable,以此保证INT2.4的中断线路是通畅的;

        8、INT1.5的ISR执行过程中,外设中断事件B发生了,中断信号一路传播到CPU Interrupt Logic(同步骤2、3、4、5);

        9、CPU暂停执行INT1.5的ISR,转去执行INT2.4的ISR

        10、INT2.4的ISR执行完后,返回继续执行INT1.5 ISR的后半段;

        11、两个ISR都执行完后,返回主程序继续执行。

应用实例

        这里展示一个示例Demo代码,直接用代码中的注释进行说明。


// C28x ISR Code	// 
// Enable nested interrupts	// 
// INT2.2的Software优先级Highest,无条件插入INT2.1的ISR中	//

void EPWM1_TZINT_ISR(void)	//INT2.1的ISR
{

		uint16_t TempPIEIER;
        TempPIEIER = PieCtrlRegs.PIEIER2.all; // Save PIEIER register for later
		
		//*****到这,所有中断线路都被芯片硬件机制自动Disable了,需要如下代码把INT2.2的中断线路打通*****//
 
		//允许Group2的中断进CPU(IER是1使能)
        IER |= 0x002;	//Group2置1,其他Group保持不变;      
        IER &= 0x002;	//Group2不变,其他Group置0;
						//最终效果:只有Group2传播途径的通畅的;
		
		//允许INT2.2中断(PIEIER是1使能)
		PieCtrlRegs.PIEIER2.all |= 0x0002;	//INT2.2置1,其他Channel保持不变;
        PieCtrlRegs.PIEIER2.all &= 0x0002;  //INT2.2,其他Channel置0;
						//最终效果:只有2.2的传播途径的通畅的
						
		//这里手动再把它置1(PIEACK是0使能)
		PieCtrlRegs.PIEACK.all &= ~(0x002);  // Enable PIE Group2 interrupts
		
		//等流水线上的指令走一走
        asm("NOP");	// Wait one cycle
		
		//开全局中断(INTM是0有效)
        EINT;	// Clear INTM(置0) to enable interrupts
		
        //*****到这,已经把INT2.2的中断线路打通打通了*****//
		
		/**************下面这段时间如果2.2的中断发生了就会进来,CPU就会跳转去执行2.2的ISR*************//
        // Insert ISR Code here.......
        // for now just insert a delay
        //
        for(i = 1; i <= 10; i++) {}
        //
		//********************************************************************************************//
		
        // Restore registers saved:		
        DINT;									// Set INTM(置1) to disable interrupts,因为马上就要退出ISR(switch context)了
        PieCtrlRegs.PIEIER2.all = TempPIEIER;	//人为干预的再把它恢复了,因为Group2后面可能还有其他挂起的中断
}
//退出2.1的ISR,芯片硬件机制又会自动设置寄存器,以此保证中断传播线路畅通

总结

        以上就是本人在研发中使用嵌入式处理器中断系统时,一些个人理解和分析的总结,主要介绍了TI C2000 DSP 中断系统的工作原理,展示了具体的使用方法,并分析了它的特点和应用场景。

        后续还会分享另外几个最近解锁的嵌入式处理器新技能,欢迎评论区留言、点赞、收藏和关注,这些鼓励和支持都将成文本人持续分享的动力。

        另外,上述例程使用的Demo工程,可以到笔者的主页查找和下载。

参考资料

        TMS320F28003x Real-Time Microcontrollers datasheet.pdf


        版权声明,原创文章,转载和引用请注明出处和链接,侵权必究!

  • 29
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.Cssust

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值