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()函數期間,中斷是禁止的。
OSCtxSw()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.