發(fā)調(diào)試環(huán)境)
說(shuō)實(shí)話ST生態(tài)里很多人入門(mén)都是Keil一把梭看代碼、編譯、下載、調(diào)試都在這一個(gè)IDE里完成。項(xiàng)目小的時(shí)候還能忍等工程文件一多、模塊一拆、想加個(gè)版本管理、想優(yōu)雅地看看調(diào)用鏈Keil那套編輯體驗(yàn)就開(kāi)始拖后腿了。我自己的做法是STM32CubeMX負(fù)責(zé)生成初始化代碼和工程骨架CLion負(fù)責(zé)日常編碼和代碼閱讀調(diào)試統(tǒng)一走SEGGER JLink JLink GDB Server。這套組合我用了一年多從F103到H743都跑過(guò)斷點(diǎn)、變量監(jiān)視、Flash下載都比以前順手很多而且整套配置是一次性的配好之后換個(gè)芯片也只是改參數(shù)的事。這篇文章就把我的完整配置過(guò)程、調(diào)試鏈路原理、踩過(guò)的坑一次性寫(xiě)清楚。適合已經(jīng)用過(guò)CubeMX、寫(xiě)了一陣子STM32、但對(duì)CLion和GDB調(diào)試還不熟的開(kāi)發(fā)者也適合被Keil工程管理搞得心煩、想換個(gè)思路的人。1. 為什么選擇CLion STM32CubeMX JLink這套組合先說(shuō)結(jié)論這三者不是替代關(guān)系而是各干各的活。CubeMX管初始化CLion管寫(xiě)代碼JLink管調(diào)試。把責(zé)任邊界劃清楚很多糾結(jié)就沒(méi)了。1.1 從Keil到CLion一次回不去的遷移KeilMDK對(duì)剛接觸ARM開(kāi)發(fā)的人來(lái)說(shuō)非常友好安裝簡(jiǎn)單、工程向?qū)倒匣c(diǎn)一下編譯就能下載。但等你維護(hù)超過(guò)十個(gè)模塊、想在代碼里精準(zhǔn)跳轉(zhuǎn)、想用Git管理每次改動(dòng)Keil的短板就暴露了。它的代碼補(bǔ)全基本聊勝于無(wú)全局搜索慢編輯器也不支持現(xiàn)代的鍵位習(xí)慣寫(xiě)起來(lái)總是差那么點(diǎn)意思。CLion是JetBrains家的C/C IDE補(bǔ)全、重構(gòu)、靜態(tài)檢查、Git集成這些能力天生在線。配合ARM GCC工具鏈完全可以做到像寫(xiě)PC程序一樣寫(xiě)嵌入式代碼跳轉(zhuǎn)準(zhǔn)確、錯(cuò)誤提示直觀代碼量一上來(lái)差距非常明顯。代價(jià)是CLion需要額外配置交叉編譯環(huán)境不像Keil開(kāi)箱即用但這份配置投入很值。1.2 CubeMX在流程中的定位代碼生成器而非IDE很多人把CubeMX當(dāng)IDE用這是誤會(huì)。CubeMX的核心價(jià)值是幫你生成初始化代碼時(shí)鐘樹(shù)、GPIO模式、外設(shè)參數(shù)、中斷優(yōu)先級(jí)全部通過(guò)圖形界面配置然后一鍵生成可編譯的工程骨架。CubeMX支持導(dǎo)出多種工具鏈形式包括Makefile、EWARM、MDK-ARM其中就包含CMake。這就是CLion能夠無(wú)縫接進(jìn)來(lái)的關(guān)鍵點(diǎn)。CLion本身對(duì)CMake工程的支持是原生的所以用CubeMX生成CMake工程后直接讓CLion打開(kāi)等于讓CLion站在CubeMX的肩膀上工作外設(shè)初始化不用手寫(xiě)專注業(yè)務(wù)邏輯就好。1.3 JLink在調(diào)試鏈中的作用GDB Server是翻譯官調(diào)試器硬件常見(jiàn)的有ST-Link、JLink、DAP-Link等其中JLink的穩(wěn)定性和速度口碑一直不錯(cuò)尤其是斷點(diǎn)數(shù)量、Flash下載速度這兩個(gè)維度實(shí)測(cè)確實(shí)比ST-Link省心。但要明白一點(diǎn)CLion本身并不直接認(rèn)識(shí)JLink硬件它認(rèn)識(shí)的是GDB協(xié)議。中間需要一個(gè)“翻譯官”把CLion發(fā)來(lái)的GDB命令翻譯成JLink能執(zhí)行的調(diào)試指令這個(gè)翻譯官就是JLink GDB Server也就是SEGGER官方提供的一個(gè)獨(dú)立程序。你可以在命令行里啟動(dòng)它也可以讓CLion調(diào)試時(shí)自動(dòng)拉起它。為什么我選JLink而不是OpenOCDOpenOCD也支持很多調(diào)試器但配置腳本有點(diǎn)繁瑣尤其是換芯片時(shí)要找對(duì)cfg文件、調(diào)速度和接口參數(shù)。JLink GDB Server這邊就簡(jiǎn)單多了圖形界面里選一下芯片型號(hào)、接口類型和速度剩下的它自己處理。對(duì)于主要用STM32系列、手頭又是JLink的人來(lái)說(shuō)這是最省事的路徑。2. 環(huán)境搭建把工具鏈一次性裝到位工欲善其事必先利其器。下面這些軟件安裝本身不難但版本和路徑有講究一次性配好比事后反復(fù)折騰強(qiáng)。2.1 需要準(zhǔn)備哪些軟件我用到的軟件清單如下全部來(lái)自官方渠道軟件作用建議版本STM32CubeMX生成初始化代碼、CMake工程6.x 均可CLion日常編碼、編譯管理、調(diào)試前端2023.x 或更新arm-none-eabi-gcc交叉編譯工具鏈10.3 或更新JLink驅(qū)動(dòng)及軟件包JLink驅(qū)動(dòng)、JLink GDB Server最新穩(wěn)定版Git可選版本管理CLion集成很舒服最新版這里有兩個(gè)容易踩的坑。第一個(gè)是arm-none-eabi-gcc不能隨便用一個(gè)聯(lián)網(wǎng)安裝的版本我建議直接去ARM官方站點(diǎn)下載壓縮包解壓后自己配環(huán)境變量可控性最好。第二個(gè)是JLink驅(qū)動(dòng)安裝包名很類似有帶“Software and Documentation Pack”的也有單獨(dú)的驅(qū)動(dòng)建議下載完整包里面包含了JLink GDB Server、JLink Commander、J-Flash等全套工具。2.2 ARM GCC工具鏈安裝與驗(yàn)證下載好arm-none-eabi-gcc壓縮包后解壓到一個(gè)不要帶空格和中文的路徑比如D:\arm-gnu-toolchain。然后把bin目錄加到系統(tǒng)PATH里。Windows下可以在環(huán)境變量里加macOS/Linux則改~/.bashrc或~/.zshrc。驗(yàn)證是否配置成功開(kāi)一個(gè)終端輸入arm-none-eabi-gcc --version能正常輸出版本信息就說(shuō)明工具鏈安裝好了。順便確認(rèn)一下arm-none-eabi-gdb也存在因?yàn)镃Lion調(diào)試的時(shí)候需要用它來(lái)加載符號(hào)和執(zhí)行GDB命令。很多人只裝了編譯器忘了檢查GDB結(jié)果后面調(diào)試器起不來(lái)。2.3 JLink驅(qū)動(dòng)與GDB Server安裝JLink安裝沒(méi)啥特別技巧一路下一步即可。安裝完成后建議先單獨(dú)打開(kāi)一次“JLink GDB Server”這個(gè)程序讓它自動(dòng)檢測(cè)或讓你手動(dòng)選擇目標(biāo)芯片型號(hào)。這樣做的好處是確保驅(qū)動(dòng)和硬件能正常通信。如果你連JLink都沒(méi)插它會(huì)提示找不到設(shè)備這是正常的。另外注意一點(diǎn)JLink GDB Server有兩種啟動(dòng)模式一種是用圖形界面手動(dòng)啟動(dòng)一種是通過(guò)命令行被CLion自動(dòng)拉起。我這里推薦讓CLion自動(dòng)拉起后面會(huì)有詳細(xì)配置說(shuō)明你先知道有這回事就行。3. CubeMX生成CMake工程的核心配置CubeMX配置本身說(shuō)起來(lái)內(nèi)容很多這里只挑跟CLion聯(lián)調(diào)強(qiáng)相關(guān)的關(guān)鍵點(diǎn)展開(kāi)其他的外設(shè)配置按你的具體項(xiàng)目來(lái)就好。3.1 調(diào)試接口必須提前留好很多人第一次燒錄正常第二次就在調(diào)試器里報(bào)“Cannot connect to target”絕大多數(shù)原因是SWD引腳被復(fù)用成GPIO了。CubeMX里這個(gè)設(shè)置藏在SYS - Debug一行默認(rèn)可能是Disable一定要改成Serial Wire也就是SWD模式。這么做會(huì)在初始化代碼里幫你把PA13SWDIO和PA14SWCLK保留為調(diào)試功能不讓用戶代碼把它們當(dāng)作普通IO使用。如果已經(jīng)不小心把SWD關(guān)掉了連不上芯片也不是世界末日用JLink Commander按住目標(biāo)板復(fù)位鍵執(zhí)行連接指令或者借助另一塊調(diào)試器做全片擦除就能救回來(lái)。后面“常見(jiàn)問(wèn)題”里我會(huì)再細(xì)說(shuō)。3.2 Toolchain選擇CMake導(dǎo)出工程結(jié)構(gòu)CubeMX的Project Manager - Project Settings頁(yè)面里有個(gè)Toolchain / IDE下拉框默認(rèn)可能是MDK-ARM。要接入CLion這里必須選CMake。生成之后工程目錄里會(huì)多出一個(gè)CMakeLists.txt還有一整套cmake子目錄里面是GCC工具鏈的定義文件。這個(gè)CMakeLists.txt是CLion能不能打開(kāi)工程的關(guān)鍵后面任何有關(guān)編譯目標(biāo)、源文件目錄的調(diào)整都會(huì)圍繞它展開(kāi)。生成完畢后建議先不要急著進(jìn)CLion看一眼目錄結(jié)構(gòu)確認(rèn)Core、Drivers、cmake這些目錄都在核心文件和庫(kù)文件都被正確帶出來(lái)了。如果中途改過(guò)芯片型號(hào)或外設(shè)配置重新生成時(shí)CubeMX會(huì)提示你確認(rèn)覆蓋一般選覆蓋即可。3.3 時(shí)鐘樹(shù)與工程參數(shù)的幾個(gè)注意點(diǎn)時(shí)鐘樹(shù)配置因芯片而異給不出統(tǒng)一模板但有個(gè)通用原則先確認(rèn)外部晶振頻率再設(shè)置PLL倍頻讓主頻盡量跑到芯片允許的高主頻這樣后續(xù)不用反復(fù)改。配置完時(shí)鐘后可以在Clock Configuration頁(yè)面看到哪些外設(shè)時(shí)鐘是否超標(biāo)或不夠一目了然。還有一個(gè)容易被忽略的參數(shù)是Project Name和Location。CubeMX默認(rèn)會(huì)創(chuàng)建帶工程名稱的目錄最好一路都使用英文字母和下劃線不要用中文、空格或特殊字符。ARM GCC的編譯腳本對(duì)不同語(yǔ)言環(huán)境的兼容性已經(jīng)不錯(cuò)了但CLion的CMake解析和GDB的路徑處理遇到中文目錄時(shí)偶爾還是會(huì)出幺蛾子與其排查半天不如一開(kāi)始就避坑。4. CLion工程導(dǎo)入與工具鏈對(duì)接CubeMX只是生成了骨架真正寫(xiě)代碼和編譯是在CLion里完成的。這步核心任務(wù)有兩個(gè)讓CLion正確讀取CMake工程讓CLion找到ARM GCC工具鏈。4.1 打開(kāi)CMake工程讓CLion認(rèn)識(shí)你的代碼打開(kāi)CLion選擇Open找到CubeMX生成目錄下的CMakeLists.txt直接打開(kāi)。CLion識(shí)別到CMake工程后會(huì)自動(dòng)做一次加載和索引左上角會(huì)出現(xiàn)可用的Target列表一般是xxx.elf這樣名字??吹竭@個(gè)Target說(shuō)明CLion已經(jīng)把源文件組織起來(lái)了可以直接跳轉(zhuǎn)和搜索。如果打開(kāi)之后沒(méi)有任何Target多半是CLion還沒(méi)配置工具鏈或者CMake配置有問(wèn)題。別慌先去設(shè)置里把工具鏈搞定再回來(lái)Reload CMake Project問(wèn)題通常就消失了。4.2 配置Toolchain指定ARM GCC路徑關(guān)鍵操作來(lái)了。打開(kāi)File - Settings - Build, Execution, Deployment - Toolchains新建一個(gè)工具鏈。名稱隨便寫(xiě)比如ARM-GCC類型選System因?yàn)槲覀兪鞘謩?dòng)配置的交叉工具鏈而不是CLion自帶的編譯環(huán)境C Compiler 填arm-none-eabi-gcc的實(shí)際路徑或者直接用命令名前提是PATH里已經(jīng)配置好C Compiler 填arm-none-eabi-gDebugger 填arm-none-eabi-gdb填完CLion會(huì)檢測(cè)并顯示這些工具的版本沒(méi)問(wèn)題就Apply。接著在CMake設(shè)置頁(yè)面里把Toolchain切到剛剛創(chuàng)建的這個(gè)ARM-GCC之后重新加載一次CMake工程。能看到Target并且能編譯通過(guò)說(shuō)明CLion已經(jīng)是一個(gè)完整的STM32開(kāi)發(fā)環(huán)境了。4.3 編譯幾個(gè)固件驗(yàn)證工具鏈可用配置完成后點(diǎn)一下“Build”按鈕看看能不能正常產(chǎn)出.elf文件。第一次編譯會(huì)比較慢因?yàn)樗袔?kù)文件都要編一遍。編譯輸出里會(huì)有arm-none-eabi-gcc的調(diào)用記錄以及最終生成的固件路徑。這一步要特別注意看有沒(méi)有報(bào)錯(cuò)。常見(jiàn)的報(bào)錯(cuò)是找不到頭文件、找不到CMSIS目錄多半是CMakeLists.txt里的include路徑有問(wèn)題或者CubeMX版本生成的工程和CLion的CMake版本有細(xì)微不兼容。大部分情況下重新生成一次CubeMX工程就能解決。固件編譯通過(guò)后可以先不接調(diào)試器直接看編譯產(chǎn)物里的xxx.elf是否生成在build目錄。這個(gè)文件是后面GDB調(diào)試時(shí)的靈魂符號(hào)表、斷點(diǎn)位置、變量地址全靠它。5. 用JLink GDB Server跑通第一次調(diào)試接下來(lái)進(jìn)入正題跑通JLink GDB Server讓CLion能下載固件、打斷點(diǎn)、看變量。5.1 硬件連接與參數(shù)確認(rèn)JLink調(diào)試器上最常見(jiàn)的是20Pin排針接口但對(duì)STM32開(kāi)發(fā)板來(lái)說(shuō)SVD調(diào)試只需要四根線就夠VTref參考電壓、GND、SWDIO、SWCLK。有條件的話再接一根RESET能提高連接穩(wěn)定性。JLink引腳目標(biāo)板引腳說(shuō)明VTref3.3VVCC參考電壓檢測(cè)GNDGND共地SWDIOSWDIOPA13數(shù)據(jù)線SWCLKSWCLKPA14時(shí)鐘線RESET可選NRST復(fù)位線接線時(shí)特別檢查VTref這一格是否接觸良好JLink就是靠它判斷目標(biāo)板的電平。如果VTref檢測(cè)不到電壓JLink會(huì)直接提示找不到目標(biāo)設(shè)備這時(shí)候很多人會(huì)誤以為調(diào)試器壞了其實(shí)只是這排線沒(méi)插好。5.2 配置CLion的Embedded GDB Server調(diào)試器CLion里點(diǎn)Run - Edit Configurations添加配置。新版CLion如果檢測(cè)到嵌入式開(kāi)發(fā)場(chǎng)景會(huì)提供Embedded GDB Server這個(gè)類型如果你的版本里沒(méi)有也可以用通用的GDB Remote Debug配置。以Embedded GDB Server為例關(guān)鍵配置項(xiàng)如下GDB Server路徑指向JLink安裝目錄里的JLinkGDBServerCL.exeWindows命令行版本而不是圖形界面的JLinkGDBServer.exeGDB Server參數(shù)寫(xiě)-device STM32F407VET6 -if SWD -speed 4000 -port 2331GDB路徑指向arm-none-eabi-gdbTargetremote :2331端口要和上面參數(shù)里的端口一致程序選擇編譯生成的xxx.elf文件其中-device參數(shù)是芯片型號(hào)要根據(jù)你實(shí)際的單片機(jī)填寫(xiě)比如F103C8對(duì)應(yīng)STM32F103C8H743對(duì)應(yīng)STM32H743VI。如果型號(hào)填錯(cuò)最典型的現(xiàn)象是GDB能啟動(dòng)但JLink連接時(shí)報(bào)錯(cuò)或固件下載失敗。-speed參數(shù)是SWD時(shí)鐘頻率4000kHz是通用值。如果連接不穩(wěn)定可以降到1000kHz如果用了杜邦線而且很長(zhǎng)頻率更是寧低勿高。啟動(dòng)調(diào)試時(shí)CLion會(huì)先啟動(dòng)GDB Server進(jìn)程再通過(guò)GDB連接過(guò)去整個(gè)過(guò)程在Run窗口里能看到完整日志??吹健癈onnected”或者類似輸出說(shuō)明你已經(jīng)邁進(jìn)JLink GDB調(diào)試的大門(mén)了。5.3 啟動(dòng)調(diào)試會(huì)話的完整流程一切配置就緒后點(diǎn)擊Debug按鈕正常流程是這樣CLion啟動(dòng)JLink GDB ServerGDB Server會(huì)打印檢測(cè)到的芯片IDGDB建立與GDB Server的遠(yuǎn)程連接CLion把.elf固件通過(guò)GDB下載到目標(biāo)板FlashGDB將PC指針停在main函數(shù)入口或復(fù)位向量處此時(shí)可以設(shè)置斷點(diǎn)、單步執(zhí)行、查看變量我第一次跑通時(shí)的感受是前面那么多配置最后點(diǎn)擊Debug的瞬間一切都值回來(lái)了。也順便說(shuō)一句如果CLion的調(diào)試沒(méi)自動(dòng)停在main入口可以在GDB命令里手動(dòng)執(zhí)行l(wèi)oad、monitor reset、break main、continue這一套流程手動(dòng)操作一次之后你就更能理解自動(dòng)配置的每一步在干什么。6. 調(diào)試實(shí)戰(zhàn)從斷點(diǎn)到寄存器監(jiān)視有了調(diào)試會(huì)話下面這些操作都是高頻場(chǎng)景。記住一個(gè)原則調(diào)試的本質(zhì)是觀察程序狀態(tài)斷點(diǎn)只是讓你在關(guān)心的位置暫停下來(lái)。6.1 斷點(diǎn)與單步調(diào)試在CLion里行號(hào)右側(cè)點(diǎn)一下就能下斷點(diǎn)這跟其他IDE沒(méi)什么區(qū)別。值得注意的是條件斷點(diǎn)當(dāng)你需要只在特定條件滿足時(shí)停下可以右鍵斷點(diǎn)設(shè)置條件表達(dá)式比如count 10或者flag true。這個(gè)功能在刷循環(huán)、查報(bào)文時(shí)非常實(shí)用比人肉數(shù)次數(shù)高效得多。單步調(diào)試時(shí)CLion提供Step Over、Step Into、Step Out三個(gè)基本操作。嵌入式場(chǎng)景下Step Into進(jìn)入庫(kù)函數(shù)后經(jīng)常要走很多匯編級(jí)別的代碼速度會(huì)很慢。我的習(xí)慣是看到庫(kù)函數(shù)就Step Over只有到了自己寫(xiě)的關(guān)鍵算法或狀態(tài)機(jī)分支時(shí)才Step Into效率高很多。6.2 變量監(jiān)視的優(yōu)化陷阱新手最常見(jiàn)的困惑是明明變量就在那Watch窗口卻顯示optimized out或者值怎么都不變。十有八九是編譯優(yōu)化等級(jí)太高。CubeMX生成的CMake工程里默認(rèn)編譯優(yōu)化可能是-O2或者沒(méi)有顯式設(shè)置這會(huì)導(dǎo)致GDB拿不到完整的變量信息或者變量的生命周期被縮短、寄存器復(fù)用之后源文件行號(hào)和機(jī)器碼對(duì)不上。我的處理辦法是在調(diào)試版本里強(qiáng)制降低優(yōu)化等級(jí)。在CMakeLists.txt合適位置加一行set(CMAKE_C_FLAGS_DEBUG -O0 -g3)然后在CLion的CMake配置里把Build Type設(shè)為Debug。這樣編譯時(shí)就會(huì)帶上-O0 -g3變量監(jiān)視基本恢復(fù)正常斷點(diǎn)行為也更容易理解。代價(jià)是固件體積變大、運(yùn)行速度變慢但只影響調(diào)試Build不影響Release版本。6.3 用GDB命令窗口做更多事CLion的調(diào)試器下方有個(gè)GDB控制臺(tái)可以直接輸入GDB命令。很多圖形界面做起來(lái)繞的事在這里一句話搞定。最常用的幾個(gè)info registers查看所有寄存器當(dāng)前值x/10wx 0x20000000以16進(jìn)制查看內(nèi)存地址從0x20000000開(kāi)始的10個(gè)字watch *(unsigned int*)0x40020000監(jiān)視某個(gè)地址的值變化硬件寄存器也能盯bt查看當(dāng)前調(diào)用棧嵌入式調(diào)試時(shí)外設(shè)寄存器往往沒(méi)有現(xiàn)成的圖形化變量直接通過(guò)GDB命令看內(nèi)存和寄存器是很高效的。我還習(xí)慣用x/1wx配合寄存器手冊(cè)的偏移地址快速確認(rèn)UART狀態(tài)寄存器的某個(gè)標(biāo)志位有沒(méi)有置位。6.4 外設(shè)寄存器查看CLion本身沒(méi)有提供類似Keil那種外設(shè)寄存器樹(shù)形視圖如果你裝了JetBrains的嵌入式插件或者用其他工具體驗(yàn)會(huì)稍有不同。但在JLink GDB Server這條鏈路里我更推薦直接用另外兩個(gè)手段一個(gè)是在GDB命令行里用x命令讀內(nèi)存配合STM32參考手冊(cè)查寄存器地址。例如USART1的SR寄存器地址是0x40013800命令就是x/1wx 0x40013800。另一個(gè)是直接在JLink的界面上看JLink GDB Server的日志窗口會(huì)顯示一些訪問(wèn)記錄但對(duì)寄存器級(jí)別的動(dòng)態(tài)監(jiān)視幫助有限。如果你的項(xiàng)目對(duì)寄存器級(jí)調(diào)試依賴很大還可以考慮用SEGGER的Ozone工具它對(duì)JLink的寄存器視圖支持非常完整而且可以掛接在同一個(gè)JLink上。不過(guò)那是另一套工具鏈不在CLion窗口內(nèi)了。7. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄這套環(huán)境配得再順利也難免遇到問(wèn)題。下面這些是我在實(shí)際項(xiàng)目中真實(shí)碰到過(guò)、并且找到原因的問(wèn)題整理成速查表給你參考。7.1 連接類故障JLink連不上目標(biāo)芯片現(xiàn)象常見(jiàn)原因解決思路打開(kāi)JLink GDB Server提示“No JLink found”驅(qū)動(dòng)沒(méi)裝好或JLink沒(méi)插好重裝驅(qū)動(dòng)換USB口看設(shè)備管理器是否識(shí)別“Cannot connect to target”目標(biāo)板沒(méi)上電或SWD引腳被復(fù)用檢查VTref確認(rèn)SYS Debug配置為Serial Wire“SWD Communication Failure”接線不穩(wěn)定或時(shí)鐘頻率太高檢查杜邦線接觸降低-speed參數(shù)到1000kHz能連上但無(wú)法下載固件芯片型號(hào)選錯(cuò)或Flash地址不對(duì)核對(duì)-device參數(shù)檢查鏈接腳本里的Flash地址有一個(gè)通用技巧JLink GDB Server設(shè)置界面的日志會(huì)打印詳細(xì)狀態(tài)報(bào)錯(cuò)時(shí)先看日志比盲目換配置高效得多。7.2 燒錄與調(diào)試類故障能連上但跑不起來(lái)連接正常但跑不起來(lái)的情況常見(jiàn)有兩類。一類是下載完成后程序不運(yùn)行。檢查是否用了monitor reset或復(fù)位腳本CLion的調(diào)試配置里如果沒(méi)有復(fù)位選項(xiàng)下載完程序可能停在復(fù)位向量。解決辦法是在GDB腳本里加上monitor reset或者直接按一下目標(biāo)板的復(fù)位鍵。另一類是能運(yùn)行但斷點(diǎn)不觸發(fā)。優(yōu)先懷疑編譯優(yōu)化等級(jí)把Debug配置改成-O0再試。如果斷點(diǎn)設(shè)在中斷服務(wù)函數(shù)里也要確認(rèn)中斷確實(shí)發(fā)生了比如UART接收中斷先確認(rèn)外設(shè)配置里中斷優(yōu)先級(jí)和使能位都對(duì)。7.3 工程配置類故障編譯和調(diào)試反復(fù)出問(wèn)題有些問(wèn)題處在CLion和CubeMX的銜接上。比如CubeMX重新生成工程后CLion的CMake配置失效出現(xiàn)源文件重復(fù)或找不到項(xiàng)目文件的現(xiàn)象。遇到這種情況我一般會(huì)做一次“干凈”處理在CLion里刪除build緩存目錄執(zhí)行File - Reload CMake Project如果還不行就關(guān)閉工程重新打開(kāi)。再就是路徑問(wèn)題。工程路徑、CubeMX安裝路徑、工具鏈路徑任何一個(gè)帶中文或空格都可能引發(fā)GCC參數(shù)解析異常。我在多個(gè)電腦上踩過(guò)這個(gè)坑現(xiàn)在新工程一律放在純英文路徑下比如D:\projects\stm32f407_demo。7.4 我的幾條避坑經(jīng)驗(yàn)最后還是老規(guī)矩分享幾條純經(jīng)驗(yàn)都屬于文檔里不大會(huì)寫(xiě)的東西。第一SWD連接線盡量短。杜邦線長(zhǎng)度超過(guò)20厘米時(shí)高速模式下很容易出現(xiàn)間歇性通信失敗。我調(diào)試臺(tái)上有兩套排線一套長(zhǎng)的用來(lái)跳線一套短的備用一旦連接異常直接換短線上省了很多排查時(shí)間。第二目標(biāo)板先上電再接JLink還是先接JLink再上電其實(shí)沒(méi)有嚴(yán)格要求但我習(xí)慣先把目標(biāo)板上電等電壓穩(wěn)定后再讓JLink連接能減少一部分上電瞬間的通信毛刺。第三CLion調(diào)試時(shí)最直觀的排查入口是Run窗口的log。每次調(diào)試失敗先看GDB Server輸出了什么再看GDB輸出了什么兩層日志對(duì)照著看問(wèn)題基本能定位到。不要一上來(lái)就猜調(diào)試問(wèn)題靠猜效率最低。第四如果你在Windows上用的是較新版本的JLink驅(qū)動(dòng)注意它可能默認(rèn)安裝了WinUSB驅(qū)動(dòng)會(huì)影響其他工具對(duì)調(diào)試器的訪問(wèn)。真遇到奇怪的不兼容問(wèn)題可以試試在SEGGER安裝目錄里重新運(yùn)行驅(qū)動(dòng)安裝程序或者用Zadig把驅(qū)動(dòng)切回WinUSB。這套組合我用了很久最大的變化是調(diào)試一個(gè)復(fù)雜的多線程狀態(tài)機(jī)時(shí)CLion里看變量和調(diào)用棧就像在看普通桌面程序不再有那種“裸機(jī)開(kāi)發(fā)就是原始人”的憋屈感。JLink GDB Server雖然配置起來(lái)比Keil多幾道工序但一旦跑通穩(wěn)定性和效率都是長(zhǎng)期受益。如果你手頭正好有JLink和一塊CubeMX工程可以按這個(gè)流程試一遍大概率半天內(nèi)就能把整套環(huán)境跑起來(lái)。