2812的CPU能够支持一个不可屏蔽中断NMI和16个可屏蔽的中断INT1-INT14、RTOSINT和DLOGINT;
2812的CPU为了能够及时有效的处理好各个外设的中断请求,特别设计了一个专门处理外设中断的扩展模块(the Peripheral Interrupt Expansion bloak),叫做外设中断控制器PIE,他能够对各种中断请求源做出判断以及相应的决策。
PIE可以支持96个不同的中断,这些中断分成了12个组,每个组有8个中断,而且每个组都被反馈到CPU内核的12条中断线中的某一条上(INT1-INT12),我们平时用到的所有的外设中断都被归入了这96个中断,被分布在不同的组里。
| INTx.8 | INTx.7 | INTx.6 | INTx.5 | INTx.4 | INTx.3 | INTx.2 | INTx.1 | |
| INT1 | WAKEINT | TINT0 | ADCINT | XINT2 | XINT1 | PDPINTB | PDPINTA | |
| INT2 | T1OFINT | T1UFINT | T1CINT | T1PINT | CMP3INT | CMP2INT | CMP1INT | |
| INT3 | CAPINT3 | CAPINT2 | CAPINT1 | T2OFINT | T2UFINT | T2CINT | T2PINT | |
| INT4 | T3OFINT | T3UFINT | T3CINT | T3PINT | CMP6INT | CMP5INT | CMP4INT | |
| INT5 | CAPINT6 | CAPINT5 | CAPINT4 | T4OFINT | T4UFINT | T4CINT | T4PINT | |
| INT6 | MXINT | MRINT | SPITXINTA | SPIRXINTA | ||||
| INT7 | ||||||||
| INT8 | ||||||||
| INT9 | ECAN1INT | ECAN0INT | SCITXINTB | SCIRXINTB | SCITXINTA | SCIRXINTA | ||
| INT10 | ||||||||
| INT11 | ||||||||
| INT12 |
2812内部外设中断的执行机制及其具体的处理过程:
2812的中断是3级中断机制,分别是外设级,PIE级以及CPU级,对于某一个具体的外设中断请求,任意一级的不许可,CPU最终都不会执行该外设中断。
外设中断------>PIE模块------>IFR--IER--INTM------->CPU
96路 PIEIER PIEIFR PIEACK
外设级 PIE级 CPU级
(1) 外设级
假如在程序的执行过程中,某一个外设产生了一个中断事件,那么在这个外设的某个寄存器中与该中断事件相关的中断标志位(IF=Interrupt Flag)被置为1。此时,如果该中断相应的中断使能位(IE=Interrupt Enable)已经被置位,外设就会向PIE控制器发出一个中断请求。相反的,如果虽然中断事件产生了,相应的中断标志也被置位1,但是该中断没有被使能(相应的使能位为0),那么外设就不会向PIE发出中断请求,但是值得一提的是,相应的中断标志位会一直保持置位状态,直到用程序清除为止。当然,在中断标志位保持在1的时候,一旦该中断被使能了,那么外设立马会向PIE发出中断请求。
外设级需要我们手动的地方:
外设中断的使能,需要将与该中断相关的外设寄存器中的中断使能位置1;
外设中断的屏蔽,需要将与该中断相关的外设寄存器中的中断使能位置0;
外设中断标志位的清除,需要将与该中断相关的外设寄存器中的中断标志位置1;
(2) PIE级
当外设产生中断事件,相关中断标志位置位,中断使能位使能之后,外设就会把中断请求提交给PIE模块。PIE模块将96个外设和外部引脚的中断进行了分组,每8个中断为1组,一共12组,分别是PIE1-PIE12。每个组的中断被多路汇集进入1个CPU中断。
和外设级类似,PIE控制器的每个组都会有一个中断标志寄存器PIEIFRx和中断使能寄存器PIEIERx,x=1,2,3,4,....12。每个寄存器的低8位对应8个外设中断,高8位保留。PIE除了每组具有PIEIERx,PIEIFRx寄存器之外,还有一个PIEACK寄存器,它的低12位分别对应着12个组,即INT1-INT12,高位保留。假如T1的周期中断被响应了,则PIEACK寄存器的第2位(对应于INT2)就会被置位,并且一直保持到手动清除这个标志位。当CPU在响应T1PNT的时候,PIEACK的第二位一直是1,这时候如果PIE2组内发生其他的外设中断,则暂时不会被PIE响应送给CPU,必须等到PIEACK的第2位被复位之后,如果该中断请求还存在,那么立马由PIE控制块将中断请求送至CPU。所以,每个外设中断被响应之后,一定要对PIEACK的相关位进行手动复位,否则同组内的其他中断都不会被响应。
PIE级需要我们手动的地方有:
PIE中断的使能。需要使能某个外设中断,就得将响应组的使能寄存器PIEIERx的响应位进行置位;
PIE中断的屏蔽。和使能操作相反;
PIE应答寄存器PIEACK相关位的清除,以使得CPU能够响应同组的其他中断。
(3) CPU级
CPU有标志寄存器IFR和使能寄存器IER。当某一个外设中断请求通过PIE发送到CPU时,CPU级中与INTx相关的中断标志位就会被置位。例如,T1的周期中断T1PINT的请求到达CPU这边时,与其相关的INT2的标志位就会被置位。该标志位就会被锁存在IFR中,这时候,CPU不会马上去执行相应的中断,而是等待CPU使能IER寄存器的相关位,并且对CPU寄存器ST1中的全局中断屏蔽位做适当的使能。如果IER中的相关位被置位了,并且INTM的值为0,则中断就会被CPU响应。
CPU接到中断请求,就得暂停正在执行的程序,转而去响应中断程序,但是还需做一些准备工作,以便于执行完中断程序之后回过头来还能找到原来的地方和原来的状态。CPU会将相应的IER和IFR位进行清除,EALLOW也会被清除,INTM被置位,就是不能相应其他中断了。CPU会存储返回地址并自动保存相关信息,例如将正在处理的数据放入堆栈,做完准备工作之后,CPU会从PIE块中取出对应的中断向量ISR,从而赚取执行中断子程序。
DSP28_PieCtrl.h:定义了和PIE相关的寄存器的数据结构;
DSP28_PieVect.h:定义了PIE的中断向量;
DSP28_PieCtrl.c:只有一个函数InitPieCtrl(),起作用是对PIE模块初始化;
DSP28_PieVect.c:对PIE中断向量表进行初始化,执行完这个程序,各个中断函数都有了明确的入口地址;
DSP28_DefaultIsr.c:定义了所有与外设相关的中断函数;