摘要:首先介紹如何構(gòu)建嵌入式開發(fā)平臺,包括硬件平臺和軟件平臺,硬件平臺的目標機采用ARM芯片,軟件平臺的宿主機采用Linux操作系統(tǒng),并采用GDB調(diào)試軟件;然后詳細闡述了嵌入式軟件的交叉開發(fā)的一般步驟。通過實踐充分證明交叉開發(fā)是嵌入式軟件開發(fā)行之有效的方法,可以大大提高嵌入式軟件的開發(fā)效率。
關(guān)鍵詞:嵌入式系統(tǒng); Linux; 交叉開發(fā)
中圖分類號:TP311文獻標志碼:A
文章編號:1001-3695(2008)01-0206-03
隨著信息技術(shù)的發(fā)展,微型化和專業(yè)化成為信息產(chǎn)品發(fā)展的新趨勢,嵌入式產(chǎn)品成為信息產(chǎn)業(yè)的主流。市場上出現(xiàn)種類眾多的商業(yè)性嵌入式操作系統(tǒng)。其中Linux以其內(nèi)核可裁減、效率高、穩(wěn)定性好、移植性好、源代碼開放等優(yōu)點受到越來越多的企業(yè)和研發(fā)機構(gòu)的關(guān)注。本文的開發(fā)就是基于Linux系統(tǒng)的。
由于嵌入式系統(tǒng)資源有限,用戶一般不具備自主開發(fā)能力,產(chǎn)品發(fā)布后用戶通常也不能對其中的軟件進行修改,必須有一套專門的開發(fā)環(huán)境由開發(fā)人員對軟件進行修改升級。該開發(fā)環(huán)境提供專門的開發(fā)工具(包括設計、編譯、調(diào)試、測試等工具),一般采用交叉開發(fā)的方式進行。
嵌入式軟件的交叉開發(fā)通常需要兩臺計算機。一臺作為主機(host),另一臺作為目標開發(fā)板(target)。主機可以是一臺運行Linux的PC,使用gcc、binutils作為編譯、鏈接器;目標開發(fā)板為gcc支持的CPU內(nèi)核的S3C2410芯片的主板作為目標開發(fā)板,并在其上運行GDB stub 的調(diào)試監(jiān)控程序。在主機上編譯、鏈接,得到包含調(diào)試符號的可執(zhí)行文件并轉(zhuǎn)換成可下載的二進制文件;然后在主機上運行g(shù)db,使用串行方式與目標板通信,實現(xiàn)下載、執(zhí)行、單步、斷點等調(diào)試功能。在系統(tǒng)開發(fā)的初期,也可以在主機上完成所有工作,使用x86模擬器來運行和調(diào)試系統(tǒng)。常見的x86模擬器有VMWare、Bochs等。本文選擇的是VMWare。
1構(gòu)建交叉開發(fā)平臺
基于Linux的嵌入式開發(fā)平臺由硬件平臺和軟件平臺組成。硬件平臺主要是指嵌入式系統(tǒng)運行的目標機,用于運行操作系統(tǒng)和系統(tǒng)應用軟件;目標板所用到的操作系統(tǒng)的內(nèi)核編譯、應用程序的開發(fā)和調(diào)試則需要通過宿主PC機來完成。軟件平臺主要是指運行在宿主機上的基于GNU的開發(fā)工具鏈和調(diào)試運行時運行在目標機上的調(diào)試服務器、監(jiān)視器等。
1)系統(tǒng)硬件平臺
在構(gòu)建硬件平臺時,微處理器的性價比是筆者最關(guān)心的。現(xiàn)在比較流行的硬件平臺有Intel公司的StrongARM 系列,Motorola公司的DragonBall系列,NEC公司的VR系列,Hitachi公司的SH3、SH4系列等。選定硬件平臺前,首先要確定系統(tǒng)的應用功能和所需要的速度,并制定好外接設備和接口標準。這樣才能準確地定位所需要的硬件方案,得到性價比最高的系統(tǒng)。本文的硬件平臺是基于三星公司ARM 9 內(nèi)核的S3C2410 芯片開發(fā)完成的。如圖1 所示, 整個硬件平臺由下面幾個部分組成[1]:
S3C2410: ARM 920T 核;
SDRAM: 8 MB;
flash: 128 MB;
LCD: 160×24016級灰度+觸摸屏;
16鍵矩陣鍵盤;
兩路RS-232接口等
其中, S3C2410 和SDRAM、或非型flash、與非型flash組成的最小系統(tǒng)可以運行指令和代碼; 通過串口、USB, SPI同外部交換信息和數(shù)據(jù); 通過LCD 進行顯示; 在交叉調(diào)試時,宿主機通過JTAG接口對目標機進行調(diào)試。
2)系統(tǒng)軟件平臺
嵌入式軟件開發(fā)的最大特點就是交叉開發(fā),體現(xiàn)在交叉編譯、交叉鏈接和交叉調(diào)試等方面。因此開發(fā)工具一定要能支持事先選定的硬件平臺,能夠生成基于特定微處理器指令集的目標程序,并能對其進行調(diào)試。建立交叉開發(fā)環(huán)境,首先要安裝軟件開發(fā)包。軟件開發(fā)包由嵌入式Linux操作系統(tǒng)、設備驅(qū)動支持包、嵌入式圖形包、GNU交叉編譯調(diào)試器組成。嵌入式Linux軟件開發(fā)平臺的系統(tǒng)結(jié)構(gòu)如圖2所示[2]。
交叉調(diào)試的原理是用戶通過串口利用GDB遠程調(diào)試功能對目標機的二進制程序進行遠程調(diào)試,調(diào)試服務程序(GDBserver)在目標機上接收GDB(宿主機)通過串口發(fā)送的控制命令,控制二進制程序的運行狀態(tài),并通過串口將GDB所需的狀態(tài)信息發(fā)給GDB。
在構(gòu)建好交叉開發(fā)平臺后就可以進行嵌入式軟件的開發(fā)了。在交叉開發(fā)時通常分成五部分:建立嵌入式Linux交叉開發(fā)環(huán)境、交叉編譯和鏈接、交叉調(diào)試、系統(tǒng)測試、固化運行。
2建立嵌入式交叉開發(fā)環(huán)境
交叉開發(fā)環(huán)境是指編譯、鏈接和調(diào)試嵌入式應用軟件的環(huán)境。一般包括文本編輯器、交叉編譯器、交叉調(diào)試器、仿真器、下載器等工具。它與運行嵌入式應用軟件的環(huán)境有所不同,通常采用宿主機/目標機模式[3]。宿主機與目標機之間在物理連接的基礎(chǔ)上建立起邏輯連接,如圖3所示。
1)宿主機
宿主機是用于開發(fā)嵌入式軟件的計算機。從硬件配置來講,它們一般為通用的PC機,其上的軟件配置很豐富。除了功能強大的桌面操作系統(tǒng)外,還具備各種開發(fā)工具,為編輯、編譯、鏈接、調(diào)試、測試及固化嵌入式應用軟件提供全程支持。
2)目標機
目標機即所開發(fā)的嵌入式系統(tǒng),是嵌入式軟件的運行環(huán)境。目標機的嵌入式操作系統(tǒng)是用于支撐嵌入式應用的,不是用于開發(fā)的環(huán)境平臺。在開發(fā)過程中目標機端需接收和執(zhí)行宿主機發(fā)出的各種命令,如設置斷點、讀內(nèi)存和寫內(nèi)存等,將結(jié)果返回給宿主機,配合宿主機各方面的工作。斷點主要功能是使程序在某個指定的地方停下來,以便觀察各種有用的信息,如寄存器的值、某個變量的值和某個內(nèi)存單元的值等。斷點可以分為硬件斷點和軟件斷點兩種。
3)物理連接和邏輯連接
物理連接是指宿主機和目標機上的一定物理端口通過物理線路連接起來。它是邏輯連接的基礎(chǔ)。邏輯連接是指宿主機和目標機間按照某種通信協(xié)議建立起來的通信連接,目前逐步形成了一些通信協(xié)議的標準。要順利地建立交叉開發(fā)環(huán)境,需要正確設置這兩種連接,缺一不可。在物理連接上,要注意使硬件線路正確連接,且硬件設備完好、能正常工作、連接線路的質(zhì)量要好;邏輯連接在于正確配置宿主機和目標機的物理端口的參數(shù),并且與實際的物理連接在一起。
3交叉編譯和鏈接
嵌入式軟件的生成可分為三個階段[3]:源代碼的編寫;將源程序交叉編譯成各個目標模塊;將所有目標模塊及相關(guān)的庫文件一起鏈接成可供下載調(diào)試或固化的可執(zhí)行代碼,如圖4所示。由于開發(fā)過程大多是在Intel公司x86系列CPU的通用計算
機上進行的,而目標環(huán)境的處理器芯片卻大多為ARM、MIPS、PowerPC、DragonBall等系列的微處理器。這就要求在建立好的交叉開發(fā)環(huán)境中進行交叉編譯和鏈接。
1)交叉編譯器
交叉編譯器的主要功能是把宿主機上編寫的高級語言程序編譯成可以運行在目標機上的代碼,即在宿主機上能夠編譯生成能在另一種CPU(嵌入式微處理器)上運行的二進制程序。在基于ARM體系結(jié)構(gòu)的gcc交叉開發(fā)環(huán)境中,arm linux gcc是交叉編譯器。
2)交叉鏈接器
嵌入式軟件的運行方式主要有兩種:調(diào)試方式和固化方式。不同方式下程序代碼或數(shù)據(jù)在目標機內(nèi)存中的定位有所不同。宿主機上提供一定的工具或手段對目標程序的運行方式和內(nèi)存定位進行選擇和配置;鏈接器再根據(jù)這些配置信息將目標模塊和庫文件中的模塊鏈接成目標程序。因此稱這樣的鏈接器為交叉鏈接器。在基于ARM體系結(jié)構(gòu)的gcc交叉開發(fā)環(huán)境中,arm linux ld是交叉鏈接器。
4交叉調(diào)試
在開發(fā)嵌入式軟件時,交叉調(diào)試是必不可少的一步。交叉調(diào)試是指調(diào)試程序和被調(diào)試程序運行在不同機器上的調(diào)試。調(diào)試器通過某種方式能控制目標機上被調(diào)試程序的運行方式,并且通過調(diào)試器查看和修改目標機上的內(nèi)存、寄存器以及被調(diào)試程序中的變量。
交叉調(diào)試的方式即調(diào)試器控制被調(diào)試程序運行的方式有很多種。本文所用的調(diào)試方案為主機端環(huán)境是標準Linux系統(tǒng),基于邊界掃描JTAG技術(shù)[4]。交叉調(diào)試系統(tǒng)由主機調(diào)試器、目標機上的調(diào)試代理、調(diào)試協(xié)議三部分組成。其體系結(jié)構(gòu)如圖5所示[4]。主機調(diào)試器主要實現(xiàn)對源文件、目標文件和符號表的訪問處理,接收用戶輸入的調(diào)試命令,并根據(jù)調(diào)試協(xié)議封裝成調(diào)試命令請求包發(fā)送給調(diào)試代理,同時接收調(diào)試代理返回的調(diào)試信息,以獲取目標程序的當前運行狀態(tài)。目標機上的調(diào)試代理負責根據(jù)調(diào)試協(xié)議接收并解析調(diào)試命令,監(jiān)控目標程序的運行狀態(tài),將目標程序狀態(tài)信息返回主機端。調(diào)試協(xié)議則規(guī)定了調(diào)試命令和調(diào)試信息的數(shù)據(jù)格式及通信過程。
圖4嵌入式軟件的生成階段圖5交叉調(diào)試系統(tǒng)體系結(jié)構(gòu)
此交叉調(diào)試的特點是主機端環(huán)境為Linux系統(tǒng),主機調(diào)試器采用GDB + JTAGER 的方案,由GDB 完成對源文件、目標文件和符號表的訪問處理及與用戶的交互,由JTAGER 程序封裝對交叉調(diào)試的支持;調(diào)試協(xié)議是JTAGER 程序與調(diào)試代理程序之間的通信規(guī)范。調(diào)試代理程序handler 則通過特有的LDIC 指令載入目標芯片的微型指令緩存中。
4.1調(diào)試協(xié)議
調(diào)試協(xié)議是整個交叉調(diào)試系統(tǒng)的中心。它規(guī)定了主機和目標機之間的數(shù)據(jù)通信過程。主機和目標機采用盡量簡單的數(shù)據(jù)包交互,JTAGER需要發(fā)往handler的調(diào)試命令包括讀寫目標機內(nèi)存(g 和p)、增加斷點(b)、繼續(xù)運行(c)。由于讀寫目標機寄存器會頻繁發(fā)生,采用輪詢方式定時完成。
在主機和目標機通信過程中用到的通信協(xié)議主要有普通RX 握手協(xié)議、快速數(shù)據(jù)下載握手協(xié)議、TX 握手協(xié)議。
4.2主機端調(diào)試器GDB+JTAGER
GDB是公開源碼的一種功能強大的通用調(diào)試器。它支持豐富的調(diào)試命令和多種編程語言,并支持遠程調(diào)試方式。運行GDB的平臺通過并行端口(或網(wǎng)口、串口等)連接到已建立運行環(huán)境的目標機時,GDB 可以按照遠程串行協(xié)議(RSP)與目標機上的插樁程序通信來調(diào)試目標系統(tǒng)。但當目標機為裸機時,GDB無法與之通信而不能調(diào)試,所以再增加一個中間軟件JTAGER。其功能是應用JTAG 技術(shù)實現(xiàn)對裸機的交叉調(diào)試。
1)GDB 交互數(shù)據(jù)包
交互過程必須遵守GDB RSP進行數(shù)據(jù)包處理[4]。數(shù)據(jù)包格式為$packet_data#checksum。其中:
$為數(shù)據(jù)包的頭標志;packet_data 為數(shù)據(jù)包內(nèi)容;#是數(shù)據(jù)包結(jié)束標志;checksum表示整個數(shù)據(jù)包的檢驗碼,用來保證數(shù)據(jù)的正確傳送。
在JTAGER 運行過程中,其主控循環(huán)不斷地接收RSP 數(shù)據(jù)包、解析,并將處理結(jié)果封裝成應答RSP數(shù)據(jù)包,交給GDB。以讀內(nèi)存為例,
GDB 發(fā)往JTAGER 的數(shù)據(jù)包:$mc0018004,4#8d
JTAGER 應答GDB 的數(shù)據(jù)包:$00d82de9#30
2)JTAGER主控流程
JTAGER在主機上與GDB 并行運行。它使用UNIX的I/O多路轉(zhuǎn)換機制監(jiān)聽指定的tcp 調(diào)試端口與GDB 進行通信。JTAGER主體控制流程偽碼如下:
JTAGER主控程序(…)
{
初始化目標板的JTAG接口;
往目標板的MiniIC載入handler;
打開GDB遠程tcp端口,接收gdb遠程調(diào)試數(shù)據(jù);
while(1)
{
監(jiān)視tcp調(diào)試端口和用戶標準輸入;
if(有數(shù)據(jù)包)解析后進入相應調(diào)試命令處理函數(shù);
else輪詢目標機的傳輸寄存器TX;
}
收到退出命令作結(jié)束程序的處理,進行tcp連接的中斷和內(nèi)存的回收。
}
4.3目標機代理handler
目標機調(diào)試代理handler按照調(diào)試協(xié)議[4]和JTAGER 進行調(diào)試命令與調(diào)試信息的交互。當調(diào)試事件發(fā)生時作為一個事件處理器對目標芯片進行控制。需要注意的是,由于微型指令緩存大小的限制(2 KB),handler代碼量要盡量地精簡。使用ARM匯編編寫,其程序流程偽碼如下所示:
handler程序流程(…)
{
初始化handler,使目標機處于就緒狀態(tài)(halt mode);
向JTAGER發(fā)送目標機就緒的信號;
while(1)
{
等待JTAGER發(fā)送相應調(diào)試指令;
//通過mrc實現(xiàn)對RX的讀出
if(接收到調(diào)試指令)進入相應調(diào)試處理子程序;
else向JTAGER發(fā)送調(diào)試結(jié)果;
//通過mcr實現(xiàn)對TX的寫入
}
}
5系統(tǒng)測試
整個軟件系統(tǒng)編譯過程中,嵌入式系統(tǒng)的硬件一般采用專門的測試儀器進行測試[3]。軟件則需要有相關(guān)的測試技術(shù)和測試工具的支持,并要采用特定的測試策略。嵌入式軟件測試中經(jīng)常用到的測試工具主要有內(nèi)存分析工具、性能分析工具、覆蓋分析工具和缺陷跟蹤工具等。
在嵌入式軟件測試中,常常要在基于目標機的測試和基于宿主機的測試間作出折中。基于目標機的測試需要消耗較多的時間和經(jīng)費;基于宿主機的測試雖然代價較小,但畢竟是在仿真環(huán)境中進行的,因此難以完全反映軟件運行時的實際情況。這兩種環(huán)境下的測試可以發(fā)現(xiàn)不同的軟件缺陷,關(guān)鍵是要對目標機環(huán)境和宿主機環(huán)境下的測試內(nèi)容進行合理取舍。
6嵌入式軟件的固化運行
當調(diào)試和測試完成后,程序代碼需要被完全燒入到目標板的非易失性存儲器中,并且在真實的硬件環(huán)境上運行。這個過程叫做固化。分析調(diào)試環(huán)境與固化環(huán)境之間的區(qū)別是解決固化問題的關(guān)鍵所在。兩者的詳細區(qū)別如表1所示[3]。
a)代碼定位不同。
在嵌入式系統(tǒng)中,一般使用兩種存儲器:可讀/寫的RAM;非易失性存儲器,如ROM、flash memory等。在調(diào)試方式下,全部應用代碼和數(shù)據(jù)都定位在RAM中,代碼在RAM中運行;在固化方式下,代碼和數(shù)據(jù)是存儲在非易失性存儲器中的,系統(tǒng)啟動時要先將數(shù)據(jù)搬移到RAM中,而程序代碼可在ROM、flash memory中運行。
b)初始化部分不同。
固化程序要創(chuàng)建boot模塊,此模塊被連接作為整個應用系統(tǒng)代碼的入口模塊。當應用程序在真實環(huán)境下運行時將首先執(zhí)行該程序,完成對CPU的初始化。在嵌入式環(huán)境中,boot模塊一般包含初始化芯片的引腳、初始化一些系統(tǒng)外部控制寄存器、初始化基本I/O設備等功能。
完成了上述準備工作,就可以利用編譯鏈接工具生成可固化的應用程序;再用固化工具將它固化到目標機的ROM、flash memory等非易失性存儲器上。當用戶啟動目標機時,該應用程序就會被自動裝入運行。
7結(jié)束語
基于Linux平臺可以方便地進行嵌入式開發(fā)。利用Linux 下免費的開發(fā)工具集大大縮短了開發(fā)周期、提高了開發(fā)效率。用戶還可以很方便地添加自己所要的功能,其結(jié)構(gòu)具有良好的移植性。但是由于嵌入式系統(tǒng)應用越來越廣泛,對嵌入式產(chǎn)品的需求高速增長,其產(chǎn)品開發(fā)效率成為開發(fā)者首要考慮的問題,提供完整的集成開發(fā)環(huán)境是每個嵌入式系統(tǒng)開發(fā)人員所期待的。Linux在基于圖形界面的特定系統(tǒng)定制平臺的研究上,與Windows操作系統(tǒng)相比還存在差距。因此,要使嵌入式Linux在嵌入式操作系統(tǒng)領(lǐng)域中的優(yōu)勢更加明顯,整體集成開發(fā)環(huán)境還有待提高和完善。
本文從應用的角度詳細闡述了當今嵌入式開發(fā)的具體步驟。這是嵌入式開發(fā)的一般步驟。實踐證明交叉開發(fā)是嵌入式軟件開發(fā)行之有效的方法,可以大大提高嵌入式軟件的開發(fā)效率。
參考文獻:
[1]安成錦,孫茂陽,李坡,等.基于嵌入式Linux系統(tǒng)的MiniGUI圖形界面開發(fā)[J].現(xiàn)代電子技術(shù),2005,28(20):108 110.
[2]唐永波,喻建文,邱緒蓮,等.基于Linux嵌入式系統(tǒng)的研究[J].計算機與數(shù)字工程,2005,33(10):98 102.
[3]羅蕾.嵌入式實時操作系統(tǒng)及應用開發(fā)[M].北京:北京航空航天大學出版社,2005:72-88.
[4]陽富民,柯滔,涂剛,等.基于JTAG技術(shù)的嵌入式交叉調(diào)試軟件[J].計算機工程與設計,2005,26(10):2817-2819.
[5]李允,熊光澤,程紅蓉.普適計算終端設備的電源管理技術(shù)研究[J].電子科技大學學報,2001,30(5):497-502.
[6]毛德操,胡希明.Linux 內(nèi)核源代碼情景分析[M].杭州:浙江大學出版社, 2001:663-671.
[7]李善平, 劉文峰, 王煥龍,等.Linux與嵌入式系統(tǒng)[M].2版.北京: 清華大學出版社, 2006:187 193.
“本文中所涉及到的圖表、注解、公式等內(nèi)容請以PDF格式閱讀原文”