新聞中心

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

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

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

OSTaskStkInit()

OSTaskCreateHook()

OSTaskDelHook()

OSTaskSwHook()

OSTaskStatHook()

OSTimeTickHook()

實際需要修改的只有OSTaskStkInit()函數(shù),其他五個函數(shù)需要聲明,但不一定有實際內(nèi)容。這五個函數(shù)都是用戶定義的,所以O(shè)S_CPU_C.C中沒有給出代碼。如果用戶需要使用這些函數(shù),請將文件OS_CFG.H中的#define constant OS_CPU_HOOKS_EN設(shè)為1,設(shè)為0表示不使用這些函數(shù)。

程序清單L 9.9 18.2Hz 的OSTickISR()函數(shù).

_OSTickISRPROCFAR

;

PUSHA; 保存被中斷任務(wù)的CPU環(huán)境

PUSHES

PUSHDS

;

MOVAX,SEG_OSIntNesting;載入 DS

MOVDS,AX

;

INCBYTEPTR_OSIntNesting;標示uC/OS-II進入中斷

;

INT081H; 調(diào)用DOS的時鐘中斷處理函數(shù)

;

CALLFARPTR_OSTimeTick; 調(diào)用OSTimeTick()函數(shù)

;

CALLFARPTR_OSIntExit;標示uC/OS-IIof中斷結(jié)束

;

POPDS; 恢復被中斷任務(wù)的CPU環(huán)境

POPES

POPA

;

IRET; 返回被中斷任務(wù)

;

_OSTickISRENDP

圖F9.7 傳遞參數(shù) pdata的堆棧初始化結(jié)構(gòu)

9.05.01 OSTaskStkInit()

該函數(shù)由OSTaskCreate()或OSTaskCreateExt()調(diào)用,用來初始化任務(wù)的堆棧。初始狀態(tài)的堆棧模擬發(fā)生一次中斷后的堆棧結(jié)構(gòu)。圖F9.7說明了OSTaskStkInit()初始化后的堆棧內(nèi)容。請注意,圖中的堆棧結(jié)構(gòu)不是調(diào)用OSTaskStkInit()任務(wù)的,而是新創(chuàng)建任務(wù)的。

當調(diào)用OSTaskCreate()或OSTaskCreateExt()創(chuàng)建一個新任務(wù)時,需要傳遞的參數(shù)是:

任務(wù)代碼的起使地址,參數(shù)指針(pdata),任務(wù)堆棧頂端的地址,任務(wù)的優(yōu)先級。

OSTaskCreateExt()還需要一些其他參數(shù),但與OSTask StkInit()沒有關(guān)系。

OSTaskStkInit()(程序清單L9.10)只需要以上提到的3個參數(shù)(task,pdata,和ptos)。

程序清單L 9.10 OSTaskStkInit().

void*OSTaskStkInit(void(*task)(void*pd),void*pdata,void*ptos,INT16Uopt)

{

INT16U*stk;

opt=opt;/*'opt'未使用,此處可防止編譯器的警告 */

stk=(INT16U*)ptos;/* 載入堆棧指針 (1)*/

*stk--=(INT16U)FP_SEG(pdata);/* 放置向函數(shù)傳遞的參數(shù) (2)*/

*stk--=(INT16U)FP_OFF(pdata);

*stk--=(INT16U)FP_SEG(task);/* 函數(shù)返回地址(3)*/

*stk--=(INT16U)FP_OFF(task);

*stk--=(INT16U)0x0202;/*SW 設(shè)置為中斷開啟 (4)*/

*stk--=(INT16U)FP_SEG(task);/* 堆棧頂端放置指向任務(wù)代碼的指針*/

*stk--=(INT16U)FP_OFF(task);

*stk--=(INT16U)0xAAAA;/*AX=0xAAAA(5)*/

*stk--=(INT16U)0xCCCC;/*CX=0xCCCC*/

*stk--=(INT16U)0xDDDD;/*DX=0xDDDD*/

*stk--=(INT16U)0xBBBB;/*BX=0xBBBB*/

*stk--=(INT16U)0x0000;/*SP=0x0000*/

*stk--=(INT16U)0x1111;/*BP=0x1111*/

*stk--=(INT16U)0x2222;/*SI=0x2222*/

*stk--=(INT16U)0x3333;/*DI=0x3333*/

*stk--=(INT16U)0x4444;/*ES=0x4444*/

*stk=_DS;/*DS=當前CPU的 DS寄存器 (6)*/

return((void*)stk);

}

由于80x86堆棧是16位寬的(以字為單位)[程序清單L9.10(1)],OSTaskStkInit()將創(chuàng)立一個指向以字為單位內(nèi)存區(qū)域的指針。同時要求堆棧指針指向空堆棧的頂端。

筆者使用的BorlandC/C++編譯器配置為用堆棧而不是寄存器來傳送參數(shù)pdata,此時參數(shù)pdata的段地址和偏移量都將被保存在堆棧中[程序清單L9.10(2)]。

堆棧中緊接著是任務(wù)函數(shù)的起始地址[程序清單L9.10(3)],理論上,此處應(yīng)該為任務(wù)的返回地址,但在μC/OS-II中,任務(wù)函數(shù)必須為無限循環(huán)結(jié)構(gòu),不能有返回點。

返回地址下面是狀態(tài)字(SW)[程序清單L9.10(4)], 設(shè)置狀態(tài)字也是為了模擬中斷發(fā)生后的堆棧結(jié)構(gòu)。堆棧中的SW初始化為0x0202,這將使任務(wù)啟動后允許中斷發(fā)生;如果設(shè)為0x0002,則任務(wù)啟動后將禁止中斷。需要注意的是,如果選擇任務(wù)啟動后允許中斷發(fā)生,則所有的任務(wù)運行期間中斷都允許;同樣,如果選擇任務(wù)啟動后禁止中斷,則所有的任務(wù)都禁止中斷發(fā)生,而不能有所選擇。

如果確實需要突破上述限制,可以通過參數(shù)pdata向任務(wù)傳遞希望實現(xiàn)的中斷狀態(tài)。如果某個任務(wù)選擇啟動后禁止中斷,那么其他的任務(wù)在運行的時候需要重新開啟中斷。同時還要修改OSTaskIdle()和OSTaskStat()函數(shù),在運行時開啟中斷。如果以上任何一個環(huán)節(jié)出現(xiàn)問題,系統(tǒng)就會崩潰。所以筆者還是推薦用戶設(shè)置SW為0x0202,在任務(wù)啟動時開啟中斷。

堆棧中還要留出各個寄存器的空間,注意寄存器在堆棧中的位置要和運行指令PUSHA,PUSHES,和PUSHDS和壓入堆棧的次序相同。 上述指令在每次進入中斷服務(wù)程序時都會調(diào)用[程序清單L9.10(5)]。AX,BX,CX,DX,SP,BP,SI,和DI的次序是和指令PUSHA的壓棧次序相同的。如果使用沒有PUSHA指令的8086處理器,就要使用多個PUSH指令壓入上述寄存器,且順序要與PUSHA相同。 在程序清單L9.10中每個寄存器被初始化為不同的值, 這是為了調(diào)試方便。

Borland編譯器支持偽寄存器變量操作,可以用_DS關(guān)鍵字取得CPUDS寄存器的值,程序清單

L9.10中(6)標記處用_DS直接把DS寄存器拷貝到堆棧中。

堆棧初始化工作結(jié)束后,OSTaskStkInit()返回新的堆棧棧頂指針,OSTaskCreate()或

OSTaskCreateExt()將指針保存在任務(wù)的OS_TCB中。

9.05.02 OSTaskCreateHook()

OS_CPU_C.C中未定義,此函數(shù)為用戶定義。

9.05.03 OSTaskDelHook()

OS_CPU_C.C中未定義,此函數(shù)為用戶定義。

9.05.04 OSTaskSwHook()

OS_CPU_C.C中未定義,此函數(shù)為用戶定義。其用法請參考例程3。

9.05.05 OSTaskStatHook()



關(guān)鍵詞:

評論


相關(guān)推薦

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

關(guān)閉