久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > 在MC68HC908GP32上移植μC/OS-II

在MC68HC908GP32上移植μC/OS-II

作者: 時間:2016-09-12 來源:網絡 收藏

(2)代碼臨界區

μC/OS-II在進入系統臨界代碼區之前要關閉中斷,等到退出臨界區后再打開,從而保護核心數據不被多任務環境下的其他任務或中斷破壞。在GP32中,開關中斷可以通過匯編指令CLI和SEI來實現。所以μC/OS-II中的宏OS_ENTER_CRITICAL()定義為指令SEI,OS_EXIT_CRITICAL()定義為指令CLI。

(3)堆棧增長方向

GP32的堆棧是由高地址向低地址方向增長的,所以常量OS_STK_GPOWTH必須設置為1。

(4)OS_TASK_SW()函數的定義

在μC/OS-II中,OS_TASK_SW()用來實現任務切換。就緒任務的堆棧初始化應該模擬一次中斷發生后的樣子,堆棧中應該按進棧次序設置好各個寄存器的內容。OS_TASK_SW()函數模擬一次中斷過程,在中斷返回的時候進行任務切換。GP32中可采用軟中斷指令SWI實現任務切換。中斷服務程序的入口點必須指向匯編函數OSCtxSw()。

OS_TASK_SW()的定義:

#define OS_TASK_SW() asm swi

3.OS_CPU08.ASM文件

μC/OS-II的移植需要改寫OS_CPU08.ASM中的4個函數:OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()和OSTickISR()。

(1)OSStartHighRdy()函數

該函數由SStart()函數調用,功能是運行優先級最高的就緒任務。在調用 OSStart()之前,必須先調用OSInit(),并且已經至少創建了一個任務。為了啟動任務,OSStartHighRdy()首先找到當前就緒的優先級最高的任務(OSTCBHighRdy中保存有優先級最高任務的任務控制塊-TCB的地址),并從任務的任務控制塊(OS_TCB)中找到指向堆棧的指針,然后從堆棧中彈出全部寄存器的內容,運行RTE中斷返回。由于任務創建時堆棧的結構就是按中斷后的堆棧結構初始化的,執行RET指令后就切換到新任務(有關μC/OS-II的任務切換機制,請參考系列講座的第2講)。對于OSStartHighRdy的代碼,我們采用在C中嵌入匯編的方法編寫。需要說明的是,由于GP32中有512字節RAM,所以地址指針必須是16位的;而GP32中累加寄存器A為8位,所以用累加器A傳遞地址必須進行兩次讀入、輸出操作。

Void OSStartHighRdy(void)

{asm

{

jsr OSTaskSwHook //調用用戶定義接口函數

lda OSRunning //設置OSRunning變量,標志進入多任務模式

inca

sta OSRunning

ldx OSTCBHighRdy //取得最高優先級就緒任務TCB地址

stx OSTCBCur //保存到OSTCBCur中

pshx

ldx OSTCBHighRdy:1//保存地址的第二個字節

stx OSTCBCur:1

pulh

lda 0,X //載放就緒任務堆棧指針

psha

ldx 1,X //載入就緒任務堆棧指針第二個字節

pulh

txs

pulh //恢復索引寄存器內容

rti //中斷返回,運行新任務

}}

(2)OSCtxSw()函數

OSCtxSw()是一個任務級的任務切換函數(在任務中調用,區別于在中斷程序中調用的OSIntCtxSw())。在GP32上實現,可通過執行一條軟中斷指令SWI來實現任務切換。軟中斷向量指向OSCtxSw()。在 μC/OS-II中,如果任務調用了某個函數,而該函數的執行結果可能造成系統任務新調度(例如試圖喚醒一個優先級更高的任務),則在函數的末尾會調用 OSSched();如果OSSched()將查找當前就緒的優先級最高的任務,若不是當前任務,則判斷是否需要進行任務調度,并找到該任務控制塊 OS_TCB的地址,將該地址拷貝到變量OSTCBHighRdy中,然后通過宏OS_TASK_SW()執行軟中斷進行任務切換。在此過程中,變量 OSTCBCur始終包含一個指向當前運行任務OS_TCB的指針。OSCtxSw()的匯編代碼如下:

Void OSCtxSw(void)

{asm

{pshh //保存X寄存器

tsx

pshx

pshh

dx OSTCBCur //載入當前任務的TCB指針

pshx

ldx OSTCBCur:1 //載入TCB的第二個字節

pulh

pula

sta 0,x //保存當前堆棧指針

pula

sta 1,x

jsr OSTaskSwHook //調用用戶定義的接口函數

lda OSPrioHighRdy //設置OSPrioCur=OSPrioHighRdy

sta OSPrioCur

pshx

ldx OSTCBHighRdy:1

stx OSTCBCur:1

pulh

lda 0,x //載入堆棧指針

psha

ldx,1,x

pulh

txs

pulh //恢復索引寄存器內容

rti //中斷返回,切換任務

}}

(4)OSTickISR()函數

在μC/OS-II中,當調用OSStart()啟動多任務環境后,時鐘中斷的使用是非常重要的。在時鐘中斷程序中負責處理所有與定時相關的工作,如任務的延時、等待操作等等。在時鐘中斷中將查詢處于等待狀態的任務,判斷是否延時結束,否則將重新進行任務調度。

為GP32編寫的函數OSTickISR()的代碼如下:

void OSTickISR()void{

asm{

pshh

LDA T1SC

BCLR 7,T1SC //允許中斷嵌套

}

OsintEnter(); /*標志進入中斷*/

OSTimeTick(); /*調用時鐘節拍函數*/

OSlntExit(); /*標志退出中斷*/

Asm{

Pulh

Rti

}}

和μC/OS-II中的其他中斷服務程序一樣,OSTickISR()首先在被中斷任務堆棧中保存CPU寄存器的值,然后調用OSIntEnter()。μC/OS-II要求在中斷服務程序開頭調用OSIntEnter(),其作用是將記錄中斷嵌套層數的全局變量OSIntNesting加1。如果不調用OSIntEnter(),直接將OSIntNesting加1也是允許的。隨后,OSTickISR()調用OSTimeTick(),檢查所有處于延時等待狀態的任務,判斷是否有延時結束就緒的任務。在OSTickISR()的最后調用OSIntExit(),如果在中斷中(或其他嵌套的中斷)有更高優先級的任務就緒,并且當前中斷為中斷嵌套的最后一層,OSIntExit() 將進行任務調度。注意:如果進行了任務調度,OSIntExit()將不同志返回調用者,而是用新任務的堆棧中的寄存器數值恢復CPU現場,然后用 IRET實現任務切換。如果當有中斷不是中斷嵌套的最后一層,或中斷中沒有改變任務的就緒狀態,OSIntExit()將返回調用者 OSTickISR(),最后OSTickISR()返回被中斷的任務。



關鍵詞:

評論


相關推薦

技術專區

關閉