試配置解析)
接手一個別人寫好的 CCS5.5 工程編譯零報錯一點 Debug 就彈出一串連接錯誤或者自己在家里的電腦上仿真跑得好好的換到公司那臺機器上打開同一個工程連仿真會話都起不來——這類問題我碰到過太多回十有八九不是代碼寫錯了而是那個平時沒人愿意點開看的仿真配置文件CCS5.5 里就是 .ccxml 目標配置文件出了岔子。它就像是調(diào)試世界的鑰匙串決定你這一槍是打向真實芯片、還是打向電腦里那顆虛擬的仿真內(nèi)核走的是 JTAG 還是純軟件模型連上之后先執(zhí)行哪段初始化腳本。很多嵌入式工程師把精力全砸在算法和驅(qū)動上卻對這份幾百行的 XML 視而不見結(jié)果一到換機器、換編譯器版本、交接項目的時候就集體翻車。這篇內(nèi)容就是圍著 CCS5.5 的仿真配置文件展開的它由哪幾塊拼成、每一塊負責什么、從零建一份能用的配置要走哪幾步、手工改 XML 要注意什么、連不上或者跑不對的時候按什么順序去查。無論你是剛上手 TI 平臺的在校學生還是接了老項目要維護的嵌入式工程師看完都能自己動手把這份配置搭起來、改明白。1. CCS5.5 里仿真配置文件到底指什么很多人第一次聽到仿真配置文件這個詞腦子里浮現(xiàn)的是某個 .ini 或者 .cfg 文件其實在 CCS5.5 的語境下絕大多數(shù)情況下它指的就是目標配置文件Target Configuration File擴展名是.ccxml。它是一份 XML 格式的純文本描述的內(nèi)容非常具體用什么通信通道、連到哪顆芯片、芯片上哪個核、連上之后要不要跑初始化腳本。CCS 在啟動調(diào)試會話的第一秒鐘就會去讀它讀不懂就直接把會話掐掉你連 main 函數(shù)都進不去。之所以強調(diào)絕大多數(shù)情況下是因為這個圈子里仿真配置這個詞被用得很隨意有人指的是 .ccxml有人指的是調(diào)試會話配置.launch還有人指的是那份 GEL 初始化腳本。這三者經(jīng)常被混著叫導致排查問題時溝通成本極高——你說配置有問題對方理解成GEL 寫錯了兩個人對著兩個不同的文件查了半天。所以動手之前先把這三個東西的分工掰清楚是省時間的關鍵。1.1 ccxml、GEL、Debug Configuration 三者的分工我用一個打電話的類比來解釋它們的關系。.ccxml是撥號方案你用的是座機還是手機連接類型是仿真器還是軟件仿真撥的是哪個號碼目標器件型號走哪條線路JTAG 通道、時鐘速率。.gel是通話腳本電話接通以后先說什么、先讓對方做什么對應到芯片上就是設置 PLL 倍頻、初始化 DDR 控制器、關掉看門狗、建立內(nèi)存映射這些動作。.launchDebug Configuration是通話記錄記錄你這次通話要干什么事加載哪個 .out 可執(zhí)行文件、跑到哪個函數(shù)停、要不要自動運行到 main、多核的時候每個核分別加載什么。三者的引用關系是這樣的Debug Configuration 里有一個 Target 頁簽指向某個 .ccxml.ccxml 里的每個 CPU 節(jié)點上可能掛著若干 .gel 文件。鏈條一旦斷掉一環(huán)現(xiàn)象各不相同。ccxml 丟了或者路徑變了報的是找不到目標配置gel 寫錯了會話能建立但彈一堆初始化失敗的提示debug configuration 配錯了會話建立了、GEL 也跑完了但加載的是別人上次編譯的舊 out 文件你死活想不通為什么改了代碼沒效果。我見過最典型的翻車場景是交接前同事把整個工程文件夾打包發(fā)過來里面只有src、include和一個工程描述文件targetConfigs目錄被當成個人環(huán)境相關的東西刪掉了。新同事打開工程Debug 按鈕是灰的折騰一下午以為是 CCS 裝壞了。記住一條在 CCS5.5 里.ccxml 是可以也應該跟隨工程走的它跟你的個人環(huán)境關系不大別隨便刪。1.2 三種連接方式?jīng)Q定了你能驗證什么、驗證不了什么打開 Target Configuration 編輯器最上面那個 Connection 下拉框是整份配置的靈魂。里面大致分兩大陣營一類是真實的硬件仿真器驅(qū)動各種 XDS 系列一類是純軟件仿真驅(qū)動Texas Instruments Simulator 分類下的那些條目。硬件仿真器這一類的名稱通常長這樣Texas Instruments XDS100v2 USB Emulator、Texas Instruments XDS200 USB Emulator、XDS510 USB Emulator、XDS560v2 System Trace 等等。選它們的含義是調(diào)試指令會被真正發(fā)到 JTAG 口上目標板必須上電。這類配置的壞處是依賴硬件好處是所見即所得。軟件仿真這一類的條目通常帶器件名比如某些 C6000、C5000 系列器件的 CPU 仿真驅(qū)動。選它的含義是CCS 會在 PC 內(nèi)存里搭一個虛擬的處理器模型程序在里面跑完全不需要目標板。這個特性在兩種場景下非常值錢一是手頭沒板子、想先把算法邏輯跑通二是想復現(xiàn)一個偶發(fā)問題但真機上跑一遍要幾分鐘仿真里可以反復跑。這里必須潑一盆冷水不是所有器件在 CCS5.5 里都有軟件仿真驅(qū)動。以我接觸過的情況C2000 那一類控制器的仿真支持在 CCS5.x 時代就已經(jīng)很弱甚至沒有了你就算把 Connection 下拉框翻到底也找不到對應條目別在這上面浪費時間老老實實插板子。另外軟件仿真還分成功能級和周期精確兩類周期精確的模型時序更接近真實芯片但速度慢得讓人抓狂功能級的跑得飛快但時序、中斷延遲、外設行為都可能和真機差得遠。拿仿真結(jié)果去論證實時性指標是我見過最常見的誤用。1.3 配置文件放哪兒決定了它跟不跟你走在 CCS5.5 里新建目標配置文件時編輯器會問你放哪兒。Target Configurations視圖里能看到兩類節(jié)點一類是掛在工程下面的工程目錄下會多出一個targetConfigs文件夾另一類是User Defined節(jié)點下的一堆散裝配置。這兩類的物理位置和可移植性完全不同。掛在工程下的物理路徑就是工程根目錄/targetConfigs/xxx.ccxml。這份文件跟著工程走你壓縮打包發(fā)給同事他解壓導入就能用前提是路徑引用別寫死后面會講。User Defined下面的物理位置在 CCS 工作空間的元數(shù)據(jù)區(qū)里說得直白點就是換一個 workspace 就找不到了。所以那些習慣把配置放在 User Defined 下的人一旦重建工作空間或者換電腦就會經(jīng)歷一次我的配置去哪了的靈魂拷問。還有第三種情況配置放在 CCS 安裝目錄的targetdb體系下做成全局可用的自定義驅(qū)動或自定義器件描述。這種一般是給整團隊統(tǒng)一環(huán)境用的改動影響面大除非你確實在做團隊級的封裝否則不建議動安裝目錄里的東西——升級一次 CCS 就全沒了。2. 從零建一份能用的仿真配置界面操作全流程理解了上面這些動手就不難了。下面這套流程是我自己重復過幾十遍的順序從打開視圖到點下第一次 Debug一步都不跳。整個過程中我會刻意強調(diào)幾個看起來可以跳過、但跳過之后一定出事的動作。2.1 打開 Target Configurations 視圖并新建文件菜單路徑是View Target Configurations如果找不到去Window Show View Other里翻或者直接敲視圖名搜。視圖打開以后右鍵空白處New Target Configuration File。彈出的對話框只有兩件事要填文件名以及放哪兒。文件名我建議跟工程名保持一致比如工程叫motor_ctrl配置就叫motor_ctrl.ccxml。這不是強制要求但是在 Debug Configuration 里選配置的時候同名能讓你一眼確認自己沒選錯尤其是工程里有三四份配置的時候。放哪兒那一欄如果想把配置塞進某個工程就取消勾選Use shared location然后瀏覽到目標工程目錄如果只是自己臨時用用保持默認走共享位置也行但要記得它不跟著工程走。文件建好之后CCS5.5 會直接用內(nèi)置的 XML 編輯器打開它——注意它同時也是一個普通的 XML 文件你完全可以用文本編輯器打開改這一點后面第三章會詳細講。編輯器界面主要是三個頁簽Basic、Advanced、Source有的版本叫 XML。日常配置九成工作在 Basic 頁完成Advanced 頁處理時鐘和內(nèi)存映射Source 頁用于排查和手工修復。2.2 Connection 與 Board/Device 的選擇邏輯Basic 頁有三個下拉/輸入框從上到下依次是 Connection、Board or Device、以及可選的器件過濾框。這里的順序是有講究的先定連接方式再定器件。因為某些器件只支持仿真器連接某些 CPU 模型只存在于軟件仿真分類下反過來操作會讓你反復回頭改。Connection 選定之后在器件過濾框里敲型號關鍵詞。這里有個容易混淆的點列表里會同時出現(xiàn)Board和Device兩類條目。Board 指的是整塊評估板選中它會自動帶出板上所有器件、以及這塊板推薦的連接方式優(yōu)點是省事缺點是靈活性差Device 指的是單顆芯片選中它之后你只得到一個芯片節(jié)點連接方式自己配。做產(chǎn)品開發(fā)一般選 Device做評估板教學實驗選 Board 更省心。把 Device 加進右側(cè)的器件列表之后你會看到樹狀結(jié)構(gòu)最上面是器件型號下面掛著 CPU 核再下面是核的屬性。單核芯片到這里基本就完了多核芯片要留意每個核是否需要單獨的 GEL。2.3 GEL 文件的掛載與初始化順序選中某個核右鍵可以看到Open GEL File或在屬性里配置 GEL 的入口。GEL 文件本身是 TI 早期定義的一套腳本語法長得像 C 但完全不是 C它跑在調(diào)試器的宿主環(huán)境里作用是在 CPU 復位之后、程序加載之前把芯片帶到可以運行程序的狀態(tài)。掛載 GEL 時有幾個細節(jié)值得說。第一GEL 是掛在核上的多核器件每個核可能有各自的 GEL別只在第一個核上掛完就以為搞定了。第二GEL 的執(zhí)行順序是連接建立并復位目標后先跑 GEL 里的StartUp()然后才輪到OnTargetConnect()、OnReset()這類熱函數(shù)順序搞反的話你會看到一些莫名其妙的狀態(tài)。第三仿真模式下很多 GEL 語句會失效因為 GEL 里常見的動作是寫 PLL、寫 DDR 控制器寄存器而軟件仿真模型壓根沒有這些外設。這時候要么在 GEL 里加條件判斷按連接方式分支要么干脆為仿真單獨準備一份簡化版 GEL。我個人的習慣是GEL 里凡是寫寄存器的地方前面都加一句注釋標明僅真機有效交接的時候下一個人能少踩一個坑。2.4 Advanced 頁里的時鐘、內(nèi)存映射與 CPU 屬性Advanced 頁日常用得少但一旦出了問題多半就出在這里。這里面最關鍵的配置項是內(nèi)存映射和時鐘頻率。內(nèi)存映射為什么重要因為調(diào)試器訪問內(nèi)存是靠地址映射表來翻譯的。如果你的程序訪問了一塊沒有被映射的地址真機上可能只是讀到一個無效值但在調(diào)試器里會直接報錯中斷會話。仿真模式下這個問題更突出因為仿真模型的默認映射往往比真機保守。很多仿真環(huán)境里都有一個啟用全部內(nèi)存之類的選項勾上它未映射地址就不再報錯。代價是你失去了非法訪問檢測這個能力調(diào)試越界指針的時候就沒那么好用了。所以我的建議是排查階段打開它定位階段關掉它。時鐘頻率主要用于調(diào)試器估算超時和某些外設的時序設置填錯一般不會立刻報錯但可能表現(xiàn)為斷點響應異?;蛘吣承┑却h(huán)卡死。這個值在真機配置下應該和你板子上的晶振、PLL 配置一致仿真配置下隨便填一個合理值即可。2.5 從 Test Connection 到 Set as Default配置改完先點Save然后點Test Connection。仿真模式下這個測試基本一定通過因為根本沒有硬件可連所以它對你的參考價值有限硬件模式下這個測試很有用能提前把驅(qū)動、供電、JTAG 時鐘這些問題暴露出來省得在 Debug 里一次次重試。最后一步容易被忽略在Target Configurations視圖里右鍵這份配置選Set as Default。設置之后新建 Debug Configuration 時 CCS 會默認選它。不設的話CCS 會用一個它自己覺得合理的默認值而這個默認值往往不是你剛建的那份于是你改了半天的 GEL 根本沒被加載還在那兒納悶。3. 把 ccxml 當代碼來管文件結(jié)構(gòu)與手工維護界面操作能覆蓋八成場景剩下兩成必須靠文本編輯。比如批量把一批配置里的絕對路徑改成相對路徑、比如對比兩個版本之間到底哪個字段被人改過、比如在沒有圖形界面的構(gòu)建服務器上準備一份配置。這時候.ccxml作為純文本的價值就體現(xiàn)出來了。3.1 XML 骨架逐層拆解一份典型的 ccxml 結(jié)構(gòu)大致是這樣的層次根節(jié)點configurations下面一個或多個configuration每個 configuration 里包含描述連接的instance節(jié)點和描述器件的hardware/device節(jié)點再往下是各個 CPU 核的property記錄以及 GEL 文件的引用。下面這段是示意結(jié)構(gòu)字段值會隨 CCS 版本和器件支持包變化實際內(nèi)容請以你自己工程里生成的文件為準?xml version1.0 encodingUTF-8 standaloneno? configurations XML_version1.2 idconfigurations_0 configuration XML_version1.2 idconfiguration_0 !-- 連接方式XDS100v2 仿真器 -- instance XML_version1.2 descTexas Instruments XDS100v2 USB Emulator hrefconnections/TIXDS100v2_Connection.xml idTexas Instruments XDS100v2 USB Emulator xmlTIXDS100v2_Connection.xml xmlpathconnections/ !-- 目標器件 -- hardware XML_version1.2 descTMS320C6748 hrefdevices/tms320c6748.xml idTMS320C6748 xmltms320c6748.xml xmlpathdevices/ !-- CPU 核及其屬性 -- device XML_version1.2 idC674x_0 descC674x property idCoreName valueC674x/ property idGELFile valueinit.gel/ /device /configuration /configurations看這份結(jié)構(gòu)能明白幾件事。第一href和xmlpath指向的是 CCS 安裝目錄下targetdb體系里的描述文件這些文件描述了每種連接、每顆器件的具體能力。所以換一臺 CCS 版本差別很大的機器同一個 ccxml 可能因為找不到對應的描述文件而加載失敗——這也是升級工具鏈時最容易被忽略的兼容性問題。第二GEL 的引用是以property的形式存在核節(jié)點里的找到它就能改路徑。第三整個文件是扁平且可 diff 的誰改了哪個字段一目了然。3.2 絕對路徑是跨機器遷移的頭號殺手CCS 自動生成的 GEL 路徑默認是絕對路徑長這樣C:/Users/zhangsan/workspace/motor_ctrl/init.gel。這份配置在你自己的機器上跑得好好的發(fā)給同事就炸了因為他的工作空間路徑不一樣。修法有兩種。一種是把 GEL 連同配置一起放進工程目錄然后把引用改成相對路徑。CCS5.5 對相對路徑的解析基準各版本略有差異實測下來以工程根目錄或配置所在目錄為基準的情況都有所以改完一定要換一個路徑試一次別想當然。另一種是干脆不用外部 GEL把初始化邏輯放進啟動代碼里用 C 實現(xiàn)——這種做法犧牲了調(diào)試便利性換來的是徹底的可移植性在跨團隊協(xié)作的項目里很常見。順帶說一個容易踩的坑路徑里的反斜杠。Windows 下 CCS 生成的路徑有時用反斜杠手工改成相對路徑時如果兩種斜杠混用某些版本會解析失敗。統(tǒng)一用正斜杠是最穩(wěn)的寫法。3.3 版本管理與交付策略ccxml 是文本天生適合進版本庫。我的做法是把工程/targetConfigs/整個目錄納入版本控制同時在工作空間的.metadata目錄里放一份.gitignore防止有人不小心把 User Defined 下的副本也提交上去造成兩套配置打架。提交之前做兩件事一是確認引用到的 GEL 文件也在版本庫里并且路徑是相對路徑二是確認配置里沒有混進個人的絕對路徑。這兩點用文本搜索就能查搜一下盤符或者用戶名中招的一眼就能看出來。還有個細節(jié)如果你們團隊在 CCS 安裝目錄里放了一些自定義的器件描述文件這些東西不在版本庫里新同事拉下代碼后會加載失敗。這種情況要么在項目 README 里寫清楚需要拷貝哪些文件到哪個目錄要么把這些描述文件也放在工程里然后改 xmlpath 指過去——后者更干凈但需要改的地方更多看你團隊的接受度。4. 仿真跑不起來時的排查鏈路前面講的是怎么建這一段講建完了跑不動怎么辦。強調(diào)一點排查順序比排查技巧重要得多。我見過太多人一上來就懷疑代碼改了半天算法最后發(fā)現(xiàn)是 JTAG 線沒插緊。4.1 先分清故障落在哪一層我的第一刀永遠是分類因為不同層的現(xiàn)象和解法完全不同。大致分三類故障層典型現(xiàn)象關注對象連接層會話根本起不來彈出 Error connecting 之類ccxml 的連接配置、驅(qū)動、供電、線纜初始化層會話能建立但啟動時彈 GEL 錯誤或內(nèi)存訪問錯誤GEL 腳本、內(nèi)存映射、時鐘配置程序?qū)右磺姓<虞d但運行結(jié)果不對程序邏輯、仿真模型的保真度分層的判斷標準很簡單看錯誤彈窗出現(xiàn)在加載程序之前還是之后。加載之前出的問題幾乎可以斷定是前兩層加載之后運行起來才出的問題才輪到第三層。這個判斷能幫你省掉至少一半的無用功。4.2 連接層報錯的逐層定位連接類報錯的花樣最多我把常見的幾種和應對方式列一下。注意這些是天真的排查動作不是讓你照著背錯誤碼提示驅(qū)動或 USB 相關的錯誤先去看操作系統(tǒng)的設備管理器里有沒有認到仿真器。CCS5.5 時代 XDS100 系列在部分系統(tǒng)上需要單獨裝驅(qū)動裝完要重啟。別在 CCS 里反復重試那里解決不了驅(qū)動問題。提示目標未響應、超時之類檢查板子供電、JTAG 排線方向、復位腳狀態(tài)。JTAG 時鐘速率也是一大嫌疑速率調(diào)低往往能連上連上之后再逐步調(diào)高。提示找不到目標配置文件這種最冤通常是文件被移動或者路徑寫死。檢查 Debug Configuration 的 Target 頁簽里指向的那個路徑是不是還存在以及 ccxml 內(nèi)部的路徑引用有沒有失效。提示沒有指定連接ccxml 被覆蓋或者手工編輯時刪掉了instance節(jié)點。用 Source 頁看一眼結(jié)構(gòu)就知道。還有一種很隱蔽的情況目標配置文件本身沒問題但 CCS 加載了緩存里的舊版本。這種時候重啟 CCS、或者刪掉工作空間元數(shù)據(jù)里的相關緩存再試往往就通了。所以排查到一半發(fā)現(xiàn)改了什么都沒反應的時候先懷疑緩存別懷疑人生。4.3 軟件仿真特有的幾個問題如果你的連接方式是純軟件仿真會遇到幾個硬件模式下不存在的現(xiàn)象值得單獨說。未映射內(nèi)存報錯。仿真模型的默認內(nèi)存映射通常只覆蓋主存和少量區(qū)域你的程序如果訪問了外設地址調(diào)試器會報內(nèi)存訪問錯誤。解法就是前面提到的在配置里啟用完整內(nèi)存映射或者用 GEL 里的映射指令把相關區(qū)域加進去。外設寄存器讀回固定值。仿真模型對很多外設是空殼讀回來要么全 0要么是固定值。如果你的代碼里靠輪詢某個狀態(tài)位來推進流程仿真下必然死循環(huán)。這種問題沒法靠改配置解決只能改用條件編譯把輪詢繞過去或者換真機驗證。時序不真實。功能級仿真對指令周期、中斷延遲、總線仲裁的建模都是近似的。拿仿真跑出來的耗時數(shù)據(jù)去評估實時性結(jié)論基本不可信。周期精確模型可信度高一些但速度慢跑大規(guī)模循環(huán)會讓人失去耐心。加載和執(zhí)行速度慢。代碼量一大仿真加載時間會明顯拉長尤其是帶符號調(diào)試信息的時候。臨時把優(yōu)化等級調(diào)高、或者縮小測試用例規(guī)模都是常規(guī)操作。4.4 GEL 報錯與加載順序問題GEL 報錯的表現(xiàn)通常是啟動時彈出腳本錯誤或者狀態(tài)欄提示某條語句執(zhí)行失敗。排查思路是先確認腳本語法沒問題GEL 的語法和 C 差別不小比如變量聲明、函數(shù)定義方式都不一樣直接從 C 代碼抄過來是最常見的錯誤來源再確認腳本引用的寄存器在當前連線下是否存在仿真模式下這一步經(jīng)常失敗。還有一種不那么明顯的情況GEL 里做了復位動作而復位之后調(diào)試器又去讀某個還沒穩(wěn)定的狀態(tài)導致時序性的失敗。這種問題在真機上偶發(fā)、在仿真下必現(xiàn)或者反過來排查起來很費勁。我的辦法是在 GEL 的每個階段之間加一段延時或者狀態(tài)打印把執(zhí)行順序和實際狀態(tài)對照起來看比盲猜快得多。5. 工程實踐里的幾條經(jīng)驗配置這東西建一次不難難的是長期維護和團隊協(xié)作。下面幾條是我在多個項目里攢下來的做法。5.1 一個工程配多份目標配置的組織方式真實項目往往需要同時支持幾種調(diào)試環(huán)境手上有 XDS100 的開發(fā)機、有 XDS560 的實驗室臺架、還有沒有板子的純仿真驗證。這時候不要試圖用一份配置通吃而是建多份命名上做區(qū)分比如proj_sim.ccxml、proj_xds100.ccxml、proj_xds560.ccxml。然后針對每種環(huán)境建一個對應的 Debug Configuration切環(huán)境就是切一個下拉框的事。命名上我強烈建議把用途寫在文件名里而不是靠目錄區(qū)分。因為 CCS 的配置選擇列表只顯示文件名你看著三個都叫target.ccxml的條目會瘋掉。5.2 與 Debug Configuration、多核調(diào)試的配合新建 Debug Configuration 的時候Target 頁簽里選 ccxmlProgram 頁簽里選要加載的 out 文件。單核器件到這里就完了。多核器件要注意每個核都要指定自己那份 out 文件而且加載順序可能影響初始化——比如從核依賴主核先完成某些外設配置這時候就要在 Debug Configuration 里調(diào)整加載和運行的順序或者干脆用 GEL 來協(xié)調(diào)。還有一個大家常問的點能不能讓程序自動跑到 main 停住??梢栽?Debug Configuration 的運行控制選項里勾上相關設置即可。調(diào)試啟動時省掉手動點幾次的麻煩日積月累能省不少時間。但注意仿真模式下停到 main 的速度會比真機慢心理預期要調(diào)整。5.3 交給同事之前的自查清單交接是配置問題的高發(fā)環(huán)節(jié)我給自己定了一份檢查清單每次打包工程前過一遍檢查項通過標準配置文件位置在工程目錄內(nèi)不在 User Defined 或安裝目錄下路徑引用全文搜索無盤符、無用戶名、無絕對路徑GEL 文件隨工程一起提交引用路徑與工程內(nèi)實際位置一致連接方式與接收方的硬件條件匹配或已額外提供一份仿真配置工具鏈版本README 里注明 CCS 版本和器件支持包版本默認配置明確指定了默認目標配置且與預期一致這份清單看著啰嗦但每一條都是我真被坑過才加上去的。尤其是路徑那一條我至今記得有一次查了大半天最后發(fā)現(xiàn)是 GEL 路徑里寫著一個早就離職的同事的用戶名。最后分享一個我自己一直在用的小技巧把目標配置文件和 GEL 文件都放在工程的targetConfigs目錄下然后在工程根目錄放一個簡短的說明文件寫清楚每種配置對應什么硬件條件、需要什么版本的 CCS。等到半年后自己再打開這個工程或者交給下一個人這份說明能救命。配置這種東西寫的時候覺得我肯定記得實際上三個月后就是陌生人。