2.2 中断系统分析
中断可认为是由外部或内部单元产生的“同步事件”。事件产生后,处理器会“中断”当前程序转而执行该事件的“服务程序”。“服务程序”执行完毕后,程序从刚才的“断点”处接着执行。
F2833x的CPU级中断有16个,如图2.11所示,其中两个称为“不可屏蔽中断”(Reset、NMI);剩余14个称为“可屏蔽中断”,也就是说,允许用户“使能或禁止”这14个中断。
图2.11 包含的16个CPU级中断
“1”表示使能,“0”表示禁止。将用户希望的“屏蔽字”写入CPU的IER寄存器后,就可使能或禁止这14个可屏蔽中断。然而对于不可屏蔽中断,我们不能“禁止”,只能无条件地执行。因此不可屏蔽中断的优先级最高,常用于安全考虑及系统的紧急停止。
2.2.1 中断系统的结构
F2833x的中断源简单可以分为片内中断源和片外中断源。
片内中断源由片内的软硬件事件产生,比如3个CPU定时器、各个外设(如eCAP、ePWM、看门狗等)以及一些用户自定义的中断事件。
片外中断源一般是与DSP的引脚联系在一起,在特定引脚上检测到一定长度的脉冲或捕获到电平的跳变,就会产生中断标志事件,比如XINT1-7外部触发中断引脚、XRS引脚(产生复位事件)、XNMI_XINT13(不可屏蔽中断)等。
由于DSP片上外设的中断事件种类繁多(比如一个ePWM模块中的定时器就可以包含上溢、周期、比较等多种中断)。为了实现对众多外设中断的有效管理,F28335的中断系统采用了外设级、PIE级和CPU级三级管理机制,用一个简图来表示这些中断源的处理方法,如图2.12所示。
图2.12 中断源处理方法示意图
(1)外设级
外设级中断是指F28335片上各种外设产生的中断。F28335片上的外设有多种,每种外设可以产生多种中断。目前这些中断包括外设中断、看门狗与低功耗模式唤醒共享中断、外部中断(XINT1~XINT7)及定时器0中断,共56个。
二维码2.4
(2) PIE级
PIE模块分成INT1~INT12(共12组,每组最多支持8个外设中断),每组占用一个CPU级中断。例如,第1组占用INT1中断,第2组占用INT2中断,…,第12组占用INT12中断(注意,定时器T1和T2的中断及非屏蔽中断NMI直接连到了CPU级,没有经PIE模块的管理)。外设中断分组见表2.1。
(3) CPU级
CPU级包括通用中断INT1~INT14、数据标志中断DLOGINT和实时操作系统中断TOSINT,这16个中断组成了可屏蔽中断。可屏蔽中断能够用软件加以屏蔽或使能。
除可屏蔽中断外,F28335还配置了非屏蔽中断,包括硬件中断NMI和软件中断。非屏蔽中断不能用软件进行屏蔽,发生中断时CPU会立即响应并转入相应的服务子程序。
表2.1 F28335外设中断分组
(续)
2.2.2 可屏蔽中断处理
1.可屏蔽中断工作流程
图2.13为可屏蔽中断的流程示意图,按从内核到中断源的顺序更容易解释中断处理流程。INTM 是主中断开关,此开关必须闭合才能使中断传播至内核。再往外一层是中断使能寄存器,相应的中断线路开关必须闭合才能使中断通过。当中断发生时,中断标志寄存器置位。
内核中断寄存器由中断标志寄存器、中断使能寄存器和中断全局掩码位组成。注意,中断全局掩码位启用时为0,禁用时为1。中断使能寄存器通过对掩码值执行或运算和与运算来管理。
当某外设中断请求通过PIE模块发送到CPU级时,IFR中与该中断相关的标志位INTx就会置位(如T0的周期中断TINT0的请求到达CPU级时,IFR中的标志位INT1就会被置位)。此时CPU并不马上进行中断服务,而是要判断IER寄存器允许位INT1是否已经使能,并且CPU寄存器ST1中的全局中断屏蔽位INTM也要处于非禁止状态(INTM为0)。如果IER中的允许位INT1被置位,并且INTM的值为0,则该中断申请就会被CPU响应。
2.CPU级中断相关寄存器
CPU级中断设置有中断标志寄存器IFR、中断使能寄存器IER和调试中断使能寄存器DBGIER。IFR、IER和DBGIER寄存器格式类似,如图2.14所示。
图2.13 可屏蔽中断的流程示意图
注1:特定中断行上的有效信号触发锁存,将在相应位显示“1”
注2:若单个开关或全局开关“打开”,中断将到达内核
图2.14 IFR、IER寄存器位格式
中断标志寄存器IFR寄存器的某位为1,表示对应的外设中断请求产生,CPU确认中断及DSP复位时,相应的IFR清零;IER寄存器的某位为1,表示对应的外设中断使能;DBGIER寄存器的某位为1,表示对应的外设中断的调试中断使能。
常用如下方式进行寄存器的置位和清零。
ST1寄存器位格式如图2.15所示。
图2.15 ST1寄存器的位格式
INTM用于使能/屏蔽总中断,且仅能通过汇编代码来修改INTM。
3.如何开启受PIE模块管理的可屏蔽中断?
1)设置中断向量。例如,PieVectTable.ADCINT=&ADC_isr;(其中,ADC_isr为中断服务程序的名称)。
2)使能PIE模块:PieCtrlRegs.PIECTRL.bit.ENPIE=1;。
3)使能PIE中对应外设的中断(对应group组中的相应位)。例如,PieCtrlRegs.PIEIER1.bit.INTx8=1;PieCtrlRegs.PIEIER1.bit.INTx6=1;。
4) 使能CPU的相应中断 (INT1~INT12),IER|=M_INT1;(使能INT1,其中,M_INT1=0x0001)。
5)使能CPU响应中断EINT。其中,EINT为asm("CLRC INTM")。
2.2.3 非屏蔽中断处理
非屏蔽中断是指不能通过软件进行禁止和使能的中断,CPU检测到有这类中断请求时会立即响应,并转去执行相应的中断服务子程序。F28335的非屏蔽中断包括软件中断、硬件中断NMI、非法指令中断ILLEGAL和硬件复位中断。
1.软件中断
(1) INTR指令
INTR指令用于执行某个特定的中断服务程序。该指令可以避开硬件中断机制而将程序流程直接转向由INTR指令参数所对应的中断服务程序。指令的参数为INT1~INT14、DLOGINT、RTOSINT和NMI。例如:
(2) TRAP指令
TRAP指令用于通过中断向量号来调用相应的中断服务子程序。该指令的中断向量号的范围是0~31。
2.非法指令中断
当F28335执行无效的指令时,会触发非法指令中断。若程序跳入非法中断,TI公司并未给出具体的解决方案。建议读者在该中断服务程序使能看门狗加入死循环,从而触发软件复位。
3.硬件NMI中断
NMI中断与XINT13共用引脚。若使用非屏蔽中断,需要将控制寄存器XNMICR的D0=1。但D0=1,表明NMI和INT13都可能发生,具体的配置见表2.2。
表2.2 NMI和INT13中断配置表
Timestamp表示时间戳。对于外部中断,可以利用16位的计数器记录中断发生的时刻,该计数器在中断发生时和系统复位时清零。
4.硬件复位中断
硬件复位是F28335中优先级最高的中断。硬件复位发生后,CPU会转到0x3F FFC0地址去取复位向量,执行引导程序。
2.2.4 外设中断扩展模块(PIE)的使用详解
1.PIE模块的结构
F2833x设置了一个专门对外设中断进行分组管理的PIE模块,F2833x所构成的三级中断结构如图2.16所示。
外设中断一共分为12组,每组支持8个中断,因此F2833x共支持96个中断。
若只讨论PIE的工作流程,则将图2.16可提炼成图2.17的形式。
图2.16 F2833x所构成的三级中断结构示意图
PIE模块的每组都有一个中断标志寄存器PIEIFRx(x=1,2,…,12)和中断使能寄存器PIEIERx。每个寄存器的低8位对应8个外设中断(高8位保留)。此外,设有一个中断响应寄存器PIEACK,它的低12位(bit11~bit0)分别对应INT1~INT12。
如TINT0中断响应时,PIEACK寄存器的bit0(即ACK1,对应INT1组)就会被置位(封锁本组的其他中断),并且一直保持到应用程序清除这个位。在CPU响应TINT0过程中,ACK1一直为1,这时如果PIE1组内发生其他的外设中断,则暂时不会被PIE送给CPU,必须等到ACK1被清0。ACK1被清0后,若该中断请求还存在,那么PIE模块就会将新的中断请求送至CPU。所以,每个外设中断响应后,一定要对PIEACK的相关位进行“写1清0”,否则同组内的其他中断都不会被响应。
PIE寄存器的使用方法如下:
图2.17 PIE的工作流程图
2.中断向量和中断向量表
CPU中断向量是22位,它是中断服务程序的入口地址。F2833x支持32个CPU中断向量(包括复位向量)。每个CPU中断向量占2个连续的存储器单元。低地址保存中断向量的低16位,高地址保存中断向量的高6位。当中断被确定后,22位(高10位忽略)的中断向量会被取出并送往PC。
32个CPU中断向量占据了64个连续的存储单元,形成了CPU中断向量表。CPU中断向量见表2.3。
表2.3 F28335的CPU中断向量和优先级
(续)
向量表的映射由以下几个模式控制位/信号进行控制:
1) VMAP,状态寄存器ST1的bit3。VMAP的复位值默认为1。该位可以由SETC VMAP指令进行置1,由CLRC VMAP指令清0。
2) M0M1MAP,状态寄存器ST1的bit11,复位值默认为1。该位可以由SETC M0M1MAP指令进行置1,由CLRC M0M1MAP指令清0。
3) ENPIE,PIECTRL寄存器的bit0,复位值默认为0,即PIE处于禁止状态。可以对PIECTRL寄存器(地址00 0CE0H)进行修改。
CPU中断向量表可以映射到存储空间的4个不同位置,见表2.4。
表2.4 中断向量表映射配置表
注:M1和M0向量表保留用于TI公司的产品测试。
系统上电复位时ENPIE=0;VMAP=1;M0M1MAP=1;OBJMODE=0;AMODE=0,因此复位向量总是取自BROM向量表(实际上该区仅用到复位向量)。
PIE模块用于外设的中断管理,复位后用户需完成PIE中断向量表的初始化。当VMAP=0,ENPIE=1时PIE中断向量映射如图2.18所示。
地址0x00 0D40~0x00 0DFF用于PIE的空间扩展,每一个中断向量(PIEINT1.1~PIEINT12.8)的地址均为32位。使能PIE后的中断向量见表2.5。
上电复位时,PIE中断向量表没有任何内容,程序初始化时需要对它进行修改。读者可将TI提供的DSP2833x_PieVect.c文件加到自己的工程中进行调用。PIE使能后,TRAP#1取INT1.1向量,TRAP#2取INT1.2向量……。
综上,DSP复位后直至开始运行主函数的示意图如图2.19所示。
图2.18 BROM向量表(复位时默认的中断向量表)
表2.5 使能PIE(ENPIE=1)后的中断向量指向
图2.19 DSP复位后直至开始运行主函数的示意图
2.2.5 非法中断产生原因及解决方案
问题1:造成非法中断的原因?
答:造成程序进入非法中断的情况大致如下:
1) 操作码被解码为0x0000,该操作码对应于ITRAP0指令。
2) 操作码被解码为0xFFFF,该操作码对应于ITRAP1指令。
3) 试图使用@SP寻址32位操作。
4) 将寻址模式AMODE=1,同时PAGE0=1。
问题2:如何调试ITRAP,如何避免进入ITRAP?
答:1)ITRAP通常是堆栈溢出或缓冲区溢出的迹象。要快速查看是否为堆栈空间不足,可以使用已知的数值填充该区域,然后运行应用程序,查看区域地址长度。
2)确保程序代码没有过于接近内存块的结尾(一般为无效内存)。这在器件勘误中进行了说明。
3)ISR中插入返回指令。在返回指令上设置断点,然后一步步查看代码的来源。
4)程序进入非法中断时,寄存器(包括返回地址)会自动入栈。通过查看堆栈上的返回地址值,就可找出ITRAP发生的位置。
问题3:进入ITRAP后如何退出?
答:大部分读者会将DSP下电重启。实际上还有另一种解决方案:非法中断服务程序中写一个死循环,并使能看门狗,但不喂狗,从而触发DSP复位。程序如下:
2.2.6 中断嵌套之我见
我们通常所说的PIE中断优先级指的是当几个中断同时发出请求时,CPU先响应高优先级别的中断,处理完该中断服务函数之后,再响应低优先级的中断。当然,如果在这个期间,等待的中断有新的中断事件出现时,该中断事件就会丢失。按正常的程序设置,进入中断服务函数之后,CPU会关掉全局中断使能,所以高优先级的中断打断不了低优先级别的中断。但是C2000也是支持中断嵌套的,即高优先级别的中断能够打断低优先级别的中断。也就是说,当CPU在执行SCIB中断服务函数时,可以被EPWM中断来打断,实现中断嵌套。
本节介绍如何通过简单更改中断服务程序(ISR)代码来实现中断嵌套。在此之前,读者需熟悉C28x的PIE模块原理及中断控制寄存器(IER、IFR、INTM)的常用操作。
1.硬件优先级
中断由C28x硬件自动设置优先级。所有中断的优先级可以在系统控制指南中找到。对应于CPU INT1的组1具有最高优先级。每个组中有8个中断,INTx.1是最高优先级,INTx.8是最低优先级。
2.PIE的组织形式
PIE块将中断按照从高到低的逻辑顺序进行组织。C28x系统的中断可分类如下(按从高到低的顺序排列):
(1)非周期性的快速响应中断
这类中断可在任何时间发生,且当它们发生时必须尽可能快地得到响应。这类中断分配给PIE组1和PIE组2中的前几个位置。这个位置给予它们在PIE组内的最高优先级。此外,组1复用到CPU中断INT1。CPU INT1具有最高的硬件优先级。PIE组2复用到CPU第二高的硬件优先级的INT2。
(2)周期性的快速响应中断
这些中断会周期性发生,并且当它们发生时,必须尽可能快地被响应以减少延迟,A-D转换就是一个很好的例子。这样的中断被分配给PIE表中的组1。
(3)周期性中断
这些中断同样会周期性发生,但必须在下一个中断之前得到服务。PWM中断就是一个例子。这些中断被映射到组2~组5,这些组被复用到CPU INT3~INT5(ePWM、eCAP和eQEP)。
(4)周期性的带缓冲中断
这些中断在周期性事件中发生,但是被缓冲。当缓冲器满标志位置1或清空标志位置1时,处理器才会执行这样的中断服务程序。所有串行端口(SCI/SPI/I2C/CAN)都具有FIFO或多个邮箱,以便CPU有足够的时间响应事件,而不必担心丢失数据。这些中断映射到INT6、INT8和INT9。
3.C28x中断响应——无嵌套方式(默认)
表2.6显示了处理中断时所采取的步骤。
表2.6 中断处理的步骤
(续)
注.1.表中的硬件、软件的含义如下:
硬件:由芯片本身执行。软件不需要任何操作。
软件:通过软件执行。使用编译器时,这些步骤由编译器处理。
2.
当某个中断服务程序开始时,其他中断自动禁止。
步骤1~3受硬件保护。
步骤4通过设置INTM和DBGM位来禁止中断,防止CPU在进行中断服务程序期间处理新的中断。
INTM和DBGM将保持置1,除非软件重新允许中断或CPU从中断服务程序返回。
4.全局及组的优先级
在中断服务程序的开始处或在关键代码完成后重新启用中断。全局优先级使用IERx,组内优先级使用PIEIERx。对PIEIERx寄存器进行操作需注意:
PIEIER寄存器的修改只能在本组内的ISR进行。例如,PIEIER1只能在组1的ISR中修改,同样PIEIER2应该只在组2的 ISR中修改。此外,这种修改应在PIEACK置位时完成,因此在进行修改时,不会有中断发送到CPU。若违反此规则,则可触发错误的INTx.1中断。
5.中断优先级在什么情况下有意义?
1)两个中断同时发生,优先级高的中断优先被响应。
2)两个中断按时间先后顺序发生,但是此时已经有中断正在执行,也就是说它们都需要排队。当正在执行的中断完成后,优先级高的中断优先被响应。
3)使能中断嵌套后,高优先级的中断可以打断正在执行的低优先级的中断。
4)默认情况下,F28335不支持中断嵌套。也就是说,即便一个中断的优先级比另一个高,默认情况下,也不会出现低优先级中断正在执行时,被高优先级打断的情况。
6.中断嵌套软件操作方法
硬件上并未直接支持中断嵌套,但软件可以实现,具体操作步骤如下。
步骤1:设置全局中断优先级,即修改IER寄存器以允许处理更高优先级的CPU中断(注意:此时IER已保存在堆栈中)。
步骤2:设置PIE组中断优先级,即修改相应的PIEIERx寄存器以允许具有较高优先级的组中断得到服务。
步骤3:使能中断,先将PIEACK应答位写1清0,再等待最少一个机器周期,最后将INTM位清0(asm“CLRC INTM”)。
步骤4:运行中断服务程序。
步骤5:禁止总中断,即INTM位置1(asm“SETC INTM”)。
步骤6:PIEIERx恢复。
步骤7:中断返回。
例程分析:
7.使用掩码来管理优先级
TI提供了一种使用掩码来管理全局和PIE组优先级的方法,该文件中相关变量的含义如下。
1)分配全局优先级:INT1PL~INT16PL。
这些值用于为CPU级的16个中断分配优先级,其中,0表示不使用;1表示优先级最高;16表示优先级最低。可以为多个中断分配相同的优先级,在这种情况下,默认的硬件优先级将决定CPU首先响应哪个中断。
2)分配PIE组优先级:GxyPL(其中,x=PIE组编号1~12,y=中断编号1~8)。
这些值用于为PIE组中的8个中断分配优先级,其中,0表示不使用;1表示优先级最高;8表示优先级最低。可以为组内多个中断分配相同的优先级,在这种情况下,默认的硬件优先级将决定CPU首先响应哪个组内中断。
编译器将用户分配的全局和组内优先级生成可用于更改IER和PIEIERx寄存器的掩码值,其中,IER掩码值为MINT1~MINT16;PIEIERxy掩码值为MGxy(其中,x=PIE组编号1~12,y=中断编号1~8)。
操作步骤如下。
步骤1:设置CPU级中断优先级。
例如,设置第2组优先级最高,其他中断优先级如下:
步骤2:设置组内中断优先级。
以第2组为例,令EPWM2_TZINT优先级最高,其他中断优先级如下:
步骤3:优先级设置好后到 DSP281x_SWPrioritizedDefaultIsr.c文件,在该文件中找到相应的函数,以EPWM2_TZINT为例。
2.2.7 中断应用分析
应用实例1—外部中断示例
GPIO0和GPIO1分别作为XINT1和XINT2,GPIO30和GPIO31分别作为XINT1和XINT2的触发信号,因而硬件上需GPIO30与GPIO0相连,GPIO31与GPIO1相连。XINT1输入与SYSCLKOUT同步,XINT2输入使用采样窗口进行限定。
二维码2.5
应用实例2—组内两个中断服务程序示例
//主程序
//中断服务程序