每次进入中断后,系统都会出现无法进行任务切换和进入内核时钟中断的问题,这似乎是总中断被屏蔽了的现象。通过对程序的跟踪发现是内核函数OSIntExit函数导致的。 OSIntExit函数代码如下:
void OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3;
OS_CPU_SR cpu_sr;
#endif
if (OSRunning == TRUE) {
OS_ENTER_CRITICAL();
if (OSIntNesting > 0){
OSIntNesting--;
}
if ((OSIntNesting == 0) &&(OSLockNesting == 0)) {
OSIntExitY = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((OSIntExitY<< 3) + UnMapTbl[OSRdyTbl[OSIntExitY]]);
if (OSPrioHighRdy != OSPrioCur){
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++;
OS_EXIT_CRITICAL();//这句是添加的,内核中没有
OSIntCtxSw();
}
}
OS_EXIT_CRITICAL();
}
}
在源代码中,并没有加粗字体“OS_EXIT_CRITICAL()”语句 。下面分析一下缺少上面语句导致系统出现以上问题的原因:
uC\OS-II是一个可剥夺型内核。OSIntExit函数有两个出口:一个是按原路返回出中断,另一个是返回到优先级更高的任务,从OSIntCtxSw函数出中断。OSIntCtxSw函数中执行了RTI语句,说明中断服务函数将从此处终止,但是OSIntExit函数在调用OSIntCtxSw函数之前并没有执行“OS_EXIT_CRITICAL()”去恢复中断。由于使用的第三种临界中断保护方式,屏蔽中断寄存器中的值保存在临时变量cpu_sr中,所以当系统执行完OSIntExit函数后,中断就永远处于屏蔽状态,因此系统以后就会出现无法进行任务切换的现象。解决方法就是按上面的程序在内核程序OSIntExit函数中添加上“OS_EXIT_CRITICAL()”语句,内核便能够良好运行。