摘 要:介紹將μC/OS-Ⅱ?qū)崟r操作系統(tǒng)移植到Coldfire處理器 MCF52235上的方法,為MCF5223x系列微控制器的軟件開發(fā)提供了一個實時操作系統(tǒng)平臺。首先分析μC/OS-Ⅱ的特點和內(nèi)核結(jié)構(gòu),結(jié)合MCF52235的結(jié)構(gòu)特點以及使用的軟硬件開發(fā)工具,深入研究移植條件和實現(xiàn)方法,詳細闡述系統(tǒng)移植中需要修改的文件、編寫的代碼及需要注意的問題。然后使用Codewarrior 6.4集成開發(fā)環(huán)境和評估板,通過建立兩個應用任務,驗證了移植代碼的正確性,說明在MCF52235上移植μC/OS-Ⅱ是成功和可行的。在此介紹的移植過程和方法可以作為μC/OS-Ⅱ在其他微控制器中移植的典型范例。
關鍵詞:μC/OS-Ⅱ;移植;Coldfire;MCF52235
中圖分類號:TP311文獻標識碼:A
文章編號:1004-373X(2010)06-029-05
Transplantation of μC/OS-Ⅱon Coldfire MCF52235
SUN Qingxuan,SUN Tongjing,TAO Liang
(School of Control Science and Engineering,Shandong University,Ji′nan,250061,China)
Abstract:Transplanting μC/OS-II to Coldfire MCF52235,a real-time operating system platform is provided for software development upon microcontroller MCF5223x.The characteristics and kernel structure of μC/OS-II are analyzed.Conditions and implemenation of transplantation according to the structure of MCF52235 and software/hardware development tools are deeply researched,the files and the code need to be modified and the problems should be noticed are illuminated.The correctness of ported codes is validated by establishing two application tasks on evaluation board by Codewarrior 6.4 IDE.The results show that the tansplantation of μC/OS-II on Coldfire MCF52235 is successful and feasible.The process and implementation of transplantation shall be a typical example for tansplantation of μC/OS-Ⅱ to other microcontrollers.
Keywords:μC/OS-II;tansplantation;Coldfire;MCF52235
0 引 言
μC/OS-Ⅱ是一種多任務實時操作系統(tǒng)。內(nèi)核源代碼公開、短小精干、可裁剪、執(zhí)行時間可確定,可移植性較強,非常適用于一些中小型嵌入式系統(tǒng)開發(fā)。μC/OS-Ⅱ可以移植到8~64 位的不同類型、不同規(guī)模的嵌入式系統(tǒng),并能在大部分的8 位、16 位、32 位,甚至64位的微處理器和DSP上運行[1]。
MCF52235是飛思卡爾公司Coldfire系列32位單片機解決方案的嵌入式微控制器,采用的是V2版本的RISC內(nèi)核。MCF52235內(nèi)部有32 KB SRAM 和256 KB FLASH,并且集成了標準的Coldfire外圍設備,包括三個適合中長距離通信的SCI,一個I2C和一個用于系統(tǒng)內(nèi)部和外圍設備通信的QSPI。在60 Hz的核心頻率下,MCF52235的處理能力為56 MIPS,具備較高的性能價格比。
MCF52235對于移植μC/OS-Ⅱ來說有足夠的RAM和FLASH,且有較快的處理速度和較低的成本,所以對于嵌入式應用系統(tǒng)的開發(fā)來說,嵌入μC/OS-Ⅱ到MCF52235微控制器是一個不錯的選擇。
1 μC/OS-Ⅱ的體系結(jié)構(gòu)
要實現(xiàn)μC/OS-Ⅱ向MCF52235的移植,需要做兩方面的工作:一是重新定義內(nèi)核的大小和功能;二是為內(nèi)核編寫與硬件相關的代碼。μC/OS-Ⅱ的文件結(jié)構(gòu)如圖1所示。
可以看到,μC/OS-Ⅱ與CPU類型無關的C代碼文件μCOS-Ⅱ.C包括很多文件,它們是μC/OS-Ⅱ的內(nèi)核和很多功能函數(shù),其中前三個文件是實時內(nèi)核、任務管理和時鐘節(jié)拍,這三個文件是一定要用的。后面6個功能函數(shù)用于任務間的通信,應用程序中可能只用到其中的幾個,不用的可以不包含進去,以免編譯時生成沒用的代碼。這部分代碼與CPU類型無關,在移植時,這些文件不要改動。
配置文件OS_CFG.H需要根據(jù)應用要求來進行,主要作用是確定μC/OS-Ⅱ提供的系統(tǒng)功能函數(shù),應用程序用哪些和不用哪些,這個文件移植時需要修改。
與CPU類型有關的代碼文件主要有三個:OS_CPU.H,OS_CPU_A.ASM和OS_CPU_C.C。文件定義用于特定CPU的數(shù)據(jù)類型來定義相關的宏。OS_CPU_A.ASM是用匯編語言寫的與硬件有關的代碼,OS_CPU_C.C是用C語言寫的與硬件有關的代碼。由于移植使用C交叉編譯工具,在C代碼中可以插入?yún)R編語句,在移植中可將這兩個文件合并成一個文件[5]。
產(chǎn)生時鐘節(jié)拍的定時中斷來自微控制器內(nèi)部,但并非來自V2內(nèi)核內(nèi)部,可以用實時時鐘產(chǎn)生定時中斷,也可以用片內(nèi)的外設模塊定時器單元來產(chǎn)生定時中斷,這部分代碼顯然與硬件相關,移植時要自己寫[6]。
圖1 μC/OS-Ⅱ的文件結(jié)構(gòu)
2 移植過程
所謂移植,就是使一個實時內(nèi)核能在某個微處理器或微控制器上運行。為了方便移植,大部分的μC/OS-Ⅱ代碼是用C語言寫的,但仍需要用C和匯編語言寫一些與處理器相關的代碼,這是因為μC/OS-II在讀寫處理器寄存器時只能通過匯編語言來實現(xiàn)[7]。
移植過程主要包括移植前的準備、BSP (板級支持包) 的編寫和與處理器相關代碼的修改和編寫。μC/OS-Ⅱ核心代碼、與CPU相關的接口程序、BSP和用戶應用程序之間的關系如圖2所示。
2.1 移植前的準備
進入μC/OS-Ⅱ官方網(wǎng)站下載μC/OS-Ⅱ源代碼。打開Codewarrior 6.4 建立MCF52235的工程文件,然后把μC/OS-Ⅱ的源代碼文件加入到工程里面[8]。其中有幾個地方需要改動:
(1) 下載的源代碼中os_cfg_r.h改為os_cfg.h;os_dbg_r.c改為os_dbg.c。
(2) 由于會引起重復定義錯誤,需要把源代碼中重復包含的文件注釋掉。
(3) 需要在INTERNAL_FLASH模式下編譯,而不能在RAM模式下,否則會產(chǎn)生溢出錯誤。
圖2 系統(tǒng)中各部分之間的關系
2.2 編寫B(tài)SP
板級支持包(BSP)是介于底層硬件和操作系統(tǒng)之間的軟件層次,負責進行系統(tǒng)啟動后最初的硬件和軟件初始化,并對底層硬件進行封裝,使得操作系統(tǒng)不再面對具體的硬件[9]。
在此建立兩個BSP文件:BSP.ASM和BSP.C。其中,BSP.ASM中包含了匯編語言寫的中斷接口程序。BSP.C中包含了硬件和軟件的初始化程序和產(chǎn)生時鐘節(jié)拍的中斷服務程序。
2.3 與處理器相關代碼的修改和編寫
有三個與處理器相關的文件,即OS_CPU.H,OS_CPU_A.ASM和OS_CPU_C.C需要修改。由于MCF52235有eMAC模塊,所以還需要編寫OS_CPU_I.ASM文件,用來在任務切換和中斷時以及中斷返回時保存和恢復相關寄存器。
2.3.1 OS_CPU.H的移植
OS_CPU.H包含了一些與處理器和編譯器相關的宏定義和數(shù)據(jù)類型定義。由于使用Codewarrior編譯器,short類型是16位的,int類型是32位的。MCF52235的堆棧是32位寬的,因此OS_STK定義為32位,所有任務的堆棧必須聲明使用OS_STK這種數(shù)據(jù)類型。數(shù)據(jù)類型定義如下:
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef signed char INT8S;
typedef unsigned short INT16U;
typedef signed short INT16S;
typedef unsigned int INT32U;
typedef signed int INT32S;
typedef float FP32;
typedef double FP64;
typedef unsigned int OS_STK;
typedef unsigned short OS_CPU_SR;
(1) 臨界區(qū)域處理。
像所有的實時性內(nèi)核一樣,在進入代碼臨界區(qū)時要關中斷,完成時要開中斷。μC/OS-Ⅱ定義了兩個宏來關閉和使能中斷:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。μC/OS-Ⅱ定義了三種方法來關閉和使能中斷,大多數(shù)情況下選擇第三種方法。
#define OS_CRITICAL_METHOD #3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}//關中斷
#defineOS_EXIT_CRITICAL(){OS_CPU_SR_Restore(cpu_sr);}//開中斷
(2) 任務層上下文切換。
當μC/OS-Ⅱ調(diào)用OS_TASK_SW()時發(fā)生任務層的上下文切換。因為上下文切換是根據(jù)處理器的不同而不同的,所以需要執(zhí)行一個匯編的函數(shù)。在這種情況下,用TRAP指令來產(chǎn)生一個異常,用TRAP指令的優(yōu)點是能使它像發(fā)生了一次中斷一樣。這里用#14 TRAP,因為大多數(shù)情況下,#15 TRAP被調(diào)試和監(jiān)控程序保留了。#14 TRAP定位于VBR+0x00B8,然后跳轉(zhuǎn)到相應的地址。在這個向量處放置OSCtxSw()的地址。這個函數(shù)聲明在OS_CPU_A.ASM里。VBR代表向量基址寄存器,包含異常向量表的基址,程序開始時被初始化為0x00000000,但是在運行時可以改變。
#define OS_TASK_SW() asm(TRAP #14;)
(3) 堆棧的增長方向。
MCF52235的堆棧增長方向是從高地址向低地址,因此OS_STK_GROWTH置為1。
#define OS_STK_GROWTH 1
2.3.2 OS_CPU_C.C的移植
OS_CPU_C.C里面包含10個比較簡單的C語言函數(shù),一般來說μC/OS-Ⅱ只需要OSTaskStkInit()。其他函數(shù)是用來讓用戶在自己的程序里擴展操作系統(tǒng)功能的。如果需要使用這些函數(shù),需要在OS_CFG.H里設置OS_CPU_HOOKS_EN為1。
堆棧的初始化:
OSTaskStkInit()雖然是用C語言編寫的,但它是一個與CPU硬件相關的函數(shù)。這個函數(shù)功能是初始化任務的堆棧,由建立任務函數(shù)OSTaskCreate()或擴展地建立任務函數(shù)OSTaskCreateExit()調(diào)用。任務堆棧初始化的實質(zhì)就是模擬一次中斷,使堆??雌饋砭拖駝偘l(fā)生過中斷一樣。任務堆棧中保存了任務代碼的起始地址和一些CPU 寄存器的值,一旦條件滿足,就可以執(zhí)行該任務。初始化后的任務堆棧結(jié)構(gòu)如圖3所示。
圖3 初始化后的任務堆棧結(jié)構(gòu)
2.3.3 OS_CPU_A.ASM的移植
這個文件包含5個相當簡單的匯編函數(shù),因為一般不能用C語言來保存和恢復寄存器。
(1) OS_CPU_SR_Save()
這個函數(shù)是通過保存中斷屏蔽寄存器,然后關閉中斷來實現(xiàn)OS_CRITICAL_METHOD #3的。當函數(shù)返回時,D0包含了狀態(tài)寄存器的內(nèi)容,里面包含當前的中斷關閉狀態(tài)。這個返回值被調(diào)用函數(shù)保存到變量cpu_sr中。
(2) OS_CPU_SR_Restore()
這個函數(shù)用來實現(xiàn)恢復中斷屏蔽到調(diào)用OS_ENTER_CRITICAL()之前的狀態(tài)。也就是說調(diào)用OS_ENTER_CRITICAL()之前中斷是關閉的,那么在OS_EXIT_CRITICAL()之后,中斷是關閉的。
(3) OSStartHighRdy()
這個函數(shù)被OSStart()調(diào)用來運行優(yōu)先級最高的任務。OSStart()設置OSTCBHighRdy指向優(yōu)先級最高任務的OS_TCB。一旦從OSTaskSwHook()返回,就把OSRunning設為OS_TRUE,它表明現(xiàn)在RTOS將要運行。從最高優(yōu)先級任務的OS_TCB中恢復堆棧指針,然后從任務堆棧里取出CPU寄存器。最后執(zhí)行一個RET指令,這個指令可以從堆棧中彈出SR和PC,現(xiàn)在的任務代碼就開始執(zhí)行。
(4) OSCtxSw()
當一個任務不再運行時就會發(fā)生一個任務級的任務切換,比如任務調(diào)用一個延遲10個時鐘節(jié)拍的函數(shù)。這時,μC/OS-Ⅱ需要找出下一個最重要的任務準備去運行。OSCtxSw()的功能是保存需要掛起的任務的CPU寄存器和堆棧,恢復需要運行任務的CPU寄存器和堆棧。任務級上下文切換如圖4所示。
圖4 任務級上下文切換
(5) OSIntCtxSw()
當中斷服務函數(shù)完成時,調(diào)用OSIntExit()函數(shù)去決定是否有一個更重要的任務比被中斷的任務更需要執(zhí)行。這種情況下,OSIntExit()決定運行哪個任務,然后調(diào)用OSIntCtxSw()。這種情況下,中斷服務程序已經(jīng)保存了被中斷任務的CPU寄存器,而需要做的只是去恢復新任務的CPU寄存器。
2.3.4 OS_CPU_I.ASM的編寫
如果用到增強的乘法累加單元(eMAC)模塊,在上下文切換和中斷時就應該保存和恢復eMAC寄存器。保存和恢復eMAC寄存器通過兩個宏來實現(xiàn)[10]。代碼如下:
.macroOS_EMAC_SAVE
MOVE.LMACSR,D7
CLR.L D0
MOVE.LD0,MACSR
MOVE.LACC0,D0
MOVE.LACC1,D1
MOVE.LACC2,D2
MOVE.LACC3,D3
MOVE.LACCEXT01,D4
MOVE.LACCEXT23,D5
MOVE.LMASK,D6
LEA-32(A7),A7
MOVEM.LD0-D7,(A7)
.endm
.macroOS_EMAC_RESTORE
MOVEM.L(A7),D0-D7
MOVE.L #0,MACSR
MOVE.L D0,ACC0
MOVE.L D1,ACC1
MOVE.L D2,ACC2
MOVE.L D3,ACC3
MOVE.L D4,ACCEXT01
MOVE.L D5,ACCEXT23
MOVE.L D6,MASK
MOVE.L D7,MACSR
LEA32(A7),A7
.endm
2.4 時鐘節(jié)拍的產(chǎn)生
最后還需要編寫利用片內(nèi)定時器產(chǎn)生時鐘節(jié)拍的中斷服務程序。μC/OS-Ⅱ要求微控制器提供一個簡單的時鐘,用于任務的延時等功能。在此利用可編程中斷定時器來產(chǎn)生時鐘節(jié)拍中斷。在定時器中斷服務程序中調(diào)用OSTimeTick()就產(chǎn)生了系統(tǒng)所需要的時鐘節(jié)拍。μC/OS-Ⅱ中產(chǎn)生中斷后的中斷處理程序如下所示:
_BSP_TickISR:
MOVE.W #0x2700,SR
LEA-60(A7),A7
MOVEM.LD0-D7/A0-A6,(A7)
OS_EMAC_SAVE
MOVEQ.L#0,D0
MOVE.B (_OSIntNesting),D0
ADDQ.L #1,D0
MOVE.B D0,(_OSIntNesting)
CMPI.L #1,D0
BNE_BSP_TickISR_1
MOVE.L (_OSTCBCur),A1
MOVE.L A7,(A1)
_BSP_TickISR_1:
JSR_BSP_TickISR_Handler
JSR_OSIntExit
OS_EMAC_RESTORE
MOVEM.L(A7),D0-D7/A0-A6
LEA60(A7),A7
RTE
3 任務的創(chuàng)建和移植代碼的測試
源程序移植完,用戶就可以試著制作自己的項目。編寫任務代碼,與以前在前后臺系統(tǒng)中基本相同,不同的是要把每個任務獨立編寫成一個文件,最后由主程序統(tǒng)一調(diào)度。為了測試是否移植成功,用OSTaskCreateExt()創(chuàng)建了兩個任務。一個任務使板上LED每一秒閃動一次,另一個任務是用片內(nèi)A/D采樣板上的加速度傳感器信號,并在數(shù)碼管上顯示出當前加速度數(shù)值。最后調(diào)用OSStart()啟動多任務調(diào)度。
3.1 定義每個任務的堆棧大小
OS_STK
TaskStartStk;
OS_STK ADTaskStk;
然后在main()函數(shù)里系統(tǒng)初始化:
OSInit();
3.2 創(chuàng)建任務
OSTaskCreateExt(TaskStart,(void *)0,(OS_STK *)TaskStartStk,TASK_START_PRIO,TASK_START_PRIO,(OS_STK*)TaskStartStk,TASK_START_STK_SIZE,(void *)0,OS_TASK_OPT_STK_CHK| OS_TASK_OPT_STK_CLR);
OSTaskCreateExt(ADTask,(void*)0,(OS_STK *)ADTaskStk,ADTASK_PRIO,ADTASK_PRIO,(OS_STK *)ADTaskStk,TASK_STK_SIZE,(void *)0,OS_TASK_OPT_STK_CHK);
3.3 系統(tǒng)啟動運行
OSStart();
3.4 測試結(jié)果
測試代碼經(jīng)過編譯下載到實驗板上運行后,通過實驗板上顯示的信息,表示兩個任務在交替運行,說明移植工作是成功的,如圖5所示。
圖5 實驗結(jié)果
4 結(jié) 語
μC/OS-Ⅱ具有很強的實時性,而且代碼量較小的特點,并可被廣泛移植到x86,ColdFire,DSP,68 KB,AMD等許多處理器上。 利用這種實時操作系統(tǒng)構(gòu)建的嵌入式工業(yè)控制系統(tǒng)具有成本低,性能高等特點,有著廣泛的應用發(fā)展前景,因此將μC/OS-Ⅱ移植到MCF52235微控制器上,具有較高的應用價值。
參考文獻
[1] Jean J Labrosse.嵌入式實時操作系統(tǒng)μC/ OS -Ⅱ[M].2版.邵貝貝,譯.北京:北京航空航天大學出版社,2003.
[2]Freescale Semiconductor Inc.MCF2235 ColdFire Integrated Microprocessor Reference Manual[Z].Rev.5.09,2007.
[3]Munir Bannoura,Rudan Bettelheim,Richard Soja.Coldfire微處理器與微控制器[M].李晶皎,王愛俠,高曉興,譯.北京:電子工業(yè)出版社,2008.
[4]王宜懷,陳建明,蔣銀珍.基于32位ColdFrie構(gòu)建嵌入式系統(tǒng)[M].北京:電子工業(yè)出版社,2008.
[5]邵貝貝.單片機嵌入式應用的在線開發(fā)方法[M].北京:清華大學出版社,2004.
[6]孫同景,陳桂友.Freescale 9S12十六位單片機原理及嵌入式開發(fā)技術[M].北京:機械工業(yè)出版社,2008.
[7]劉鐵志.μC/OS-Ⅱ在嵌入式系統(tǒng)中的研究與應用[D].成都:電子科技大學,2005.
[8]申忠如,陶慧斌,曹建安.ColdFire嵌入式系統(tǒng)設計[M].西安:西安電子科技大學出版社,2006.
[9]寇鵬.實時操作系統(tǒng)μC/OS-Ⅱ在MCF5307 處理器上的移植[J].現(xiàn)代電子技術,2007,30(6):70-72.
[10]諶利,張瑞,王浩.深入淺出ColdFire系統(tǒng)32位嵌入式微處理器[M].北京:北京航空航天大學出版社,2009.