gdb調(diào)試一個(gè)通過(guò)串行線同PC相連的嵌入式系統(tǒng)
中華工控網(wǎng)
|
|
鄒思軼(syzou),西南交通大學(xué)在讀研究生整理提供<BR> 1. 概論<BR> 我們將學(xué)習(xí)使用gdb來(lái)調(diào)試通過(guò)一個(gè)通過(guò)串行線同PC相連的嵌入式系統(tǒng).<BR> Gdb可以調(diào)試各種程序,包括C、C++、JAVA、PASCAL、FORAN和一些其它的語(yǔ)言。包括GNU所支持的所有微處理器的匯編語(yǔ)言。<BR> 在gdb的所有可圈可點(diǎn)的特性中,有一點(diǎn)值得注意,就是當(dāng)運(yùn)行g(shù)db的平臺(tái)(宿主機(jī))通過(guò)串行端口(或網(wǎng)絡(luò)連接,或是其他別的方式)連接到目標(biāo)板時(shí)(應(yīng)用程序在板上運(yùn)行),gdb 可以調(diào)試對(duì)應(yīng)用程序進(jìn)行調(diào)試。這個(gè)特性不光在將GNU工具移植到一個(gè)新的操作系統(tǒng)或微處理器時(shí)侯很有用,對(duì)于那些使用GNU已經(jīng)支持的芯片的嵌入式系統(tǒng)進(jìn)行開(kāi)發(fā)的設(shè)計(jì)人員來(lái)講,也是非常有用的。<BR> 當(dāng)gdb被適當(dāng)?shù)募傻侥硞(gè)嵌入式系統(tǒng)中的時(shí)候,它的遠(yuǎn)程調(diào)試功能允許設(shè)計(jì)人員一步一步的調(diào)試程序代碼、設(shè)置斷點(diǎn)、檢驗(yàn)內(nèi)存,并且同目標(biāo)交換信息。Gdb同目標(biāo)板交換信息的能力相當(dāng)強(qiáng),勝過(guò)絕大多數(shù)的商業(yè)調(diào)試內(nèi)核,甚至功能相當(dāng)于某些低端仿真器。</P><P> 2.Gdb在嵌入式領(lǐng)域的功能實(shí)現(xiàn)<BR> 當(dāng)調(diào)試一個(gè)遠(yuǎn)端目標(biāo)設(shè)備時(shí),gdb依靠了一個(gè)調(diào)試stub來(lái)完成其功能。調(diào)試stub即是嵌入式系統(tǒng)中一小段代碼,它提供了運(yùn)行g(shù)db的宿主機(jī)和所調(diào)試的應(yīng)用程序間的一個(gè)媒介。<BR> Gdb和調(diào)試stub通過(guò)GDB串行協(xié)議進(jìn)行通信。GDB串行協(xié)議是一種基于消息的ASCII碼協(xié)議,包含了諸如讀寫(xiě)內(nèi)存、查詢寄存器、運(yùn)行程序等命令。由于絕大多數(shù)嵌入式系統(tǒng)設(shè)計(jì)人員為了最好的利用他們手中特定的硬件的特征,總是自己編寫(xiě)自己的stub。所以我們有必要清楚的了解一下gdb的串行通信協(xié)議。在后面我們會(huì)詳細(xì)介紹。</P><P> 為了設(shè)置斷點(diǎn),gdb使用內(nèi)存讀寫(xiě)命令,來(lái)無(wú)損害地將原指令用一個(gè)TRAP命令或其它類似的操作碼(在此假定,被調(diào)試的應(yīng)用程序是處在RAM中的,當(dāng)然,如果stub有足夠好的性能,硬件也不錯(cuò)的話,這個(gè)條件也不是必須的)代替,使得執(zhí)行該命令時(shí),可以使得控制權(quán)轉(zhuǎn)移到調(diào)試stub手中去。在此時(shí),調(diào)試stub的任務(wù)就是將當(dāng)前場(chǎng)景傳送給gdb(通過(guò)遠(yuǎn)程串行通信協(xié)議),然后從gdb處接收命令,該命令告訴了stub下一步該做什么。</P><P> 為了說(shuō)明,下面的代碼是Hitachi SH-2處理器的一個(gè)TRAP異常處理程序:</P><P> /*將當(dāng)前寄存器的值存儲(chǔ)到堆棧中*/<BR> /* 然后調(diào)用gdb_exception. */<BR> asm("<BR> .global _gdb_exception_32<BR> _gdb_exception_32:</P><P> /* 將堆棧指針和r14壓入堆棧*/<BR> mov.l r15, @-r15<BR> mov.l r14, @-r15</P><P> /*當(dāng)執(zhí)行一個(gè)陷阱異常時(shí),sh2 自動(dòng)的將pc 和sr 放入堆棧 */<BR> /*所以我們必須調(diào)整我們給gdb的堆棧指針值,以此來(lái)說(shuō)明這個(gè)特別的數(shù)據(jù) */<BR> /* 換言之,在該陷阱被執(zhí)行前,gdb想看看堆棧指針的值,*/<BR> /* 而不是陷阱被執(zhí)行當(dāng)前時(shí)的值。*/<BR> /*所以,從我們剛壓入堆棧的sp值中減去8*/<BR> /*(pc和sr都是4個(gè)字節(jié)的 )*/</P><P> mov.l @(4,r15), r14<BR> add #8, r14<BR> mov.l r14, @(4,r15)</P><P> /*將其它寄存器值壓入堆棧 */<BR> mov.l r13, @-r15<BR> mov.l r12, @-r15<BR> mov.l r11, @-r15<BR> mov.l r10, @-r15<BR> mov.l r9, @-r15<BR> mov.l r8, @-r15<BR> mov.l r7, @-r15<BR> mov.l r6, @-r15<BR> mov.l r5, @-r15<BR> mov.l r4, @-r15<BR> mov.l r3, @-r15<BR> mov.l r2, @-r15<BR> mov.l r1, @-r15<BR> mov.l r0, @-r15<BR> sts.l macl, @-r15<BR> sts.l mach, @-r15<BR> stc vbr, r7<BR> stc gbr, r6<BR> sts pr, r5</P><P> /* 調(diào)用gdb_exception, 令其異常值=32 */<BR> mov.l _gdb_exception_target, r1<BR> jmp @r1<BR> mov #32, r4</P><P> .align 2<BR> _gdb_exception_target: .long _gdb_exception<BR> ");</P><P> /* 下面是一個(gè)從調(diào)試stub返回對(duì)某個(gè)應(yīng)用程序的控制的樣例(針對(duì)Hitachi SH2)*/<BR> /*如果用C語(yǔ)言寫(xiě),那么該語(yǔ)句的原型為:*/<BR> /* void gdb_return_from_exception( gdb_sh2_registers_T registers );*/<BR> /* 總而言之,我們可以用同gdb_exception_nn把寄存器壓入堆棧同樣的方式*/<BR> /* 將其從堆棧中彈出。然而,通常返回指針同我們的返回堆棧指針不一樣。*/<BR> /*所以如果我們?cè)诳截恜c和sr到返回指針之前將r15彈出的話,我們就回*/<BR> 丟失掉pc和sr。<BR> */ <BR> asm("<BR> .global _gdb_return_from_exception<BR> _gdb_return_from_exception:</P><P> /*恢復(fù)某些寄存器*/<BR> lds r4, pr<BR> ldc r5, gbr<BR> ldc r6, vbr<BR> lds r7, mach<BR> lds.l @r15+, macl<BR> mov.l @r15+, r0<BR> mov.l @r15+, r1<BR> mov.l @r15+, r2<BR> mov.l @r15+, r3<BR> mov.l @r15+, r4<BR> mov.l @r15+, r5<BR> mov.l @r15+, r6<BR> mov.l @r15+, r7<BR> mov.l @r15+, r8<BR> mov.l @r15+, r9<BR> mov.l @r15+, r10<BR> mov.l @r15+, r11<BR> mov.l @r15+, r12</P><P> /* 將pc和 sr彈出到應(yīng)用程序的堆棧*/<BR> mov.l @(8,r15), r14<BR> mov.l @(16,r15), r13<BR> mov.l r13, @-r14<BR> mov.l @(12,r15), r13<BR> mov.l r13, @-r14</P><P> /* 完成恢復(fù)寄存器的工作*/<BR> mov.l @r15+, r13<BR> mov.l @r15+, r14<BR> mov.l @r15, r15</P><P> /*調(diào)整應(yīng)用程序的堆棧,來(lái)說(shuō)明pc, sr */<BR> add #-8, r15</P><P> /* ...返回到應(yīng)用程序*/<BR> rte<BR> nop<BR> ");</P><P> <BR> 當(dāng)處理器遇到了一個(gè)TRAP指令(該指令是由gdb 設(shè)置的,做斷點(diǎn)用)時(shí),該指令使得處理器的當(dāng)前場(chǎng)景轉(zhuǎn)向一個(gè)名為gdb_exception()的函數(shù)。最終,目標(biāo)調(diào)用了gdb_return_from_exception()函數(shù),該函數(shù)恢復(fù)了處理器的場(chǎng)景并將控制權(quán)交給應(yīng)用程序。</P><P> 遠(yuǎn)程串行協(xié)議的步進(jìn)命令稍微更有挑戰(zhàn)性些,特別當(dāng)目標(biāo)處理器不提供一個(gè)"跟蹤位"或類似的功能時(shí)。在這些情況下,唯一的替代辦法就是讓stub把將要執(zhí)行的指令反匯編。這樣它就會(huì)知道程序下一步要執(zhí)行到何處。<BR> 幸運(yùn)的是,在gdb的源代碼中也提供了關(guān)于如何一些實(shí)現(xiàn)這些步近命令的建議。對(duì)于Hitachi SH-2芯片而言,在gdb/sh-stub.c文件中說(shuō)明了函數(shù)doSStep()的使用,對(duì)于其它種類的芯片,函數(shù)的名字也差不多,請(qǐng)看文件gdb/i386-stub.c和gdb/m68k-stub.c</P><P> 3.gdb的其它功能 <BR> Gdb還可以求解在控制臺(tái)中輸入的任意的C表達(dá)式的值,包括包含有對(duì)遠(yuǎn)端目標(biāo)的函數(shù)功能調(diào)用的表達(dá)式。我們可以輸入如下命令:</P><P> print foo( sh_sci[current_sci]->smr.brg )</P><P> gdb就會(huì)將mr.brg的值傳送給foo(),并報(bào)告其返回值。<BR> 當(dāng)然,gdb也可以反匯編代碼。只要可能的話,它還可以很好的為所需的數(shù)據(jù)提供等價(jià)的符號(hào)信息。例如,gdb用下列輸出:</P><P> jmp 0x401010 <main + 80></P><P> 告訴了我們,所顯示的地址與從函數(shù)main()的起始地址起偏移80個(gè)字節(jié)的地址相等。<BR> Gdb 可以顯示其自身和所調(diào)試的目標(biāo)間的遠(yuǎn)程串行調(diào)試信息,也可以將該信息記錄到日志文件中去。這些特性對(duì)于我們調(diào)試一個(gè)新的stub,了解stub是如何使用遠(yuǎn)程串行協(xié)議來(lái)實(shí)現(xiàn)用戶對(duì)數(shù)據(jù)、程序內(nèi)存、系統(tǒng)調(diào)用等等的需求是十分有用的。</P><P> Gdb擁有腳本語(yǔ)言,允許對(duì)目標(biāo)自動(dòng)的設(shè)置和檢測(cè)。該語(yǔ)言是對(duì)目標(biāo)處理器獨(dú)立的,所以應(yīng)用程序從一個(gè)目標(biāo)處理器移植到另外的處理器時(shí),腳本可以重用。</P><P> 最后,gdb還提供了跟蹤點(diǎn)的功能,該功能可以記錄某個(gè)運(yùn)行程序的信息,而盡可能的不打斷程序收集數(shù)據(jù)。跟蹤點(diǎn)需要特別的調(diào)試stub來(lái)實(shí)現(xiàn)。 </P><P> 4.一個(gè)典型的gdb會(huì)話過(guò)程<BR> 現(xiàn)在我們已經(jīng)探討了gdb的通用功能,現(xiàn)在我們來(lái)看看gdb的執(zhí)行。下面給出了一個(gè)典型的gdb 調(diào)試會(huì)話過(guò)程。在該過(guò)程中,gdb初始化了同一個(gè)運(yùn)行調(diào)試stub的遠(yuǎn)端目標(biāo)間的通信,然后下載程序,設(shè)置斷點(diǎn),并運(yùn)行該程序。當(dāng)遇到斷點(diǎn)時(shí),調(diào)試stub通知gdb,gdb然后就將其源代碼行顯示給用戶。接著,用戶顯示了一個(gè)變量,步近執(zhí)行一個(gè)指令,然后推出gdb 。<BR> 請(qǐng)注意,下面并未顯示用戶在使用gdb時(shí)所見(jiàn)到的內(nèi)容。用戶所見(jiàn)到的是一個(gè)終端,顯示的內(nèi)容都是用英文寫(xiě)成的源代碼、要顯示的變量等等。但是,下面顯示的腳本說(shuō)明了當(dāng)用戶鍵入命令時(shí)在幕后發(fā)生的內(nèi)容。 </P><P> 典型的gdb會(huì)話過(guò)程的描述</P><P> <br><A HREF="/editor/uploadfiles/learns01/200382910381371880.jpg" TARGET=_blank><IMG SRC="/editor/uploadfiles/learns01/200382910381371880.jpg" border=0 alt=按此在新窗口瀏覽圖片 onload="javascript:if(this.width>580)this.width=580"></A><BR> <br><A HREF="/editor/uploadfiles/learns01/200382910384964469.jpg" TARGET=_blank><IMG SRC="/editor/uploadfiles/learns01/200382910384964469.jpg" border=0 alt=按此在新窗口瀏覽圖片 onload="javascript:if(this.width>580)this.width=580"></A></P><P> 上圖中,左邊一欄顯示了gdb控制臺(tái)的一部分。在此用戶鍵入命令并監(jiān)視數(shù)據(jù)。右邊一欄顯示了一些使用GDB遠(yuǎn)程串行協(xié)議在宿主機(jī)和嵌入式設(shè)備之間的通信消息。在方括號(hào)中是一些解釋信息。如果想清楚的了解這些信息的含義,請(qǐng)見(jiàn)附錄《GDB遠(yuǎn)程串行協(xié)議》部分。</P><P> 5.Gdb調(diào)試stub的源代碼<BR> 雖然遠(yuǎn)程軟件調(diào)試具有依賴于目標(biāo)的特性,但是還是可以創(chuàng)建一個(gè)有高度的可移植性的調(diào)試stub,在不同的嵌入式處理器芯片之間可以被重用,而所需的修改最小。<BR> 有人已經(jīng)嘗試了這方面的工作。如果各位感興趣,可以去上網(wǎng)查閱相關(guān)的資料。例如<img align=absmiddle src=pic/url.gif border=0><a target=_blank href=http://sourceforge.net/projects/gdbstubs> http://sourceforge.net/projects/gdbstubs</a>。</P><P> 處理器特定的代碼包含在與處理器相關(guān)的文件名中,例如gdb_sh2*.c。我們可以針對(duì)我們特定的處理器下載相關(guān)的文件(例如gdb_m68k*.c),然后在用其替代我們機(jī)器上的相關(guān)內(nèi)容。</P><P> 6.關(guān)于改造gdb來(lái)解決特定問(wèn)題的考慮<BR> gdb使用了一個(gè)模塊化的體系結(jié)構(gòu)來(lái)實(shí)現(xiàn),那么對(duì)它某些不適合我們需要的特性就可以很直接的加以處理。例如,如果我們的產(chǎn)品僅僅有一個(gè)通信端口,而它使用的并不是gdb的通信協(xié)議的話,那么,可以修改gdb,使得調(diào)試器的信息同我們產(chǎn)品已經(jīng)使用的信息包相匹配。</P><P> 類似地,如果我們的產(chǎn)品沒(méi)有串行端口,而有些別的通信接口(例如CAN端口),那么我們可以加強(qiáng)gdb的遠(yuǎn)程通信功能,來(lái)適應(yīng)該端口。<BR> 我們也可以修改gdb的工作方式使其同我們嵌入式應(yīng)用程序更加的相容。例如,如果我們正在使用TRAPA #32來(lái)做些同gdb無(wú)關(guān)的工作,我們就可以改變gdb為了設(shè)置斷點(diǎn)而使用的操作碼,或者我們可以使用gdb來(lái)產(chǎn)生一個(gè)新的消息告訴我們的目標(biāo)板開(kāi)啟指令追蹤的功能或使能芯片內(nèi)的斷點(diǎn)產(chǎn)生硬件。<BR> 文件gdb/remote.c包含了gdb的遠(yuǎn)程串行協(xié)議的實(shí)現(xiàn)過(guò)程。對(duì)于研究gdb的模塊化的實(shí)現(xiàn)是如何允許我們快速的將其改造以適應(yīng)特定的調(diào)試目標(biāo)而言,該文件是個(gè)很好的起點(diǎn)。其它的文件,例如gdb/remote-hms.c 和gdb/remote-e7000.c,使用了該模塊化的結(jié)構(gòu)來(lái)為諸如Hitachi, Motorola等公司的芯片的調(diào)試器和仿真器提供支持。<BR> 7.總結(jié)<BR> gdb對(duì)于調(diào)試目標(biāo)(包括對(duì)其內(nèi)存的使用,通信媒介等等方面)的可適應(yīng)性使得它對(duì)于目標(biāo)板的調(diào)試而言,常常是唯一的選擇?紤]到單芯片高集成度、基于IP的嵌入式產(chǎn)品的普及,情況更是如此。在今天,嵌入式設(shè)備的復(fù)雜性與日俱增,在進(jìn)行新的設(shè)計(jì)時(shí),其供選擇的技術(shù)的選擇也越來(lái)越多,要找到一個(gè)商業(yè)的開(kāi)發(fā)產(chǎn)品是越來(lái)越困難了。<BR> 而使用GNU工具將是個(gè)很好的選擇。GNU工具對(duì)各種流行的嵌入式處理器的支持意味著,當(dāng)我們正在使用的開(kāi)發(fā)工具對(duì)我們將要在下一個(gè)設(shè)計(jì)中使用的處理器不支持時(shí),我們可以減少尋找新的開(kāi)發(fā)工具所帶來(lái)的危險(xiǎn)。<BR>
|
|
狀 態(tài):
離線
公司簡(jiǎn)介
產(chǎn)品目錄
|
|
公司名稱:
|
中華工控網(wǎng)
|
聯(lián) 系 人: |
客服中心
|
電 話: |
0755-26546361
|
傳 真: |
0755-26585268 |
地 址: |
深圳市南山區(qū)創(chuàng)業(yè)路現(xiàn)代城華庭1棟6A |
郵 編: |
518054 |
主 頁(yè): |
|
|
|
|
|