第二章 任务管理
uCOS-II的中断
概念
暂停当前的程序,转而处理异步事件,处理完毕后,再返回原来的程序继续执行的过程叫做中断;应中断请求,运行的程序叫做中断服务子程序(Interrupt Service Routines,ISR);中断服务程序的入口地址叫做中断向量。
中断过程
如果μC/OS-Ⅱ系统收到中断请求,若处理器当前处于中断允许的状态,则系统停止正在运行的当前任务,而按照中断向量的指向转而去运行中断服务子程序。执行完毕后,根据情况,系统有两种走向,并执行其中的一种:
1.返回原来被中断的任务继续执行。
2.转到更高优先级的就绪任务上去执行。
注:为什么会有两种不同的走向?因为对于可剥夺型的uCOS-II内核来说,中断服务子程序运行结束前,需要进行一次任务调度。正因为有这样的任务调度,在中断结束时,系统才有可能去运行另外一个优先级别最高的就绪任务,而不是一定要返回被中断的任务。中断嵌套
机制:uCOS-II允许中断嵌套,即在中断服务程序的运行过程中,处理器可响应别的高优先级的中断源的请求。
全局变量:μC/OS-Ⅱ定义了一个全局变量OSIntNesting来记录中断嵌套的层数。该全局变量有两个作用:1.作为调度器是否进行调度的标志,以保证调度器不会在中断服务子程序中进行任务调度。2.记录中断嵌套层数- 体系结构
μC/OS-Ⅱ的体系结构如图1所示。它是一个微内核,只对处理器和硬件时钟进行了抽象和逻辑封装。
1.进入中断服务函数OSIntEnter()的源码如下:void OSIntEnter() { if(OSIntNesting<255) { OSIntNesting++;//中断嵌套层数计数器加1 } }
2.退出中断服务函数OSIntExit()的源码
void OSIntExit() { #if OS_CRITICAL_MENHOD == 3 OS_CPU_SR cpu_sr; #endif if(OSRunning == TRUE)//如果内核已经运行 { OS_ENTER_CRITICAL(); //关中断 if(OSIntNesting>0) { OSIntNesting--; //中断嵌套次数减1 } if((OSIntNesting == 0) && (OSLockNesting == 0)) //如没有中断嵌套和调度器被加锁 { OSIntExity=OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy=(INT8U)( OSIntExity<<3) + OSUnMapTbl[OSRdyTbl[OSIntExity]];//找出最高就绪优先级任务 if(OSPrioHighRdy != OSPrioCur)//如最高就绪优先级任务不是当前任务 { OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];//获取TCB指针 OSCtxSwCtr++; //任务切换次数加1 OSIntCtxSw(); //调用中断级任务切换函数 } } OS_EXIT_CRITICAL(); //开中断 } }
根据OSIntExit()的源码,什么时候会进行中断级的任务切换函数OSIntCtxSw()?需满足以下3个条件:
1.当前控制流处于最外层中断服务程序之中
2.调度器未被锁定
3.任务就绪表中的最高优先级任务不是当前被中断的任务
注意: uCOS-II有两种调度器:任务级的调度器和中断级的调度器,这里的OSIntExit()就是中断级的调度器