
目录文章目录前言二、中断可嵌套的实现1.官方例子2.应用实例总结前言DSP的中断默认是不可嵌套的即当执行某个中断服务函数时即使有更高优先级的中断触发也需要等待当前中断执行完后才可响应。近来工作需要保证TMS320F28377D的IPC中断优先执行即使当前正在执行其它中断也需要挂起优先执行IPC中断。一、DSP的中断是怎样的28377D的CPU有14个外设中断线其中两个INT13和INT14分别直接连接到CPU定时器1和2.其余12个通过增强型外设中断扩展模块ePIE连接到外设中断信号。CPU内核有IER中断使能寄存器和IFR中断标志寄存器这两个十六位的寄存器的低十四位分别对应INT1到INT14的中断使能和中断标志。如果使用的是新的driverlib库在cpu.h文件中有如下声明可直接代码中对IER和IFR寄存器读写。#ifndef _TMS320C28XX_CLA_ extern _cregister volatile uint16_t IFR; #endif #ifndef _TMS320C28XX_CLA_ extern _cregister volatile uint16_t IER; #endifPIE将多达16个外设中断复用到每个CPU中断线上它还扩展中断向量表以允许每个中断具有自己的ISR这允许CPU支持大量的外设。中断路径位外设-PIE-CPU每个级都有自己的使能和标志寄存器该系统在处理一个中断时其它可屏蔽中断是禁止的需要在软件中实现嵌套中断并在某些关键任务期间禁用中断。设备中断架构28377D的PIE有12组每组有16个通道中断其中断优先级如下表从上往下优先级逐减从左往右优先级逐减即左上优先级最高右下优先级最低。PIE的寄存器如下外设到CPU的执行流程1.当外设产生中断中断被锁存在PIEIFRx.y2.如果设置了PIEIERx.y中断将被传递3.如果PIEACK.x清零非零将不传递则中断传递到CPUPIEACK.x被置位直到ISR中软件手动清除ACK4.中断在CPU的IFR.x中锁存5.如果cpu的IER.x设置了则中断传播6.如果INTM清零指EINT使能中断或CLER INTMCPU接收中断7.CPU保存上下文8.清除IFR.x,和IER.x,INTM设置DINT 或SETC INTM这时禁止其它可屏蔽中断9.CPU从PIE中获取ISR向量PIEIFRx.y被清除10.CPU分支到ISR注意当对IER、IFR、PIE的寄存器操作时需要先DINT禁用中断操作完后再EINT启用中断二、中断可嵌套的实现1.官方例子添加简单的软件优先级嵌套第 1 步设置全局优先级 修改 IER 寄存器以允许处理具有更高用户优先级的 CPU 中断。 注意此时 IER 已经保存在栈上。 第 2 步设置组优先级可选 修改相应的 PIEIERx 寄存器以允许处理具有更高用户设置优先级的组中断。 不要从除此 ISR 服务的组之外的另一组清除 PIEIER 寄存器位。这样做可能会导致发生错误的中断。 第 3 步启用中断 有三个步骤可以做到这一点 清除 PIEACK 位 等待至少一个周期 清除 INTM 位。使用汇编语句 asm( CLRC INTM); 或 TI 示例使用 #define EINT asm( CLRC INTM) 第 4 步 运行 ISR 的主要部分 第 5 步 设置 INTM 以禁用中断。使用 asm( SETC INTM); 或 TI 示例使用 #define DINT asm( SETC INTM) 第 6 步 恢复 PIEIERx可选取决于步骤 2 第 7 步从 ISR 返回 这将自动恢复 INTM 和 IER。实例代码// // C28x ISR Code // // Enable nested interrupts // // interrupt void EPWM1_TZINT_ISR(void) { uint16_t TempPIEIER; TempPIEIER PieCtrlRegs.PIEIER2.all; // Save PIEIER register for later IER | 0x002; // Set global priority by adjusting IER IER 0x002; PieCtrlRegs.PIEIER2.all 0x0002; // Set group priority by adjusting PIEIER2 to allow INT2.2 to interrupt current ISR PieCtrlRegs.PIEACK.all 0xFFFF; // Enable PIE interrupts asm( NOP); // Wait one cycle EINT; // Clear INTM to enable interrupts // // Insert ISR Code here....... // for now just insert a delay // for(i 1; i 10; i) {} // // Restore registers saved: // DINT; PieCtrlRegs.PIEIER2.all TempPIEIER; }官方例子是在EPWM1_TZ的中断中能够响应EPWM2_TZ的中断通过下图可看出EPWM2_TZ的优先级比EPWM1_TZ的优先级低这说明软件实现中断可嵌套根据用户的需求来实现非常灵活2.应用实例1. XINT5和IPC1中断可嵌套要求IPC1中断优先执行且可打断XINT5中断不同组中断可嵌套下图是DSP两个引脚的逻辑分析仪采集的波形图其中tst_adInterrupt引脚在DSP的外部中断5的ISR进入时置1执行完时复位dsp_Ad_update引脚在DSP的IPC1中断的ISR进入时置位执行完后复位。从图中可以看出第二个波形即IPC1中断需要等外部中断5执行完才执行导致IPC1中断执行太晚了因此需要中断可嵌套保证IPC1中断优先执行查询IPC1的中断通道号位INT1.14XINT5的中断通道号为INT12.3因此IPC1的中断优先级本来就比XINT5的中断优先级高因此不需要在XINT5的ISP中设置全局优先级和组优先级只需要在XINT5的ISR中做如下修改__interrupt void xint5ISR() { GPIO_writePin(Pin_CON4,1); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP12);//清除PIE的ACK对应位 NOP; EINT;//使能中断 //业务代码 GPIO_writePin(Pin_CON4,0); } //__interrupt关键字编译器在ISR执行完后会自动执行IRET指令以上修改后再用逻辑分析抓取DSP引脚波形图如下可以看出第二个引脚即IPC1中断能够打断XINT5的中断保证了IPC1中断的优先执行2. XINT1和TIMER0中断可嵌套要求XINT1中断优先级高且可打断TIMER0中断同组中断可嵌套其配置过程如下//外部中断正常写 _interrupt void ISR_xint1() { //业务代码 //清除中断组号 Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1); } //定时器0中断允许被打断 _interrupt void timer0_isr() { IER | 0X001; IER 0X001; HWREGH(PIECTRL_BASE PIE_O_ACK) 0xFFFF; NOP; EINT; //业务代码 }总结本文主要讲解了DSP中断可嵌套的实现借助了官方同组内低优先级的PWM2_TZ中断能够打断PWM1_TZ的例子实现了IPC1中断打断XINT5中断的需求其它中断可嵌套的实现可参考本文原理上是相同的