摘要 本文介紹了實(shí)時(shí)操作系統(tǒng)µC/OS-II的特點(diǎn),討論了其在51系列單片機(jī)上移植的必要性。并選擇8位單片機(jī)C8051F120作為移植目標(biāo),分析了µC/OS-II的具體移植過(guò)程。最后設(shè)計(jì)例程驗(yàn)證了移植的正確性。
關(guān)鍵詞 C8051F120;µC/OS-II;移植
[align=center]The Porting of Real-Time Operation System µC/OS-II on C8051F120
Taiyuan University of Technology Tian Juan[/align]
Abstract The paper introduces the characteristic of real-time operation system µC/OS-II, and discusses the necessity of porting µC/OS-II on 51 series MCU. Then the specific process of porting µC/OS-II on C8051F120 which is selected as porting target is analyzed. The paper ends with designing test program to prove the success of the porting.
Keywords C8051F120; µC/OS-II; porting
引言
傳統(tǒng)的嵌入式系統(tǒng)設(shè)計(jì)往往采用前/后臺(tái)系統(tǒng)。應(yīng)用程序是一個(gè)無(wú)限的循環(huán),在循環(huán)中調(diào)用相應(yīng)的函數(shù)完成對(duì)應(yīng)的操作,這部分可以看成后臺(tái)行為。中斷服務(wù)程序處理異步事件,這部分可以看成前臺(tái)行為[1]。在大多數(shù)對(duì)實(shí)時(shí)性要求較高的場(chǎng)合中,這種系統(tǒng)結(jié)構(gòu)就無(wú)法滿足應(yīng)用的要求,實(shí)時(shí)內(nèi)核逐步成為嵌入式系統(tǒng)設(shè)計(jì)的主流。µC/OS-II是一個(gè)完整的,可移植、固化、裁減的占先式實(shí)時(shí)多任務(wù)內(nèi)核,不僅結(jié)構(gòu)簡(jiǎn)單,絕大部分采用C語(yǔ)言,而且可移植性好,很容易被移植到各種微處理器上,在移植過(guò)程中,只需要做少量的修改工作即可。目前µC/OS-II最多支持64個(gè)任務(wù),總是在執(zhí)行處于就緒態(tài)的優(yōu)先級(jí)最高的任務(wù)。并且因其源代碼的完全公開(kāi)和優(yōu)越性能而得到了廣泛的應(yīng)用。
51系列單片機(jī)是美國(guó)Intel公司在1980年推出的高性能8位單片機(jī),目前仍然是我國(guó)使用最廣泛的單片機(jī)系列之一,有非常大的應(yīng)用環(huán)境與前景。如果開(kāi)發(fā)一套基于51系列單片機(jī)的操作系統(tǒng),那么用戶只需要編寫(xiě)各個(gè)任務(wù)的程序,不必同時(shí)將所有任務(wù)運(yùn)行的各種情況記在心中,不但大大減少了程序編寫(xiě)的工作量,而且減少了出錯(cuò)的可能性[2]。
所以,在51系列單片機(jī)上移植實(shí)時(shí)操作系統(tǒng)µC/OS-II是很有必要的。
1 µC/OS-II的移植條件
要使µC/OS-II移植到處理器后能正常運(yùn)行,處理器必須滿足以下條件:
● 處理器的C編譯器能產(chǎn)生可重入代碼。µC/OS-II是可剝奪型內(nèi)核,總是讓就緒態(tài)的高優(yōu)先級(jí)的任務(wù)先運(yùn)行,中斷服務(wù)程序可以搶占CPU,所以只能通過(guò)C編譯器產(chǎn)生可重入代碼。可重入函數(shù)可以被一個(gè)以上的任務(wù)調(diào)用,而不必?fù)?dān)心數(shù)據(jù)被破壞。
● 處理器的C編譯器能在C語(yǔ)言中開(kāi)中斷和關(guān)中斷。因?yàn)?micro;C/OS-II在處理臨界段的時(shí)候,須關(guān)中斷,處理完畢后,再開(kāi)中斷。
● 處理器支持中斷,并且能產(chǎn)生定時(shí)中斷。因?yàn)?micro;C/OS-II是通過(guò)硬件中斷來(lái)實(shí)現(xiàn)系統(tǒng)時(shí)鐘,并在時(shí)鐘中斷服務(wù)程序中來(lái)處理與時(shí)間相關(guān)的問(wèn)題,實(shí)現(xiàn)任務(wù)之間的調(diào)度。
● 處理器具有一定數(shù)量的硬件堆棧,并且有將堆棧指針和其他CPU寄存器內(nèi)容讀出、并存儲(chǔ)到堆?;騼?nèi)存中的指令。因?yàn)?micro;C/OS-II為每一個(gè)任務(wù)分配任務(wù)堆棧,在任務(wù)切換時(shí),需要先保存當(dāng)前任務(wù)堆棧內(nèi)容,再恢復(fù)最高優(yōu)先級(jí)任務(wù)堆棧內(nèi)容。
2 CPU芯片的選擇
隨著現(xiàn)代通信技術(shù)的發(fā)展,智能化系統(tǒng)對(duì)DSP需求的增長(zhǎng)要求不斷提高單片機(jī)運(yùn)算速度[3]。C8051F系列單片機(jī)就是在這樣的情況下由Silabs公司推出的,它是完全集成的混合信號(hào)系統(tǒng)級(jí)芯片,具有與8051兼容的微控制器內(nèi)核,在不擴(kuò)展8位數(shù)據(jù)總線的情況下,使單周期指令速度提高到原8051的12倍。而C8051F120作為C8051F系列中的高端產(chǎn)品就被選擇為系統(tǒng)移植的對(duì)象。
C8051F120的內(nèi)部資源有:64個(gè)I/O引腳,5個(gè)16位通用計(jì)數(shù)器/定時(shí)器,6個(gè)捕獲/比較模塊,硬件實(shí)現(xiàn)的SPI,SMBus/IIC和兩個(gè)UART串行接口,片內(nèi)看門(mén)狗定時(shí)器,2個(gè)比較器,真正12位100ksps的8通道ADC,8位500ksps的8通道ADC,128KB的FLASH存儲(chǔ)器,8448B的內(nèi)部數(shù)據(jù)RAM[4]。
由于C8051F120處理器和使用的Keil編譯器都能夠很好的滿足上述移植條件,所以可以把µC/OS-II移植到C8051F120上。在實(shí)際開(kāi)發(fā)系統(tǒng)中,使用外部晶體振蕩器,晶振頻率為22.1184MHZ,并外擴(kuò)256KB的RAM。
3 移植過(guò)程
µC/OS-II的移植可以看作是對(duì)µC/OS-II代碼的修改。µC/OS-II的代碼分為與處理器無(wú)關(guān)的代碼,與處理器相關(guān)的代碼和與應(yīng)用相關(guān)的代碼。與處理器無(wú)關(guān)的代碼原則上是不用修改可以直接添加,但由于Keil編譯器的特殊性,必須在需要可重入的函數(shù)聲明的后面標(biāo)注reentant關(guān)鍵字,即加上重入屬性;又因?yàn)閜data既是Keil的關(guān)鍵字又是µC/OS-II的一些函數(shù)的形參,會(huì)導(dǎo)致編譯錯(cuò)誤,所以把pdata改為pdat。與處理器相關(guān)的代碼包括3個(gè)文件:OS_CPU.H、OS_CPU_C.C、OS_CPU_A.ASM,需要大量的修改后才能添加,這是移植工作的重點(diǎn)。另外,與應(yīng)用相關(guān)的代碼包括2個(gè)頭文件:INCLUDES.H和OS_CFG.H。INCLUDES.H是一個(gè)主頭文件,出現(xiàn)在每個(gè).C文件的第一行。INCLUDES.H文件使得工程項(xiàng)目中的每個(gè).C文件無(wú)需分別考慮它實(shí)際上需要哪些頭文件。還可以在頭文件列表的最后添加自己的頭文件。OS_CFG.H是系統(tǒng)配置文件,µC/OS-II的裁減過(guò)程是通過(guò)對(duì)OS_CFG.H中的相關(guān)常量進(jìn)行設(shè)置來(lái)完成[5]。可以分為任務(wù)管理功能的裁減,節(jié)省代碼存儲(chǔ)空間;數(shù)據(jù)結(jié)構(gòu)的裁減,節(jié)省數(shù)據(jù)存儲(chǔ)空間;系統(tǒng)節(jié)拍頻率設(shè)置和任務(wù)堆棧大小設(shè)置。
3.1 OS_CPU.H
OS_CPU.H包括了用#define語(yǔ)句定義的、與處理器相關(guān)的常數(shù)、宏以及類(lèi)型。
數(shù)據(jù)類(lèi)型的定義是為了保證可移植性。而且必須把任務(wù)堆棧的數(shù)據(jù)類(lèi)型告訴µC/OS-II,通過(guò)為OS_STK聲明恰當(dāng)?shù)腃數(shù)據(jù)類(lèi)型來(lái)實(shí)現(xiàn)的。C8051F120的堆棧是8位的,所以聲明OS_STK:
typedef INT8U OS_STK; //堆棧的寬度為8位
µC/OS-II為了處理臨界段代碼,須關(guān)中斷,處理完畢后,再開(kāi)中斷。所以定義2個(gè)宏來(lái)關(guān)中斷和開(kāi)中斷:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。這2個(gè)宏可以用3種方法實(shí)現(xiàn),具體用哪種方法,取決于使用的處理器類(lèi)型和C編譯器。C8051F120使用方法1來(lái)處理臨界段,即直接開(kāi)關(guān)中斷。這樣定義既減少了程序行數(shù),又避免了退出臨界區(qū)后關(guān)中斷造成的死機(jī)。根據(jù)中斷允許寄存器 IE的第7位EA為中斷允許總控制位,EA=0屏蔽所有中斷,EA=1允許所有中斷,所以定義語(yǔ)句為:
#define OS_ENTER_CRITICAL() EA=0 //關(guān)中斷
#define OS_EXIT_CRITICAL() EA=1 //開(kāi)中斷
C8051F120堆棧從下向上增長(zhǎng)(0=向上,1=向下),通過(guò)配置常數(shù)OS_STK_GROWTH指定堆棧的方向。所以定義語(yǔ)句為:
#define OS_STK_GROWTH 0 //堆棧從下向上增長(zhǎng),1=向下增長(zhǎng)
µC/OS-II的任務(wù)切換是通過(guò)模仿中斷動(dòng)作完成的,但C8051F120沒(méi)有軟中斷指令,所以用函數(shù)調(diào)用的方式實(shí)現(xiàn)任務(wù)切換,定義語(yǔ)句為:
#define OS_TASK_SW() OSCtxSw() // OSCtxSw()是用于實(shí)現(xiàn)任務(wù)切換的函數(shù)
3.2 OS_CPU_C.C
OS_CPU_C.C包括10個(gè)C函數(shù):OSTaskStkInit()函數(shù)和9個(gè)Hook函數(shù)。OSTaskStkInit()函數(shù)在任務(wù)創(chuàng)建時(shí)被調(diào)用,用來(lái)初始化任務(wù)堆棧。Hook函數(shù)用來(lái)擴(kuò)展µC/OS-II的功能,可以不包含任何代碼,但必須聲明。最后添加Timer0初始化函數(shù),包括選擇工作模式,設(shè)定初值和使能中斷,因?yàn)橐褂肅8051F120的Timer0實(shí)現(xiàn)時(shí)鐘中斷。
在修改OSTaskStkInit()函數(shù)之前,需要先知道任務(wù)堆棧的結(jié)構(gòu)。µC/OS-II為每一個(gè)任務(wù)都分配了任務(wù)堆棧,任務(wù)堆棧由系統(tǒng)堆棧和仿真堆棧兩部分組成。由于C8051F120要求堆棧設(shè)置在片內(nèi)RAM中,而片內(nèi)RAM空間又非常有限,因此所有任務(wù)的任務(wù)堆棧設(shè)置在片內(nèi)RAM中是幾乎不可能的。只能把任務(wù)堆棧存放在片外RAM,并在片內(nèi)RAM設(shè)置一個(gè)公共堆棧,即系統(tǒng)堆棧,棧底地址為?STACK。在任務(wù)切換時(shí),需先保存當(dāng)前任務(wù)堆棧內(nèi)容,再恢復(fù)最高優(yōu)先級(jí)任務(wù)堆棧內(nèi)容,即進(jìn)行任務(wù)堆棧和系統(tǒng)堆棧的復(fù)制。仿真堆棧是用來(lái)為可重入函數(shù)完成參數(shù)傳遞和存放局部變量的,設(shè)置在片外RAM,增長(zhǎng)方向由上向下,棧指針為?C_XBP。
所以,任務(wù)堆棧初始化可以看作是把處于就緒態(tài)的最高優(yōu)先級(jí)任務(wù)的任務(wù)堆棧內(nèi)容復(fù)制到系統(tǒng)堆棧的過(guò)程。首先要獲得任務(wù)堆棧最低地址和長(zhǎng)度,因?yàn)樾枰獜娜蝿?wù)堆棧中恢復(fù)15個(gè)寄存器內(nèi)容到系統(tǒng)堆棧,所以堆棧長(zhǎng)度為15。然后從下向上依次復(fù)制寄存器內(nèi)容,復(fù)制順序是:PCL,PCH,PSW,ACC,B,DPL,DPH,R0,R1,R2,R3,R4,R5,R6,R7。最后保存仿真堆棧地址,并返回任務(wù)堆棧最低地址。這樣就完成了任務(wù)堆棧初始化。
3.3 OS_CPU_A.ASM
OS_CPU_A.ASM包括4個(gè)匯編語(yǔ)言函數(shù),這4個(gè)函數(shù)都是不可重入的,并且定義了系統(tǒng)堆??臻g大小。
OSStartHighRdy ()函數(shù),用來(lái)使就緒態(tài)任務(wù)中優(yōu)先級(jí)最高的任務(wù)開(kāi)始運(yùn)行。OSCtxSw()函數(shù),實(shí)現(xiàn)CPU正常運(yùn)行時(shí)任務(wù)間的切換,即對(duì)當(dāng)前任務(wù)堆棧的保存和對(duì)最高優(yōu)先級(jí)任務(wù)堆棧的彈出,使最高優(yōu)先級(jí)任務(wù)獲取CPU的控制權(quán)。OSIntCtxSw()函數(shù),作用是在中斷服務(wù)程序中執(zhí)行中斷級(jí)別任務(wù)切換。它的絕大多數(shù)代碼和OSCtxSw()函數(shù)是一樣的,區(qū)別在于中斷服務(wù)函數(shù)已經(jīng)保存了寄存器內(nèi)容,則不需要再在OSIntCtxSw()函數(shù)中保存。OSTickISR()函數(shù),是系統(tǒng)時(shí)鐘的中斷服務(wù)程序,主要功能是檢查是否有由于延時(shí)而被掛起的任務(wù)成為就緒任務(wù)。如果有,就調(diào)用OSIntCtxSw()函數(shù)進(jìn)行任務(wù)切換,從而運(yùn)行最高優(yōu)先級(jí)任務(wù)。因?yàn)?micro;C/OS-II在每一個(gè)節(jié)拍都要檢查有沒(méi)有更高優(yōu)先級(jí)的任務(wù)在等待執(zhí)行,如果有,就要進(jìn)行任務(wù)切換。所以,時(shí)鐘節(jié)拍率越高,系統(tǒng)的額外負(fù)荷就越重。
4 系統(tǒng)測(cè)試
按照上述移植步驟,作者在Keil編譯環(huán)境下實(shí)現(xiàn)了µC/OS-II在C8051F120上的具體移植。為了防止在編譯時(shí)出現(xiàn)段過(guò)大的錯(cuò)誤,需要選擇內(nèi)存模式為大模式,并相應(yīng)的在STARTUP.A51 文件中設(shè)置XBPSTACK=1。創(chuàng)建2個(gè)任務(wù)來(lái)驗(yàn)證µC/OS-II移植的成功:
OSTaskCreate (TaskLed, (void *)0, TaskStartStkLed,2);
OSTaskCreate (TaskSmg, (void *)0, TaskStartStkSmg,3);
程序流程圖如圖1所示。任務(wù)TaskLed閃爍1次后,向任務(wù)TaskSmg發(fā)送消息并等待回復(fù),任務(wù)TaskSmg得到消息后顯示閃爍次數(shù),并進(jìn)行回復(fù)。最終效果為P4.0連接的LED閃爍1次,則P5口連接的數(shù)碼管顯示數(shù)字加1,最大顯示為9,之后自動(dòng)清零。經(jīng)過(guò)4小時(shí)的連續(xù)實(shí)驗(yàn),一切運(yùn)行正常,這就驗(yàn)證了移植代碼的正確性。
[align=center]

圖1 程序流程圖[/align]
需要注意的是,C8051F120的使用涉及到SFRPAGR的保護(hù),因?yàn)镃8051F120擁有太多的模擬和數(shù)字資源,它們都需要相應(yīng)的SFR控制,而標(biāo)準(zhǔn)8051保留的SFR空間不能滿足所需的SFR寄存器,所以C8051F120另外安排了SFRPAGE來(lái)擴(kuò)展更多的SFR寄存器空間。同一個(gè)SFR地址配合不同的SFRPAGE值,控制不同的資源。但如果是非中斷情況下發(fā)生任務(wù)切換,并且在新任務(wù)中改變了SFRPAGE,那么回到以前的任務(wù)后很可能SFRPAGE已經(jīng)改變,從而無(wú)法控制正確的資源,還有可能使程序跑飛。因?yàn)椴煌馁Y源往往需要不同的SFRPAGE,為了解決這一問(wèn)題,在所有出現(xiàn)SFRPAGE賦值的地方都應(yīng)當(dāng)作臨界代碼保護(hù)起來(lái),這樣就可以完全避免因SFRPAGE值的錯(cuò)誤而引出的問(wèn)題[6]。
5 結(jié)論
µC/OS-II是一種實(shí)時(shí)性好、代碼量小的多任務(wù)實(shí)時(shí)操作系統(tǒng),具有很好的穩(wěn)定性與可靠性,可廣泛移植到不同構(gòu)架的微處理器上。本文完整的闡述了µC/OS-II的移植過(guò)程,并在C8051F120上實(shí)現(xiàn)了雙任務(wù)同步通信。論文對(duì)51系列單片機(jī)的µC/OS-II移植具有普遍的指導(dǎo)意義。