新聞中心

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

        在MC68HC908GP32上移植μC/OS-II

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

        (2)代碼臨界區(qū)

        μC/OS-II在進入系統(tǒng)臨界代碼區(qū)之前要關閉中斷,等到退出臨界區(qū)后再打開,從而保護核心數據不被多任務環(huán)境下的其他任務或中斷破壞。在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()用來實現任務切換。就緒任務的堆棧初始化應該模擬一次中斷發(fā)生后的樣子,堆棧中應該按進棧次序設置好各個寄存器的內容。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()函數調用,功能是運行優(yōu)先級最高的就緒任務。在調用 OSStart()之前,必須先調用OSInit(),并且已經至少創(chuàng)建了一個任務。為了啟動任務,OSStartHighRdy()首先找到當前就緒的優(yōu)先級最高的任務(OSTCBHighRdy中保存有優(yōu)先級最高任務的任務控制塊-TCB的地址),并從任務的任務控制塊(OS_TCB)中找到指向堆棧的指針,然后從堆棧中彈出全部寄存器的內容,運行RTE中斷返回。由于任務創(chuàng)建時堆棧的結構就是按中斷后的堆棧結構初始化的,執(zhí)行RET指令后就切換到新任務(有關μC/OS-II的任務切換機制,請參考系列講座的第2講)。對于OSStartHighRdy的代碼,我們采用在C中嵌入匯編的方法編寫。需要說明的是,由于GP32中有512字節(jié)RAM,所以地址指針必須是16位的;而GP32中累加寄存器A為8位,所以用累加器A傳遞地址必須進行兩次讀入、輸出操作。

        Void OSStartHighRdy(void)

        {asm

        {

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

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

        inca

        sta OSRunning

        ldx OSTCBHighRdy //取得最高優(yōu)先級就緒任務TCB地址

        stx OSTCBCur //保存到OSTCBCur中

        pshx

        ldx OSTCBHighRdy:1//保存地址的第二個字節(jié)

        stx OSTCBCur:1

        pulh

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

        psha

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

        pulh

        txs

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

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

        }}

        (2)OSCtxSw()函數

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

        Void OSCtxSw(void)

        {asm

        {pshh //保存X寄存器

        tsx

        pshx

        pshh

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

        pshx

        ldx OSTCBCur:1 //載入TCB的第二個字節(jié)

        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()啟動多任務環(huán)境后,時鐘中斷的使用是非常重要的。在時鐘中斷程序中負責處理所有與定時相關的工作,如任務的延時、等待操作等等。在時鐘中斷中將查詢處于等待狀態(tài)的任務,判斷是否延時結束,否則將重新進行任務調度。

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

        void OSTickISR()void{

        asm{

        pshh

        LDA T1SC

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

        }

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

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

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

        Asm{

        Pulh

        Rti

        }}

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



        關鍵詞:

        評論


        相關推薦

        技術專區(qū)

        關閉
        主站蜘蛛池模板: 略阳县| 仙桃市| 东阳市| 华安县| 宜州市| 金溪县| 河北区| 陇川县| 霞浦县| 中江县| 汉阴县| 桃园县| 新龙县| 凉山| 林口县| 江都市| 鹰潭市| 芦溪县| 徐汇区| 丰镇市| 苏尼特左旗| 大足县| 永寿县| 南乐县| 甘肃省| 南平市| 尼木县| 南阳市| 南木林县| 桓台县| 涞源县| 莲花县| 顺义区| 朝阳市| 犍为县| 改则县| 申扎县| 小金县| 会宁县| 通州区| 娄烦县|