不时总有人问起DSP的中断嵌套问题,有必要说明白几个概念上的问题,同时今天做了一个小示例供参考,欢迎拍砖。
概念:
#1. 中断优先级的概念。没有高优先级可以打断低优先级中断的说法。优先级只针对于处于pending状态的中断,中断控制器取高优先级的中断执行。对于正在处理当中的中断,如果不做软件上的特殊处理(即示例代码),是不能被别的中断打断的,除了NMI中断。
#2. 为什么正在处理当中的中断不能被其它中断打断,因为中断控制在进入中断时,把全局中断(GIE)关了,当然别的中断进不来了。
#3. 不难理解为什么NMI可以响应了,因为NMI不受GIE控制。
好了,应用当中有需要对某个中断及时响应怎么办?也就是说某个中断一来,希望它及马上跳到中断服务程序,哪怕是在执行别的中断服务程序。方法如下:
#1. C674x DSP参考文档sprufe8b 5.6.2节 Nested Interrupts. C64x+参考文档spru732j 5.7.2 Nested Interrupts. 内容如下。
To allow nested interrupts, the interrupt service routine must perform the following initial steps in
addition to its normal work of saving any registers (including control registers) that it modifies:
1. The contents of IRP (or NRP) must be saved
2. The contents of the PGIE bit must be saved
3. The contents of ITSR must be saved
4. The GIE bit must be set to 1
spru732j里还提供了一段示例如代码:
附件例子就是参照这个示例代码实现的。初步测试没看出有什么问题,也想不出能有什么问题。
#2. 如果用BIOS的话呢,在HWI里Masking Options里设置,下图红圈位置。
老版本的BIOS里,这地方没有BITMASK的输入框(上图是BIOS6_76的,已有了),根据下面贴子,还需要设disableMask and restoreMask instance configuration parameters,有兴趣自己去找怎么设吧。
https://e2e.ti.com/support/legacy_forums/embedded/tirtos/f/355/t/143228
附件的代码来源于L138 starterware C:\ti\OMAPL138_StarterWare_1_10_03_03\examples\lcdkOMAPL138\timer\timerCounter.c
将附件替换这个文件,用例子C:\ti\OMAPL138_StarterWare_1_10_03_03\build\c674x\cgt_ccs\omapl138\lcdkOMAPL138\timer编译即可验证一下中断嵌套了。
我是开了两个timer, 在timer 3 ISR里打开了嵌套,等timer 2的中断进来,执行完再回到timer 3 ISR,再退出。
Victorsunhao:
您好,您的例子中,明确知道其他中断会在 while(!flagIsrCnt);之后执行restore的操作,但是如果我不是明确知道会在什么地方打断,该如何实现嵌套呢?
Tony Tang:
回复 Victorsunhao:
这个while(!flagIsrCnt)可以换成任何代码,这只是个示例啊.
static void Timer3Isr(void){
unsigned int old_csr; unsigned int old_irp; /* Disable the timer interrupt */ TimerIntDisable(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
#ifdef _TMS320C6X /* Clear interrupt status in DSPINTC */// IntEventClear(SYS_INT_T64P2_TINTALL); // not necessary to clear.#else /* Clear the interrupt status in AINTC */ IntSystemStatusClear(SYS_INT_TIMR2_ALL);#endif TimerIntStatusClear(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE); printf("Save INT context for nest.\n"); /*Protect context for interrupt nest */ old_irp=IRP; old_csr = CSR; CSR = (old_csr | 1);
while(!flagIsrCnt); //wait timer 2 interrupt.
/* Signal application to print a new character */ flagIsrCnt = 0; CSR = old_csr; IRP = old_irp; printf("Restored INT context.\n");
/* Enable the timer interrupt */ TimerIntEnable(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE);}