新聞中心

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

        μC/OS-II在80x86上的移植

        作者: 時間:2016-10-08 來源:網(wǎng)絡(luò) 收藏

        OSIntExit()函數(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ù)的堆棧中了。

        圖F 9.4 任務(wù)級任務(wù)切換時的80x86堆棧結(jié)構(gòu).

        程序清單L9.5給出的代碼大部分與OSCtxSw()的代碼相同,不同之處是,第一,由于中斷已

        經(jīng)發(fā)生, 此處不需要再保存CPU寄存器 (沒有PUSHA,PUSHES,或PUSHDS) ; 第二, OSIntCtxSw()需要調(diào)整堆棧指針,去掉堆棧中一些不需要的內(nèi)容,以使堆棧中只包含任務(wù)的運行環(huán)境。圖F9.5可以幫助讀者理解這一過程。

        程序清單L 9.5 OSIntCtxSw().

        _OSIntCtxSwPROCFAR

        ;;IgnorecallstoOSIntExitandOSIntCtxSw

        ;ADDSP,8;(UncommentifOS_CRITICAL_METHODis1,seeOS_CPU.H)(1)

        ADDSP,10;(UncommentifOS_CRITICAL_METHODis2,seeOS_CPU.H)

        ;

        MOVAX,SEG_OSTCBCur; 載入DS

        MOVDS,AX

        ;

        LESBX,DWORDPTRDS:_OSTCBCur;OSTCBCur->OSTCBStkPtr=SS:SP(2)

        MOVES:[BX+2],SS

        MOVES:[BX+0],SP

        ;

        CALLFARPTR_OSTaskSwHook(3)

        ;

        MOVAX,WORDPTRDS:_OSTCBHighRdy+2;OSTCBCur=OSTCBHighRdy(4)

        MOVDX,WORDPTRDS:_OSTCBHighRdy

        MOVWORDPTRDS:_OSTCBCur+2,AX

        MOVWORDPTRDS:_OSTCBCur,DX

        ;

        MOVAL,BYTEPTRDS:_OSPrioHighRdy;OSPrioCur=OSPrioHighRdy(5)

        MOVBYTEPTRDS:_OSPrioCur,AL

        ;

        LESBX,DWORDPTRDS:_OSTCBHighRdy;SS:SP=OSTCBHighRdy-

        >OSTCBStkPtr (6)

        MOVSS,ES:[BX+2]

        MOVSP,ES:[BX]

        ;

        POPDS; 載入新任務(wù)的CPU環(huán)境 (7)

        POPES (8)

        POPA (9)

        ;

        IRET; 返回新任務(wù) (10)

        ;

        _OSIntCtxSwENDP

        圖F 9.5 中斷級任務(wù)切換時的80x86堆棧結(jié)構(gòu)

        當(dāng)中斷發(fā)生后,CPU在完成當(dāng)前指令后,進(jìn)入中斷處理過程。首先是保存現(xiàn)場,將返回地址

        壓入當(dāng)前任務(wù)堆棧,然后保存狀態(tài)寄存器的內(nèi)容。接下來CPU從中斷向量處找到中斷服務(wù)程序的

        入口地址,運行中斷服務(wù)程序。在μC/OS-II中,要求用戶的中斷服務(wù)程序在開頭保存CPU其他寄

        存器的內(nèi)容[圖F9.5(1)]。此后,用戶必須調(diào)用OSIntEnter()或著把全局變量OSIntNesting加1。

        此時,被中斷任務(wù)的堆棧中保存了任務(wù)的全部運行環(huán)境。在中斷服務(wù)程序中,有可能引起任務(wù)

        就緒狀態(tài)的改變而需要任務(wù)切換,例如調(diào)用了OSMboxPost(),OSQPostFront(),OSQPost(),或試

        圖喚醒一個優(yōu)先級更高的任務(wù)(調(diào)用OSTaskResume()),還可能調(diào)用OSTimeTick(),

        OSTimeDlyResume()等等。

        μC/OS-II要求用戶在中斷服務(wù)程序的末尾調(diào)用OSInt Exit(),以檢查任務(wù)就緒狀態(tài)。在調(diào)用

        OSInt Exit()后,返回地址會壓入堆棧中[圖F9.5(2)]。

        進(jìn)入OSIntExit()后,由于要訪問臨界代碼區(qū),首先關(guān)閉中斷。由于OS_ENTER_CRITICAL()可

        能有不同的操作(見9.03.02節(jié)),狀態(tài)寄存器SW的內(nèi)容有可能被壓入堆棧[圖F9.5(3)]。如果

        確實要進(jìn)行任務(wù)切換,指針OSTCBHighRdy將指向新的就緒任務(wù)的OS_TCB,OSIntExit()會調(diào)用

        OSIntCtxSw()完成任務(wù)切換。注意,調(diào)用OSIntCtxSw()會在再一次在堆棧中保存返回地址[圖

        F9.5(4)]。在進(jìn)行任務(wù)切換的時候,我們希望堆棧中只保留一次中斷發(fā)生的任務(wù)環(huán)境(如圖

        F9.5(1)),而忽略掉由于函數(shù)嵌套調(diào)用而壓入的一系列返回地址(圖F9.5(2),(3),(4))。忽

        略的方法也很簡單,只要把堆棧指針加一個固定的值就可以了[圖F9.5(5)/程序清單L9.5(1)]。

        如果用方法2實現(xiàn)OS_ENTER_CRITICAL(),這個固定值是10;如果用方法1,則是8。實際操作中

        還與編譯器以及編譯模式有關(guān)。例如,有些編譯器會為OSIntExit()在堆棧中分配臨時變量,這

        都會影響具體占用堆棧的大小,這一點需要提醒用戶注意。

        一但堆棧指針重新定位后,就被保存到將要被掛起的任務(wù)OS_TCB中[圖F9.5(6)/程序清單

        L9.5(2)]。在μC/OS-II中(包括μC/OS),OSIntCtxSw()是唯一一個與編譯器相關(guān)的函數(shù),也是

        用戶問的最多的。如果您的系統(tǒng)移植后運行一段時間后就會死機,就應(yīng)該懷疑是OSIntCtxSw()

        中堆棧指針重新定位的問題。

        當(dāng)當(dāng)前任務(wù)的現(xiàn)場保存完畢后,用戶定義的對外接口函數(shù)OSTaskSwHook()會被調(diào)用[程序清

        單L9.5(3)]。注意到OSTCBCur指向當(dāng)前任務(wù)的OS_TCB,OSTCBHighRdy指向新任務(wù)的OS_TCB。在

        函數(shù)OSTaskSwHook()中用戶可以訪問這兩個任務(wù)的OS_TCB。如果不用對外接口函數(shù),請在頭文

        件中關(guān)閉相應(yīng)的開關(guān)選項,提高任務(wù)切換的速度。

        從對外接口函數(shù)OSTaskSwHook()返回后,由于任務(wù)的更替,變量OSTCBHighRdy被拷貝到

        OSTCBCur中[程序清單L9.5(4)],同樣,OSPrioHighRdy被拷貝到OSPrioCur中[程序清單

        L9.5(5)]。此時,OSIntCtxSw()將載入新任務(wù)的CPU環(huán)境,首先從新任務(wù)OS_TCB中取出SS和SP寄

        存器的值[圖F9.5(7)/程序清單L9.5(6)],然后運行POPDS[圖F9.5(8)/程序清單L9.5(7)],

        POPES[圖F9.5(9)/程序清單L9.5(8)],POPA[圖F9.5(10)/程序清單L9.5(9)]取出其他寄存器

        的值,最后用中斷返回指令I(lǐng)RET[圖F9.5(11)/程序清單L9.5(10)]完成任務(wù)切換。

        需要注意的是在運行OSIntCtxSw()和用戶定義的OSTaskSwHook()函數(shù)期間,中斷是禁止的。

        9.04.04 OSTickISR()

        在9.03.05節(jié)中,我們已經(jīng)提到過實時系統(tǒng)中時鐘節(jié)拍發(fā)生頻率的問題,應(yīng)該在10到100Hz



        關(guān)鍵詞:

        評論


        相關(guān)推薦

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

        關(guān)閉
        主站蜘蛛池模板: 安溪县| 元江| 翁牛特旗| 尤溪县| 镇雄县| 平阳县| 太仆寺旗| 闸北区| 武定县| 渝北区| 大丰市| 南岸区| 镇安县| 曲阳县| 南召县| 蓝山县| 临高县| 景洪市| 元阳县| 紫金县| 信阳市| 乳山市| 浮山县| 堆龙德庆县| 杨浦区| 阜城县| 长阳| 英德市| 襄汾县| 红原县| 来凤县| 明水县| 江安县| 页游| 金门县| 措美县| 鸡东县| 郓城县| 永福县| 西充县| 会理县|