薛晴
(北京郵電大學 信息與通信工程學院,北京100876)
μC/OS-II系統是一款源碼公開的,針對嵌入式系統的實時內核操作系統,與其它實時操作系統如Vxworks,Linux和Windows CE等相比,它比較適用于小型控制系統,同時具有執行效率高、占用空間小、實時性能優良和可擴展性強等優點[4]。
LPC1788是恩智浦公司于2011年底推出的業界首款采用ARM?CortexTM-M3技術的微控制器,目前已批量上市。120 MHz的LPC178x系列擁有512 kB閃存、96 kB SRAM和4 kB EEPROM。32位外部存儲控制器支持SDRAM、NOR和SRAM器件,提供4種芯片選擇[2]。其先進的低功耗工藝,特別適用于消費電子、工業控制、安防、通訊系統,以及需要高速計算的數據采集系統領域。
由于該款微處理器上市時間較短,目前還沒有μC/OS-II操作系統應用于該款微處理器的移植代碼。文中詳細探討了在IAR6.3集成開發環境下,如何在LPC1788處理器上移植μC/OS-II操作系統的過程與實現步驟,該移植與開發過程已成功地在LPC1788目標板上進行了運行測試。
圖1說明了μC/OS-II的軟硬件體系結構。應用程序處于整個系統的頂層,每個任務都可以認為自己獨占了CPU,因而可以設計成一個無限循環。μC/OS-II與處理器無關的代碼,提供了μC/OS-II的系統服務,應用程序可以使用這些API函數進行內存管理、任務間通信及創建、刪除任務。其中,μC/OS-II內核最核心的作用就是對任務的管理。

圖1 μC/OS-II的系統總體結構圖Fig.1 Structure diagram of μC/OS-II system
μC/OS—II的任務擁有自己的代碼和堆棧空間 (保存該任務的寄存器、返回地址和臨時參數),一般都是空函數,不會返回任何值。任務執行一次后,設置延時參數OSTCBDly。表明在經過OSTCBDly個時鐘周期后再次運行,然后任務進行切換.使其他任務運行。
μC/OS-Ⅱ下的任務有 5種狀態:睡眠態、就緒態、運行態、等待狀態、中斷服務態。調度就是決定該輪到哪個任務運行了,從而使一就緒的任務切換到運行態,這是內核的主要職責之一。μC/OS-Ⅱ是基于優先級調度算法的:也就是讓處于就緒態、優先級最高的任務先運行。
由圖 1可知,μC/OS-Ⅱ的接口文件是 OS_CPU.H,OS_CPU_C.C和OS_CPU_A.ASM,移植的主要任務是改寫這3個文件的代碼,使μC/OS-Ⅱ能在LPC1788上正常運行。移植工作包括以下幾個內容:
2.1 OS_CPU.H包括了用#defines定義的與處理器相關的常量,宏和類型定義,堆棧寬度和增長方式以及開關中斷的宏定義[6]。

在IAR6.3環境下改寫該文件時的幾點說明:
1)由于Cortex-M3內核堆棧支持從上往下的生長方式,所以L1根據所選芯片LPC1788支持的類型對宏OS_STK_GRWOTH進行定義,
2)因LPC1788的狀態寄存器是32位寬,L2,L3定義的os_cpu_sr用于OS_CRITICAL_METHOD#3.中保存中斷狀態[3]。
3)OS_CPU.H文件中另外3個宏OS_CRITICAL_METHOD,OS_ENTER_CRITICAL (),OS_EXIT_CRITICAL()用于定義開關中斷的方式及開關中斷的實現。而OS_CPU_SR_Save()和 OS_CPU_SR_Restore(cpu_sr)的代碼則在OS_CPU_A.asm文件中匯編語言編寫,稍候會詳細介紹。
4)任務級的切換是通過調用L6的宏OS_TASK_SW()來實現,OSCtxSw()的具體代碼在 OS_CPU_A.asm中用匯編語言實現。
在OS_CPU_C.C中要求用戶編寫8個簡單的C函數:OSTaskStkInit ()、OSTaskCreateHook ()、OSTaskDelHook ()、OSTaskSwHook ()、OSTaskStatHook ()、OSTimeTickHook ()、OS_TaskStkIni ()、OS_CPU_SysTickInit ()、OS_CPU_SysTick Handler(),除三個必須的函數 OS_TaskStkIni,OS_CPU_SysTickInit和OS_CPU_SysTickHandler外,其它的5個函數是鉤子函數,必須聲明但沒必要包含代碼。
1) OSTaskStkInit()函數
定義任務堆棧初始化函數OSTaskStkIni()的具體程序及注釋如下所示::

μC/OS-Ⅱ要求用戶提供一個周期性的時鐘源,以實現時間延遲和超時確認功能,時鐘節拍每秒發生10~100次。必須在開始多任務后,啟動時鐘節拍中斷,所以可以在OSStart()運行之后,μC/OS啟動的第1個任務中調用OS_CPU_SysTickInit()初始化節拍中斷。基于LPC1788移植下的時鐘初始化函數的OS_CPU_SysTickInit()的代碼如下所示:OSIntExit();} /*告訴 uC/OS-II退出中斷服務程序*/當時鐘節拍中斷發生時,CPU會自動把CPU寄存器推人堆棧。當某任務的任務控制塊中時間延時項OSTCBDly減到了零,OSTimtick()就進入了就緒態。 OSIntExit()會調用中斷級的任務切換函數OSIntCtxSw執行任務切換,而不再執行后面的指令。


在OS_CPU_A.ASM中,因為C語言不能直接存取寄存器,用戶在移植μC/OS-Ⅱ的時候,需要用匯編語言編寫5個函 數 : OS_CPU_SR_Save ()、OS_CPU_SR_Restore ()、OSStartHighRdy ()、OSCtxSw ()、OS_CPU_PendSVHandler ()。如下所示:
1) OS_CPU_SR_Save()函數
OS_CPU_SR_Save()函數實現用R0保存中斷屏蔽寄存器PRIMASK的狀態值,該函數被OS_ENTER_CRITICAL()宏調用[3]。


4) OSCtxSw()函數
當一個任務放棄對CPU的控制后,OSCtxSw()就會被調用以實現任務切換,但對于ARM Cortex-M3來說,所有的任務切換都是由PendSV中斷服務程序來實現的,所以OSCtxSw()只是簡單觸發PendSV中斷,然后返回調用者。

OS_CPU_PendSVHandler()負責處理 ARM Cortex-M3 所有的任務切換[3],在該程序開始執行時,CPU首先把xPSR、PC、LR、R12,R0-R3和R4-R11寄存器保存到任務堆棧,然后獲得最高優先級任務的堆棧指針,將最高優先級任務的寄存器按順序從任務堆棧中恢復出來,最后執行中斷返回:

不同任務的切換會發生在停止當前低優先級的任務轉而去執行較高優先級任務的情形,這是由一個任務級切換函數OS_TASK_SW()實現的,該函數通過調用 OSCtxSw()函數觸 發 PendSV中 斷 ,PendSV中 斷 服 務 程 序OS_CPU_PendSVHandler完成具體的任務切換操作。OS_CPU_PendSVHandler的編寫實質上是通過改變PC中的內容來實現的,首先將當前任務環境保存到相應的任務堆棧中,同時將PC指向新任務開始運行的地方,然后將新任務環境從堆棧中恢復到相應的寄存器中,最后執行中斷返回。在中斷返回時,Cortex-M3將從堆棧中恢復R3-R0,R12,LR,PC和xPSR寄存器,開始運行新任務,從而實現任務的切換。
文中使用LPC1788目標板對上述移植進行了實驗測試,目標板有四個按鍵和兩個LED,本測試建立了App_TaskStart()、App_TaskKbd()、App_TaskLed()三個任務。 App_TaskStart()負責硬件初始化及OS初始化,建立消息郵箱及另兩個任務,然后進入無限循環,在循環體內調用OSTimeDly(200)以實現延時和任務調度。App_TaskKbd()負責查詢按鍵并通過消息郵箱將鍵值發送給任務App_TaskLed(),App_TaskLed()根據鍵值改變LED的閃爍頻率。測試程序通過IAR6.3編譯,把生成的二進制文件固化到LPC1788目標板上,接通電源后可以準確穩定地運行,說明在IAR6.3環境下基于LPC1788的μC/OS-II移植成功。
文中分析了μC/OS-Ⅱ內核的文件結構及基本工作原理,成功實現了其在LPC1788上的移植。文中相應的源代碼不用作任何改變,直接復制到μC/OS-Ⅱ相應文件中,可順利實現多任務調度,且運行穩定、可靠,可以進行ARM Cortex-M3微控制器LPC17xx系列的各種應用系統的設計與開發。
[1]Jean J.Labrosse.嵌入式實時操作系統μ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]孫繼如,郭敏,張宇翔,等.嵌入式實時操作系統μC/OS-Ⅱ在LPC2378上的移植及應用[J].現代電子技術,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的移植及多任務的實現[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內核超時等待機制的分析與改進[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-Ⅱ的數控機床嵌入式執行控制器實現[J].現代電子技術,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-Ⅱ的在線磷酸根離子監測儀設計[J].現代電子技術,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.