涂 撰, 趙 標
(1.上海交通大學 船舶海洋與建筑工程學院,上海200240;2.上海船舶運輸科學研究所 研發(fā)中心,上海200135)
嵌入式實時操作系統(tǒng)RT-Thread是由國內(nèi)開發(fā)人員主創(chuàng)的穩(wěn)定的開源實時操作系統(tǒng),它得益于中國開源社區(qū)的發(fā)展,已經(jīng)歷了6年的開發(fā),得到了來自全國各地嵌入式工程師的鼎力支持。現(xiàn)在它不僅是一款開源意義的實時操作系統(tǒng),也是一款產(chǎn)品級的實時操作系統(tǒng)。該系統(tǒng)已經(jīng)被國內(nèi)十多所企業(yè)所采用,是一款能夠穩(wěn)定持續(xù)運行的操作系統(tǒng),具有良好的應(yīng)用前景。
嵌入式實時操作系統(tǒng)RT-Thread采用面向?qū)ο蟮脑O(shè)計風格,但不同于一般的面向?qū)ο笙到y(tǒng),它并不是利用C++實現(xiàn)的,而是采用了C語言的方式實現(xiàn)面向?qū)ο缶幊?。這樣的系統(tǒng)內(nèi)核簡潔、高效、穩(wěn)定和易于移植。它不僅是單一的實時操作系統(tǒng)內(nèi)核,還包含了一系列完整的嵌入式組件,如:Fin SH Shell命令行工具、分布式文件系統(tǒng)(Distributed File System,DFS)、優(yōu)化的網(wǎng)絡(luò)協(xié)議棧l wip、圖形用戶界面RTGUI和完整的C運行庫等。
NXP公司推出的32位RISC處理器LPC2378采用了ARM7 TDMI內(nèi)核,具有豐富而獨特的外設(shè),功能強大,大大減少了系統(tǒng)電路中除處理器以外的元器件配置,能夠最小化系統(tǒng)成本,性價比高,十分適合于如工業(yè)控制、Internet設(shè)備、網(wǎng)絡(luò)和調(diào)制解調(diào)設(shè)備等嵌入式應(yīng)用。因此,將嵌入式實時操作系統(tǒng)RT-Thread移植到LPC2378芯片具有現(xiàn)實意義。
隨著在嵌入式系統(tǒng)的應(yīng)用開發(fā)中廣泛的采用嵌入式實時操作系統(tǒng),使得實時系統(tǒng)(Real-Ti me Operating System,RTOS)有了很快的發(fā)展。常見的嵌入式實時操作系統(tǒng)主要有free RTOS、u C/OS-II、Vx Wor ks、QNX等。表1中列舉了u C/OS-II、free RTOS、Vx Works和RT-Thread的比較。
表1 RT-Thread與其他RTOS的比較
RT-thread的源代碼可由官方網(wǎng)站獲取,或者通過Google SVN下載。目前RT-Thread最新的穩(wěn)定版本是1.0.0,最新的測試版本為1.1.0beta1。RT-thread源代碼的目錄結(jié)構(gòu)見圖1。
板級支持包(Boar d Support Package,BSP)和libcpu文件夾中的內(nèi)容均與中央處理器(Central Pr ocessing Unit,CPU)類型和硬件平臺有關(guān),因此是移植RT-Thread的重點。其他部分都與硬件平臺無關(guān)。
RT-Thread有多種開發(fā)環(huán)境,如scons命令行、GNU的GCC編譯環(huán)境和ARM公司的MDK開發(fā)工具等。個人可以根據(jù)各自習慣選擇合適的開發(fā)環(huán)境。RT-Thread發(fā)展到0.3.0以后,主要的編譯器切換到了ARM公司的Real View ARM Co mpiler,因此推薦采用ARM公司的MDK作為開發(fā)工具。
RT-Thread在LPC2378上的移植是通過Real View MDK工具進行的。首先在RT-Thread源碼的bsp目錄下新建l pc2378目錄,將與LPC2378相近的芯片(如l pc2478)目錄內(nèi)容拷貝到新建目錄下。在Real View MDK中新建立1個工程文件,保存在bsp/l pc2378目錄下。創(chuàng)建工程時CPU選擇NXP的LPC2378芯片,可以使用工具自動生成的啟動文件。由于需要修改部分代碼以適應(yīng)RT-Thread,因此建議不采用自動生成文件,導入自己編寫的啟動代碼。
修改啟動文件start_rvds.s,主要是修改對中斷請求(Interr upt Request,IRQ)代碼的處理,由 RTThread操作系統(tǒng)截獲,重新實現(xiàn)。實現(xiàn)代碼如下:IRQ_Handler PROC
圖1 RT-Thread 1.0.0版本的目錄結(jié)構(gòu)
rt_h w_context_s witch_interr upt_do為中斷結(jié)束后實現(xiàn)上下文切換的函數(shù)。在啟動代碼中,還要對目標板進行看門狗初始化,關(guān)閉系統(tǒng)中斷,配置芯片時鐘、內(nèi)存映射方式等。
上下文切換文件context_r vds.s,由于ARM體系結(jié)構(gòu)的相似性,基本不用修改。
trap.c文件與ARM體系結(jié)構(gòu)的中斷模式有關(guān),但是需要重新實現(xiàn)的只有rt_hw_trap_irq函數(shù)。該函數(shù)用于判斷IRQ來自芯片的何種外設(shè)。通過總的中斷向量寄存器獲取當前中斷向量,并跳轉(zhuǎn)到相應(yīng)的中斷服務(wù)程序,具體實現(xiàn)如下所示。對于不同芯片這里的實現(xiàn)略有不同。
修改interr upt.c文件,根據(jù)不同的芯片類型對于中斷管理略有不同。需要實現(xiàn)的函數(shù)如下:rt_h w_interrupt_handle,默認的IRQ處理函數(shù),一般可以只輸出一些提示信息,如點燈或者串口打印等;rt_hw_interr upt_init,中斷初始化函數(shù);rt_h w_interr upt_mask,中斷屏蔽函數(shù),參數(shù)為中斷號;rt_h w_interr upt_u mask,中斷禁止屏蔽函數(shù),參數(shù)同為中斷號;rt_hw_interrupt_install,中斷服務(wù)程序安裝函數(shù),將中斷服務(wù)程序安裝到對應(yīng)的中斷向量上。
cpu.c文件,主要是CPU復位函數(shù)和關(guān)閉函數(shù),可以根據(jù)LPC2378芯片手冊修改,也可不修改,直接為空函數(shù)。
stack.c文件,“手工”設(shè)置線程的初始棧,使調(diào)度器明確切換線程的入口地址和參數(shù)地址。同樣,由于ARM體系結(jié)構(gòu)的相似性,基本不用修改。
最后是操作系統(tǒng)心跳時鐘的移植。操作系統(tǒng)心跳時鐘以及相關(guān)硬件的初始化工作在BSP包中實現(xiàn),其內(nèi)容就是初始化1個硬件定時器并啟動它,同時編寫好定時器中斷服務(wù)程序,在中斷服務(wù)程序中調(diào)用rt_tick_increase函數(shù),告知操作系統(tǒng)內(nèi)核心跳了1次。
完成操作系統(tǒng)內(nèi)核移植后,更重要的工作就是編寫與目標板對應(yīng)的設(shè)備驅(qū)動程序。RT-Thread與Vx-Works一樣,在設(shè)備驅(qū)動程序和上層應(yīng)用之間提供了1個中間層,用于管理I/O類設(shè)備,稱為I/O設(shè)備管理模塊。
I/O管理模塊實現(xiàn)了對設(shè)備驅(qū)動程序的封裝,設(shè)備驅(qū)動程序的實現(xiàn)與I/O管理模塊獨立,提高了模塊的可移植性。應(yīng)用程序通過I/O管理模塊提供的標準接口訪問底層設(shè)備,設(shè)備驅(qū)動程序的升級不會對上層應(yīng)用產(chǎn)生影響。這種方式降低了代碼的復雜性,提高了系統(tǒng)的可靠性。
在RT-Thread中,設(shè)備也被認為是1類對象,每個設(shè)備對象都是由基對象派生而來,每個具體設(shè)備都可以繼承其父類對象的屬性,并派生出其私有屬性。圖2為設(shè)備對象的繼承和派生關(guān)系示意圖[3]。
圖2 設(shè)備對象的繼承和派生關(guān)系示意圖
該數(shù)據(jù)結(jié)構(gòu)就是RT-Thread的設(shè)備基對象。實現(xiàn)設(shè)備的驅(qū)動函數(shù)就是實現(xiàn)數(shù)據(jù)結(jié)構(gòu)中的接口函數(shù)的具體化。
1.實現(xiàn)str uct rt_device中的公共接口函數(shù),以串口設(shè)備為例:
rt_serial_init函數(shù)實現(xiàn)init接口功能,即設(shè)備初始化;
rt_serial_open函數(shù)實現(xiàn)open接口功能,即打開設(shè)備;
rt_serial_close函數(shù)實現(xiàn)close接口功能,即關(guān)閉設(shè)備;
rt_serial_read函數(shù)實現(xiàn)read接口功能,即讀取設(shè)備數(shù)據(jù);
rt_serial_write函數(shù)實現(xiàn)write接口功能,即向設(shè)備發(fā)送數(shù)據(jù);
rt_serial_control函數(shù)實現(xiàn)contr ol接口功能,即設(shè)置設(shè)備參數(shù)。
所有函數(shù)不一定都要實現(xiàn),比如rt_serial_close,可以只是1個空函數(shù),返回rt_err_t類型數(shù)據(jù)即可。
2.根據(jù)自己的具體設(shè)備對象定義設(shè)備數(shù)據(jù)類型中的私有數(shù)據(jù),用于特定的需要。
3.擴展設(shè)備對象。
1)利用str uct rt_device作為父類,增加屬性進行派生,如以串口設(shè)備為例:
2)定義自己的數(shù)據(jù)類型,將str uct rt_device中的void*private指向該數(shù)據(jù)類型。
4.利用rt_device_register函數(shù)將設(shè)備注冊到RT-Thread的設(shè)備框架中。
5.對于需要使用中斷等異步方式的設(shè)備驅(qū)動,還需要編寫相應(yīng)中斷服務(wù)程序。在init接口函數(shù)中掛接相應(yīng)的中斷向量。
RT-Thread最開始由main函數(shù)調(diào)用rtthread_startup函數(shù),完成對目標板的中斷向量初始化、心跳時鐘定時器的初始化、系統(tǒng)內(nèi)核的初始化、相關(guān)組件的初始化、外圍設(shè)備的初始化、調(diào)用用戶接口函數(shù)和空閑任務(wù)的初始化等。在rt_system_scheduler_start函數(shù)開始任務(wù)調(diào)度以前,用戶必須確認操作系統(tǒng)至少建立1個除idle任務(wù)以外的任務(wù)才能保證內(nèi)核的順利調(diào)度,無論這個任務(wù)是系統(tǒng)自身組件的任務(wù)(如tshell),還是用戶自己的任務(wù)。在用戶接口函數(shù)rt_application_init中,用戶可以根據(jù)需要創(chuàng)建自己的應(yīng)用程序。
完成了RT-Thread在LPC2378芯片的移植之后,編寫了1個CAN-Et her net網(wǎng)關(guān)的多任務(wù)應(yīng)用程序,一方面可以進行RT-Thread移植后的穩(wěn)定測試;另一方面也為RT-Thread在產(chǎn)品化方面做研究。圖3顯示了串口終端輸出的內(nèi)容,通過Fin SH Shell指令,可以觀察內(nèi)核的運行情況和各個任務(wù)的運行信息。通過程序的測試,表明RT-Thread已能在LPC2378芯片穩(wěn)定運行。
圖3 RT-Thread CAN-以太網(wǎng)網(wǎng)關(guān)多任務(wù)程序串口輸出
嵌入式實時操作系統(tǒng)RT-Thread與其他國外成熟的操作系統(tǒng)相比,還是1個新系統(tǒng)。但是隨著中國開源社區(qū)的發(fā)展,越來越多的開發(fā)人員參與到RT-Thread的更新維護中,越來越多的企業(yè)公司選擇RTThread作為操作系統(tǒng)平臺,這必將推動RT-Thread在國內(nèi)穩(wěn)定、持續(xù)的發(fā)展,對于企業(yè)和RT-Thread開源社區(qū)都將形成雙贏的局面。同時,將RT-Thread移植到LPC2378芯片,可以為RT-Thread和LPC2378的產(chǎn)品設(shè)計開發(fā)起到拋磚引玉的作用。
[1] 朱傳宏,張麗全.嵌入式實時操作系統(tǒng)RT-Thread在SEP4020上的移植[J].計算機與數(shù)字工程,2010(11):93-96.
[2] 邱煒.嵌入式實時操作系統(tǒng)RT_thread的設(shè)計與實現(xiàn)[D].西安:西安電子科技大學,2007.
[3] 杜春雷.ARM體系結(jié)構(gòu)與編程[M].北京:清華大學出版社,2003.
[4] 馬忠梅,馬廣云,徐英慧,等.ARM嵌入式處理器結(jié)構(gòu)與應(yīng)用基礎(chǔ)[M].北京:航空航天大學出版社,2002.