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