因为在任务调度中涉及到时间片这个概念,因而转而先学习下一章,中断管理和时间管理,一共俩小节。html
一、前言app
ucos是实时多任务操做系统,系统的实时性主要体如今对中断的响应上;除了响应时间,ucos要求对中断服务程序(ISR)运行时间不能过长。在以前分析过的任务删除函数中,由于涉及到有关全局变量的操做,函数关掉了中断;而为了不关中断的时间太长,因而在删除任务的过程当中又开了一次中断。函数
对于不一样的硬件系统,ISR的编写时彻底不一样的,由于这涉及到对底层寄存器的操做,操做系统中提供的中断管理函数位于core.c中。学习
事实上,任务的调度大多也依靠中断。ISR在发现了有更高优先级的就绪任务就会进行任务调度。当操做系统有其余的外中断时,如定时器中断,外中断,串口中断等,只要中断时打开的,并且正在运行的任务并无关中断,就会响应中断,这时任务就被切换了。this
这一节只是涉及中断管理,暂不涉及中断设计。spa
二、ucos中断的实现操作系统
上图:设计
从图中看到有三个待学习的函数:OSIntEnter()、OSIntExit()、OSIntCtxSw()。code
三、OSIntEnter()函数orm
源码
1 void OSIntEnter (void) 2 { 3 if (OSRunning == OS_TRUE) { 4 if (OSIntNesting < 255u) { 5 OSIntNesting++; /* Increment ISR nesting level */ 6 } 7 } 8 }
代码中有一个全局变量OSIntNesting非常重要,表示ISR的嵌套层数,每进入一次中断则将其加1。
注意下,在与这个函数对应的OSIntExit()中也有相似处理OSIntNesting的代码,只不过是每退出一次中断则将其减1。
四、时钟中断中的任务切换函数OSIntExit()函数
ucos中任务调度分两种:任务级任务调度和中断级任务调度。这儿先就着中断管理部分把中断级任务调度讲述了。
ucos在每一个时钟滴答进入时钟中断服务程序,若是有比目前运行的任务更高优先级的任务就绪,在须要时进行一次任务调度。这个任务调度函数表示OSIntExit()。
在时钟中断的时候,紧接着OSTimeTick,操做系统调用OSIntExit()实现任务的切换。
源码
1 void OSIntExit (void) 2 { 3 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ 4 OS_CPU_SR cpu_sr = 0; 5 #endif 6 7 8 9 if (OSRunning == OS_TRUE) { 10 OS_ENTER_CRITICAL(); 11 if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */ 12 OSIntNesting--; 13 } 14 if (OSIntNesting == 0) { /* Reschedule only if all ISRs complete ... */ 15 if (OSLockNesting == 0) { /* ... and not locked. */ 16 OS_SchedNew(); 17 if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ 18 OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; 19 #if OS_TASK_PROFILE_EN > 0 20 OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ 21 #endif 22 OSCtxSwCtr++; /* Keep track of the number of ctx switches */ 23 OSIntCtxSw(); /* Perform interrupt level ctx switch */ 24 } 25 } 26 } 27 OS_EXIT_CRITICAL(); 28 } 29 }
line 9,肯定在多任务已经启动的时候才调度。
然后关中断。
line 14,当肯定已无中断嵌套时(若是有嵌套,要先执行那个任务),而且调度器还未上锁,执行OS_SchedNew ()。(嵌套一下!)
**********************************************************************************************
OS_SchedNew ()源码
1 //FIND HIGHEST PRIORITY TASK READY TO RUN 2 3 static void OS_SchedNew (void) 4 { 5 #if OS_LOWEST_PRIO <= 63 /* See if we support up to 64 tasks */ 6 INT8U y; 7 8 9 y = OSUnMapTbl[OSRdyGrp]; 10 OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); 11 #else /* We support up to 256 tasks */ 12 INT8U y; 13 INT16U *ptbl; 14 15 16 if ((OSRdyGrp & 0xFF) != 0) { 17 y = OSUnMapTbl[OSRdyGrp & 0xFF]; 18 } else { 19 y = OSUnMapTbl[(OSRdyGrp >> 8) & 0xFF] + 8; 20 } 21 ptbl = &OSRdyTbl[y]; 22 if ((*ptbl & 0xFF) != 0) { 23 OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl & 0xFF)]); 24 } else { 25 OSPrioHighRdy = (INT8U)((y << 4) + OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8); 26 } 27 #endif 28 }
其函数功能是找到优先级最高的任务,具体实现即是修改全局变量中有关优先级的变量。
*****************************************************************************************************
line 17,若是最高优先级就绪任务不是当前运行任务的话(若是是,便没有调度的必要了),则进行调度。
这儿有一个新函数,叫作OSIntCtxSw()。
五、中断中任务切换函数OSIntCtxSw
OSIntCtxSw()才是真正在中断程序中进行实际的任务切换的地方。
源码
1 //PERFORM A CONTEXT SWITCH (From an ISR) 2 3 void OSIntCtxSw() 4 { 5 DWORD n = 0; 6 7 if(!(SS_SP->Exit)) { 8 n = SuspendThread(SS_SP->Handle); 9 } 10 11 OSTaskSwHook(); 12 13 OSTrace( OBJ_SW, PT_SW_INT, OSTCBHighRdy, 0, OSPrioCur,OSPrioHighRdy,0 ); 14 15 OSTCBCur = OSTCBHighRdy; 16 OSPrioCur = OSPrioHighRdy; 17 SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr; 18 19 ResumeThread(SS_SP->Handle); 20 }
这个函数的具体实现,在不一样平台是不同的。这儿先不分解,等到学习移植的时候在看。
六、结束
至此,中断管理第一部分完结,下一节涉及时间管理。