uC/OS-II的任务切换归根到底都是由以下三个函数引起的: - OSStart();
- OSIntExit();
- OS_Sched();
一、OSStart(): OSStart()函数是uC/OS-II任务调度的引导函数,它调用更底层的函数OSStartHighRdy()来完成最初的任务切换;OSStartHighRdy()唯一地在OSStart()函数中被调用。OSStart()函数代码如下: /**********************************************************/ void OSStart (void) { INT8U y; INT8U x; if (OSRunning == FALSE) { y = OSUnMapTbl[OSRdyGrp]; x = OSUnMapTbl[OSRdyTbl[y]]; OSPrioHighRdy = (INT8U)((y << 3) + x); OSPrioCur = OSPrioHighRdy; OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSTCBCur = OSTCBHighRdy; OSStartHighRdy(); } } /**********************************************************/ 而OSStartHighRdy()函数需要用户移植实现,主要的工作是: - OSRunning = TRUE;
- 调用OSTaskSwHook()函数;
- 设置处理器的堆栈指针寄存器为 OSTCBHighRdy->OSTCBStkPtr;
- 恢复所有处理器的寄存器内容(不包括堆栈指针寄存器和PC寄存器);
- 恢复PC寄存器并开始执行PC指向的指令。
二、OSIntExit(): OSIntExit()函数由中断服务代码调用,用户的中断服务代码要求如下: - 把全部CPU寄存器(包括堆栈指针寄存器和PC寄存器)推入当前任务堆栈;
- 调用OSIntEnter()函数或OSIntNesting++;
- 执行用户的中断处理代码;
- 调用OSIntExit()。
OSIntExit()函数调用更底层的函数OSIntCtxSw()来实现任务切换,而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) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]); if (OSPrioHighRdy != OSPrioCur) { OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; OSIntCtxSw(); } } OS_EXIT_CRITICAL(); } } /**********************************************************/ 函数OSIntCtxSw()需要用户移植实现,主要内容如下: - 调用OSTaskSwHook()函数;
- OSPrioCur = OSPrioHighRdy;
- OSTCBCur = OSTCBHighRdy;
- 设置处理器的堆栈指针寄存器为 OSTCBHighRdy->OSTCBStkPtr;
- 恢复所有处理器的寄存器内容(不包括堆栈指针寄存器和PC寄存器);
- 恢复PC寄存器并开始执行PC指向的指令。
三、OS_Sched(): OS_Sched()函数被各种任务间通信函数如xxxPost()和xxxPend()调用,OS_Sched()函数调用更底层的函数OS_TASK_SW()来实现任务切换,OS_Sched()函数的源代码如下: /**********************************************************/ void OS_Sched (void) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif INT8U y; OS_ENTER_CRITICAL(); if ((OSIntNesting == 0) && (OSLockNesting == 0)) { y = OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); if (OSPrioHighRdy != OSPrioCur) { OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; OS_TASK_SW(); } } OS_EXIT_CRITICAL(); } /**********************************************************/ OS_TASK_SW()函数需要用户移植实现,主要内容如下: - 把全部CPU寄存器(包括堆栈指针寄存器和PC寄存器)推入当前任务堆栈;
- 调用OSTaskSwHook()函数;
- OSPrioCur = OSPrioHighRdy;
- OSTCBCur = OSTCBHighRdy;
- 设置处理器的堆栈指针寄存器为 OSTCBHighRdy->OSTCBStkPtr;
- 恢复所有处理器的寄存器内容(不包括堆栈指针寄存器和PC寄存器);
- 恢复PC寄存器并开始执行PC指向的指令。
|