陳 豹,石 鋒
(徐州工程學院 a.信電工程學院;b.教務處,江蘇 徐州 221000)
μC/OS-II在ARM平臺的移植研究
陳 豹a,石 鋒b
(徐州工程學院 a.信電工程學院;b.教務處,江蘇 徐州 221000)
在嵌入式系統(tǒng)中引入操作系統(tǒng),可以提高嵌入式設備的穩(wěn)定性和可靠性,加快系統(tǒng)軟件的開發(fā)效率。文章完成μC/OS-II在ARM平臺上的移植,給出詳細的移植方案。經(jīng)測試移植成功,系統(tǒng)可穩(wěn)定運行,從而給μC/OS在其他處理器上的移植提供一些參考。
移植;μC/OS-II;ARM
在復雜的應用場合,可以在嵌入式硬件平臺上引入操作系統(tǒng),μC/OS[1]是由Jean J.Labrosse先生編寫的一個嵌入式實時操作系統(tǒng),代碼開源、免費、短小精悍、可擴展性強,最小內(nèi)核可編譯至2KB,從推出以來,經(jīng)過長期的應用測試,其可靠性得到了驗證,目前已經(jīng)在很多場合得到廣泛使用,嚴格地說μC/OS-II只是一個實時操作系統(tǒng)內(nèi)核,僅提供了任務調(diào)度、任務管理、時間管理、內(nèi)存管理和任務間的通信和同步等基本功能,文章研究其在高性能ARM[2]處理器上的移植細節(jié),給出詳細的移植方案。
μC/OS-II實際上是若干程序文件的集合體,主要是C程序文件,并且這些文件間存在一定的關系,操作系統(tǒng)的文件組成如圖1所示。

圖1 μC/OS-II的文件結(jié)構
本次移植用的硬件是三星公司生產(chǎn)的ARM920T內(nèi)核的S3C2410嵌入式微處理器,軟件使用ARM公司的集成開發(fā)環(huán)境ADS1.2。
ARM處理器具有7種工作模式,除用戶模式外其他6種都屬于特權模式,系統(tǒng)運行過程中會涉及到工作模式的轉(zhuǎn)換,比如發(fā)生IRQ中斷時處理器會切換到IRQ異常模式,處理器切換到不同模式時能訪問的物理寄存器是有差別的,在ARM處理器上運行時,μC/OS-II移植需要實現(xiàn)的開關中斷函數(shù)、任務切換函數(shù)都涉及到對ARM處理器中當前程序狀態(tài)寄存器CPSR的操作處理,而CPSR的訪問和主動修改只能在系統(tǒng)處于特權模式下才能實現(xiàn),所以,本次移植設定操作系統(tǒng)代碼和用戶代碼運行在系統(tǒng)模式,系統(tǒng)模式屬于特權模式,這樣在程序中可以方便的直接修改CPSR中相關位的值,比如中斷允許位I、工作模式位M[4:0],以滿足系統(tǒng)開關中斷函數(shù)、任務切換函數(shù)功能實現(xiàn)的需要。
μC/OS-II在設計的時候就已經(jīng)考慮了將來在不同硬件平臺的使用問題,在設計軟件代碼的時候把與硬件平臺相關的代碼分別放在了三個文件,分別是OS_CPU_C.C、OS_CPU_A.ASM和OS_CPU.H,所謂的移植,主要就是修改這三個與處理器相關的文件,在不同的微處理器上移植UCOS,其區(qū)別就在這三個文件中相關程序的編寫。
4.1 OS_CPU.H的編寫
在OS_CPU.H文件中,UCOS為了代碼的直觀性和可移植性,定義了不依賴于處理器平臺的數(shù)據(jù)類型以及相關宏的定義,當運行在一具體處理器上的時候,需要根據(jù)處理器和編譯器對這些數(shù)據(jù)類型做重新定義,因為即使同一數(shù)據(jù)類型在不同的處理器和編譯器環(huán)境下代表的數(shù)據(jù)長度也是不一樣的,結(jié)合ARM處理器的特性及ADS1.2編譯器的特性,對數(shù)據(jù)類型做如下定義:
tyPedefunsigned char BOOLEAN;
tyPedefunsigned char INT8U;
tyPedefsigned char INT8S;
tyPedefunsigned short INT16U;
tyPedefsigned short INT16S;
tyPedefunsigned int INT32U;
tyPedefsigned int INT32S;
tyPedeffloat FP32;
tyPedefdouble FP64;
tyPedefINT32U OS_STK;
μC/OS-II使用結(jié)構常量OS_STK_GROWTH中指定堆棧的生長方式,ARM處理器支持四種堆棧[4]類型,但編譯器ADS只支持滿遞減堆棧,所以做如下定義:
#define OS_STK_GROWTH 1
開關中斷宏的定義:
#defineOS_ENTER_CRITICAL()ARMDisableInt()
#defineOS_EXIT_CRITICAL() ARMEnableInt()
普通任務切換宏的定義:
#define OS_TASK_SW() OSCtxSw()
4.2 OS_CPU_C.C編寫
在這個文件中,一共是10個函數(shù),一個OSTaskStkInit( ),9個Hook函數(shù),在μC/OS中,多個任務輪流切換運行,當一個任務需要重新切換出來運行時需要得到上次被切換暫停時現(xiàn)場的相關數(shù)據(jù),然后接著往下繼續(xù)運行,這些數(shù)據(jù)就保存在每一個任務自己的私有堆棧區(qū)內(nèi),任務第一次運行時實際上是模擬其經(jīng)過一次中斷重新運行的結(jié)果,這時任務所需要的數(shù)據(jù)實際上就是任務堆棧初始化時的數(shù)據(jù)結(jié)構,完成這些數(shù)據(jù)在任務堆棧區(qū)的結(jié)構由函數(shù)OSTaskStk Init( )完成,其他9個Hook函數(shù)是留給用戶擴展功能使用的,用戶不需要的話可以保持其為空函數(shù)即可,本次移植中均為空函數(shù),本次移植任務堆棧結(jié)構設計如圖2所示。
系統(tǒng)堆棧初始化函數(shù)OSTaskStkInit( )在任務創(chuàng)建函數(shù)OSTaskCreat()中調(diào)用,返回值為該任務堆棧棧頂指針,這個指針會被賦給任務控制塊的成員:OSTCBStkPtr,顯然,得到某一任務的任務控制塊就可訪問到堆棧區(qū),從而得到該任務重新切換運行所需的數(shù)據(jù)信息,把這些值送給處理器的相關寄存器,任務代碼占領了處理器便開始運行,即該任務得到切換運行,OSTaskStkInit( )代碼如下:

圖2 堆棧結(jié)構圖

4.3 OS_CPU_A.S的編寫
操作系統(tǒng)的移植工作主要集中在這個文件中,工作量最大,一共需要實現(xiàn)6個匯編函數(shù):void OSStartHighRdy(void)、void OSCtxSw(void)、void OSIntCtxSW(void)、void OSTick ISR(void)、unsigned int ARMDisabInt(void)、void ARMEnableInt(unsigned int)。
4.3.1 void OSStartHighRdy(void)的實現(xiàn)
這個函數(shù)在OSStart(void)中調(diào)用,功能是運行系統(tǒng)中最高優(yōu)先級的任務,多任務系統(tǒng)UCOS剛一運行起來時,會根據(jù)算法計算出當前處于就緒態(tài)的最高優(yōu)先級任務的優(yōu)先級號OSPrioHighRdy,根據(jù)這個最高優(yōu)先級號查找數(shù)組OSTCBPrioTbl[],從而訪問到該任務的控制塊OSTCBHighRdy,任務控制塊結(jié)構體中訪問該任務的堆棧指針SP,按照圖2所示的任務堆棧結(jié)構將任務初次運行所需的相關初始化數(shù)據(jù)出棧送給處理器的相關寄存器,該任務即得到運行,下面給出其實現(xiàn)的示意性偽代碼:
voidOSStartHighRdy(void)
{OSTaskSwHook();
OSRunning=True;
計算處于就緒態(tài)的優(yōu)先級最高任務的優(yōu)先級號;
得到要運行最高優(yōu)先級任務控制塊OSTCBHighRdy;
處理器的堆棧指針SP=OSTCBHighRdy->OSTCBStkPtr;
恢復堆棧中的各個字段到處理器的寄存器;
恢復PC字段,跳轉(zhuǎn)到任務代碼處運行;
}
4.3.2 void OSCtxSw(void)的實現(xiàn)
系統(tǒng)中任務級的切換函數(shù),當任務需要主動放棄CPU的使用權(比如調(diào)用系統(tǒng)延時函數(shù)OSTimeDly()時),從而導致一次任務切換時,調(diào)用這個函數(shù),在μC/OS-II中,這是通過宏調(diào)用實現(xiàn),即define OS_TASK _SW OSCtxSw,系統(tǒng)調(diào)用OSSched()進行一次任務調(diào)度,在OSSched()中調(diào)用OS_TASK_SW,實際是執(zhí)行的OSCtxSw,在這個函數(shù)中實現(xiàn)切換任務,當然在進入OS_TASK_SW前,系統(tǒng)會先計算出OSPrioHighRdy,以確定要切換出來運行的任務,給出OSCtxSw()示意性代碼如下:
voidOSCtxSw(void)
{
保存處理器各寄存器值到當前任務堆棧;
保存當前堆棧地址到當前任務控制塊的OSTCBStkPtr;
OSTaskSwHook();
OSPrio=OSPrioHighRdy;
OSTCBCur=OSTCBHighRdy;
處理器的堆棧指針SP=OSTCBHighRdy->OSTCBStkPtr;
恢復堆棧中數(shù)據(jù)到處理器各寄存器;
恢復PC字段,跳轉(zhuǎn)到任務代碼處運行;
}
4.3.3 void OSIntCtxSW(void)的實現(xiàn)
中斷級任務切換函數(shù),這個函數(shù)只在中斷處理程序中被OSIntExit調(diào)用,UCOS系統(tǒng)響應中斷的原理是當任務被中斷打斷去響應中斷服務程序時,在執(zhí)行中斷服務程序的過程中如果使另外一個更高優(yōu)先級的任務轉(zhuǎn)變?yōu)榫途w態(tài),那么在中斷服務程序退出后不會接著執(zhí)行之前被打斷的任務,而是切換到那個更高優(yōu)先級的任務執(zhí)行,因為在進入中斷服務程序時任務的所有狀態(tài)已經(jīng)被保存到了任務堆棧中,所以這個函數(shù)只需要直接裝載新任務的堆棧內(nèi)容使其運行就可以了,當然在進入OSIntCtxSw(void)函數(shù)前,系統(tǒng)也會先計算出要運行的更高優(yōu)先級任務的優(yōu)先級號以用于訪問該任務的相關數(shù)據(jù)結(jié)構,OSIntCtxSw(void)示意性代碼如下:
voidOSIntCtxSw(void)
{
處理器的堆棧指針SP=OSTCBHighRdy->OSTCBStkPtr;
恢復堆棧中數(shù)據(jù)到處理器各寄存器;
恢復PC字段,跳轉(zhuǎn)到任務代碼處運行;
}
可見,內(nèi)容和上面void OSCtxSw(void)函數(shù)的后半部分一樣。
4.3.4 void OSTick ISR(void)的實現(xiàn)
系統(tǒng)時鐘中斷服務函數(shù),μC/OS-II需要一個周期性的時鐘信號才能運行,這個時鐘信號由硬件處理器的定時器來實現(xiàn),比如設定每隔10毫秒產(chǎn)生一次定時中斷,每次定時時間間隔到,系統(tǒng)進入時鐘中斷服務程序OSTickISR(void),如果在定時中斷處理過程中有更高優(yōu)先級的任務進入就緒態(tài),并且當前中斷為中斷嵌套的最后一層,那么在中斷退出時,系統(tǒng)會調(diào)用OSIntExit函數(shù)實現(xiàn)任務切換,使更高級的就緒任務運行;如果在定時中斷處理程序中沒有出現(xiàn)更高優(yōu)先級的任務進入就緒態(tài),那么中斷程序最后直接回到被中斷的任務接著運行,另外,UCOS操作系統(tǒng)要求在系統(tǒng)時鐘中斷服務函數(shù)中調(diào)用系統(tǒng)函數(shù)OSTimeTick()來處理所有任務的定時操作,void OSTick ISR(void)代碼示意如下:
void OSTick ISR(void)
{
保存被中斷任務的現(xiàn)場數(shù)據(jù)到其私有堆棧中;
設置被中斷任務TCB的堆棧棧頂指針;
OSIntEnter();
清中斷標志位;
OSTimeTick();
OSIntExit();
恢復被中斷任務的現(xiàn)場數(shù)據(jù);
}
移植過程中,第一步“保存被中斷任務的現(xiàn)場數(shù)據(jù)到其私有堆棧中”是實現(xiàn)重點,這里要保存的現(xiàn)場數(shù)據(jù)如圖2所示,程序要按順序?qū)崿F(xiàn)圖2中數(shù)據(jù)的入棧工作,本次移植的方案中,應用任務是設置運行在系統(tǒng)模式,發(fā)生定時中斷ARM系統(tǒng)進入IRQ模式,而被中斷任務的原先的堆棧區(qū)只能在系統(tǒng)模式才能訪問,要想保存現(xiàn)場數(shù)據(jù)到任務堆棧中,需要從IRQ模式主動切換到系統(tǒng)模式,這可以IRQ模式中通過修改SPSR _irq值的模式位實現(xiàn),此時,SPSR_irq和LR_irq是被中斷任務現(xiàn)場數(shù)據(jù)的一部分,為了在切換到系統(tǒng)模式后能訪問到并壓入堆棧,可以把這個值先保存在設定的全局變量中,這樣切換到系統(tǒng)模式后就能訪問到這兩個數(shù)據(jù),其中,SPSR_irq的值修改模式位為系統(tǒng)模式后送到堆棧圖中的CPSR位置,LR_irq的值減4后送到堆棧中的lr位置,其他寄存器R0—R12的值按照圖2的順序入棧就可以了。
4.3.5 unsigned int ARMDisabInt(void)、void ARMEnableInt(unsigned int)的實現(xiàn)
這兩個函數(shù)是ARM系統(tǒng)開關中斷函數(shù),實現(xiàn)相對比較簡單,通過匯編語句修改CPSR寄存器的中斷允許位I即可。
多任務系統(tǒng)能否穩(wěn)定運行,移植后需要測試是否移植成功,在ADS中建立工程,創(chuàng)建兩個任務Task1和Task2,分別控制開發(fā)板上的led亮滅和數(shù)碼管顯示,優(yōu)先級分別為6、14。
voidMain(void)
{
ARMTargetInit();
OSInit();
OSTaskCreate(Task1,(void*)0,(OS_STK*)&StackLED[STACKSIZE-1],6);
OSTaskCreate(Task2,(void*)0,(OS_STK*)&StackSEG[STACKSIZE-1],14);
OSStart();
}
兩個任務運行時可以在屏幕上打印出各自的運行信息,串口調(diào)試助手軟件DNW上顯示,如圖3所示:

圖3 DNW顯示
同時,任務Task1運行時開發(fā)板上的4個跑馬燈每隔100個時鐘節(jié)拍閃爍一次;任務Task2每隔200個時鐘節(jié)拍使開發(fā)板上的6個數(shù)碼管從1到F循環(huán)顯示一次,實驗結(jié)果證明,μC/OS-II移植成功,可以穩(wěn)定運行。
本文在基于三星公司S3C2410 ARM處理器的開發(fā)板平臺上,采用ADS集成開發(fā)環(huán)境,詳細論述了嵌入式操作系統(tǒng)μC/OS-II的移植過程,給出了需要移植修改的地方,以偽代碼的方式給出了移植編程思路,并重點闡述了難點即系統(tǒng)時鐘中斷服務函數(shù)實現(xiàn),最后經(jīng)過測試驗證系統(tǒng)移植成功,該移植過程可以給嵌入式操作系統(tǒng)μC/OS-II在其他ARM處理器上的移植提供一定的借鑒作用,從而充分發(fā)揮基于ARM處理器嵌入式系統(tǒng)[5]的優(yōu)良性能。
[1] 任哲.嵌入式實時操作系統(tǒng)UC/OS-II原理及應用[M].2版.北京:北京航空航天大學出版社,2009.
[2] 杜春雷.ARM體系結(jié)構與編程[M].北京:清華大學出版社,2008.
[3] 疏國會,金鑫.基于μC/OS的嵌入式系統(tǒng)應用開發(fā)平臺的研究[J].制造業(yè)自動化,2012(4):145-147.
[4] 謝國波,羅路天.嵌入式系統(tǒng)層次體系結(jié)構模型研究[J].廣東工業(yè)大學學報,2015(1):109-112.
[5] 劉芳宇.基于ARM嵌入式系統(tǒng)的設計及其應用[J].計算機光盤軟件與應用,2012(9):173-174.
責任編輯:吳旭云
Research ofμC/OS-IITransPlantation Based on ARM Platform
CHEN Baoa,SHIFengb
(a.DePartment of Information and Electrical Engineering;b.DePartment of Academic Affairs,Xuzhou Institute of Technology,Xuzhou 221000,China)
With the introduction of the oPerating system to the embedded system,the stability and reliability of the embedded devices can be imProved and the develoPment efficiency of system software can also be sPed uP.The transPlantation ofμC/OS-II based on ARM Platform is comPleted in the PaPer and a detailed transPlantation Plan is given.The system oPerates stably after successful im-Plantation,which Provides some references forμC/OS-II transPlantation based on other Processors.
transPlantation;μC/OS-II;ARM
TP393.19
A
1009-3907(2015)06-0014-05
2015-03-10
2013年度徐州工程學院校級科研項目(XKY2013405)
陳豹(1980-),男,江蘇徐州人,講師,碩士,主要從事嵌入式系統(tǒng)方面研究,石鋒(1982-),女,江蘇徐州人,講師,碩士,主要從事計算機應用方面研究。