摘 要: 介紹了實時操作系統μC/OS-II的特點和內核結構,并實現了μC/OS-II在Philips嵌入式處理器LPC2114上的移植。
關鍵詞: μC/OS-II LPC2114 移植
作為一個實時內核,μC/OS從1992年開始為人們熟悉,到現在已經發展為μC/OS-II。μC/OS-II最多支持56個任務,其內核為占先式,即總是執行就緒態的優先級最高的任務,并支持Semaphore(信號量)、Mailbox(郵箱)、Message Queue(消息隊列)等多種常用的進程間通信機制。與大多數商用RTOS不同的是,μC/OS-II公開其全部源代碼,并可以免費獲得,對商業應用只收取少量的License費用。
LPC2114是Philips公司開發的一款支持實時仿真和跟蹤的ARM7TDMI-S CPU,并嵌入了128KB的高速Flash存儲器。其內部集成了與片內存儲器控制器接口的ARM7局部總線、與中斷控制器接口的AMBA高性能總線(AHB)和連接片內外設功能的VLSI外設總線(VPB,ARM AMBA總線的兼容超集)。LPC2114將ARM7TDMI-S配置為小端(little-endian)字節順序。128位寬度的存儲器接口和獨特的加速結構使32位代碼能夠在最大時鐘頻率下運行。
將μC/OS-II移植在LPC2119上不僅有益于ARM和μC/OS-II在車用控制器上的應用,其成果還可以用于其他嵌入式工業控制領域。本次移植中,使用CodeWarrior For ARM Developer Suite v1.2編譯調試環境。
1 μC/OS-II系統結構
圖1為μC/OS-II的軟硬件體系結構。應用程序處于整個系統的頂層,每個任務都可以認為自己獨占了CPU,因而可以設計成為一個無限循環。μC/OS-II處理器無關的代碼提供了μC/OS-II的系統服務,應用程序可以使用這些API函數進行內存管理、任務間通信以及創建、刪除任務等。
大部分μC/OS-II代碼是使用ANSI C語言編寫的,因此μC/OS-II的可移植性較好。盡管如此,仍然需要使用C和匯編語言寫一些處理器相關的代碼。μC/OS-II的移植需要滿足下列要求:(1)處理器的C編譯器可以產生可重入代碼。(2)可以使用C調用進入和退出Critical Code(臨界區代碼)。(3)處理器必須支持硬件中斷,并且需要一個定時中斷源。(4)處理器需要能夠容納一定數據的硬件堆棧。(5)處理器需要有能夠在CPU寄存器與內存和堆棧交換數據的指令。
移植μC/OS-II的主要工作涉及處理器及編譯器相關代碼以及BSP的編寫。
2 μC/OS-II BSP的編寫
BSP(板級支持包)是介于底層硬件和操作系統之間的軟件層次,它完成系統上電后最初的硬件和軟件初始化,并對底層硬件進行封裝,使得操作系統不再面對具體的硬件。
為μC/OS-II編寫一個簡單的BSP的方法是:首先設置CPU內部寄存器和系統堆棧,并初始化堆棧指針,建立程序的運行和調用環境;然后使用C語言設置LPC2114向量中斷控制器、GPIO以及SRAM控制器,初始化串口(UART0)作為默認打印口,并向操作系統提供一些硬件相關例程和函數(如dprintf( )),以方便調試;在CPU、板級和程序自身初始化完成后,就可以把CPU的控制權交給操作系統了。
LPC2114處理器支持七種類型的異常。異常出現后,CPU強制從異常類型對應的固定存儲地址開始執行程序,因此需要在程序頭建立起異常向量表,例如:
向量從上到下依次為復位、未定義指令異常、軟件中斷、預取指令中止、預取數據中止、保留的異常、IRQ和FIQ。保留的異常向量位置所填的數據0xb9205f80是為了使向量表中所有的數據32位累加和為0。這個向量在ARM文件中標識為保留,該位置被Boot裝載程序用作有效的用戶程序關鍵字。當向量表中所有的數據累加為0(且外部硬件禁止進入ISP程序)時,Boot裝載程序將執行用戶程序。
從異常向量表可知:芯片復位時程序會跳轉到標號Reset處。程序首先調用InitStack初始化各種模式的堆棧,然后調用TargetResetInit對系統進行基本的初始化,最后跳轉到ADS提供的啟動代碼__main。例如:
Reset
BL InitStack
BL TargetResetInit
B__main
同時在每個硬件時鐘到來后,μC/OS-II會在中斷服務例程中調用OSIntCtxSw( )進行任務調度。另外,當某個任務因等待資源而被掛起時,它可以自己主動放棄CPU,而沒有必要等到自己的時間片全都用完。這可以通過調用一個任務級的任務調度函數OSCtxSw( )來實現,其中相對復雜的是OSIntCtxSw( )。由于OSLickISR( )調用了 OSIntExit( ),OSIntExit( )又再次調用了OSIntCtxSw( ),如果進行任務切換,則二次調用都不會返回,而不同的C編譯器、不同的編譯選項處理C調用時對堆棧的使用也不盡相同。因此OSIntCtxSw( )是與編譯器相關的。在ADS編譯環境下,OSIntCtxSw的軟件流程如圖2所示。
3 μC/OS-II 任務堆棧初始化
μC/OS-II中每個任務都有自己的任務堆棧。在任務創建初期由OSTaskStkInit( )初始化。初始化堆棧的目的就是模擬一次中斷。任務堆棧中保存了任務代碼的起始地址和一些CPU寄存器(初值是無關緊要的),這樣一旦條件滿足,就可以執行任務了。LPC2114在中斷發生時,會自動保存程序指針PC、狀態寄存器SR以及其他一些信息。圖3為針對LPC2114編程結構設計的堆棧結構。
本次移植的函數OSTaskStkInt( )代碼為:
4 μC/OS-II系統時鐘管理
μC/OS-II需要在系統初始化時開始一個系統時鐘節拍,它是OS系統的時間基準。該時鐘節拍一般由時間中斷產生。LPC2114中可產生時鐘節拍的模塊很多,本次移植采用定時器0異常。因為它與外部中斷使用不同的異常向量,便于對異常事件的管理,有利于提高OS的穩定性。32位定時器TC的計數頻率由plck經過PR分頻控制得到,而定時器的啟動/停止、計數復位由TCR控制。當有捕獲事件或比較匹配事件發生時,IR會設置相關的中斷標志,若已打開中斷允許,則會產生中斷。
本次移植設置系統時鐘頻率為11.0592MHz,代碼在時鐘初始化和每次進入定時器0異常時,將定時器0的計數器PWMTC設置為11.0592M/OS_TICKS_PER_SEC,這樣可使OS每秒鐘產生OS_TICKS_PER_SEC的時鐘節拍。
5 應用方法
在使用移植后的OS時,用戶需要編寫自己的主程序main( ),其流程圖如圖4。在適當的初始化后即可啟動OS。
另外,用戶需在TaskStart任務中啟動時鐘節拍,調用OS_StartInit( )函數初始化統計任務,創建所需的其他任務,最后調用OSTaskDel( )函數刪除TaskStart任務。OS在該函數調用結束后,會自動允許異常和中斷,OS正常運轉,不斷調度任務,響應中斷。
參考文獻
1 LABROSSE J J.μC/OS-II:the Real Time Kernel.RS:R&D
Books,1999
2 周立功.ARM微控制器基礎與實戰.北京:北京航空航天大學出版社,2003
3 Labrosse J著,邵貝貝譯.嵌入式實時操作系統μC/OS-II(第二版).北京:北京航空航天大學出版社,2003