引言
傳統(tǒng)上,調(diào)試嵌入式Linux產(chǎn)品需要將硬件和軟件工具結(jié)合起來,如用JTAG工具進(jìn)行硬件bring-up,用基于代理(agent- based)的解決方案進(jìn)行軟件開發(fā)。這些JTAG和基于代理的工具相結(jié)合的方法通??梢越鉀Q單點(diǎn)問題,但它們最初并不是專門針對集成化的Linux開發(fā)而設(shè)計(jì)的。因而,在當(dāng)今集成化的產(chǎn)品開發(fā)中,這些傳統(tǒng)方法常常是不可行的。
但是,我們可以在Linux內(nèi)核的配置、補(bǔ)丁管理以及在基于Eclipse的IDE環(huán)境中的用戶空間應(yīng)用開發(fā)、調(diào)試和分析之中,將傳統(tǒng)JTAG 硬件調(diào)試融入其中得到一種全新的方法,從而完全改變開發(fā)人員使用JTAG連接進(jìn)行Linux設(shè)備軟件調(diào)試的方法,這就是Wind RiverWorkbench。
Linux設(shè)備調(diào)試的復(fù)雜性
在嵌入式設(shè)備領(lǐng)域,Linux的應(yīng)用正在迅速增加。根據(jù)技術(shù)市場研究機(jī)構(gòu)VDC的報(bào)告,在新的設(shè)備研發(fā)項(xiàng)目中,有23%會采用Linux。由于開發(fā)工作跨越Boot Loader、Linux內(nèi)核、內(nèi)核模塊和應(yīng)用,調(diào)試工作很可能極為復(fù)雜。Linux開發(fā)人員必須面對的問題包括為Boot Loader建立目標(biāo)配置文件,在用戶模式和內(nèi)核模式之間雙向?qū)τ睱inux虛擬地址、映射內(nèi)核符號信息以及排除遍布于用戶和內(nèi)核空間之中的差錯(cuò)。包括內(nèi)核GNU調(diào)試器和GNU調(diào)試器在內(nèi),在基于代理的調(diào)試方案中,要想解決上述任何問題都會遇到極大困難。
Boot Loader調(diào)試
如果浪費(fèi)太多的時(shí)間在BootLoader的開發(fā)與調(diào)試上,將會嚴(yán)重影響開發(fā)人員對于系統(tǒng)穩(wěn)定性、設(shè)備軟件與應(yīng)用開發(fā)的精力投入。因此,開發(fā)人員應(yīng)當(dāng)借助于先進(jìn)的工具,盡快逾越這個(gè)階段。
Linux需要依靠BootLoader來啟動操作系統(tǒng)。這段代碼存放在Flash或者其他非易失性存儲器之中,在系統(tǒng)開機(jī)或者復(fù)位之后立即運(yùn)行。Boot Loader的調(diào)試可能會非常復(fù)雜。這段代碼與硬件密切相關(guān),在系統(tǒng)啟動之后開發(fā)人員必須把它從Flash存儲重新定位到RAM之中。在今天的SoC處理器中可能包括了數(shù)百個(gè)配置寄存器,都需要在此時(shí)進(jìn)行初始化,這項(xiàng)工作需要熟悉數(shù)千頁的特殊設(shè)定文檔。如果設(shè)定寄存器錯(cuò)誤,可能導(dǎo)致隨后Linux內(nèi)核或者應(yīng)用調(diào)試的異常。并且手工編輯寄存器設(shè)定是一項(xiàng)極為繁瑣易錯(cuò)的工作。
Boot Loader開發(fā)的另一項(xiàng)常見挑戰(zhàn)出現(xiàn)在Boot Loader把Linux裝入RAM并啟動操作系統(tǒng)的時(shí)候?;诖淼恼{(diào)試解決方案不支持BootLoader調(diào)試,因?yàn)樵诖诉^程中還沒有開始發(fā)揮作用。因此,開發(fā)人員只能寄希望于JTAG工具。
JTAG調(diào)試解決方案提供了很強(qiáng)的能力來幫助開發(fā)人員快速有效地完成Boot Loader的測試與故障排除工作。它使寄存器設(shè)置工作大大簡化,通過設(shè)置硬件斷點(diǎn)以及單步執(zhí)行Flash中的代碼,可以快速發(fā)現(xiàn)原代碼中的錯(cuò)誤。IDE 可以支持反匯編,還可以讓你混合查閱源代碼和匯編代碼,符號管理功能比較便于代碼從Flash向RAM的重新定位,使整個(gè)調(diào)試工作得到很大幫助。
JTAG調(diào)試解決方案不需要通過Boot Loader即可裝載Linux內(nèi)核。對于那些在Boot Loader尚未完成之前就希望開始系統(tǒng)開發(fā)的項(xiàng)目管理人員來說,這項(xiàng)功能具有特殊的重要意義。提供了引導(dǎo)行能力的JTAG調(diào)試解決方案可以支持Boot Loader和操作系統(tǒng)穩(wěn)定化的并行開發(fā),從而加速軟件開發(fā)項(xiàng)目的整體進(jìn)程。
Linux內(nèi)核及內(nèi)核模塊調(diào)試
Linux內(nèi)核及內(nèi)核模塊是Linux操作系統(tǒng)的核心構(gòu)建。在系統(tǒng)被Boot Loader初始化之后,首先裝載的就是Linux內(nèi)核。Linux模塊則根據(jù)需要進(jìn)行裝載。在進(jìn)行操作系統(tǒng)bring-up時(shí),開發(fā)人員必須專注于 Linux操作系統(tǒng)的優(yōu)化或剪裁以及內(nèi)核模塊的開發(fā),需要必須密切監(jiān)控硬件與軟件之間的互動。Linux內(nèi)核調(diào)試要求具備觀察寄存器、數(shù)據(jù)緩存器及其它底層數(shù)據(jù)。LinuxKGDB要求具備穩(wěn)定的Linux內(nèi)核,并且確保諸如設(shè)備驅(qū)動之類的客戶硬件接口處于就緒狀態(tài),其中的代理才能工作?;诖淼恼{(diào)試不具備底層硬件的可視化能力,也不能提供完全的診斷功能,因而無法讓開發(fā)者了解硬件與Linux內(nèi)核之間的互動。
如果采用代理來調(diào)試Linux內(nèi)核和內(nèi)核模塊,在進(jìn)入調(diào)試斷點(diǎn)時(shí)可能會涉及系統(tǒng)暫?;蛘邇鼋Y(jié)方面的問題。例如,KGDB無法暫停CPU(特別是在多核或者多處理器環(huán)境中)來讓開發(fā)人員檢查CPU的現(xiàn)行狀態(tài),它也不能幫助開發(fā)人員對崩潰的系統(tǒng)進(jìn)行調(diào)試,因?yàn)楸罎⒌牟僮飨到y(tǒng)顯然已經(jīng)不能再運(yùn)行代理。而且,KGDB還需要以太網(wǎng)等通信接口實(shí)現(xiàn)主機(jī)系統(tǒng)與目標(biāo)之間的溝通??傊?,采用代理來實(shí)現(xiàn)Linux內(nèi)核模式調(diào)試,需要具備由IP棧、穩(wěn)定的Linux 內(nèi)核和處于運(yùn)行狀態(tài)的設(shè)備驅(qū)動。在上述條件尚未具備,或者上述軟件本身還需要調(diào)試的時(shí)候,基于代理的調(diào)試顯然就無能為力。
為了實(shí)現(xiàn)并驗(yàn)證一個(gè)目標(biāo)系統(tǒng)中的Linux內(nèi)核,必須擁有可以監(jiān)控和管理Linux內(nèi)核和內(nèi)核模塊的全面調(diào)試解決方案?;贘TAG的調(diào)試解決方案功能特性包括查看局部/全局符號和寄存器以及指令和數(shù)據(jù)緩存器。已經(jīng)有商業(yè)化的JTAG調(diào)試解決方案可以把物理內(nèi)存和虛擬內(nèi)存順暢地映射過來,從而幫助開發(fā)人員正確地觀察內(nèi)存地址和內(nèi)容,也具有對Linux內(nèi)核模塊進(jìn)行調(diào)試的能力,以及在不必反復(fù)連接和切斷目標(biāo)系統(tǒng)的前提下多次裝載和卸載。
JTAG調(diào)試解決方案的另一個(gè)重要能力是把系統(tǒng)完全置于暫停狀態(tài)并且全面觀察操作系統(tǒng)和應(yīng)用的狀態(tài)。這種能力又被稱為“系統(tǒng)模式調(diào)試 (system mode debug)”,對于Linux內(nèi)核和Linux內(nèi)核模塊的調(diào)試是極為有用的。有了系統(tǒng)模式調(diào)試能力,開發(fā)人員就可以把整個(gè)系統(tǒng)完全暫停下來,包括處理器、操作系統(tǒng)和所有的線程以及中斷處理程序。以這種方式暫停系統(tǒng),就有可能獲得系統(tǒng)硬件和軟件的完整細(xì)節(jié)視圖,當(dāng)然也可以讓系統(tǒng)繼續(xù)執(zhí)行或者分步驟執(zhí)行某些代碼。
因此,在一些KGDB無法使用的情況下,JTAG解決方案就可大派用場,特別是在Linux內(nèi)核出錯(cuò)或者目標(biāo)崩潰的情況下更是如此。因此JTAG解決方案在提升操作系統(tǒng)和設(shè)備驅(qū)動穩(wěn)定性方面特別有用。
Linux應(yīng)用調(diào)試
Linux應(yīng)用是在Linux內(nèi)核控制之下運(yùn)行的用戶程序,它通過系統(tǒng)調(diào)用來訪問系統(tǒng)資源。Linux內(nèi)核負(fù)責(zé)處理系統(tǒng)調(diào)用并且決定如何來提供硬件和內(nèi)存訪問。
對于用戶模式下的應(yīng)用調(diào)試,開發(fā)人員需要通過啟動和停止線程、查看變量和堆棧來直接訪問應(yīng)用線程。由于一個(gè)應(yīng)用可能由多個(gè)進(jìn)程或者線程組成,所以有可能需要停止與正在調(diào)試的應(yīng)用線程相關(guān)的所有線程。開發(fā)人員也常常需要跨越不同的進(jìn)程和CPU來查看外設(shè)寄存器。然而,GDB只能在線程的級別上操作,而且只能啟動和停止單個(gè)線程,根本不具備啟動和停止整個(gè)系統(tǒng)或者同時(shí)啟動/停止多個(gè)線程的能力。
另外,在用戶模式下進(jìn)行調(diào)試的時(shí)候,可能會因?yàn)閱尾竭\(yùn)行系統(tǒng)調(diào)用而從用戶模式進(jìn)入Linux內(nèi)核模式,然后又單步執(zhí)行回到用戶模式。在 Linux的虛擬內(nèi)存結(jié)構(gòu)下,在兩種模式之間來回轉(zhuǎn)換的同時(shí)還要保持內(nèi)存地址跟蹤,僅僅依賴于物理地址將會效果有限。于是,基于代理的解決方案需要同時(shí)采用GDB和KGDB來跟蹤系統(tǒng)調(diào)用進(jìn)入Linux內(nèi)核和內(nèi)核模塊。同時(shí),這個(gè)過程將會非常復(fù)雜。
Linux應(yīng)用開發(fā)人員也常常遇到?jīng)]有配備以太網(wǎng)或者串行通信接口的設(shè)備開發(fā)項(xiàng)目。即便是配有這些通信接口,相應(yīng)的軟件也不一定能很快就開發(fā)完成。而基于代理的調(diào)試方法必須依賴這些通信接口才能工作。如果目標(biāo)設(shè)備沒有通信接口,或者這些通信接口本身還需要開發(fā)與調(diào)試,或者內(nèi)存對于IP?;虼碥浖豢捎?,在這些情況下,基于代理的方法也不能使用。
基于JTAG的調(diào)試方法對于運(yùn)行在Linux用戶模式下的應(yīng)用則具有深度可視化能力。對于提出系統(tǒng)調(diào)用的應(yīng)用,雙模式的JTAG調(diào)試解決方案還將可視化的深度延伸到Linux內(nèi)核,所有的應(yīng)用線程、運(yùn)行環(huán)境以及在線程變量中用到的參數(shù)都一覽無遺,而且這些功能的實(shí)現(xiàn)不會對Linux內(nèi)核本身造成任何影響。對于沒有通信接口的目標(biāo)設(shè)備,例如移動電話、醫(yī)療設(shè)備、車載設(shè)備等,基于JTAG的調(diào)試解決方案都顯示出遠(yuǎn)高于基于代理調(diào)試的優(yōu)越性。一個(gè) Linux的軟件與硬件連接如圖1所示。
采用系統(tǒng)模式調(diào)試可以讓多線程應(yīng)用調(diào)試大大簡化,這是因?yàn)殚_發(fā)人員獲得了暫停處理器并觀察操作系統(tǒng)和全部線程運(yùn)行狀態(tài)的能力。如前所述,許多問題的發(fā)生是因?yàn)槎鄠€(gè)線程之間的交互。而基于代理的調(diào)試根本不具備停止全部線程的能力,自然也就難以發(fā)現(xiàn)問題所在,這就意味著工程進(jìn)度將會因?yàn)檎{(diào)試工作的低效率而被大大延遲。
基于JTAG的調(diào)試解決方案與目標(biāo)硬件的連接是非干擾性的,可以連接到一個(gè)已經(jīng)運(yùn)行并且發(fā)生錯(cuò)誤的目標(biāo)系統(tǒng)之中,也可以不改變處理器寄存器的狀態(tài),即可觀察到Linux內(nèi)核和應(yīng)用的運(yùn)行狀況并進(jìn)行調(diào)試。例如,如果一個(gè)Linux的目標(biāo)設(shè)備進(jìn)入死鎖狀態(tài),利用JTAG調(diào)試工具,開發(fā)人員就可以在不會破壞現(xiàn)場狀態(tài)的前提下與目標(biāo)系統(tǒng)連接,進(jìn)而觀察其中的Linux內(nèi)核對象、應(yīng)用運(yùn)行情況,找到引發(fā)錯(cuò)誤的線程、系統(tǒng)調(diào)用以及調(diào)用參數(shù)。在有些情況下,基于代理的調(diào)試工具根本無法使用,而基于JTAG的調(diào)試工具卻可以簡化調(diào)試工作,加快調(diào)試進(jìn)度。
Wind River基于JTAG的Linux調(diào)試工具
Wind Rivet推出的基于JTAG的OCD((On-Chip Debugging,片上調(diào)試)解決方案運(yùn)行在符合工業(yè)標(biāo)準(zhǔn)的Eclipse平臺上,為嵌入式Linux設(shè)備提供了先進(jìn)的基于JTAG的調(diào)試功能特性。
Workbench OCD主要支持Wind River Linux。不過,對于開發(fā)者自行獲得的Linux或者半導(dǎo)體廠商提供的Linux版本,Wind River也可提供片上調(diào)試功能,也為kernel.org Linux提供基于JTAG的內(nèi)核及用戶模式調(diào)試。Wind River調(diào)試解決方案還支持廣泛的目標(biāo)硬件,包括先進(jìn)的多核處理器。它還支持移動終端設(shè)備市場上所有最新的主流處理器,實(shí)現(xiàn)各種量身定制的增強(qiáng)功能特性,使設(shè)備軟件和硬件的開發(fā)調(diào)試變得更加簡單、更加直觀。
Workbench實(shí)現(xiàn)了與Eclipse全整合,并且通過在Workbench基于Eclipse的環(huán)境中加入新的視圖和功能模塊,進(jìn)一步加強(qiáng)了IDE的支持。
目前,大多數(shù)移動終端設(shè)備都采用了多處理內(nèi)核,對很多片上調(diào)試解決方案都造成很大的挑戰(zhàn)。JTAG Server和JTAG Accelerator技術(shù)提供了面向多內(nèi)核處理器的高速JTAG調(diào)試能力。JTAG Accelerator技術(shù)支持當(dāng)前最復(fù)雜的32位和64位處理器,實(shí)現(xiàn)了JTAG帶寬利用率的最大化。JTAG Servet技術(shù)則使開發(fā)人員能夠同時(shí)連接多達(dá)128個(gè)處理器,并且在單個(gè)IDE實(shí)例中動態(tài)地調(diào)試多個(gè)處理器。
這樣,Linux開發(fā)人員可以靈活地采用JTAG連接來進(jìn)行硬件bring-up、Linux內(nèi)核、中間件和用戶模式應(yīng)用的調(diào)試,并且在適當(dāng)?shù)臅r(shí)候轉(zhuǎn)移到基于代理的調(diào)試方式之下,而且不論是JTAG或是代理模式都在同一個(gè)IDE架構(gòu)之中,這種功能可以顯著改善多個(gè)開發(fā)團(tuán)隊(duì)之間的協(xié)同效率,節(jié)省排除差錯(cuò)的時(shí)間。
結(jié)語
由于嵌入式系統(tǒng)已經(jīng)變得越來越復(fù)雜,軟件開發(fā)人員在調(diào)試工作上所面臨的挑戰(zhàn)也越來越多。傳統(tǒng)基于代理的Linux調(diào)試解決方案在用戶模式和內(nèi)核模式的調(diào)試上的有效性都面臨尷尬。基于JTAG的調(diào)試可以在Linux開發(fā)中扮演極有價(jià)值的角色,當(dāng)它與Eclipse之類的標(biāo)準(zhǔn)化開發(fā)環(huán)境相結(jié)合,就可以顯著改善編輯-編譯-調(diào)試過程。在產(chǎn)品上市速度已經(jīng)成為關(guān)鍵因素的今天,擁有高效率的Wind RiverWorkbench調(diào)試工具無疑是明智的選擇。
評論
查看更多