嵌入式系統(tǒng)除錯的工作量,,可望占了嵌入式軟體專案工作量的一半以上。了解硬體除錯功能以及它們所能解決的問題,,是選擇正確的晶片,、建立除錯系統(tǒng)以及提高生產(chǎn)效率的關(guān)鍵,。
很多人都相信"臭蟲(bug)"此一用詞起源于海軍少將 Grace Murray Hopper。但事實(shí)上,,沒人知道這種用法的真正來源,,它可能可以回溯到 Thomas A Edison,或甚至更早,。美國海軍后備役軍官 Hopper 在 1945 年 9 月 9 日于哈佛大學(xué)對 Mark II Aiken 繼電計(jì)算器( Relay Calculator)進(jìn)行測試時,,于短路的 Panel F #70 號繼電器處發(fā)現(xiàn)了一雙臭蟲。她把這只臭蟲拿掉后(就是對電腦進(jìn)行除臭蟲(debugging)),,就解決了這臺機(jī)器不定時關(guān)機(jī)的故障(參考文獻(xiàn) 1),。雖然這個早期的例子指的是從系統(tǒng)硬體中去除臭蟲,但今天"debugging"這個詞是指發(fā)現(xiàn)一個程式的問題,,并去掉缺陷代碼(defective code)的過程,。這些問題包括任何與原始意向的差異,而去掉缺陷代碼的做法則遠(yuǎn)優(yōu)于增加糾正代碼(correction code),。理想情況下,,在任何時間都可以獲得所有的特性(如系統(tǒng)的匯流排與暫存器值),供監(jiān)控與修改,。但隨著 IC 轉(zhuǎn)向 SoC,,可存取性(accessibility)就變得更加困難了。
對硬體除錯,,是要盡可能地可以存取到嵌入式系統(tǒng)內(nèi)部資源,,這可以透過觀察系統(tǒng)的特性,,如 CPU 狀態(tài)和 PC 值,或修改系統(tǒng)的參數(shù),。在嵌入式系統(tǒng)設(shè)計(jì)的早期可以用簡單技術(shù)進(jìn)行除錯,,如記錄(logging)與監(jiān)控,或者對多核心 SoC而言,,可以采用最新開發(fā)的方法,,如跟蹤、緩衡記憶體除錯(cache debugging)和交叉觸發(fā)(cross-triggering)等,。本文的重點(diǎn)不是在如何編寫代碼或?yàn)榇a除錯,,而是描述現(xiàn)在可用的嵌入式硬體硅智財(cái)權(quán)(intellectual property ,IP),,以及該 IP 能解決哪方面的除錯問題,。
記錄與監(jiān)控
最古老也是最常用的除錯方法就是在代碼中增加一些列印敘述(print statement),,它可以顯示軟體某個部分的執(zhí)行資訊,,并提供暫存器和變數(shù)的實(shí)際值。這可能是一年級學(xué)生練習(xí)"hello world"的一種延續(xù),,該程式會在熒幕上顯示這兩個詞,,用于表示程式能夠運(yùn)行,以及執(zhí)行到了某個點(diǎn),。列印敘述(或 printf 語句)只是記錄的一種變型,,它是用處理器將重要資訊寫入一個"管道(pipe)",作為外部跟蹤的過程,。所使用的管道將視系統(tǒng)而訂,,在 printf 情況下,管道是標(biāo)準(zhǔn)的輸出(熒幕),,但它也可以是 UART,、USB,甚至是通用 I/O,。
當(dāng)你需要用一種對程式設(shè)計(jì)工程師有意義的方式,,組織各個部分資訊時(例如提供感測器資訊或狀態(tài)機(jī)的轉(zhuǎn)換),采用記錄的方法是很有價(jià)值的,??梢杂糜涗浌ぞ邅矸治鲇涗浀馁Y訊,并產(chǎn)生一個后處理資料庫,。必須小心使用記錄功能才能獲得高效率,。例如,記錄資訊應(yīng)使用關(guān)鍵字開頭,,如"警告",、"錯誤"或"除錯"等,,并應(yīng)能識別出資訊的建立者。應(yīng)將記錄功能劃分為一小組檔案,,以便于維護(hù),,并提供時間戳資訊。不幸的是,,記錄是一種侵入性的方法,,它會修改軟體的即時狀態(tài),因而不同于最終應(yīng)用,。
除錯監(jiān)控器是另一種常見的除錯工具,,它與運(yùn)行在 CPU 記憶體中的目標(biāo)代碼一起工作(參考文獻(xiàn) 2 和參考文獻(xiàn) 3)。除錯器運(yùn)行在一臺主機(jī)上,,它透過一個專用的埠發(fā)送指令和接收響應(yīng),,從而達(dá)到與監(jiān)控器通信的目的??梢詫?Linux 上的 gdbserver 程式當(dāng)作一個除錯監(jiān)控器,,不過它比早期的 ROM 監(jiān)控器更復(fù)雜
(圖 1)。
當(dāng)使用者希望在某條指令處設(shè)置一個中斷點(diǎn)時,,gdbserver 會保存該指令,,而用一個系統(tǒng)呼叫(system call)來替代它。Gdbserver 然后用 Linux 的 ptrace 程式獲得所有進(jìn)行系統(tǒng)呼叫的應(yīng)用程式資訊,。接著,,當(dāng)發(fā)生系統(tǒng)呼叫而啟動中斷點(diǎn)時,gdbserver 可以取得對被除錯應(yīng)用的控制,。除錯器運(yùn)行在一臺主控機(jī)上,,透過串列埠或乙太網(wǎng)路連接到目標(biāo)物件(參考文獻(xiàn) 4)。監(jiān)控器的方法既便宜又實(shí)用,,但也有一些缺點(diǎn),,例如需要在進(jìn)行任何除錯前載入代碼,并可能與應(yīng)用軟體相互影響,。如果代碼位于快閃記憶體中就不能使用監(jiān)控器軟體,,因?yàn)橐迦胲涹w中斷點(diǎn)就需要修補(bǔ)應(yīng)用軟體。
內(nèi)電路模擬
內(nèi)電路模擬器(in-circuit emulator ,,ICE)是第一種以硬體為基礎(chǔ)的除錯技術(shù),,它是所除錯處理器的一個版本。ICE 通常使用一顆現(xiàn)場可編程閘陣列(field-programmable gate array,,F(xiàn)PGA),。FPGA 外合(bond out)其內(nèi)部匯流排和狀態(tài)信號,而讓使用者可以使用它們(圖 2)。
ICE 提供的除錯功能多于 ROM 監(jiān)控器,。使用 ICE 時,,必須用一個連接到 ICE 盒的連接替換待除錯電路板上的處理器。一個運(yùn)行并模擬除錯器功能的主機(jī)控制這個 ICE 盒,。ICE 的主要局限性之一是它的價(jià)格昂貴,。另外,雖然這個方法很適合簡單的處理器,,但現(xiàn)代 SoC 有更高的復(fù)雜性,、整合度和頻率,因此 IC 供應(yīng)商難以為現(xiàn)代處理器提供 ICE 版本,。
一些歐洲公司在1985 年成立了聯(lián)合測試活動組(Joint Test Action Group,,JTAG),這個聯(lián)盟嘗試要解決測試半導(dǎo)體 IC 的各種問題,。它們?yōu)?IC 的邊界掃描測試建立了 IEEE 1149.1 標(biāo)準(zhǔn),,并在 1990 年公布了此一標(biāo)準(zhǔn)(參考文獻(xiàn) 5 和 圖 3)。
JTAG 標(biāo)準(zhǔn)定義了一個有限的 I/O JTAG 埠,,有多達(dá)五個信號,,透過串列通信完成電路的測試與分析:測試時鐘(test clock,TCK),、測試模式選擇(test-mode select,,TMS),、可選的測試重定(test reset,, TRST)、測試資料登錄(test-data in ,,TDI)和 測試資料輸出(test-data out,,TDO)。
IEEE 將 JTAG 硬體建立在一個 16 態(tài)的有限狀態(tài)(finite-state)機(jī)上,,并由 TMS 信號控制,。TCK的上升沿時鐘(rising- edge clock)擷取到此一 TMS 信號。資料資訊在TDI 墊(TDI pad)移入,,并在TDO 墊移出,。最后用 TRST 來對設(shè)計(jì)重新設(shè)定。IC 的每個墊都可以增加掃描暫存器,,并將它們內(nèi)部連接起來構(gòu)成一個邊界掃描鏈,。可以透過 TDI/TDO 和 JTAG 命令將此鏈移入和移出,,以測試電路板上的外部連接,,測試 IC 內(nèi)部的邏輯連接,擷取 IC 墊的值,并將 JTAG 置于旁路模式,。JTAG 提供了低成本的製造測試功能,,并成為最常用的測試方法。但是,,由于它有易于使用,、高可用性和低成本實(shí)現(xiàn)的特點(diǎn),設(shè)計(jì)者經(jīng)常會把 JTAG 當(dāng)作除錯埠,,以存取片上的除錯資源(參考文獻(xiàn) 6),。
JTAG 是除錯通信的傳輸層,位于運(yùn)行在主機(jī)上的除錯器與嵌入式處理器除錯資源之間,。命令被移入命令暫存器,,以存取除錯中的硬體 IP。由于 ICE 增加了成本,,很多半導(dǎo)體供應(yīng)商將更多除錯硬體整合在晶片上,,以解決除錯限制的問題,并提供與 ICE 相似的功能,。片上除錯硬體的一種常見實(shí)現(xiàn)是飛思卡爾半導(dǎo)體公司在 68-kbit Coldfire 嵌入式處理器和 PowerPC(現(xiàn)在是 Power 架構(gòu))處理器上的背景除錯模式(background debugger mode ,,BDM)。其他供應(yīng)商也有相似功能的專有名稱,。
片上除錯硬體增加了一些功能,,如硬體中斷點(diǎn)、內(nèi)部暫存器存取,、讀/寫到記憶體,,以及觀察點(diǎn)(watchpoint)等,這些功能以前只能透過 ICE 使用,。在一個多處理器 SoC 中,,可以將每塊晶片除錯硬體連接到主 JTAG 控制器。不同供應(yīng)商的連接可能有所不同,,但典型的作法是在片上除錯 JTAG 狀態(tài)機(jī)和主除錯器之間建立起一個 TDI-TDO JTAG 鏈(圖 4),。
跟蹤
即時系統(tǒng)除錯中最大的問題之一就是海森堡的臭蟲(Heisenberg bug),或探針效應(yīng)(probe effect):為除錯或監(jiān)控而增加的任何軟體或硬體都可能改變即時系統(tǒng)的行為,。當(dāng)增加用于剖析,、除錯或監(jiān)控資訊的軟體時,就會發(fā)生這種情況,。使用除錯硬體時也會有類似的影響,。例如,片上除錯硬體可能將處理器的執(zhí)行流程修改到插入中斷點(diǎn)處,,或者用于剖析的硬體可能"偷取(steal)"從處理器到記憶體的部分頻寬,,以便用來保存剖析的資訊。
除錯硬體還可能以 UART 連接來記錄資訊,而產(chǎn)品軟體也可能使用這個介面,。ICE 通常提供非侵入式的跟蹤功能,,開發(fā)者可以在任何時候存取處理器的程式計(jì)數(shù)器。越來越多的 SoC 供應(yīng)商正在把跟蹤硬體整合到晶片上,,以提供類似的功能(圖 5),。
透過專用的跟蹤硬體、專用的跟蹤埠,、跟蹤資料與處理器資料分離的資料匯流排,,以及 JTAG 介面,使跟蹤硬體得以實(shí)現(xiàn)非侵入式的跟蹤,。
使用者可以利用一個跟蹤埠來擷取跟蹤資訊,。在這種方式下,將一個跟蹤盒或邏輯分析儀連接到跟蹤埠,,以重建資訊并讓它們與原始碼建立關(guān)聯(lián)性,。另一種擷取跟蹤資訊的方法是使用一個虛擬跟蹤緩衝記憶體,處理器記憶體將跟蹤資訊存入緩衝記憶體,,而當(dāng)測試結(jié)束時由主機(jī)(例如透過 JTAG 埠)來檢索(retrieve)這些資訊,。第叁種方法是使用一個專用的跟蹤緩衝記憶體,專門用來保存跟蹤資訊,,這可以讓主機(jī)在測試結(jié)束時檢索,。
全球嵌入式處理器除錯介面(Global Embedded Processor Debug Interface)的IEEE-ISTO 5001TM 2003 Nexus 5001TM 論壇標(biāo)準(zhǔn)可為嵌入式處理器的軟體發(fā)展和除錯提供一個開放而通用的介面(參考文獻(xiàn) 7)。Nexus Forum 在 1998 年開始運(yùn)作,,在1999 年發(fā)表了第一個 Nexus 標(biāo)準(zhǔn),,并在 2003 年做了更新。其目標(biāo)是,,在嵌入式系統(tǒng)除錯與工具領(lǐng)域多個供應(yīng)商的經(jīng)驗(yàn)基礎(chǔ)上,,實(shí)現(xiàn)片上除錯功能與介面的標(biāo)準(zhǔn)化。由于該論壇的多個供應(yīng)商已經(jīng)為片上除錯提供了專有產(chǎn)品,,因此基本的片上除錯要求已經(jīng)足以輕鬆地達(dá)到 Nexus 的符合性。好處是 Nexus 跟蹤介面的標(biāo)準(zhǔn)化,,例如跟蹤功能,、信號、消息協(xié)定和應(yīng)用編程介面(application-programming interface,,API),。同時,標(biāo)準(zhǔn)化還為供應(yīng)商的定制化提供充分的空間,。Nexus 標(biāo)準(zhǔn)最初是針對汽車應(yīng)用的,,現(xiàn)已快速擴(kuò)充到無線與網(wǎng)路市場。
多核心除錯
緩衡記憶體能提供高性能,但卻難以除錯,,因?yàn)樗鼈儗?CPU 的執(zhí)行情況與外部記憶體匯流排隱藏起來,,并且難以了解到核心與 DMA 或加速硬體之間的一致性。嵌入式跟蹤硬體有助于解決這個問題,,因?yàn)楸桓櫟膮R流排通常是虛擬的(在緩衡記憶體以前),,而非實(shí)體的。跟蹤緩衝記憶體前,、后的匯流排也非常有助于更完整地了解緩衡記憶體的行為(圖 6),。
兩個跟蹤結(jié)果的比較,能夠提供快取失敗(cache miss)的良好指示,,此時緩衡記憶體造成對實(shí)體匯流排的存取,。這種方法有助于減少快取失敗,并提高軟體的性能,。另一種方法是增加嵌入式的緩衡記憶體除錯硬體,,在除錯模式下讀取緩衡記憶體內(nèi)容,或?qū)懭刖徍庥洃涹w,。這種方法通常采用緩衡記憶體除錯暫存器形式,,并透過軟體或 JTAG 埠存取。使用者使用除錯器可以暫停程式的執(zhí)行,,并檢查緩衡記憶體的內(nèi)容,。使用者可以用這個資訊解決各種緩衡記憶體清除問題,如無效,、同步或溢出,。
現(xiàn)代 SoC 經(jīng)常在一顆晶片內(nèi)整合多個處理器,用傳統(tǒng)的除錯硬體難以對多個核心之間的互通性進(jìn)行除錯,。有一種最新出現(xiàn)的除錯技術(shù)叫交叉觸發(fā)(Cross-triggering),,它成為對復(fù)雜多核心 SoC 除錯的常用方法(參考文獻(xiàn) 8)。該方法的原理是將一個核心域的事件轉(zhuǎn)換到其他核心域或相同核心域的產(chǎn)生觸發(fā)器(generate trigger)上,。典型事件是進(jìn)入除錯模式,、發(fā)生中斷、出現(xiàn)觀察點(diǎn),,以及出現(xiàn)中斷點(diǎn),。輸入觸發(fā)器一般是除錯要求。觸發(fā)器產(chǎn)生一個除錯要求,、一個中斷,,或一個 SoC 墊(SOC pad)的突波雜訊(glitch)。它們都可以啟動或停止處理器上的跟蹤,。觸發(fā)器的組合將所有彈性留給了最終使用者,,使他們能夠設(shè)計(jì)出復(fù)雜的除錯序列,。可以在 Core B 到達(dá)某個程式位址時,,用交叉觸發(fā)器啟動 Core A 上的一個跟蹤,,或當(dāng) Core A 進(jìn)入除錯時,停止 Core B 的活動,。
隨著對 SoC 尺寸壓力不斷地增加,,低成本除錯可能成為嵌入式系統(tǒng)架構(gòu)的圣杯。但是必須牢記一件重要的事:永遠(yuǎn)不要在系統(tǒng)的除錯能力方面作出妥協(xié),。如果不能預(yù)先處理好系統(tǒng)的所有臭蟲,,那么以后就無法獲得更大發(fā)現(xiàn)問題的機(jī)會。在減少嵌入式除錯硬體上所節(jié)省的成本,,其代價(jià)可能是在專案后期付出更高昂的軟體除錯成本,。另外還應(yīng)記得,除錯與安全兩種要求是相互矛盾的,。很多制造商現(xiàn)在交付產(chǎn)品時只是簡單地關(guān)掉除錯功能來防止駭客的攻擊,。這種做法是不明智的。你永遠(yuǎn)不可能預(yù)期會在現(xiàn)場遇到什么問題,。比較好的做法是采用各種安全方式防止進(jìn)入除錯部分,,如用密鑰或熔絲(fuse),這樣才不會危及你的除錯功能,。