薛晴
(北京郵電大學 信息與通信工程學院,北京100876)
μC/OS-II系統(tǒng)是一款源碼公開的,針對嵌入式系統(tǒng)的實時內(nèi)核操作系統(tǒng),與其它實時操作系統(tǒng)如Vxworks,Linux和Windows CE等相比,它比較適用于小型控制系統(tǒng),同時具有執(zhí)行效率高、占用空間小、實時性能優(yōu)良和可擴展性強等優(yōu)點[4]。
LPC1788是恩智浦公司于2011年底推出的業(yè)界首款采用ARM?CortexTM-M3技術的微控制器,目前已批量上市。120 MHz的LPC178x系列擁有512 kB閃存、96 kB SRAM和4 kB EEPROM。32位外部存儲控制器支持SDRAM、NOR和SRAM器件,提供4種芯片選擇[2]。其先進的低功耗工藝,特別適用于消費電子、工業(yè)控制、安防、通訊系統(tǒng),以及需要高速計算的數(shù)據(jù)采集系統(tǒng)領域。
由于該款微處理器上市時間較短,目前還沒有μC/OS-II操作系統(tǒng)應用于該款微處理器的移植代碼。文中詳細探討了在IAR6.3集成開發(fā)環(huán)境下,如何在LPC1788處理器上移植μC/OS-II操作系統(tǒng)的過程與實現(xiàn)步驟,該移植與開發(fā)過程已成功地在LPC1788目標板上進行了運行測試。
圖1說明了μC/OS-II的軟硬件體系結(jié)構(gòu)。應用程序處于整個系統(tǒng)的頂層,每個任務都可以認為自己獨占了CPU,因而可以設計成一個無限循環(huán)。μC/OS-II與處理器無關的代碼,提供了μC/OS-II的系統(tǒng)服務,應用程序可以使用這些API函數(shù)進行內(nèi)存管理、任務間通信及創(chuàng)建、刪除任務。其中,μC/OS-II內(nèi)核最核心的作用就是對任務的管理。
圖1 μC/OS-II的系統(tǒng)總體結(jié)構(gòu)圖Fig.1 Structure diagram of μC/OS-II system
μC/OS—II的任務擁有自己的代碼和堆??臻g (保存該任務的寄存器、返回地址和臨時參數(shù)),一般都是空函數(shù),不會返回任何值。任務執(zhí)行一次后,設置延時參數(shù)OSTCBDly。表明在經(jīng)過OSTCBDly個時鐘周期后再次運行,然后任務進行切換.使其他任務運行。
μC/OS-Ⅱ下的任務有 5種狀態(tài):睡眠態(tài)、就緒態(tài)、運行態(tài)、等待狀態(tài)、中斷服務態(tài)。調(diào)度就是決定該輪到哪個任務運行了,從而使一就緒的任務切換到運行態(tài),這是內(nèi)核的主要職責之一。μC/OS-Ⅱ是基于優(yōu)先級調(diào)度算法的:也就是讓處于就緒態(tài)、優(yōu)先級最高的任務先運行。
由圖 1可知,μC/OS-Ⅱ的接口文件是 OS_CPU.H,OS_CPU_C.C和OS_CPU_A.ASM,移植的主要任務是改寫這3個文件的代碼,使μC/OS-Ⅱ能在LPC1788上正常運行。移植工作包括以下幾個內(nèi)容:
2.1 OS_CPU.H包括了用#defines定義的與處理器相關的常量,宏和類型定義,堆棧寬度和增長方式以及開關中斷的宏定義[6]。
在IAR6.3環(huán)境下改寫該文件時的幾點說明:
1)由于Cortex-M3內(nèi)核堆棧支持從上往下的生長方式,所以L1根據(jù)所選芯片LPC1788支持的類型對宏OS_STK_GRWOTH進行定義,
2)因LPC1788的狀態(tài)寄存器是32位寬,L2,L3定義的os_cpu_sr用于OS_CRITICAL_METHOD#3.中保存中斷狀態(tài)[3]。
3)OS_CPU.H文件中另外3個宏OS_CRITICAL_METHOD,OS_ENTER_CRITICAL (),OS_EXIT_CRITICAL()用于定義開關中斷的方式及開關中斷的實現(xiàn)。而OS_CPU_SR_Save()和 OS_CPU_SR_Restore(cpu_sr)的代碼則在OS_CPU_A.asm文件中匯編語言編寫,稍候會詳細介紹。
4)任務級的切換是通過調(diào)用L6的宏OS_TASK_SW()來實現(xiàn),OSCtxSw()的具體代碼在 OS_CPU_A.asm中用匯編語言實現(xiàn)。
在OS_CPU_C.C中要求用戶編寫8個簡單的C函數(shù):OSTaskStkInit ()、OSTaskCreateHook ()、OSTaskDelHook ()、OSTaskSwHook ()、OSTaskStatHook ()、OSTimeTickHook ()、OS_TaskStkIni ()、OS_CPU_SysTickInit ()、OS_CPU_SysTick Handler(),除三個必須的函數(shù) OS_TaskStkIni,OS_CPU_SysTickInit和OS_CPU_SysTickHandler外,其它的5個函數(shù)是鉤子函數(shù),必須聲明但沒必要包含代碼。
1) OSTaskStkInit()函數(shù)
定義任務堆棧初始化函數(shù)OSTaskStkIni()的具體程序及注釋如下所示::
μC/OS-Ⅱ要求用戶提供一個周期性的時鐘源,以實現(xiàn)時間延遲和超時確認功能,時鐘節(jié)拍每秒發(fā)生10~100次。必須在開始多任務后,啟動時鐘節(jié)拍中斷,所以可以在OSStart()運行之后,μC/OS啟動的第1個任務中調(diào)用OS_CPU_SysTickInit()初始化節(jié)拍中斷?;贚PC1788移植下的時鐘初始化函數(shù)的OS_CPU_SysTickInit()的代碼如下所示:OSIntExit();} /*告訴 uC/OS-II退出中斷服務程序*/當時鐘節(jié)拍中斷發(fā)生時,CPU會自動把CPU寄存器推人堆棧。當某任務的任務控制塊中時間延時項OSTCBDly減到了零,OSTimtick()就進入了就緒態(tài)。 OSIntExit()會調(diào)用中斷級的任務切換函數(shù)OSIntCtxSw執(zhí)行任務切換,而不再執(zhí)行后面的指令。
在OS_CPU_A.ASM中,因為C語言不能直接存取寄存器,用戶在移植μC/OS-Ⅱ的時候,需要用匯編語言編寫5個函 數(shù) : OS_CPU_SR_Save ()、OS_CPU_SR_Restore ()、OSStartHighRdy ()、OSCtxSw ()、OS_CPU_PendSVHandler ()。如下所示:
1) OS_CPU_SR_Save()函數(shù)
OS_CPU_SR_Save()函數(shù)實現(xiàn)用R0保存中斷屏蔽寄存器PRIMASK的狀態(tài)值,該函數(shù)被OS_ENTER_CRITICAL()宏調(diào)用[3]。
4) OSCtxSw()函數(shù)
當一個任務放棄對CPU的控制后,OSCtxSw()就會被調(diào)用以實現(xiàn)任務切換,但對于ARM Cortex-M3來說,所有的任務切換都是由PendSV中斷服務程序來實現(xiàn)的,所以OSCtxSw()只是簡單觸發(fā)PendSV中斷,然后返回調(diào)用者。
OS_CPU_PendSVHandler()負責處理 ARM Cortex-M3 所有的任務切換[3],在該程序開始執(zhí)行時,CPU首先把xPSR、PC、LR、R12,R0-R3和R4-R11寄存器保存到任務堆棧,然后獲得最高優(yōu)先級任務的堆棧指針,將最高優(yōu)先級任務的寄存器按順序從任務堆棧中恢復出來,最后執(zhí)行中斷返回:
不同任務的切換會發(fā)生在停止當前低優(yōu)先級的任務轉(zhuǎn)而去執(zhí)行較高優(yōu)先級任務的情形,這是由一個任務級切換函數(shù)OS_TASK_SW()實現(xiàn)的,該函數(shù)通過調(diào)用 OSCtxSw()函數(shù)觸 發(fā) PendSV中 斷 ,PendSV中 斷 服 務 程 序OS_CPU_PendSVHandler完成具體的任務切換操作。OS_CPU_PendSVHandler的編寫實質(zhì)上是通過改變PC中的內(nèi)容來實現(xiàn)的,首先將當前任務環(huán)境保存到相應的任務堆棧中,同時將PC指向新任務開始運行的地方,然后將新任務環(huán)境從堆棧中恢復到相應的寄存器中,最后執(zhí)行中斷返回。在中斷返回時,Cortex-M3將從堆棧中恢復R3-R0,R12,LR,PC和xPSR寄存器,開始運行新任務,從而實現(xiàn)任務的切換。
文中使用LPC1788目標板對上述移植進行了實驗測試,目標板有四個按鍵和兩個LED,本測試建立了App_TaskStart()、App_TaskKbd()、App_TaskLed()三個任務。 App_TaskStart()負責硬件初始化及OS初始化,建立消息郵箱及另兩個任務,然后進入無限循環(huán),在循環(huán)體內(nèi)調(diào)用OSTimeDly(200)以實現(xiàn)延時和任務調(diào)度。App_TaskKbd()負責查詢按鍵并通過消息郵箱將鍵值發(fā)送給任務App_TaskLed(),App_TaskLed()根據(jù)鍵值改變LED的閃爍頻率。測試程序通過IAR6.3編譯,把生成的二進制文件固化到LPC1788目標板上,接通電源后可以準確穩(wěn)定地運行,說明在IAR6.3環(huán)境下基于LPC1788的μC/OS-II移植成功。
文中分析了μC/OS-Ⅱ內(nèi)核的文件結(jié)構(gòu)及基本工作原理,成功實現(xiàn)了其在LPC1788上的移植。文中相應的源代碼不用作任何改變,直接復制到μC/OS-Ⅱ相應文件中,可順利實現(xiàn)多任務調(diào)度,且運行穩(wěn)定、可靠,可以進行ARM Cortex-M3微控制器LPC17xx系列的各種應用系統(tǒng)的設計與開發(fā)。
[1]Jean J.Labrosse.嵌入式實時操作系統(tǒng)μC/OS-Ⅱ [M].2版.邵貝貝,譯.北京航空航天大學出版社,2003.
[2]NXP LPC178x/7x preliminary user manual,[EB.OL]2011.http://www.nxp.com
[3]Micriμm μC/OS-II and ARM Cortex-M3 Processors Application Note(2011)http://www.Micrium.com
[4]孫繼如,郭敏,張宇翔,等.嵌入式實時操作系統(tǒng)μC/OS-Ⅱ在LPC2378上的移植及應用[J].現(xiàn)代電子技術,2010(12):33-36.
SUN Ji-ru,GUO Min,ZHANG Yu-xiang,et al.Transplant and application of the embedded real-time OS μC/OS-Ⅱon LPC2378[J].Modern Electronics Technique,2010(12):33-36.
[5]顧鳳玉,施國梁,楊濤.基于LPC2478的μC/OS-II的移植及多任務的實現(xiàn)[J].電腦知識與技術,2009(5):1736-1739.GU Feng-yu,SHI Guo-liang,YANG Tao.On the porting of μC/OS-II to LPC2478 ARM processor and the implementation of multitasks[J].Computer Knowledge and Technology,2009(5):1736-1739.
[6]韓明峰,李小濱,鄭永志.uC/OS-II內(nèi)核超時等待機制的分析與改進[J].計算機工程, 2009,35(7):259-266.
HAN Ming-feng,LI Xiao-bin,ZHENG Yong-zhi.Analysis and improvement of waiting-timeout mechanism in uC/OS-II Kernel[J].Computer Engineering,2009,35(7):259-266.
[7]劉艷軍.基于C8051和μC/OS-Ⅱ的數(shù)控機床嵌入式執(zhí)行控制器實現(xiàn)[J].現(xiàn)代電子技術,2010(16):63-65.
LIU Yan-jun.Realization of embedded actuator&Controller for CNC machine tool based on C8051 and μC/OS-Ⅱ[J].Modern Electronics Technique,2010(16):63-65.
[8]汪獻忠,郭鳳華,田增國.基于ARM和μC/OS-Ⅱ的在線磷酸根離子監(jiān)測儀設計[J].現(xiàn)代電子技術,2010(19):154-155,158.
WANG Xian-zhong,GUO Feng-hua,TIAN Zeng-guo.Design of phosphate ion online monitoring instrument based on ARM and μC/OS-Ⅱ[J].Modern Electronics Technique,2010(19):154-155,158.