MicroC/OS-II在80C196上的移植實(shí)現(xiàn)

時(shí)間:2022-11-17 10:05:00

導(dǎo)語(yǔ):MicroC/OS-II在80C196上的移植實(shí)現(xiàn)一文來(lái)源于網(wǎng)友上傳,不代表本站觀點(diǎn),若需要原創(chuàng)文章可咨詢客服老師,歡迎參考。

MicroC/OS-II在80C196上的移植實(shí)現(xiàn)

摘要:在嵌入式系統(tǒng)中使用實(shí)時(shí)操作系統(tǒng),可以提高系統(tǒng)的穩(wěn)定性、可靠性和實(shí)時(shí)性。microc/os-ii是一個(gè)完整的,可移植、可固化、可剪裁的搶占式多任務(wù)實(shí)時(shí)內(nèi)核,并且開(kāi)放源代碼,得到了廣泛應(yīng)用。本文結(jié)合具體應(yīng)用,介紹了MicroC/OS-II在80c196移植實(shí)現(xiàn)過(guò)程和注意事項(xiàng)。

關(guān)鍵詞:實(shí)時(shí)操作系統(tǒng)MicroC/OS-II80C196移植

在嵌入式系統(tǒng)開(kāi)發(fā)中,很長(zhǎng)時(shí)間以來(lái),一直采用傳統(tǒng)的嵌入式系統(tǒng)軟件設(shè)計(jì)模式:無(wú)限循環(huán)+中斷服務(wù)。該模式下,主程序?yàn)橐粋€(gè)無(wú)限循環(huán),單任務(wù)順序執(zhí)行各個(gè)處理任務(wù)。在循環(huán)之外,設(shè)計(jì)一個(gè)或多個(gè)中斷服務(wù)函數(shù),用于處理異步事件。在相對(duì)簡(jiǎn)單的應(yīng)用中,這種模式,完全可以勝任。而對(duì)于實(shí)時(shí)性要求較高、處理任務(wù)較多的應(yīng)用,就會(huì)暴露出實(shí)時(shí)性差的缺點(diǎn),甚至不能夠達(dá)到應(yīng)用的要求,系統(tǒng)可靠性低,穩(wěn)定性差。引入實(shí)時(shí)操作系統(tǒng),可以較好解決這個(gè)問(wèn)題。

MicroC/OS-II是一個(gè)完整的,可移植、可固化、可剪裁的搶占式多任務(wù)實(shí)時(shí)內(nèi)核,并且開(kāi)放源代碼,在嵌入式系統(tǒng)中得到了廣泛應(yīng)用。為了實(shí)現(xiàn)老系統(tǒng)功能升級(jí),達(dá)到了不改變硬件設(shè)計(jì),增加系統(tǒng)功能、提高系統(tǒng)性能的目的,從而采用該實(shí)時(shí)操作系統(tǒng)。本文介紹了將其移植應(yīng)用于80C196的具體實(shí)現(xiàn)和注意事項(xiàng)。

所謂移植,就是使一個(gè)實(shí)時(shí)內(nèi)核能夠在其他微處理器或微控制器上運(yùn)行。移植要做的是,修改或編寫(xiě)與處理器硬件相關(guān)的代碼。由于80C196系統(tǒng)的資源有限,除了代碼移植,還要根據(jù)具體應(yīng)用,對(duì)MicroC/OS-II進(jìn)行裁剪,以達(dá)到系統(tǒng)的設(shè)計(jì)要求。

1.MicroC/OS-II簡(jiǎn)介

MicroC/OS-II的系統(tǒng)結(jié)構(gòu)見(jiàn)圖1。

MicroC/OS-II最主要的特點(diǎn)之一是源代碼開(kāi)放,有利于用戶根據(jù)具體應(yīng)用對(duì)操作系統(tǒng)進(jìn)行充分的裁減。這也使得其可移植性非常的強(qiáng)。

MicroC/OS-II是為嵌入式應(yīng)用專門(mén)設(shè)計(jì)的,完全可與應(yīng)用軟件融合在一起,進(jìn)行編譯、連接,進(jìn)而作為產(chǎn)品的一部分。

MicroC/OS-II是完全可剝奪型的實(shí)時(shí)內(nèi)核,總是運(yùn)行就緒任務(wù)中最高優(yōu)先級(jí)的任務(wù),即準(zhǔn)備就緒的高優(yōu)先級(jí)任務(wù)可以剝奪正在運(yùn)行的低優(yōu)先級(jí)任務(wù)的CPU使用權(quán)。

2.移植的基本思路

2.1編譯器

采用TASKING公司的C196編譯器,可以方便的嵌入?yún)R編語(yǔ)言,因此該移植所有的函數(shù)都在OS_CPU_C.C中實(shí)現(xiàn),沒(méi)有OS_CPU_A.ASM文件。能夠采用C語(yǔ)言編碼的,盡量采用C語(yǔ)言編碼;不能采用C代碼的,采用嵌入?yún)R編的方式。以此降低代碼的分散度,提高代碼的可讀性。

2.2代碼移植

代碼移植,需要修改或編寫(xiě)與處理器硬件相關(guān)的代碼。包括與處理器相關(guān)的數(shù)據(jù)類型定義,函數(shù)定義,存儲(chǔ)器操作等。其中的主要任務(wù)有:

1)重新編輯INCLUDES.H文件,增加與應(yīng)用相關(guān)的頭文件;改寫(xiě)OS_CPU.H文件;

2)改寫(xiě)OS_CFG.H文件;編寫(xiě)OS_CPU_C.C;

3)優(yōu)化代碼效率。

2.3存儲(chǔ)資源

由于80C196系統(tǒng)的物理資源十分有限,需要對(duì)系統(tǒng)內(nèi)核進(jìn)行充分的裁剪。

片內(nèi)可用內(nèi)存為220個(gè)字節(jié),在系統(tǒng)中外部擴(kuò)展3584(3.5K)個(gè)字節(jié)。為了提高系統(tǒng)速度,操作系統(tǒng)盡量使用片內(nèi)存儲(chǔ)區(qū)。系統(tǒng)應(yīng)用中經(jīng)常使用的變量,也需要分配在片內(nèi)存儲(chǔ)區(qū)。

為了節(jié)約存儲(chǔ)資源采取以下措施:

1)裁剪不使用的功能模塊和其使用相應(yīng)變量。

2)根據(jù)應(yīng)用的需要裁剪所需資源的規(guī)模。例如,在應(yīng)用中實(shí)際使用任務(wù)為6個(gè),所以將OSRdyTbl由一個(gè)數(shù)組,更改為一個(gè)8位變量,并去掉OSRdyGrp,因?yàn)槠溆肋h(yuǎn)是0。

3)修改OS_InitTaskIdle內(nèi)容,將OS_TaskIdle任務(wù)換為應(yīng)用的最低優(yōu)先級(jí)的任務(wù)。

4)裁剪OS_TCB的內(nèi)容。例如,永遠(yuǎn)不會(huì)使用的變量OSTCBY和OSTCBBitY。

5)裁剪中斷嵌套的相關(guān)內(nèi)容。

2.4時(shí)間資源

MicroC/OS-II推薦的時(shí)鐘節(jié)拍為10~200ms,而本系統(tǒng)的實(shí)際時(shí)鐘節(jié)拍為250μs,這樣系統(tǒng)額外開(kāi)銷必然大幅度增加,系統(tǒng)時(shí)間資源十分緊張。

為了節(jié)約時(shí)間資源采取以下措施:

1)棄用OSTimeDly函數(shù),直接操作任務(wù)定時(shí)器,調(diào)用OS_Sched函數(shù)。

2)棄用OSIntExit和OSIntCtxSw函數(shù),將其源代碼直接加入軟件定時(shí)器中斷服務(wù)函數(shù)。

3)降低其他中斷服務(wù)函數(shù)的代碼長(zhǎng)度,且不進(jìn)行任務(wù)切換,降低系統(tǒng)時(shí)鐘的誤差。

4)根據(jù)編譯得到的匯編代碼,對(duì)部分C語(yǔ)言代碼進(jìn)行優(yōu)化。

3.移植實(shí)現(xiàn)

3.1任務(wù)分配

一個(gè)任務(wù),也稱為一個(gè)線程,是一個(gè)簡(jiǎn)單的程序,該程序可以認(rèn)為CPU完全屬于自己。每個(gè)任務(wù)有獨(dú)立的堆??臻g和優(yōu)先級(jí)。

根據(jù)每個(gè)任務(wù)的內(nèi)容可以在相應(yīng)位置,使任務(wù)就緒。而任務(wù)就緒和任務(wù)切換可以分開(kāi)。例如,在接收中斷中,使可以CAN通信任務(wù)就緒,但可以不進(jìn)行任務(wù)切換,而在系統(tǒng)時(shí)鐘函數(shù)中進(jìn)行任務(wù)切換。系統(tǒng)總是讓處于就緒態(tài)的、優(yōu)先級(jí)最高的任務(wù)先運(yùn)行。

3.2時(shí)鐘節(jié)拍

時(shí)鐘節(jié)拍是特定的周期性中斷,根據(jù)應(yīng)用系統(tǒng)的需要,時(shí)鐘節(jié)拍的周期為250μs,采用軟件定時(shí)器實(shí)現(xiàn)。在該服務(wù)函數(shù)中實(shí)現(xiàn)任務(wù)切換,為了節(jié)省時(shí)間和存儲(chǔ)資源,不進(jìn)行函數(shù)調(diào)用。

軟件定時(shí)器中斷服務(wù)函數(shù)實(shí)現(xiàn)代碼如下:

voidOSTickISR(void)

{

……//重置軟件定時(shí)器

OS250usCount++;//計(jì)數(shù)器加1

if((OS250usCount&0x03)==0){

……

OS1msCount++;//1ms定時(shí)器

OS50msDly++;//50ms定時(shí)器

OSRdyTbl|=0x20;//1ms定時(shí)到,就緒TaskChk任務(wù)

……}

//OSIntExit()中斷退出任務(wù)切換

OSPrioHighRdy=OSUnMapTbl[OSRdyTbl];//取得最高優(yōu)先級(jí)就緒任務(wù)的優(yōu)先級(jí)

if(OSPrioHighRdy!=OSPrioCur)//判斷當(dāng)前任務(wù)優(yōu)先級(jí)是否與最高優(yōu)先級(jí)就緒任務(wù)的優(yōu)先級(jí)相同

{

//OSIntCtxSw();

OSTCBCur->OSTCBStkPtr=psp;//存儲(chǔ)被中斷任務(wù)的堆棧指針

OSTCBCur=OSTCBPrioTbl[OSPrioHighRdy];//取得最高優(yōu)先級(jí)就緒任務(wù)的TCB

OSPrioCur=OSPrioHighRdy;//設(shè)當(dāng)前任務(wù)優(yōu)先級(jí)為最高優(yōu)先級(jí)就緒任務(wù)的優(yōu)先級(jí)

psp=OSTCBCur->OSTCBStkPtr;//取得堆棧指針

asm{//現(xiàn)場(chǎng)恢復(fù)

popdx;popcx;popbx;popax;popa;

ret;//切換到最高優(yōu)先級(jí)就緒任務(wù),必須要有的

}

}

}

3.3中斷

由于中斷的存在,任何代碼在任何時(shí)候,都有可能被中斷。而有些代碼是不可分割的,如果被中斷將會(huì)產(chǎn)生不可預(yù)料的后果。因此定義臨界段,以處理不可分割的代碼。一旦該部分代碼開(kāi)始執(zhí)行,不允許任何中斷插入。為了確保臨界段代碼的執(zhí)行不被中斷,在進(jìn)入臨階段之前,必須關(guān)中斷,臨界段代碼執(zhí)行結(jié)束,開(kāi)中斷。

為80C196定義OS_ENTER_CRITICAL和OS_EXIT_CRITICAL如下:

//中斷禁止函數(shù)

#defineOS_ENTER_CRITICAL()asmDI

//中斷使能函數(shù)

#defineOS_EXIT_CRITICAL()asmEI

3.4其他代碼實(shí)現(xiàn)

3.4.1任務(wù)堆棧初始化函數(shù)

任務(wù)堆棧初始化函數(shù)代碼如下:

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

{

……

stk=(OS_STK*)ptos;

*--stk=(OS_STK)task;//任務(wù)開(kāi)始地址

*--stk=(OS_STK)0x0000|gimask;//PSWIMASK

*--stk=(OS_STK)0x0000|gimask1;//IMASK1WSR

*--stk=(OS_STK)4;//DX

*--stk=(OS_STK)3;//CX

*--stk=(OS_STK)2;//BX

*--stk=(OS_STK)1;//AX

return((OS_STK*)stk);

}

3.4.2開(kāi)始運(yùn)行最高優(yōu)先級(jí)就緒任務(wù)

系統(tǒng)開(kāi)始運(yùn)行時(shí),調(diào)用該函數(shù),以開(kāi)始運(yùn)行,其實(shí)現(xiàn)代碼如下:

voidOSStartHighRdy(void)

{

OSRunning=TRUE;//置系統(tǒng)正在運(yùn)行標(biāo)志

……

OSTCBCur=OSTCBHighRdy;//置當(dāng)前TCB為最高優(yōu)先級(jí)就緒任務(wù)的TCB

psp=OSTCBHighRdy->OSTCBStkPtr;//取得堆棧指針

asm{//恢復(fù)現(xiàn)場(chǎng)

popdx;popcx;popbx;popax;popa;//轉(zhuǎn)到新任務(wù)

}

}

3.4.3現(xiàn)場(chǎng)切換函數(shù)

OS_Sched函數(shù)調(diào)用該函數(shù)實(shí)現(xiàn)真正的任務(wù)切換。

voidOSCtxSw(void)

{

asm{//保存被中斷任務(wù)的現(xiàn)場(chǎng)

pusha;pushax;pushbx;pushcx;pushdx;

}

OSTCBCur->OSTCBStkPtr=psp;//存儲(chǔ)被中斷任務(wù)的堆棧指針

OSTCBCur=OSTCBPrioTbl[OSPrioHighRdy];//取得最高優(yōu)先級(jí)就緒任務(wù)的TCB

OSPrioCur=OSPrioHighRdy;//設(shè)當(dāng)前任務(wù)優(yōu)先級(jí)為最高優(yōu)先級(jí)就緒任務(wù)的優(yōu)先級(jí)

psp=OSTCBCur->OSTCBStkPtr;//取得堆棧指針

asm{//現(xiàn)場(chǎng)恢復(fù)

popdx;popcx;popbx;popax;popa;

}

}

4.注意事項(xiàng)

在實(shí)現(xiàn)過(guò)程中的得到如下經(jīng)驗(yàn)教訓(xùn):

1)盡量減少任務(wù)的數(shù)量,以減少系統(tǒng)額外開(kāi)銷。相對(duì)少的任務(wù)數(shù),可以減少,系統(tǒng)花在任務(wù)切換上的時(shí)間。

2)合理分配各個(gè)任務(wù)的優(yōu)先級(jí)。

3)注意開(kāi)中斷、關(guān)中斷的時(shí)機(jī)。

4)注意入棧和出棧要匹配。如果堆棧指針出現(xiàn)錯(cuò)位,將會(huì)出現(xiàn)災(zāi)難性后果。特別注意中斷服務(wù)函數(shù)的處理,其調(diào)用時(shí)的入棧內(nèi)容和退出中斷的出棧內(nèi)容要對(duì)應(yīng),而中斷退出有兩種可能:正常退出和任務(wù)切換。

5)合理選擇定時(shí)器時(shí)間周期。

6)同類型工作,也同樣需要有優(yōu)先級(jí)區(qū)分。例如:同樣是通信任務(wù),接收數(shù)據(jù)需要較高的優(yōu)先級(jí),而通信故障處理需要較低的優(yōu)先級(jí)。一般情況下,通信處理都有一定的故障容忍時(shí)間,只要在容忍時(shí)間內(nèi)得到處理就可以了。如果發(fā)生不可恢復(fù)性錯(cuò)誤,故障處理將會(huì)占用大量的時(shí)間,如果在較高優(yōu)先級(jí),將會(huì)影響整個(gè)系統(tǒng)的性能。

5.結(jié)論

通過(guò)在80C196上移植實(shí)現(xiàn)MicroC/OS-II,達(dá)到了不改變硬件設(shè)計(jì),增加應(yīng)用功能,提高了應(yīng)用系統(tǒng)性能的目的。在嵌入式系統(tǒng)中使用嵌入式實(shí)時(shí)操作系統(tǒng),不但可以提高系統(tǒng)的實(shí)時(shí)性、可靠性和穩(wěn)定性,還可以提高應(yīng)用軟件的可移植性和可維護(hù)性,降低開(kāi)發(fā)人員的工作量。因此,只要硬件環(huán)境允許,應(yīng)盡量采用實(shí)時(shí)操作系統(tǒng)。

參考文獻(xiàn):

1.JeanJ.Labrosse著,邵貝貝等譯,《嵌入式實(shí)時(shí)操作系統(tǒng)μC/OS-II(第二版)》,北京航空航天大學(xué)出版社,2003年5月第1版

2.孫涵芳主編,《Intel16位單片機(jī)》,北京航空航天大學(xué)出版社,1995年11月第1版