平震宇,李培峰,孟 帆
(1.江蘇信息職業(yè)技術(shù)學(xué)院物聯(lián)網(wǎng)工程學(xué)院,江蘇無(wú)錫214101;2.蘇州大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,江蘇蘇州215006)
Arduino是開(kāi)放源碼的軟硬件平臺(tái),其硬件原理圖、核心庫(kù)文件都是開(kāi)源的,它是基于單片機(jī)系統(tǒng)開(kāi)發(fā)的,具有集成開(kāi)發(fā)環(huán)境(Integrated Development Environment,IDE)。Arduino是硬件開(kāi)發(fā)的趨勢(shì),其簡(jiǎn)單的開(kāi)發(fā)方式使開(kāi)發(fā)者可以更快速地完成自己的創(chuàng)意。Arduino逐漸發(fā)展成為一個(gè)廉價(jià)的易于使用的實(shí)驗(yàn)平臺(tái),被廣泛應(yīng)用于各領(lǐng)域。由于Arduino 入門(mén)要求低,不乏文科背景的愛(ài)好者、藝術(shù)家和設(shè)計(jì)師。Arduino也可以用于設(shè)計(jì)語(yǔ)音控制小車設(shè)計(jì)[1],書(shū)畫(huà)機(jī)械手臂[2],邁克爾遜干涉儀測(cè)量的改進(jìn)[3],制作體感機(jī)械手[4],汽車并線輔助系統(tǒng)[5],移動(dòng)機(jī)器人控制系統(tǒng)[6]這樣復(fù)雜的應(yīng)用系統(tǒng)。近年來(lái)Arduino 被應(yīng)用到物聯(lián)網(wǎng)工程專業(yè)實(shí)踐教學(xué)中,利用Arduino 平臺(tái)的優(yōu)勢(shì),創(chuàng)新物聯(lián)網(wǎng)工程專業(yè)實(shí)踐教學(xué),并在物聯(lián)網(wǎng)專業(yè)教學(xué)的軟硬件整合方面進(jìn)行深入的探索和改進(jìn)[7]。通過(guò)簡(jiǎn)便、靈活的開(kāi)發(fā)平臺(tái),進(jìn)行物聯(lián)網(wǎng)感知、識(shí)別和控制中外圍功能模塊的講解,讓學(xué)生在有限的基礎(chǔ)知識(shí)上提高學(xué)習(xí)效率、快速進(jìn)行實(shí)驗(yàn)開(kāi)發(fā)。
Arduino支持使用各種電子元件、傳感器、通信組件、控制輸入輸出設(shè)備,Arduino開(kāi)發(fā)板種類很多,常用的有Arduino UNO、Due、Yun、Mega、Zero、Robot、Leonardo、Nano等,Arduino UNO是USB接口系列的常用版本。Arduino簡(jiǎn)化了硬件接口操作,它為軟件開(kāi)發(fā)者設(shè)計(jì)的硬件開(kāi)發(fā)平臺(tái)。但是調(diào)試Arduino 程序只能通過(guò)串口回傳一些信息或者通過(guò)開(kāi)發(fā)板上的LED 燈顯示程序運(yùn)行情況。這兩種方法只適用于幾十行代碼的小程序,對(duì)于復(fù)雜的程序或初學(xué)用戶就不能滿足要求了。物聯(lián)網(wǎng)專業(yè)課程通過(guò)若干Arduino 項(xiàng)目提高學(xué)生的動(dòng)手、編程和創(chuàng)新能力,課程的實(shí)踐教學(xué)也需要Arduino具有調(diào)試功能。
Arduino項(xiàng)目開(kāi)發(fā)過(guò)程中需要確定程序錯(cuò)誤的位置以及錯(cuò)誤發(fā)生的內(nèi)在原因,Arduino IDE 卻沒(méi)有提供調(diào)試功能。Arduino UNO開(kāi)發(fā)板使用的ATmega328 芯片擁有一個(gè)片上的調(diào)試模塊(on-chip debug),可以實(shí)現(xiàn)對(duì)微控制單元(Micro Controller Unit,MCU)的運(yùn)行過(guò)程進(jìn)行單步調(diào)試、設(shè)置硬件斷點(diǎn)等調(diào)試操作,可查看或修改數(shù)據(jù)存儲(chǔ)區(qū),為調(diào)試者提供了訪問(wèn)MCU運(yùn)行時(shí)狀態(tài)以及控制MCU 運(yùn)行過(guò)程的方法和途徑。Visual Micro開(kāi)發(fā)了集成于Microsoft Visual Studio 和Atmel Studio IDE 的插件(http://www. visualmicro. com)[8],但是Visual Micro的調(diào)試功能是收費(fèi)的。
因此本文設(shè)計(jì)與實(shí)現(xiàn)Eclipse 集成開(kāi)發(fā)環(huán)境下基于GDB 的Arduino 遠(yuǎn)程調(diào)試器。Arduino 使用的是Atmel AVR系列微控制單元,編譯器是使用了GNU開(kāi)發(fā)工具系統(tǒng)的avr-gcc,調(diào)試工具是avr-gdb。GDB是一個(gè)功能強(qiáng)大的調(diào)試器,支持多種硬件平臺(tái)與多種程序語(yǔ)言,可以用于本地調(diào)試,也可以用于遠(yuǎn)程調(diào)試[8]。由于Arduino開(kāi)發(fā)板資源受限等原因,不可能直接在Arduino開(kāi)發(fā)板上運(yùn)行調(diào)試器,通常的做法是采用宿主機(jī)(host)加目標(biāo)機(jī)(target)的遠(yuǎn)程調(diào)試方式。在宿主機(jī)上運(yùn)行GDB調(diào)試器,目標(biāo)機(jī)上運(yùn)行被調(diào)試程序及調(diào)試插樁(GDB stub),目標(biāo)機(jī)上的GDB stub和宿主機(jī)上的GDB通過(guò)串口,遵循GDB的遠(yuǎn)程串行協(xié)議(Remote Serial Protocol,RSP),由宿主機(jī)上的GDB 獲取對(duì)應(yīng)用程序的控制權(quán),對(duì)應(yīng)用程序進(jìn)行源碼級(jí)調(diào)試。GDB stub是一段代碼,需要把GDB stub和被調(diào)試程序編譯鏈接成一個(gè)可執(zhí)行文件在目標(biāo)機(jī)上運(yùn)行。
Arduino遠(yuǎn)程調(diào)試器系統(tǒng)模型如圖1 所示,這個(gè)模型無(wú)須額外的硬件支持。GDB 是一個(gè)強(qiáng)大且免費(fèi)的命令行調(diào)試工具,GDB遠(yuǎn)程調(diào)試功能已成功運(yùn)用于多種嵌入式平臺(tái)[9-10],但并沒(méi)有在Arduino 開(kāi)發(fā)板上實(shí)現(xiàn)。Roman Pen實(shí)現(xiàn)了Atmel AVR系列微控制單元的調(diào)試服務(wù)[11](Embedded GDB server for AVR MCU)對(duì)本項(xiàng)目有參考價(jià)值。
圖1 Arduino遠(yuǎn)程調(diào)試器系統(tǒng)模型
GDB 遠(yuǎn)程調(diào)試有兩種方法GDB stub 與GDB Server。GDB Server 是個(gè)調(diào)試代理程序,宿主機(jī)上的GDB程序可以通過(guò)運(yùn)行于目標(biāo)機(jī)的GDBserver對(duì)嵌入式系統(tǒng)軟件與應(yīng)用程序進(jìn)行調(diào)試。GDB Server是運(yùn)行于目標(biāo)機(jī)上的一個(gè)進(jìn)程,需要通過(guò)Linux 系統(tǒng)提供的ptrace()系統(tǒng)調(diào)用實(shí)現(xiàn)對(duì)被調(diào)試進(jìn)程的訪問(wèn)與控制[12]。GDB Server是非侵入式的調(diào)試代理,適用于有操作系統(tǒng)支持的嵌入式系統(tǒng)[13]。GDB stub 則是侵入式的調(diào)試代理,需要通過(guò)鏈接器把GDB stub和被調(diào)試程序鏈接成一個(gè)可執(zhí)行文件,對(duì)于沒(méi)有操作系統(tǒng)支持的Arduino UNO 平臺(tái),必須使用GDB stub 方式實(shí)現(xiàn)GDB遠(yuǎn)程調(diào)試。
GDB stub可以通過(guò)TCP/IP 協(xié)議、并行接口或者串口與宿主機(jī)GDB 進(jìn)行通信[14-15]。Arduino UNO 開(kāi)發(fā)板上的USB 采用ATMega8U2 芯片模擬串口,用于Arduino供電、下載程序。本文通過(guò)這個(gè)虛擬串口與宿主機(jī)建立物理連接,由RSP協(xié)議分析模塊來(lái)處理宿主機(jī)發(fā)生過(guò)來(lái)的調(diào)試命令。
GDB定義了RSP協(xié)議用于與目標(biāo)機(jī)GDB stub 之間的通信,GDB 是請(qǐng)求方,GDB stub 是調(diào)試應(yīng)答方。例如GDB接收到用戶繼續(xù)執(zhí)行命令(continue),GDB就遵循RSP協(xié)議規(guī)定向GDB stub發(fā)送(c#63),GDB stub接收到這條命令后繼續(xù)調(diào)試程序運(yùn)行并向GDB返回(+)。RSP協(xié)議使用ASCII 字符來(lái)描述消息,消息由“”符號(hào)開(kāi)始,以“?!狈?hào)結(jié)束,另外帶8 bit 校驗(yàn)。如果接收消息校驗(yàn)正確,并準(zhǔn)備接收下一個(gè)消息則返回“+”符號(hào),如果校驗(yàn)錯(cuò)誤需要重新傳輸則返回-符號(hào)[16-17]。
RSP協(xié)議定義的命令非常多,只有需要實(shí)現(xiàn)其中部分命令即可。
?獲取最后的信號(hào)
H 設(shè)置線程,T 查看線程是否存活。直接回復(fù)OK字符串。
g 讀寄存器命令,返回所有目標(biāo)寄存器數(shù)值,G 寫(xiě)寄存器命令,返回OK確認(rèn)數(shù)據(jù)已經(jīng)寫(xiě)入寄存器。
m 讀取內(nèi)存命令,返回要求讀取的制定內(nèi)存地址的數(shù)值,M 寫(xiě)內(nèi)存命令,返回OK 確認(rèn)數(shù)據(jù)已經(jīng)寫(xiě)入內(nèi)存。
c 繼續(xù)執(zhí)行命令,s 單步執(zhí)行命令。調(diào)用gdb_update_breakpoints()函數(shù)處理斷點(diǎn)。
Z 插入斷點(diǎn),z 刪除斷點(diǎn)。調(diào)用gdb_insert_remove_breakpoint(gdb_ctx-> buff)插入,刪除斷點(diǎn)。
斷點(diǎn)機(jī)制是GDB stub需要實(shí)現(xiàn)的核心功能,當(dāng)進(jìn)程執(zhí)行到用戶設(shè)置斷點(diǎn)的時(shí)候需要讓程序暫停,另外當(dāng)用戶需要單步調(diào)試程序時(shí),GDB 也是通過(guò)設(shè)置斷點(diǎn)來(lái)獲取控制權(quán)。
GDB通過(guò)內(nèi)存的讀寫(xiě)來(lái)實(shí)現(xiàn)設(shè)置斷點(diǎn),它使用一個(gè)trap指令來(lái)替換原有指令,當(dāng)被調(diào)試的程序運(yùn)行到斷點(diǎn)的時(shí)候產(chǎn)生單步調(diào)試中斷信號(hào)(SIGTRAP)。該信號(hào)被GDB捕獲并進(jìn)行斷點(diǎn)命中判定,當(dāng)GDB 判斷出這次SIGTRAP是斷點(diǎn)命中之后就會(huì)轉(zhuǎn)入等待用戶輸入進(jìn)行下一步處理,否則繼續(xù)。ATmega328p 擁有32KB的Flash程序存儲(chǔ)器空間,用于存放程序指令代碼[18]。使用trap指令來(lái)替換原有指令就需要頻繁地擦寫(xiě)Flash 程序存儲(chǔ)器,ATmega328p 用戶手冊(cè)表示Flash程序存儲(chǔ)器至少可以擦寫(xiě)10,000 次。Flash 程序存儲(chǔ)器空間分為兩個(gè)區(qū):引導(dǎo)程序區(qū)(BootLoader)和應(yīng)用程序區(qū),兩個(gè)區(qū)有專門(mén)的鎖定位以實(shí)現(xiàn)讀和讀/寫(xiě)保護(hù)[18]。用于寫(xiě)應(yīng)用程序區(qū)的SPM指令必須位于引導(dǎo)程序區(qū)。GDB stub必須實(shí)現(xiàn)擦寫(xiě)Flash 程序存儲(chǔ)器的功能dboot_safe_pgm_write(),并且將代碼存放在引導(dǎo)程序區(qū),也就是需要重新下載BootLoader程序。
另外一種實(shí)現(xiàn)斷點(diǎn)的方法是把所有的斷點(diǎn)位置都存放在一個(gè)鏈表中(gdb_ctx-> breaks[ind_bks]),命中判定即把被調(diào)試程序當(dāng)前的位置(gdb_ctx->pc)和鏈表中的斷點(diǎn)位置進(jìn)行比較。如果當(dāng)前位置在斷點(diǎn)鏈表中則發(fā)送GDB_SIGTRAP信號(hào),并調(diào)用函數(shù)handle_exception(),控制權(quán)就交給GDB。為了讓GDB stub比較當(dāng)前運(yùn)行指令,就需要在執(zhí)行用戶程序每個(gè)指令后產(chǎn)生一個(gè)中斷信號(hào),在中斷處理程序中讓GDB stub獲得程序的控制權(quán)。ATmega328p 在退出中斷后總是回到主程序并至少執(zhí)行一條指令后才可以去執(zhí)行其他被掛起的中斷。進(jìn)入中斷服務(wù)程序時(shí)狀態(tài)寄存器不會(huì)被保存,中斷返回時(shí)也不會(huì)自動(dòng)恢復(fù),需要用戶通過(guò)軟件來(lái)完成。
通過(guò)gdb_enable_swinterrupt()函數(shù)設(shè)置外部中斷INT0 來(lái)產(chǎn)生中斷請(qǐng)求,由中斷處理程序ISR(INT0_vect,ISR_BLOCK ISR_NAKED)來(lái)處理這個(gè)中斷請(qǐng)求。
GDB單步執(zhí)行有step 與next 兩種方法。next 命令在處理過(guò)程是在該行語(yǔ)句處設(shè)置斷點(diǎn),然后運(yùn)行continue命令,讓程序繼續(xù)執(zhí)行,當(dāng)執(zhí)行到下一個(gè)斷點(diǎn)停下。step命令需要跟蹤到函數(shù)的內(nèi)部,若執(zhí)行語(yǔ)句不包括函數(shù)則與next 命令一樣處理。如果包含函數(shù)調(diào)用,在當(dāng)單步運(yùn)行遇到call指令時(shí),找到被調(diào)用函數(shù)的第一條指令并設(shè)置斷點(diǎn)。由gdb_update_breakpoints()函數(shù)完成應(yīng)用程序Flash的斷點(diǎn)寫(xiě)入與刪除操作。
GDB stub使用鏈表gdb_ctx->breaks[]來(lái)管理用戶設(shè)置的所有斷點(diǎn)。當(dāng)程序在斷點(diǎn)處停下或者單步執(zhí)行一步后,GDB會(huì)刪除所有的斷點(diǎn),在運(yùn)行continue命令之前需要設(shè)置好下一個(gè)斷點(diǎn),由gdb_insert_breakpoint()與gdb_remove_breakpoint()函數(shù)完成鏈表gdb_ctx->breaks[]的插入和刪除操作。
GDB stub完整的代碼已共享在arduino 中文社區(qū)的綜合討論區(qū)。GDB stub 分別在windows7、windows10、ubuntu 16.04 系統(tǒng)中測(cè)試成功,Eclipse IDE for C/C++ Developers 版本是4. 7. 3a,AVR Eclipse plugin版本是2.5.0,Arduino IDE版本是1.8.5。GDB stub也可以在其他支持GDB調(diào)試的IDE環(huán)境中使用。由于Arduino IDE沒(méi)有實(shí)現(xiàn)調(diào)試配置與用戶交互界面,所有不能與Arduino IDE配合使用。
Arduino IDE功能簡(jiǎn)捷易用,非常適合不熟悉編程環(huán)境的用戶,但是對(duì)于較復(fù)雜的Arduino 項(xiàng)目開(kāi)發(fā),Arduino IDE功能就顯得過(guò)于簡(jiǎn)單。本文使用Eclipse的C/C++開(kāi)發(fā)環(huán)境(C/C++ Development Tooling,CDT),CDT Debug MI提供了Eclipse與GDB的通信機(jī)制。宿主機(jī)調(diào)試器使用Arduino 工具鏈提供的avrgdb,版本信息為GNU gdb7. 8 (AVR_8bit_GNU_Toolchain_3.5.4)。
Eclipse還有一個(gè)支持Arduino 開(kāi)發(fā)的插件(AVR Eclipse plugin,AVR),Eclipse 通過(guò)CDT 插件與AVR插件構(gòu)建一個(gè)Arduino集成開(kāi)發(fā)環(huán)境。AVR插件集成了對(duì)GNU toolchain的支持,通過(guò)設(shè)置工具鏈路徑就可以直接在Eclipse 中進(jìn)行Arduino 項(xiàng)目代碼的編輯、編譯。
需要下載的相關(guān)軟件見(jiàn)表1。其中Arduino IDE是Arduino的集成開(kāi)發(fā)環(huán)境,將會(huì)使用它的燒寫(xiě)程序AVRDude以及Arduino 的核心庫(kù)文件。Eclipse IDE for C/C++是Eclipse的C/C++集成開(kāi)發(fā)環(huán)境,在官方網(wǎng)站下載。AVR Eclipse plugin 是Eclipse 的AVR 插件,通過(guò)Eclipse 的菜單項(xiàng)Help->Install New Software直接安裝。Atmel AVR Toolchain 是Atmel 的工具鏈,將會(huì)使用其工具鏈中的avr-gdb。Mingw tools 是一套完整的開(kāi)源編譯工具集,將使用它的項(xiàng)目管理工具M(jìn)ake。
表1 相關(guān)軟件下載地址
Eclipse的AVR 插件需要配置AVRDude 下載程序設(shè)置以及配置開(kāi)發(fā)工具鏈。
(1)AVRDude 下載程序設(shè)置。選擇Project->Properties菜單項(xiàng),彈出工程設(shè)置對(duì)話框如圖2 所示,在左側(cè)窗口點(diǎn)擊“AVR”前面的“+”號(hào),展開(kāi)子項(xiàng),點(diǎn)擊選中“AVRDude”子項(xiàng),右側(cè)窗口將出現(xiàn)對(duì)應(yīng)的設(shè)置。
圖2 AVRDude下載程序設(shè)置
AVRDude的用戶配置參數(shù)選擇Arduino IDE安裝目錄下的avrdude. conf 文件(C:\ arduino-1. 8. 5 \hardware\tools\avr\etc\avrdude.conf)。
在程序配置(Program Configuration)選擇項(xiàng),選擇“Add..”新建一個(gè)下載配置。在這配置界面里硬件類型(Programmer hardware)選擇Arduino,下載默認(rèn)串口(Override default port)中輸入串口號(hào),串口號(hào)與Arduino IDE 中配置保持一致,字符串格式為(/ /. /COM3),其余參數(shù)保持不變。
(2)配置開(kāi)發(fā)工具鏈。Eclipse 的AVR 插件需要配置開(kāi)發(fā)工具鏈,包括編譯器、項(xiàng)目管理工具、頭文件目錄、下載程序,見(jiàn)表2。其中AVR-GCC 可以選擇Arduino IDE的工具鏈,由于Arduino IDE的AVR-GDB無(wú)法使用,所以就統(tǒng)一使用Atmel的工具鏈。
表2 開(kāi)發(fā)工具鏈配置
Arduino 庫(kù)有標(biāo)準(zhǔn)庫(kù)與擴(kuò)展庫(kù),標(biāo)準(zhǔn)庫(kù)是指Arduino IDE 自帶的一些常用功能,它預(yù)裝在Arduino安裝文件夾的Libraries 文件夾中。Arduino 作為一個(gè)開(kāi)源平臺(tái),全世界的開(kāi)發(fā)者都可以共享自己編寫(xiě)的擴(kuò)展庫(kù),其他開(kāi)發(fā)者可以免費(fèi)引用這些庫(kù),也可以對(duì)它們進(jìn)行擴(kuò)充和完善。如果Arduino 項(xiàng)目開(kāi)發(fā)時(shí)使用了Arduino的標(biāo)準(zhǔn)庫(kù),在鏈接階段就需要有Arduino 的標(biāo)準(zhǔn)庫(kù)的靜態(tài)庫(kù)文件,并在項(xiàng)目Properties菜單項(xiàng)中設(shè)置AVR C/C++ Linker-> Libraries。
另一種方法是將Arduino 的標(biāo)準(zhǔn)庫(kù)通過(guò)創(chuàng)建鏈接資源(linked resources)的方式導(dǎo)入到工程中。首選創(chuàng)建一個(gè)新的Arduino UNO(AVR Cross Target Application)工程,選擇CPU型號(hào)為ATmega328p,頻率為16 MHz。選擇File -> New -> Folder 菜單項(xiàng)打開(kāi)新建文件夾對(duì)話框,單擊"高級(jí)(Advanced)"按鈕,選擇"鏈接文件夾(Link to alternate location)",文件夾路徑選擇Arduino 標(biāo)準(zhǔn)庫(kù)"C:\arduino-1.8.5\hardware\arduino\avr\cores\arduino"。
最后設(shè)置項(xiàng)目屬性,右鍵單擊項(xiàng)目,打開(kāi)屬性對(duì)話框,選擇"C/C++ Bulid -> Settings",在"AVR C++Complier -> Directories"選項(xiàng)中添加上一步添加的Arduino標(biāo)準(zhǔn)庫(kù)文件夾。現(xiàn)在編譯器會(huì)搜索選項(xiàng)指定的目錄中的頭文件,并且將所需要的函數(shù)庫(kù)一起編譯到項(xiàng)目中。
調(diào)試器GDB stub 性能評(píng)估分為功能可靠性和調(diào)試性能兩個(gè)方面。其中功能可靠性是對(duì)RSP 協(xié)議解析的準(zhǔn)確性以及調(diào)試器GDB stub與Eclipse 配合與準(zhǔn)確性驗(yàn)證,調(diào)試性能統(tǒng)計(jì)了GDB stub 代碼的大小,內(nèi)存使用情況,程序運(yùn)行效率等數(shù)據(jù)。
功能可靠性評(píng)估以Arduino 集成開(kāi)發(fā)環(huán)境中自帶的示例程序?yàn)闇y(cè)試用例。將GDB stub 的源碼文件加入到Blink項(xiàng)目中與其一起編譯,需要在Blink 項(xiàng)目的setup()函數(shù)中調(diào)用初始化函數(shù)debug_init()。將程序編譯下載到開(kāi)發(fā)板后開(kāi)始調(diào)試,Eclipse IDE 負(fù)責(zé)前端界面顯示,avr-gdb 將與運(yùn)行在開(kāi)發(fā)板的GDB stub 通過(guò)串口鏈接完成調(diào)試工作。通過(guò)eclipse 來(lái)進(jìn)行遠(yuǎn)程調(diào)試,需要在調(diào)試配置中設(shè)置遠(yuǎn)程目標(biāo)(Remote Target)的串口號(hào)和波特率。
Blink程序Eclipse 調(diào)試界面如圖3 所示,可如同調(diào)試本地程序方便的設(shè)置斷點(diǎn),在代碼里需要調(diào)試的地方,鼠標(biāo)雙擊代碼行號(hào)的左邊。Debug 窗口顯示當(dāng)前線程方法調(diào)用棧及方法執(zhí)行到第幾行,圖3 所示Blink程序單步執(zhí)行到digitalWrite函數(shù),digitalWrite函數(shù)位于Arduino 標(biāo)準(zhǔn)庫(kù)中的wiring_digital. c 文件153行。函數(shù)變量顯示當(dāng)前函數(shù)的局部變量,非靜態(tài)變量等??梢越o一個(gè)變量或表達(dá)式添加永久觀察點(diǎn),當(dāng)程序在調(diào)試時(shí)觀察點(diǎn)會(huì)在表達(dá)式視圖(Expression view)中顯示出來(lái),也可以變量視圖(Variables view)查看與修改制定變量值,根據(jù)變量類型在其對(duì)應(yīng)的Value 列里輸入值即可。斷點(diǎn)(Breakpoints)視圖中可用來(lái)新增和刪除斷點(diǎn)等,控制臺(tái)(Console)用于查看打印的日志信息。在代碼視圖顯示當(dāng)前運(yùn)行的代碼,可以單步跟蹤,進(jìn)入當(dāng)前函數(shù)內(nèi)一步一步執(zhí)行或者全速運(yùn)行等。功能可靠性評(píng)估顯示可以提供所有標(biāo)準(zhǔn)的調(diào)試功能,包括設(shè)置斷點(diǎn)、單步執(zhí)行、查看修改變量和寄存器等功能。
圖3 Blink程序調(diào)試界面
調(diào)試性能采用DF 創(chuàng)客社區(qū)DFR0100 Arduino 入門(mén)套件的示例代碼作為測(cè)試用例。統(tǒng)計(jì)了測(cè)試用例程序代碼大小,內(nèi)存使用情況以及加入調(diào)試代碼以后的程序代碼大小,內(nèi)存使用情況,如表3 所示。結(jié)果顯示調(diào)試代碼大概占用4. 7KB Flash 程序存儲(chǔ)器空間,ATmega328p具有32KB Flash 程序存儲(chǔ)器空間,調(diào)試代碼占用14%的程序存儲(chǔ)器空間。調(diào)試代碼使用了277Byte內(nèi)存,ATmega328p具有2KB 內(nèi)存。這結(jié)果對(duì)于大多數(shù)Arduino項(xiàng)目是可以接受的。
表3 代碼大小以及內(nèi)存使用情況
當(dāng)測(cè)試用例設(shè)置斷點(diǎn)后,程序的運(yùn)行速度會(huì)顯著的下降。如果測(cè)試用例程序中有延時(shí)函數(shù)(delay),延時(shí)函數(shù)是通過(guò)輪詢硬件時(shí)間實(shí)現(xiàn)延時(shí)的,加入調(diào)試代碼后可能導(dǎo)致延時(shí)被延長(zhǎng)大約350 倍,100 ms的延時(shí)在調(diào)試階段可能是延時(shí)了35 s。Arduino 項(xiàng)目的程序不是很復(fù)雜,對(duì)實(shí)時(shí)性要求也不高,在調(diào)試階段這種情況完全可以滿足用戶使用需求。可以通過(guò)在合適的地方設(shè)置斷點(diǎn)或者修改延時(shí)函數(shù)來(lái)減少調(diào)試代碼對(duì)程序的影響。調(diào)試結(jié)束后把調(diào)試代碼從項(xiàng)目中移除,不要再編譯在項(xiàng)目中。
本文介紹了Arduino 的遠(yuǎn)程調(diào)試器的研究與實(shí)現(xiàn),調(diào)試器是基于開(kāi)源調(diào)試器GDB 的,并在Eclipse IDE下搭建了源碼級(jí)調(diào)試環(huán)境,為Arduino開(kāi)發(fā)平臺(tái)構(gòu)建了完整的開(kāi)發(fā)環(huán)境。解決方案是實(shí)現(xiàn)在目標(biāo)機(jī)運(yùn)行的遠(yuǎn)程調(diào)試器GDB stub,通過(guò)串口接收宿主機(jī)調(diào)試器發(fā)來(lái)的調(diào)試命令,根據(jù)調(diào)試命令來(lái)控制程序的運(yùn)行過(guò)程,并返回調(diào)試結(jié)果。GDB stub 需要與被調(diào)試的程序一起編譯后運(yùn)行于目標(biāo)機(jī),宿主機(jī)上運(yùn)行GDB調(diào)試器通過(guò)串口與目標(biāo)機(jī)的GDB stub連接,通過(guò)簡(jiǎn)單的設(shè)置即可對(duì)運(yùn)行在目標(biāo)機(jī)上的程序進(jìn)行調(diào)試。它提供了調(diào)試器所期望的設(shè)置和刪除斷點(diǎn),逐步執(zhí)行代碼和檢查變量等常用功能。大幅提高了Arduino 項(xiàng)目的調(diào)試效率,有效地為Arduino 開(kāi)發(fā)程序,縮短了開(kāi)發(fā)周期。在物聯(lián)網(wǎng)專業(yè)教學(xué)可以作為一個(gè)實(shí)驗(yàn)平臺(tái),使用Arduino教授嵌入式編程、傳感器應(yīng)用等課程。