0 引言
國內(nèi)外各類構(gòu)的嵌入式芯片在競爭激烈的市場環(huán)境不斷突破技術(shù)壁壘,飛速提升性能。芯片配套的集成開發(fā)環(huán)境(IDE,Integrated Development Environment)作為開發(fā)中的關(guān)鍵工具,其提供的交叉編譯和交叉調(diào)試功能解決了嵌入式開發(fā)中目標(biāo)機的運算能力和存儲空間有限的缺陷,對芯片嵌入式開發(fā)的重要性不言而喻。
近年來,各芯片廠商都在大力研發(fā)自己芯片的配套IDE,力圖打破 KEIL和IAR兩個行業(yè)標(biāo)桿的壟斷局面。這些免費IDE(如ST的 CubeIDE和TI的CCS)大部分是基于Eclipse深度定制的,包含 Eclipse、SDK插件、代碼生成插件、編譯工具鏈,以及調(diào)試工具鏈的開發(fā)環(huán)境。目前,這些IDE存在僅針對各自產(chǎn)品的定制化開發(fā)、源碼封閉導(dǎo)致二次開發(fā)困難等問題。基于上述原因,新上市的硬件產(chǎn)品移植適配工作量巨大,不利于IDE的推廣使用。
本文主要由Eclipse、GDB、OpenOCD(采用JTAG標(biāo)準(zhǔn))組成的自主方案實現(xiàn)了IDE。鑒于交叉調(diào)試的重要性,本文重點介紹基于GDB和OpenOCD的技術(shù)選型,實現(xiàn)了目標(biāo)機(芯片型號為基于RISC架構(gòu)的RAC102)的交叉調(diào)試方案。在該方案中,對GDB和OpenOCD源碼進(jìn)行自主編譯移植后,兩者采用遠(yuǎn)程通信協(xié)議(RSP,Remote SerialProtocol)進(jìn)行通信,完成可執(zhí)行程序的調(diào)試操作。通過此案例驗證了IDE設(shè)計方案中交叉調(diào)試的可行性,為后續(xù)其余架構(gòu)的IDE適配提供了指導(dǎo)思路。在此技術(shù)基礎(chǔ)上,提供支持多架構(gòu)芯的通用且開放的嵌入式開發(fā)集成環(huán)境。
1 設(shè)計思路
1.1 器件選型
1.1.1 編輯器選型
Eclipse平臺為更好地為C/C++開發(fā)人員服務(wù),衍生出了Eclipse CDT 擴(kuò)展套件。該套件可以為嵌入式開發(fā)者提供C/C+ +程序的編輯、編 譯、運行及本地調(diào)試等功能[1]作為利用機器接口(MI,Machine Interface)支持C/C++源碼調(diào)試最好的開源工具,采用CDT套件作 為交叉調(diào)試的前端,通過MI接口使CDT和GDB相互通信,構(gòu)建了可視化的嵌入式遠(yuǎn)程調(diào)試軟件,提高了開發(fā)效率。
1.1.2 調(diào)試器選型
GDB是GNU工具集中的開源且高適配性的調(diào)試器,根據(jù)可執(zhí)行程序的運行位置分為本地調(diào)試和遠(yuǎn)程調(diào)試兩種模式。在遠(yuǎn)程調(diào)試模式下,GDB與調(diào)試代理(OpenOCD、GDBServer等)通過RSP協(xié)議進(jìn)行信息交互,完成目標(biāo)機上可執(zhí)行文件的調(diào)試控制。注意,若目標(biāo)機架構(gòu)與宿主機架構(gòu)不同,則稱為交叉調(diào)試。此外,GDB支持兩種外部調(diào)試工具接口:MI和CLI(CommandLineInterface),其多樣化的接口、完善的目標(biāo)處理機制等特點為后續(xù)IDE的架構(gòu)適配打下了基礎(chǔ)。
1.1.3 調(diào)試代理選型
OpenOCD(Open On Chip Debugger)是一個開源、通用的片上調(diào)試器,并且可作為支持JTAG標(biāo)準(zhǔn)的調(diào)試代理。目前,可與GDB聯(lián)合為RISC V、ARM、MIPS等架構(gòu)的芯片提供在線調(diào)試工具[2]。OpenOCD開源的好處在于,可自主改寫函數(shù)源碼進(jìn)而適配目標(biāo)芯片的特性。因此,基于GDB和OpenOCD搭建的調(diào)試系統(tǒng)具備功能拓展簡單靈活、架構(gòu)兼容性強的優(yōu)勢。此外,OpenOCD支持各種商用JTAG仿真器、直接讀寫物理地址和核內(nèi)部寄存器等特點也是技術(shù)選型時考慮的因素。
1.1.4 調(diào)試標(biāo)準(zhǔn)選型
JTAG(JointTest Action Group)邊界掃描調(diào)試標(biāo)準(zhǔn)主要提供微處理器的電氣特性測試和目標(biāo)機可執(zhí)行程序調(diào)試兩大功能,適用于配置了JTAG接口的芯片電路。基于JTAG標(biāo)準(zhǔn)的微處理器在調(diào)試模式下中斷可執(zhí)行程序,上層的GDB和OpenOCD發(fā)送調(diào)試命令到調(diào)試模塊,完成后續(xù)程序調(diào)試工作。采用JTAG標(biāo)準(zhǔn)的主要原因是:①基于ARM、RISCV、Intel等主流架構(gòu)的微處理器實現(xiàn)了JTAG調(diào)試接口,該標(biāo)準(zhǔn)適配性高。②基于該標(biāo)準(zhǔn)的調(diào)試具備程序無侵入、依賴簡單、高穩(wěn)定性的特點。
1.2 整體框架
本文自主設(shè)計的IDE以主流嵌入式開發(fā)類似的宿主機目標(biāo)機通用結(jié)構(gòu)為基礎(chǔ)進(jìn)行整體框架設(shè)計,如圖1所示。考慮到目標(biāo)機存儲資源的局限性,目標(biāo)機端放置調(diào)試代理(GDB Server或GDB STUB)的傳統(tǒng)方案被摒棄。本框架方案中,目標(biāo)機端僅運行可執(zhí)行程序,宿主機端由Eclipse、GDB和OpenOCD組成,其中OpenOCD完成了傳統(tǒng)方案下目標(biāo)機端的調(diào)試代理工作。在框架中,首先CDT圖形界面通過UI操作來調(diào)用MI接口與GDB,進(jìn)行調(diào)試命令發(fā)送和調(diào)試信息獲取。GDB通過MI接口獲取調(diào)試命令后,在RSP序列包封裝和解析機制下與Open-OCD進(jìn)行調(diào)試命令傳遞和調(diào)試信息反饋。
最后,JTAG仿真器通過宿主機通信端口接收到OpenOCD的指令,將其轉(zhuǎn)換為標(biāo)準(zhǔn)的JTAG信號并通過調(diào)試訪問端口(DAP,Debug Access Port)發(fā)送給目標(biāo)機端。JTAG進(jìn)入調(diào)試模式讀取內(nèi)存和寄存器,按照需求進(jìn)行可執(zhí)行程序調(diào)試,目標(biāo)機完成調(diào)試后再將調(diào)試結(jié)果反饋給宿主機。通過上述流程,IDE完成目標(biāo)機可執(zhí)行程序的交叉調(diào)試。
圖1 IDE設(shè)計框圖
2實現(xiàn)方式
2.1 驅(qū)動適配
為了目標(biāo)機的可執(zhí)行程序被順利調(diào)試,首先要保證目標(biāo)機和宿主機之間的傳輸正常。由于使用默認(rèn)驅(qū)動時,通過USB端口與仿真器 通信會發(fā)生異常錯誤,因此,采用Zadig工具更新宿主機的USB驅(qū)動,從而保證目標(biāo)機可以與宿主機進(jìn)行正常通信。其驅(qū)動安裝步驟如下:
①在菜單欄中選擇“Options”->“List All Devices”,查看當(dāng)前連接到計算機上的所有USB設(shè)備。
②在接口復(fù)合框中分別選中目標(biāo)機對應(yīng)的“Dual RS232-HS (Interface 0)”接口,并在驅(qū)動復(fù)合框選擇“WinUSB”驅(qū)動。
③選擇“Replace Driver”進(jìn)行驅(qū)動更新即可。
④重復(fù)上述3個步驟,步驟②中接口選擇“Dual RS232-HS (Interface 1)”,完成該接口的驅(qū)動安裝。
2.2 操作系統(tǒng)適配
由于IDE設(shè)計方案中交叉調(diào)試的調(diào)試器選用了GDB,因此運行在 Unix/Linux系統(tǒng)下的GDB適配宿主機系統(tǒng)(Windows系統(tǒng))是需要完成的目標(biāo)。為了實現(xiàn)上述目的,可以采用Cygwin工具,其功能就是 在Windows上仿真Linux操作系統(tǒng),使得GNU工具鏈可以運行在Linux模擬環(huán)境。在運行Windows的同時,僅依賴Cygwin核心的動態(tài) 庫(如cygwin1.dll)也可以使用VIM、GCC、make、GDB等Linux工具。注意,安裝Cygwin時并沒有缺省安裝GNU工具鏈,應(yīng)根據(jù)需求安裝 相應(yīng)的工具。本文根據(jù)操作系統(tǒng)的配置需要安裝了binutils、gcc-core、gcc-g++、gdb、make等工具。
2.3 源碼編譯調(diào)試
2.3.1 GDB工作目錄建立
首先通過Cygwin進(jìn)入GDB源碼根目錄,新建文件夾build,用來存儲 源碼編譯后的可執(zhí)行文件。注意,Win- dows目錄在Cygwin進(jìn)行了掛 載,如D盤路徑變成/cyg- drive/d等。因此,進(jìn)入GDB源碼根目錄時要注意目錄路徑的變換。命令行操作如下:
//查看磁盤掛載情況,識別掛載后磁盤路徑
#df-h
//進(jìn)入 GDB源碼根目錄
#cd/cygdrive/d/gdb-source/gdb-10. 2
//創(chuàng)建 build工作目錄
#mkdirbuild
2.3.2 GDB源碼編譯
編譯源碼的主要流程由./configure(腳本文件配置)、make(工具編譯)、make install(工具安裝)3個步驟構(gòu)成。具體而言,首先,運行configure腳本檢查當(dāng)前的配置選項和系統(tǒng)環(huán)境設(shè)置,檢查正確 后根據(jù)源碼中Makefile.in模版文件的引導(dǎo)生 成 Makefile文件;然后,make工具根據(jù)Makefile文件的進(jìn)行預(yù)處理、編譯、鏈接等項目構(gòu)建工作,生成二進(jìn)制文件;最后,make install命令根據(jù)執(zhí)行con-figure腳本時傳遞的prefix等參數(shù)將生成的二進(jìn)制文件安裝到指定路徑。
執(zhí)行./configure需要進(jìn)行各種參數(shù)配置,GDB交叉編譯中使用的參數(shù)配置如表1所列。
表1 configure腳本參數(shù)說明
GDB源碼編譯的操作如下:
//建立交叉調(diào)試環(huán)境之前檢查 config. sub腳本是否支持目標(biāo)機架構(gòu)的編譯 。若支持 ,則返回相應(yīng)的架構(gòu)類型 ,否則會報錯
# sh config. sub riscv64 unknown elf gcc
//執(zhí)行 configure腳本 ,其中 CFLAGS= " g"的作用為后續(xù)調(diào)試 GDB源碼顯示調(diào)試信息。build和 host參數(shù)默認(rèn)均為
本機架構(gòu),不再顯性指定
#./configureCFLAGS=" g"
target=riscv64 unknown elf
prefix=/cygdrive/d/gdb source/gdb 10.2/build
//make編譯與安裝
#make
#makeinstall
2.3.3 GDB源碼調(diào)試
前面的工作已經(jīng)編譯生成了基于RISC V架構(gòu)的GDB可執(zhí)行程序,可以進(jìn)行目標(biāo)機上被調(diào)試程序的交叉調(diào)試工作。若GDB調(diào)試過程中出現(xiàn)了BUG或者需要進(jìn)一步理解內(nèi)部運行機制,則需要進(jìn)入GDB源碼調(diào)試模式。為了方便閱讀調(diào)試源碼,選擇VSCode進(jìn)行GDB源碼調(diào)試,需配置launch.json文件,該配置文件主要作用是添加GDB調(diào)試任務(wù)并運行可執(zhí)行文件。launch.json文件配置流程主要分為以下幾個步驟:
①生成launch.json文件。菜單欄選擇“運行”->“添加配置”->“C++(GDB/LLDB)”,即可生成一個配置為空的launch.json文件。
②添加默認(rèn)配置模版。在"configurations"字段域中輸入“GDB”可以自動生成默認(rèn)配置。
③修改默認(rèn)配置。"program"字段代表調(diào)試器的路徑,該字段設(shè)置為Cygwin的GDB路徑;"miDebuggerPath"字段代表被調(diào)試的可執(zhí)行文件路徑,該字段設(shè)置為前面編譯生成的GDB程序。
完成launch.json文件配置后,在VSCode中選擇“gdb啟動”就可以在調(diào)試模式下運行GDB調(diào)試器。
此外,調(diào)試代理OpenOCD的編譯和調(diào)試與GDB源碼編譯和調(diào)試工作步驟基本一致,在此不再重復(fù)說明。目標(biāo)機的被調(diào)試的可執(zhí)行程序為RAC102芯片自帶示例程序。
2.4 交叉調(diào)試
首先,運行OpenOCD程序后,會彈出運行終端窗口,顯示JATG標(biāo)準(zhǔn)選擇、芯片架構(gòu)信息、監(jiān)聽端口等第一階段信息,表示OpenOCD運行正常,與目標(biāo)機的RAC102芯片連接成功。
之后,以調(diào)試模式或者運行模式打開GDB程序,彈出運行終端窗口,在終端中依次設(shè)置指定RAC102芯片的架構(gòu)、遠(yuǎn)程調(diào)試的連接端口以及加載調(diào)試信息文件,命令執(zhí)行如下:
(gdb) set architecture riscv:rv32
The target architecture is assumed to be riscv:rv32
(gdb)target extended-remote localhost:3333
Remote debugging using localhost:3333
(gdb)file D:\led\led_debug.elf
Reading symbols from D:\led\led_debug.elf…
完成上述操作后,OpenOCD運行終端會輸出端口連接成功、中斷地址等第二階段信息,表示OpenOCD與GDB連接成功。此時可以在GDB調(diào)試終端中輸入continue、step、break等常用的調(diào)試命令進(jìn)行交叉調(diào)試。
3 功能驗證與協(xié)議分析
在交叉調(diào)試中,GDB所有的調(diào)試命令和調(diào)試信息反饋均通過RSP協(xié)議來實現(xiàn)。該協(xié)議通過串口或網(wǎng)口等媒介傳輸ASCII消息。RSP包的基本格式為:$數(shù)據(jù)包#校驗和[3-4]。其中,數(shù)據(jù)包由若干ASCII數(shù)據(jù)組成,該校驗和是數(shù)據(jù)包所有字符的ASCII碼之和取256的模后得到的值,用兩位十六進(jìn)制ASCII表示。若OpenOCD正確接收數(shù)據(jù),則會返回‘+’,否則返回‘-’表示發(fā)生錯誤,要求重新發(fā)送消息[5]。
由GDB和OpenOCD源碼調(diào)試分析可知,GDB作為RSP客戶端,在remote.c源文件中完成了讀寫、運行控制、查詢及設(shè)置、追蹤點以及停止通知等RSP常用類型通信包的接口實現(xiàn);OpenOCD作為RSP服務(wù)端,在server.cc源文件完成了GDB發(fā)送的通信包的解析與處理。在此基礎(chǔ)上,通過RSP通信包的組合實現(xiàn)常用的GDB調(diào)試命令。
在上述前提下,通過調(diào)試命令對應(yīng)的RSP協(xié)議分析來驗證在GDB+OpenOCD的方案中基于RISC-V架構(gòu)的RAC102芯片交叉調(diào)試的功能正確性。參照第2.4小節(jié)的交叉調(diào)試流程,區(qū)別在于在執(zhí)行target extended-remote localhost:port命令之前,需要使用set remotelogfile filename命令配置好遠(yuǎn)程串行通信記錄日志,日志文件名為filename,GDB會將與OpenOCD的交互數(shù)據(jù)寫入該日志文件中。通過表2給出了驗證后常用的調(diào)試命令以及對應(yīng)RSP協(xié)議指令集,證明了交叉調(diào)試方案設(shè)計的正確性與可行性。
表2 GDB命令與RSP協(xié)議對照指令集
G D B 命 令 | RSP請求序列 | RSP應(yīng)答序列 |
target extended- remotelocalhost: port |
①qSupported ②vMustReplyEmpty ③QStartNoAckMode ④! ⑤Hg thread-id ⑥qXferread ⑦qTStatus ⑧? ⑨qXferread ⑩Hc thread-id ?qC ?qAttached ?qOffsets ?g ?qXferread ?qSymbol |
①qSymbol::Size; qXferread; QStartNoAckMode; vContSupported ②空 ③OK ④OK ⑤OK ⑥m data ⑦空 ⑧S signal-id ⑨1 data ⑩OK ?QC thread-id ?1(注:數(shù)字1) ?Text =xx;Data=yy; Bss=zz ?XX..(注:寄存 器數(shù)據(jù)內(nèi)容) ?1 data ?OK |
file filename |
①qSymbol ②g |
①OK ②XX.. |
run |
①vKill;pid ②k和?組合包 ③vRun ④qC ⑤qAttached ⑥qOffsets ⑦Hg thread-id ⑧qXferread ⑨g ⑩vCont;c ?x03 ?g ?qXferread |
①空 ②W00 ③S signal-id ④QC thread-id ⑤1(注:數(shù)字1) ⑥Text=xx;Data=yy; Bss=zz ⑦OK ⑧m data ⑨XX.. ⑩ ?T siganal-id ?XX.. ?1 data |
continue |
①m ②ZO ③vCont? ④yCont;c ⑤g ⑥qXferread ⑦z0 |
①XX.. ②OK ③vCont;c;C;s:S ④T signal-id ⑤XX.. ⑥1 data ⑦OK |
next |
①m ②ZO ③vCont;s:thread - id;c ④g ⑤qXferread ⑥z0 |
①XX.. ②OK ③T thread-id ④XX.. ⑤1 data ⑥OK |
step | ||
break lineNo | ①m(若干包) | ①XX..(若干包) |
watchval | ||
print yal | ||
backtrace | ||
diassemble | ||
quit |
①D ②? |
①OK ②S siganal-id |
4 結(jié)語
本文自主設(shè)計了一套集成開發(fā)環(huán)境方案,該方案中基于自行編譯的GDB和OpenOCD實現(xiàn)了基于RSIC-V架構(gòu)的RAC102芯片的交叉調(diào)試,并且通過RSP協(xié)議分析進(jìn)行了調(diào)試功能的驗證。交叉調(diào)試方案的實現(xiàn)為后續(xù)其余架構(gòu)芯片的集成開發(fā)環(huán)境設(shè)計與實現(xiàn)提供了指導(dǎo)思路。進(jìn)一步,為自研架構(gòu)芯片設(shè)計開發(fā)的自主可控提供了保障。
審核編輯:劉清
-
寄存器
+關(guān)注
關(guān)注
31文章
5372瀏覽量
121289 -
仿真器
+關(guān)注
關(guān)注
14文章
1019瀏覽量
83962 -
嵌入式開發(fā)
+關(guān)注
關(guān)注
18文章
1036瀏覽量
47739 -
GDB調(diào)試
+關(guān)注
關(guān)注
0文章
24瀏覽量
1499 -
RISC-V
+關(guān)注
關(guān)注
45文章
2328瀏覽量
46678
原文標(biāo)題:RISC-V架構(gòu)的交叉調(diào)試系統(tǒng)設(shè)計
文章出處:【微信號:麥克泰技術(shù),微信公眾號:麥克泰技術(shù)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論