OSCtxSw()

OSCtxSw()是一个任务级的任务切换函数(在任务中调用,区别于在中断程序中调用的OSIntCtxSw())。在80x86系统上,它通过执行一条软中断的指令来实现任务切换。软中断向量指向OSCtxSw()。在µC/OS-II中,如果任务调用了某个函数,而该函数的执行结果可能造成系统任务重新调度(例如试图唤醒了一个优先级更高的任务),则在函数的末尾会调用OSSched(),如果OSSched()判断需要进行任务调度,会找到该任务控制块OS_TCB的地址,并将该地址拷贝到OSTCBHighRdy,然后通过宏OS_TASK_SW()执行软中断进行任务切换。注意到在此过程中,变量OSTCBCur始终包含一个指向当前运行任务OS_TCB的指针。程序清单L9.4为OSCtxSw()的代码。
图F9.4是任务被挂起或被唤醒时的堆栈结构。在80x86处理器上,任务调用OS_TASK_SW()执行软中断指令后[图F9.4/程序清单L9.4(1)],先向堆栈中压入返回地址(段地址和偏移量),然后是状态字寄存器SW。紧接着用PUSHA [图F9.4/程序清单L9.4(2)], PUSH ES [图F9.4/程序清单L9.4(3)],和 PUSH DS [图F9.4/程序清单L9.4(4)]保存任务运行环境。最后用OSCtxSw()在任务OS_TCB中保存SS和SP寄存器。
任务环境保存完后,将调用用户定义的对外接口函数OSTaskSwHook()[程序清单L9.4(6)]。请注意,此时OSTCBCur指向当前任务OS_TCB,OSTCBHighRdy指向新任务的OS_TCB。在OSTaskSwHook()中,用户可以访问这两个任务的OS_TCB。如果不使用对外接口函数,请在头文件中把相应的开关选项关闭,加快任务切换的速度。

程序清单L 9.4	OSCtxSw().
_OSCtxSw    PROC   FAR                     	(1)
;
    PUSHA                                 ; 保存当前任务环境	(2)
    PUSH ES                                	(3)
    PUSH DS                               	(4)
;
    MOV  AX, SEG _OSTCBCur                ; 载入DS
    MOV  DS, AX                            
;
    LES  BX, DWORD PTR DS:_OSTCBCur       ; OSTCBCur->OSTCBStkPtr = SS:S	(5)
    MOV  ES:[BX+2], SS                     
    MOV  ES:[BX+0], SP                     
;
    CALL FAR PTR _OSTaskSwHook	(6)
;
    MOV  AX, WORD PTR DS:_OSTCBHighRdy+2  ; OSTCBCur = OSTCBHighRdy	(7)
    MOV  DX, WORD PTR DS:_OSTCBHighRdy       
    MOV  WORD PTR DS:_OSTCBCur+2, AX         
    MOV  WORD PTR DS:_OSTCBCur, DX            
;
    MOV  AL, BYTE PTR DS:_OSPrioHighRdy   ; OSPrioCur = OSPrioHighRdy	(8)
    MOV  BYTE PTR DS:_OSPrioCur, AL            
;
    LES  BX, DWORD PTR DS:_OSTCBHighRdy   ; SS:SP = OSTCBHighRdy->OSTCBStkPtr	(9)
    MOV  SS, ES:[BX+2]                    
    MOV  SP, ES:[BX]                      
;
    POP  DS                               ; 载入新任务的CPU环境	(10)
    POP  ES                            	(11)
    POPA                                 	(12)
;
    IRET                                  ; 返回新任务	(13)
;
_OSCtxSw    ENDP

从对外接口函数OSTaskSwHook()返回后,由于任务的更替,变量OSTCBHighRdy被拷贝到OSTCBCur中[程序清单L9.4(7)],同样,OSPrioHighRdy被拷贝到OSPrioCur中[程序清单L9.4(8)]。OSCtxSw()将载入新任务的CPU环境,首先从新任务OS_TCB中取出SS和SP寄存器的值[图F9.4(6)/程序清单L9.4(9)],然后运行POP DS [图F9.4(7)/程序清单L9.4(10)], POP ES [图F9.4(8)/程序清单L9.4(11)], POPA [图F9.4(9)/程序清单L9.4(12)]取出其他寄存器的值,最后用中断返回指令IRET [图F9.4(10)/ L9.4(13)]完成任务切换。
需要注意的是在运行OSCtxSw()和OSTaskSwHook()函数期间,中断是禁止的。

你可能感兴趣的:(ucos-ii)