摘要:μC/OS-II具有執行效率高、占用空間小、實時性能優良和可擴展性能好等特點。本論文敘述了μC/OS-II的特點和文件結構,詳細分析了μC/OS-II在AVRmega128單片機上的移植,并對移植后的系統進行了測試。移植后的系統工作穩定,性能良好。
關鍵詞:μC/OS-II;移植;AVR;單片機
1 引言
μC/OS-II是一種專門為微處理器設計的搶占式實時多任務操作系統,具有源代碼公開、可移植性、可裁減、穩定性和可靠性高等特點。其內核主要提供進程管理、時間管理、內存管理等服務,系統最多支持56個任務,每個任務均有自己單獨的優先級。由于其內核為搶占式,所以總是運行優先級最高的任務。系統提供了豐富的API函數,便于實現進程間的通信及進程狀態的轉化。μC/OS-II是為嵌入式應用編寫的通用軟件,在具體應用時需根據不同單片機的特點進行移植,其大部分代碼是用標準C語言所寫,只有與處理器相關的一部分代碼用匯編語言寫成,因而具有很強的移植性,能在多數8位、16位、32位單片機及數字信號處理器上實現運行。[1]μC/OS-II源碼開放,許多移植的范例可以從網站上得到,用戶只要有標準的ANSI C交叉編譯器、匯編器、連接器等軟件工具,就可以將μC/OS-II嵌入到開發的產品中。μC/OS-Ⅱ的移植對硬件是有一定要求的,目前大多數的移植都針對ARM完成的,考慮到研究和學習的用途,本論文選用了AVRmega128單片機作為移植的對象。
2 μC/OS-II的文件結構
在μC/OS-II的文件結構中:
與軟件相關的有兩個頭文件,INCLUDES.H和OS_CFG.H。INCLUDES.H是μC/OS-II的主要頭文件,在每個.C文件都要包含這個頭文件。INCLUDES.H文件把工程項目中應包含的頭文件都集中到一起,使得開發者無須過多考慮。由于在移植過程中該INCLUDES.H頭文件內容不能完全滿足需要,還要對該文件進行修改。OS_CFG.H是配置文件,μC/OS-II是依靠編譯時的條件編譯來實現軟件系統裁剪性的。即把用戶可裁剪代碼寫在#if和 #endif預編譯指令之間,在編譯時根據#if預編譯指令后面常數的值來確定是否該代碼段進行編譯。
與硬件相關的文件主要是OS_CPU.H、OS_CPU_A.ASM和OS_CPU_C.C文件。OS_CPU.H文件是與應用核心相關的文件,在移植中要對該頭文件中與處理器相關的常數和宏進行修改;OS_CPU_A.ASM文件集合了所有與處理器相關的匯編語言代碼模塊;OS_CPU_C.C文件集中了所有與處理器相關的C語言代碼。
筆者將對這幾個文件的修改進行詳細敘述。
3 μC/OS-II移植與相關代碼分析
由于AVR mega128的硬件結構為系統的移植提供了一個良好的平臺,在本論文中采用ICC AVR 6.31A作為編譯器,下面對要移植代碼的重要部分進行編寫和分析。
3.1OS_CPU.H的修改
3.1.1選擇進入和離開臨界區的方法
在OS_CPU.H 文件中用#define設置OS_CRITICAL_METHOD的值,用以選擇進入和離開臨界區的方法。在本次移植中選用先將中斷關閉的狀態保存到堆棧中,然后關閉中斷,即:#defineOS_CRITICAL_METHOD2
3.1.2設置堆棧的增長方向
在OS_CPU.H中用#define聲明宏OS_STK_GROWTH 設置堆棧的增長方向,在這里我們把堆棧的增長方向設置為從上向下增長,即: #defineOS_STK_GROWTH1
3.2OS_CPU_C.C的修改
在OS_CPU_C.C中的有十個函數與用戶移植相關,但實際需要修改的只有OSTaskStkInit()函數,其它九個函數都是由用戶定義的。如果用戶需要使用這九個函數,可將文件OS_CFG.H中的constant OS_CPU_HOOKS_EN設為1,設為0表示不使用這些函數。函數OSTaskStkInit()是由OSTaskCreate()或OSTaskCreateExt()調用,用來初始化任務堆棧的。經初始化后的任務堆棧應該跟發生過一次中斷后任務的堆棧結構一樣。ATmega128發生中斷后,自動保存了程序計數器PC。為了保存全部現場,還需要保存狀態寄存器SREG,通用寄存器及SP的值。[2]
3.3OS_CPU_A.ASM中幾個匯編函數的編寫
3.3.1OSStartHighRdy函數的編寫
OSStartHighRdy()函數的功能是讓進入就緒態的優先級最高的任務運行。他由OSStart()函數調用,在調用OSStart()函數之前,必須先調用OSInit()函數,且已經建立了至少1個任務。OSStartHighRdy()的默認指針OSTCBHighRdy指向優先級最高的就緒態任務的任務。其它C語言文件可以以OSStartHighRdy()的形式對它進行調用。POP_SP,POP_SREG,POP_ALL是三個宏。其作用是恢復任務現場。當執行RET指令后,當前任務的地址將被裝入PC,從而開始執行當前任務。任務現場的恢復順序應該同自定義的任務棧的存儲順序一致,否則會出現出入棧錯誤。[3]
3.3.2任務級的任務切換函數OSCtxSw()的編寫
OSCtxSw()是一個任務級的任務切換函數,它主要完成以下幾件事:保存當前任務現場;保存當前任務的任務棧指針到當前任務的任務控制塊;切換最高優先級任務為當前任務;使SP指向最高優先級任務的任務棧的棧頂;恢復新任務的運行環境。由于ATmega128沒有軟中斷指令,只能通過匯編子程序來模擬中斷。
3.3.3中斷級任務切換函數OSIntCtxSw()的編寫
由于中斷可能會使更高優先級的任務進入就緒態。為了讓更高優先級的任務能立即運行,所以需要在中斷中進行任務切換。在中斷服務子程序的最后,OSIntExit()函數會調用OSIntCtxSw()做任務切換。OSIntCtxSw()是一個中斷級的任務切換函數。由于在此之前,中斷服務程序已經保存了被中斷任務的現場,因此不需要再保存現場了。中斷級任務切換函數OSIntCtxSw()的其它操作跟OSCtxSw()一樣,它的程序如下:
_OSIntCtxSw::
CALL_OSTaskSwHook;調用用戶接口程序
LDSR16,_OSPrioHighRdy;把最高優先級的任務切換為當前任務
STS _OSPrioCur,R16; OSPrioCur = OSPrioHighRdy
LDS R30,_OSTCBHighRdy; Z = OSTCBHighRdy->OSTCBStkPtr
LDS R31,_OSTCBHighRdy+1
STS _OSTCBCur,R30;將新任務的堆棧指針保存到
STS _OSTCBCur+1,R31; 任務控制塊中
LDR28,Z+
LDR29,Z+
POP_SP;恢復任務運行的環境
POP_SREG
POP_ALL
RET; 轉到新任務中去執行
3.3.4時鐘節拍中斷函數OSTickISR()編寫
μC/OS-II要求用戶提供一個周期行的時鐘源,來實現時間的延時和超時功能。為了達到這一要求,可以使用硬件定時器,也可以從交流電中獲得50/60Hz的時鐘頻率。本文是采用ATmega128的硬件定時器2溢出中斷來獲得周期為10ms的時鐘節拍。程序如下:
_OSTickISR::
PUSH_ALL;保存當前任務現場
INR16,SREG;保存SREG寄存器
SBR R16,0x80;使該保存值含有中斷允許信息
ST-Y,R16
PUSH_SP;保存任務硬件堆棧指針到任務棧中
LDS R16,_OSIntNesting;告訴uC/OS-II發生了中斷
INC R16;中斷嵌套計數器加1
STS _OSIntNesting,R16
CPI R16,1
BRNEOSTickISR_1
LDS R30,_OSTCBCur
LDS R31,_OSTCBCur+1
STZ+,R228
STZ+,R29
OSTickISR_1:
CALL_OSTickISR_Handler;調用OSTickISR_Handler
CALL_OSIntExit;調用OSIntExit
POP_SP
POP_SREG
POP_ALL
RET
還要增加定時器初始化工作的代碼:
voidOSTickISR_Init (void)
{TCCR2 = 0x00;
TCNT2 = 256 - (8000000 / 100 / 1024);
TCCR2 = 0x05;
TIMSK = 0x40;}
4仿真調試
4.1系統時鐘準確性的驗證
任何操作系統都需要提供一個周期性的時鐘源,以供系統處理諸如任務等待,延時等與時間有關的事情。如果時鐘源的工作不正常或者設置不正確,不但會影響系統執行任務的準確性而且很可能造成不可預測的后果,所以有必要對系統時鐘源的準確性進行測試,在這里,利用Proteus 7中的虛擬示波器對系統的時鐘源進行測試。具體的測試方法如下:利用系統周期性的時鐘節拍中斷輸出一個方波,虛擬示波器來檢測。測試代碼如下:
voidOSTickISR_Handler (void)
{TCNT2= 256 - (4000000 / 100 / 1024);
PORTF=~PORTF;
OSTimeTick();}
上面的函數是由時鐘節拍中斷函數OSTickISR()調用的,圖1是在Proteus 7中時鐘節拍的驗證圖。圖中示波器打在10毫秒檔位上,方波的的半周期是10毫秒,跟時鐘節拍中斷程序的定時時間設置相同,證明時鐘節拍正常。

4.2 系統性能測試
操作系統移植后的性能是直接影響開發產品性能的,如果操作系統不能在高負荷下運作,那么移植后的系統在實際中將不能普及應用。所以對系統的性能測試是必不可少的。
具體的測試方法是開啟系統的所有功能,啟動四個任務,每個任務分別完成不同的功能。每個任務的功能占用的I/O口如表1[4]所示。

圖2中,左上角和右上角顯示的信息是單片機兩個同時對外發送的信息。在虛擬示波器中第一條曲線是單片機I/O口輸出方波的波形,而第二和第三條曲線則是單片機輸出PWM的波形。可以看出在每個任務在延時一個時鐘節拍的情況下,系統可以順利完成任務,沒有出現異常情況。可見移植后的系統具有良好的實時性。可以滿足大部分工程開發的需要。

5 結論
詳細分析了μC/OS-II在AVRmega128單片機上的移植。并對移植后的系統進行了測試。移植后的系統工作穩定,性能良好。本設計思路明晰,應用廣泛。其可廣泛適用于大部分的工程開發中,也可以用于教學。
參考文獻
[1]任哲,潘樹林,房紅征. 嵌入式操作系統基礎μC/OS-II和Linux[M].北京:北京航空航天大學出版社,2006.
[2]霍宏偉.ATmega128/2560系列單片機原理與高級應用[M].北京:中國林業出版社,2006.
[3]任哲.嵌入式實時操作系統μC\\OS-Ⅱ原理及應用[M].北京:北京航空航天大學出版社,2005.
[4]陳是知.μC/OS-II 內核分析、移植與驅動程序開發[M].北京:人民郵電出版社,2008.