色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

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

          在MC68HC908GP32上移植μC/OS-II

          作者: 時(shí)間:2016-09-12 來源:網(wǎng)絡(luò) 收藏

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

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

          (3)堆棧增長方向

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

          (4)OS_TASK_SW()函數(shù)的定義

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

          OS_TASK_SW()的定義:

          #define OS_TASK_SW() asm swi

          3.OS_CPU08.ASM文件

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

          (1)OSStartHighRdy()函數(shù)

          該函數(shù)由SStart()函數(shù)調(diào)用,功能是運(yùn)行優(yōu)先級(jí)最高的就緒任務(wù)。在調(diào)用 OSStart()之前,必須先調(diào)用OSInit(),并且已經(jīng)至少創(chuàng)建了一個(gè)任務(wù)。為了啟動(dòng)任務(wù),OSStartHighRdy()首先找到當(dāng)前就緒的優(yōu)先級(jí)最高的任務(wù)(OSTCBHighRdy中保存有優(yōu)先級(jí)最高任務(wù)的任務(wù)控制塊-TCB的地址),并從任務(wù)的任務(wù)控制塊(OS_TCB)中找到指向堆棧的指針,然后從堆棧中彈出全部寄存器的內(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ī)制,請(qǐng)參考系列講座的第2講)。對(duì)于OSStartHighRdy的代碼,我們采用在C中嵌入?yún)R編的方法編寫。需要說明的是,由于GP32中有512字節(jié)RAM,所以地址指針必須是16位的;而GP32中累加寄存器A為8位,所以用累加器A傳遞地址必須進(jìn)行兩次讀入、輸出操作。

          Void OSStartHighRdy(void)

          {asm

          {

          jsr OSTaskSwHook //調(diào)用用戶定義接口函數(shù)

          lda OSRunning //設(shè)置OSRunning變量,標(biāo)志進(jìn)入多任務(wù)模式

          inca

          sta OSRunning

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

          stx OSTCBCur //保存到OSTCBCur中

          pshx

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

          stx OSTCBCur:1

          pulh

          lda 0,X //載放就緒任務(wù)堆棧指針

          psha

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

          pulh

          txs

          pulh //恢復(fù)索引寄存器內(nèi)容

          rti //中斷返回,運(yùn)行新任務(wù)

          }}

          (2)OSCtxSw()函數(shù)

          OSCtxSw()是一個(gè)任務(wù)級(jí)的任務(wù)切換函數(shù)(在任務(wù)中調(diào)用,區(qū)別于在中斷程序中調(diào)用的OSIntCtxSw())。在GP32上實(shí)現(xiàn),可通過執(zhí)行一條軟中斷指令SWI來實(shí)現(xiàn)任務(wù)切換。軟中斷向量指向OSCtxSw()。在 μC/OS-II中,如果任務(wù)調(diào)用了某個(gè)函數(shù),而該函數(shù)的執(zhí)行結(jié)果可能造成系統(tǒng)任務(wù)新調(diào)度(例如試圖喚醒一個(gè)優(yōu)先級(jí)更高的任務(wù)),則在函數(shù)的末尾會(huì)調(diào)用 OSSched();如果OSSched()將查找當(dāng)前就緒的優(yōu)先級(jí)最高的任務(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()的匯編代碼如下:

          Void OSCtxSw(void)

          {asm

          {pshh //保存X寄存器

          tsx

          pshx

          pshh

          dx OSTCBCur //載入當(dāng)前任務(wù)的TCB指針

          pshx

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

          pulh

          pula

          sta 0,x //保存當(dāng)前堆棧指針

          pula

          sta 1,x

          jsr OSTaskSwHook //調(diào)用用戶定義的接口函數(shù)

          lda OSPrioHighRdy //設(shè)置OSPrioCur=OSPrioHighRdy

          sta OSPrioCur

          pshx

          ldx OSTCBHighRdy:1

          stx OSTCBCur:1

          pulh

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

          psha

          ldx,1,x

          pulh

          txs

          pulh //恢復(fù)索引寄存器內(nèi)容

          rti //中斷返回,切換任務(wù)

          }}

          (4)OSTickISR()函數(shù)

          在μC/OS-II中,當(dāng)調(diào)用OSStart()啟動(dòng)多任務(wù)環(huán)境后,時(shí)鐘中斷的使用是非常重要的。在時(shí)鐘中斷程序中負(fù)責(zé)處理所有與定時(shí)相關(guān)的工作,如任務(wù)的延時(shí)、等待操作等等。在時(shí)鐘中斷中將查詢處于等待狀態(tài)的任務(wù),判斷是否延時(shí)結(jié)束,否則將重新進(jìn)行任務(wù)調(diào)度。

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

          void OSTickISR()void{

          asm{

          pshh

          LDA T1SC

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

          }

          OsintEnter(); /*標(biāo)志進(jìn)入中斷*/

          OSTimeTick(); /*調(diào)用時(shí)鐘節(jié)拍函數(shù)*/

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

          Asm{

          Pulh

          Rti

          }}

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



          關(guān)鍵詞:

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉