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

新聞中心

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

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

作者: 時間:2016-10-08 來源:網絡 收藏

OSIntExit()函數檢查任務就緒狀態,如果需要進行任務切換,將調用OSIntCtxSw()。所以

OSIntCtxSw()又稱為中斷級的任務切換函數。由于在調用OSIntCtxSw()之前已經發生了中斷,

OSIntCtxSw()將默認CPU寄存器已經保存在被中斷任務的堆棧中了。

圖F 9.4 任務級任務切換時的80x86堆棧結構.

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

經發生, 此處不需要再保存CPU寄存器 (沒有PUSHA,PUSHES,或PUSHDS) ; 第二, OSIntCtxSw()需要調整堆棧指針,去掉堆棧中一些不需要的內容,以使堆棧中只包含任務的運行環境。圖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; 載入新任務的CPU環境 (7)

POPES (8)

POPA (9)

;

IRET; 返回新任務 (10)

;

_OSIntCtxSwENDP

圖F 9.5 中斷級任務切換時的80x86堆棧結構

當中斷發生后,CPU在完成當前指令后,進入中斷處理過程。首先是保存現場,將返回地址

壓入當前任務堆棧,然后保存狀態寄存器的內容。接下來CPU從中斷向量處找到中斷服務程序的

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

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

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

就緒狀態的改變而需要任務切換,例如調用了OSMboxPost(),OSQPostFront(),OSQPost(),或試

圖喚醒一個優先級更高的任務(調用OSTaskResume()),還可能調用OSTimeTick(),

OSTimeDlyResume()等等。

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

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

進入OSIntExit()后,由于要訪問臨界代碼區,首先關閉中斷。由于OS_ENTER_CRITICAL()可

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

確實要進行任務切換,指針OSTCBHighRdy將指向新的就緒任務的OS_TCB,OSIntExit()會調用

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

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

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

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

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

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

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

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

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

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

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

當當前任務的現場保存完畢后,用戶定義的對外接口函數OSTaskSwHook()會被調用[程序清

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

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

件中關閉相應的開關選項,提高任務切換的速度。

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

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

L9.5(5)]。此時,OSIntCtxSw()將載入新任務的CPU環境,首先從新任務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)]取出其他寄存器

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

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

9.04.04 OSTickISR()

在9.03.05節中,我們已經提到過實時系統中時鐘節拍發生頻率的問題,應該在10到100Hz



關鍵詞:

評論


相關推薦

技術專區

關閉