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()函數期間,中斷是禁止的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章