MC68K的C編譯器實(shí)現(xiàn)μC/OS-II向MC68K移值解析方案
3.OS_CPU32.ASM文件
μC/OS-II的移植需要用戶改寫OS_CPU_A.ASM中的4個(gè)函數(shù):OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()和OSTickISR()。
(1)OSStartHighRdy()函數(shù)
該函數(shù)由OSStart()函數(shù)調(diào)用,功能是運(yùn)行優(yōu)先級最高的就緒態(tài)任務(wù)。在調(diào)用OSStart() 之前,用戶必須先調(diào)用OSInit(),并且已經(jīng)至少創(chuàng)建了一個(gè)任務(wù)。為啟動(dòng)任務(wù),OSStartHighRdy()首先找到當(dāng)前就緒的優(yōu)先級最高的任務(wù),OSTCBHighRdy中保存有優(yōu)先級最高任務(wù)的任務(wù)控制塊(TCB)的地址,并從任務(wù)的任務(wù)控制塊中找到指向堆棧的指針,然后運(yùn)行指令 MOVEM.L(A7)+,A0-A6/D0-D7,從堆棧中彈出全部寄存器的內(nèi)容,運(yùn)行RTE中斷返回。由于任務(wù)創(chuàng)建時(shí)堆棧的結(jié)構(gòu)就是按中斷捕撈堆棧結(jié)構(gòu)初始化的,執(zhí)行RET指令后就切換到了新任務(wù)。有關(guān)μC/OS- II的任務(wù)切換機(jī)制,請參考系列計(jì)座(3).
OSStartHighRdy的匯編代碼如下:
_OSStarHighRdy
MOVE.L(_OSTCBHighRdy),A1
;獲取最高優(yōu)先級就緒任務(wù)的TCB地址
MOVE.L A1,(_OSTCBCur)
MOVE.L (A1),A7 ;取得堆棧指針
MOVEM.L (A7)+,A0-A6/D0-D7
RTE ;中斷返回,切換任務(wù)
(2)OSCtxSw( )函數(shù)
OSCtxSw( )是一個(gè)任務(wù)級的任務(wù)切換函數(shù)(在任務(wù)中調(diào)用,區(qū)別于在中斷程序中調(diào)用的OSIntCtxSw(),在MC68K系統(tǒng)上,通過執(zhí)行一條軟中斷指令來實(shí)現(xiàn)任務(wù)切換。軟中斷向量指向函數(shù),而該函數(shù)的執(zhí)行結(jié)構(gòu)可能造成系統(tǒng)任務(wù)重新調(diào)度(例如,試圖喚醒一個(gè)優(yōu)先級更高的任務(wù)),則在函數(shù)的末尾會(huì)調(diào)用OSSched (),OSSched()將查找當(dāng)前就緒的優(yōu)先級最高的任務(wù)。如果不是當(dāng)前任務(wù),則判斷是否需要進(jìn)行任務(wù)調(diào)度,再找到該任務(wù)控制塊OS_TCB的地址,并將該地址拷貝到變量OSTCBHighRdy中,然后通過寵OS_TASK_SW()執(zhí)行軟中斷,進(jìn)行任務(wù)切換。在此過程中,變量OSTCBCur始終包含一個(gè)指向當(dāng)前運(yùn)行任務(wù)OS_TCB的指針。OSCtxSw()的匯編代碼如下:
_OSCtxSw
MOVEM.L A0-A6/D0-D7,-(A7) ;存儲當(dāng)前任務(wù)環(huán)境
MOVE.L (_OSTCBCur),A1 ;保存當(dāng)前任務(wù)TCB指針
MOVE.L A7,(A1)
MOVE.L (_OSTCBHighRdy),A1 ;獲取最高優(yōu)先級就緒任務(wù)的TCB地址
MOVE.L A1,(_OSTCBCur) ;將就緒任務(wù)設(shè)置為當(dāng)前運(yùn)行任務(wù)
MOVE.L (A1),A7 ;取得新任務(wù)的堆棧指針
MOVEM.L (A7)+,A0-A6/D0-D7 ;
RTE ;中斷返回,切換任務(wù)
(3)OSIntCtxSw()函數(shù)
在μC/OS -II中,由于中斷的產(chǎn)生可能會(huì)引起任務(wù)切換,在中斷服務(wù)程序的最后會(huì)調(diào)用OSICntExit()函數(shù)檢查任務(wù)就緒狀態(tài)。如果需要進(jìn)行任務(wù)切換,將調(diào)用 OSIntCtxSw(),所以,OSIntCtxSw()又稱為中斷級的任務(wù)切換函數(shù)。由于在調(diào)用OSIntCtxSw()之前已經(jīng)發(fā)生了中斷, OSIntCtxSw()默認(rèn)CPU寄存器已經(jīng)保存在被中斷任務(wù)的堆棧了。OSIntCtxSw()的代碼與OSCtxSw()的大部分相同,不同之處是:第一,由于中斷已經(jīng)發(fā)生,此處不需要再保存CPU寄存器;第二,OSIntCtxSw()需要調(diào)整堆棧指針,去掉堆棧中一些不需要的內(nèi)容,以使堆棧中包含任務(wù)的運(yùn)行環(huán)境。
_OSIntCtxSw
ADDA #10,A7 ;忽略掉由于函數(shù)嵌套調(diào)
;用而壓入堆棧的內(nèi)容
MOVE.L (_CSTCBCur),A1 ;在TCB中保存當(dāng)前
;任務(wù)的堆棧指針
MOVE.L A7,(A1)
MOVE.L (_OSTCBHighRdy),A1
;獲取最高優(yōu)先級就緒任務(wù)的TCB地址
MOVE.L A1,(_OSTCBCur) ;將就緒任務(wù)設(shè)備為當(dāng)前
;運(yùn)行任務(wù)
MOVE.L (A1),A7 ;取得堆棧指針
MOVEM.L (A7)+,A0-A6/D0-D7 ;
RTE ;中斷返回,切換任務(wù)
(4)OSTickISR()函數(shù)
在μC/OS-II中,當(dāng)調(diào)用OSStart()啟動(dòng)多任務(wù)環(huán)境后,時(shí)鐘中斷非常重要。在時(shí)鐘中斷中處理所有與定時(shí)相關(guān)的工作,如任務(wù)的延時(shí)、等待操作等等。在時(shí)鐘中斷中將查詢處于等待狀態(tài)的任務(wù),判斷是否延時(shí)結(jié)束,以重新進(jìn)行任務(wù)調(diào)度。
評論