戰(zhàn):手動(dòng)為 J-Link 添加不支持的 MCU)
SEGGER 這次把 Open Flash Loader 能力拉到 J-Link、J-Trace、Flasher 三款產(chǎn)品線上對(duì)搞單片機(jī)開發(fā)的兄弟來(lái)說(shuō)確實(shí)是個(gè)好消息。尤其是用非主流 MCU、剛流片回來(lái)還沒(méi)拿到官方燒錄算法的團(tuán)隊(duì)以前碰到J-Link 不支持這顆料基本就是卡死狀態(tài)現(xiàn)在 Open Flash Loader 給了一條完全不同的路。這篇文章結(jié)合我最近的項(xiàng)目經(jīng)歷把 Open Flash Loader 是什么、怎么配、怎么在 J-Link 里手動(dòng)添加一顆不在支持列表里的 IC以及 J-Link、J-Trace、Flasher 三者在這種情況下分別怎么用一次說(shuō)清楚。順手把網(wǎng)上問(wèn)得最多的J-Link 點(diǎn)位和 S32DS 調(diào) J-Link 時(shí)報(bào) GDB Server 超時(shí)的坑也一并聊了。1. Flash 編程的底層邏輯與 Open Flash Loader 的定位1.1 傳統(tǒng) Flash 編程是怎么工作的要理解 Open Flash Loader 到底解決了什么問(wèn)題得先看傳統(tǒng) J-Link 燒錄 Flash 的過(guò)程。J-Link 通過(guò) SWD 或 JTAG 連上目標(biāo)芯片之后并不會(huì)直接把燒錄指令一點(diǎn)點(diǎn)塞進(jìn) Flash。原因是 Flash 的寫操作有嚴(yán)格時(shí)序要求比如需要先擦除扇區(qū)、再按頁(yè)編程、寫完還要做校驗(yàn)這些操作如果靠調(diào)試接口一條條指令去驅(qū)動(dòng)速度會(huì)慢到?jīng)]法用。所以 J-Link 的做法是把一段燒錄程序?qū)I(yè)叫法是 flash algorithmFlash 算法下載到目標(biāo)芯片的 RAM 里然后讓 CPU 運(yùn)行這段程序通過(guò)它去操作片內(nèi) Flash 控制器完成擦除和寫入。燒錄完成后再通過(guò)調(diào)試接口讀取 Flash 內(nèi)容做校驗(yàn)。這套思路本身沒(méi)問(wèn)題問(wèn)題出在flash algorithm 從哪來(lái)。傳統(tǒng)上每款芯片都需要 SEGGER 官方針對(duì)內(nèi)核、Flash 控制器、RAM 地址空間做適配編譯好之后集成到 J-Link 軟件里。也就是說(shuō)芯片廠商必須先跟 SEGGER 對(duì)接用戶才能用 J-Link 燒錄這顆芯片。你要是用了一顆很小眾的 MCU或者芯片還在工程樣品階段官方適配列表里沒(méi)有那 J-Link 就完全沒(méi)辦法幫你燒錄。1.2 為什么 Open Flash Loader 能破局Open Flash Loader 是 ARM 在 CMSIS-Pack 體系里定義的一套開放標(biāo)準(zhǔn)。它的核心思路是把Flash 算法從 J-Link 軟件內(nèi)部剝離出來(lái)變成一個(gè)個(gè)獨(dú)立的 ELF 格式文件由芯片廠商或者用戶自己來(lái)維護(hù)。J-Link 只負(fù)責(zé)把這份 ELF 加載到目標(biāo) RAM然后調(diào)用里面約定的函數(shù)完成燒錄至于 Flash 控制器具體怎么操作完全由 ELF 文件里的代碼決定。SEGGER 把 Open Flash Loader 支持加入到 J-Link、J-Trace、Flasher 之后意味著三件事同時(shí)發(fā)生第一J-Link 對(duì)第三方 Flash 算法的兼容邊界被徹底打開了。以前只能用 SEGGER 官方適配好的算法現(xiàn)在只要你有 ELF 格式的 loader 文件不管芯片多小眾都可以燒。第二用戶手里有了一顆新芯片的工程樣片想先評(píng)估或者燒個(gè) bootloader 做 bring-up不用再干等官方支持自己花半天時(shí)間就能把 loader 配好。第三公司里如果有多款芯片需要統(tǒng)一燒錄平臺(tái)Open Flash Loader 讓團(tuán)隊(duì)可以自己維護(hù)一套算法文件不依賴外部廠商供應(yīng)鏈上更可控。1.3 什么人最需要關(guān)注這個(gè)能力我列一下最典型的幾類場(chǎng)景你可以對(duì)號(hào)入座使用國(guó)產(chǎn)或小眾 MCU 的團(tuán)隊(duì)。很多國(guó)產(chǎn)芯片廠商的 SEGGER 適配進(jìn)度滯后經(jīng)常出現(xiàn)芯片已經(jīng)量產(chǎn)、J-Link 軟件里還沒(méi)有的情況。芯片原廠的 FAE 或嵌入式工程師。給客戶提供燒錄支持時(shí)Open Flash Loader 是最高效的方式不綁定特定燒錄器品牌。做板級(jí) bring-up 的硬件工程師。新板子回來(lái)Flash 算法不對(duì)所有調(diào)試都做不了自己配 loader 能省出好幾天的等待時(shí)間。產(chǎn)線燒錄相關(guān)工程師。Flasher 是獨(dú)立的離線燒錄設(shè)備支持 Open Flash Loader 之后能掛載的芯片范圍大大擴(kuò)展。2. Open Flash Loader 的運(yùn)行機(jī)制與配置原理2.1 核心文件與目錄結(jié)構(gòu)Open Flash Loader 落到文件層面主要有兩種東西一是loader 算法的 ELF 文件一般以.elf或.flm結(jié)尾。FLM是 Keil MDK 那套 Flash 算法的老格式本質(zhì)上也是 ELF 的變種。里面的代碼不依賴任何操作系統(tǒng)通過(guò)固定的導(dǎo)出函數(shù)接口和 J-Link 通信。二是設(shè)備映射 XML 文件SEGGER 管它叫JLinkDevices.xml。這個(gè)文件的作用是告訴 J-Link某顆芯片屬于哪個(gè)內(nèi)核、RAM 空間在哪、Flash 起始地址在哪、用的 loader 文件又放在哪個(gè)路徑。J-Link 軟件啟動(dòng)時(shí)會(huì)掃描這個(gè) XML把芯片信息加載進(jìn)支持列表。SEGGER 推薦的做法是把這些文件統(tǒng)一放在一個(gè)業(yè)務(wù)目錄下。比如我的工作目錄是這樣的C:\Work\FlashLoaders\ ├── Devices\ │ └── MyVendor\ │ ├── MyMCU\ │ │ ├── FlashLoader.elf │ │ └── flash_device.h └── JLinkDevices.xml實(shí)際配置的時(shí)候JLinkDevices.xml里的條目長(zhǎng)這樣DataBase Device ChipInfo VendorMyVendor NameMyMCU-100 CoreJLINK_CORE_CORTEX_M4 WorkRAMAddr0x20000000 WorkRAMSize0x00010000/ FlashBankInfo NameInternal Flash BaseAddr0x08000000 MaxSize0x00080000 LoaderDevices/MyVendor/MyMCU/FlashLoader.elf LoaderTypeFLASH_ALGO_TYPE_OPEN/ /Device /DataBase這里的路徑是相對(duì) J-Link 安裝目錄來(lái)說(shuō)的所以Loader一項(xiàng)要注意路徑寫對(duì)。SEGGER 新版本也已經(jīng)支持從 CMSIS-Pack 的安裝目錄里直接引用 loader這種情況下路徑可以指向%PACK_FOLDER%之類的通配位置。2.2 關(guān)鍵配置項(xiàng)逐一拆解在JLinkDevices.xml里幾個(gè)關(guān)鍵屬性的含義一定要搞清楚配錯(cuò)了會(huì)非常痛苦。Core目標(biāo)芯片的內(nèi)核類型。必須是 J-Link 認(rèn)識(shí)的表達(dá)方式比如JLINK_CORE_CORTEX_M4、JLINK_CORE_CORTEX_M33、JLINK_CORE_RISCV等。這一項(xiàng)決定 J-Link 用什么寄存器訪問(wèn)方式來(lái)初始化 CPU 和下載 loader 程序。WorkRAMAddr / WorkRAMSizeloader 程序要放到目標(biāo)芯片的哪塊 RAM 里運(yùn)行。這個(gè)地址必須是你芯片上真實(shí)存在的可讀可寫 RAM而且燒錄期間不能有別的程序占用它。很多芯片的 RAM 是分塊的比如 0x20000000 開頭的 SRAM 和 0x10000000 開頭的 CCM RAM 就完全不同一定要選 loader 能正常訪問(wèn)的區(qū)域。BaseAddr / MaxSizeFlash 的起始地址和最大容量。起始地址一般看數(shù)據(jù)手冊(cè)里的 Flash 基地址Cortex-M 芯片通常是 0x08000000 或者 0x00000000如果你開啟了 BOOT 映射。容量按芯片型號(hào)填比如 512KB 就填0x00080000。Loaderloader 算法文件的路徑。LoaderType這是 Open Flash Loader 支持的關(guān)鍵字段填FLASH_ALGO_TYPE_OPEN表示走開放格式。如果你的 loader 是老式的 SEGGER 私有格式就不該用這個(gè)類型。2.3 loader 程序的導(dǎo)出符號(hào)Open Flash Loader 的 ELF 文件不是隨便編譯一個(gè)固件就能用它必須導(dǎo)出 5 個(gè)固定的函數(shù)符號(hào)J-Link 靠這些符號(hào)來(lái)調(diào)用算法int Init(uint32_t clk); int UnInit(uint32_t fnc); int EraseChip(void); int EraseSector(uint32_t addr); int ProgramPage(uint32_t addr, uint32_t size, uint8_t *buf);你可以把Init理解成開機(jī)自檢對(duì) Flash 控制器做時(shí)鐘使能和解鎖操作EraseSector按照地址擦除一個(gè)扇區(qū)ProgramPage往某個(gè)頁(yè)里寫入指定長(zhǎng)度的數(shù)據(jù)。每個(gè)函數(shù)返回 0 表示成功非 0 表示失敗。J-Link 在燒錄過(guò)程中會(huì)調(diào)用EraseChip或循環(huán)調(diào)用EraseSector然后一頁(yè)頁(yè)調(diào)ProgramPage寫入數(shù)據(jù)。這個(gè)接口非常簡(jiǎn)潔芯片廠商的 SDK 里通常都會(huì)給參考模板照著改就行。我見(jiàn)過(guò)不少團(tuán)隊(duì)在這個(gè)環(huán)節(jié)踩坑函數(shù)名大小寫不對(duì)、沒(méi)有做好符號(hào)導(dǎo)出、編譯時(shí)加了優(yōu)化導(dǎo)致參數(shù)傳遞被改壞這些都會(huì)讓 J-Link 在加載 loader 后直接報(bào)錯(cuò)或者卡住。3. 手動(dòng)為 J-Link 添加一顆不在列表里的 IC3.1 第一步從數(shù)據(jù)手冊(cè)里撈出 Flash 參數(shù)拿一顆 J-Link 原本不支持的 MCU 來(lái)舉例。假設(shè)芯片是 Cortex-M33 內(nèi)核內(nèi)部集成 1MB Flash 和 256KB RAM。要配 Open Flash Loader需要從數(shù)據(jù)手冊(cè)里找到這些信息內(nèi)核型號(hào)Cortex-M33支持 ARMv8-M Mainline 指令集Flash 基地址0x08000000容量 0x00100000Flash 扇區(qū)大小前 16 個(gè)扇區(qū)每個(gè) 8KB后面每個(gè) 64KBRAM 基地址0x20000000容量 0x00040000編程頁(yè)大小256 字節(jié)扇區(qū)和頁(yè)大小這兩個(gè)參數(shù)直接決定你看待擦除和寫入的最小單位。如果手冊(cè)里寫的是雙 Bank 結(jié)構(gòu)半頁(yè)編程之類記得把 Bank 切換邏輯在 loader 里實(shí)現(xiàn)。這里我建議你先別急著寫 XML。先用 J-Link 自帶的命令行工具做一次最小驗(yàn)證。SEGGER 的JLink.exe允許直接指定要連接的芯片試一下能不能通過(guò) SWD 正常連接到這顆芯片JLink.exe -device Cortex-M33 -if SWD -speed 4000如果這一步能連上說(shuō)明 J-Link 的調(diào)試鏈路沒(méi)問(wèn)題問(wèn)題只在 Flash 算法層如果連不上那是接線或電源問(wèn)題先排查完再繼續(xù)。3.2 第二步編譯 or 獲取 loader 文件如果芯片原廠已經(jīng)提供了 CMSIS-Pack里面通常會(huì)有 Open Flash Loader 的.flm或.elf文件直接找出來(lái)用。如果原廠沒(méi)有給就得自己編譯一個(gè)。最常見(jiàn)的做法是從 Keil MDK 的FlashOS模板工程改起因?yàn)镕lashOS工程本身就是按 Open Flash Loader 接口寫的你只需要根據(jù)芯片手冊(cè)修改底層的 Flash 操作函數(shù)重新編譯生成.flm文件。以我做過(guò)的某顆國(guó)產(chǎn) M33 內(nèi)核芯片為例只需要改動(dòng) 4 處FlashDev.c里的器件描述結(jié)構(gòu)體填寫 Flash 大小、起始地址、扇區(qū)大小、頁(yè)大小、FlashOS.c里的 Init/UnInit/EraseSector/ProgramPage 函數(shù)體、啟動(dòng)文件里的??臻g設(shè)置、以及鏈接腳本里的加載地址。編譯參數(shù)里記得把目標(biāo)內(nèi)核選成 Cortex-M33并開啟 Hardware FPU 支持如果芯片帶 FPU 的話。3.3 第三步在 J-Link 中注冊(cè)新器件有了 ELF 文件接下來(lái)注冊(cè)就有兩條路改JLinkDevices.xml或者用 J-Flash 的圖形界面。改 XML 的方式適合批量維護(hù)我把一個(gè)真實(shí)可用的例子放出來(lái)Device ChipInfo VendorMyVendor NameMyM33-1000 CoreJLINK_CORE_CORTEX_M33 WorkRAMAddr0x20000000 WorkRAMSize0x00040000/ FlashBankInfo NameInternal Flash BaseAddr0x08000000 MaxSize0x00100000 LoaderDevices/MyVendor/MyM33/MyM33_1M.elf LoaderTypeFLASH_ALGO_TYPE_OPEN/ /Device把這段寫進(jìn) J-Link 安裝目錄下的JLinkDevices.xml或者你自己維護(hù)的新 XML 文件保存后重啟 J-Link 軟件。用JLink.exe測(cè)試時(shí)-device參數(shù)會(huì)多出MyM33-1000這個(gè)選項(xiàng)。J-Flash 的圖形界面方式更適合單次操作打開 J-Flash文件菜單里新建工程在設(shè)備選擇界面點(diǎn)擊Add創(chuàng)建自定義器件把內(nèi)核類型、RAM 地址、Flash Bank 地址、loader 文件路徑填進(jìn)去保存為*.jflash工程文件。以后每次直接用 J-Flash 打開這個(gè)工程就能燒錄。3.4 第四步第一次燒錄驗(yàn)證與調(diào)優(yōu)配置完成后先用最小的 bin 文件測(cè)試比如一個(gè) 256 字節(jié)的啞數(shù)據(jù)只做擦寫和校驗(yàn)不要上來(lái)就刷整個(gè)固件。我常用的驗(yàn)證流程是JLink.exe -device MyM33-1000 -if SWD -speed 4000 -CommanderScript burn_simple.jlinkburn_simple.jlink腳本里寫的是connect erase loadbin C:\Work\test.bin, 0x08000000 verifybin C:\Work\test.bin, 0x08000000 exit如果loadbin和verifybin都通過(guò)說(shuō)明流程通了。接下來(lái)可以嘗試燒錄真實(shí)固件同時(shí)觀察燒錄速度。Open Flash Loader 的編程性能通常會(huì)比官方適配算法慢一些如果慢得離譜比如一個(gè) 1MB 固件要燒 5 分鐘就要檢查ProgramPage函數(shù)里的緩沖實(shí)現(xiàn)和時(shí)鐘配置。4. J-Link、J-Trace、Flasher 的定位與 Open Flash Loader 的協(xié)作4.1 三款設(shè)備到底誰(shuí)是誰(shuí)很多人分不清 J-Link、J-Trace 和 Flasher簡(jiǎn)單說(shuō)J-Link 是日常軟件開發(fā)調(diào)試用的調(diào)試探針支持下載、單步、斷點(diǎn)、變量監(jiān)視通過(guò) USB 連接電腦配合 IDE 使用。J-Trace 是 J-Link 的加強(qiáng)版主要多出了指令跟蹤功能支持 ETM 等 trace 接口可以完整記錄 CPU 執(zhí)行過(guò)程對(duì)分析復(fù)雜崩潰問(wèn)題、代碼覆蓋率評(píng)估、實(shí)時(shí)性能分析非常有用。Flasher 則是產(chǎn)線用的獨(dú)立編程燒錄器可以完全脫離電腦工作通過(guò) SD 卡或網(wǎng)口存儲(chǔ)固件按一個(gè)按鈕就批量燒錄追求的是生產(chǎn)效率和穩(wěn)定性。這三款設(shè)備在 Flash 燒錄這個(gè)動(dòng)作上的底層邏輯是完全一致的都需要把算法加載到目標(biāo) RAM 里執(zhí)行。Open Flash Loader 支持加入后三款設(shè)備都能加載同一份 ELF 格式 loader也就是說(shuō)你花時(shí)間配好的算法文件開發(fā)、測(cè)試、產(chǎn)線三端通用不需要為不同工具各維護(hù)一份。4.2 在 J-Trace 上使用 Open Flash Loader 的注意事項(xiàng)J-Trace 運(yùn)行 Open Flash Loader 的機(jī)制和 J-Link 相同但 J-Trace 多了 trace 相關(guān)的硬件資源。實(shí)際調(diào)試中有一個(gè)容易被忽略的問(wèn)題如果你在 Open Flash Loader 里配置的WorkRAMAddr恰好覆蓋了 trace 數(shù)據(jù)要用的 RAM 緩沖區(qū)地址燒錄完成后 trace 功能可能異常。因?yàn)?loader 程序被下載到 RAM 里去執(zhí)行燒錄時(shí) CPU 要跑這段程序trace 硬件也在持續(xù)監(jiān)控總線活動(dòng)。某些芯片的 ETM trace 對(duì) RAM 地址有優(yōu)先級(jí)要求或者 trace buffer 設(shè)在了運(yùn)行 loader 的同一塊 RAM這時(shí)候燒錄過(guò)程會(huì)讓 trace 數(shù)據(jù)被覆蓋。我的建議是給 loader 單獨(dú)保留一塊 RAM不要和 trace buffer 共用。如果芯片 RAM 足夠大把 loader 用的 WorkRAM 放在不沖突的地址范圍如果 RAM 緊張至少保證燒錄時(shí) trace buffer 的地址被排除在 loader 的 RAM 范圍之外。4.3 Flasher 生產(chǎn)模式下的 Loader 配置Flasher 和 J-Link 的燒錄流程走的是不同的軟件鏈。Flasher 的固件配置是通過(guò) SEGGER 的 J-Flash 軟件或者 Flasher 自帶的命令行工具來(lái)完成的配置內(nèi)容主要包括通信接口SWD/JTAG、目標(biāo)器件加載 Open Flash Loader、固件文件、是否自動(dòng)校驗(yàn)、是否加密等。生產(chǎn)環(huán)境下Flasher 會(huì)把整個(gè)燒錄配置連同 loader 算法一起打包進(jìn) Flasher 的存儲(chǔ)空間?,F(xiàn)場(chǎng)操作員只需要把目標(biāo)板通過(guò)排線連到 Flasher按一下 Start 按鈕設(shè)備就自動(dòng)完成連接、擦除、寫入、校驗(yàn)的完整流程。這個(gè)過(guò)程完全不依賴電腦也就避免了生產(chǎn)現(xiàn)場(chǎng) USB 驅(qū)動(dòng)、病毒、權(quán)限等因素的干擾。我建議在 Flasher 上線之前先做一次完整的試燒錄驗(yàn)證重點(diǎn)檢查Open Flash Loader 里 Init 函數(shù)對(duì)目標(biāo)芯片時(shí)鐘的初始化是否穩(wěn)定擦除整個(gè) Flash 所需時(shí)間是否在產(chǎn)線期望范圍內(nèi)編程一頁(yè)數(shù)據(jù)之后的 ACK 等待時(shí)間是否足夠長(zhǎng)多塊板卡連測(cè)確認(rèn) loader 不會(huì)在反復(fù)擦寫后出現(xiàn)內(nèi)存泄漏Open Flash Loader 的 ELF 文件在 Flasher 上的兼容性一般不會(huì)有問(wèn)題但我見(jiàn)過(guò)有些 loader 依賴了 C 庫(kù)的初始化邏輯這類 loader 在 J-Link 上跑得挺好放到 Flasher 上反而會(huì)死機(jī)因?yàn)?Flasher 的 loader 加載環(huán)境更裸。所以產(chǎn)線用 loader 寫完之后一定要在 Flasher 上單獨(dú)驗(yàn)證。5. 高頻問(wèn)題與排查實(shí)錄5.1 J-Link 點(diǎn)位到底怎么確認(rèn)網(wǎng)上搜j-link 點(diǎn)位的人大多數(shù)是剛接觸 J-Link 的新手想知道 JLINK 探針上的引腳定義和接線方法。J-Link 最常見(jiàn)的物理接口有兩種20-pin JTAG 接口和 10-pin 的 SWD 排針。20-pin 接口里做 SWD 接線只需要關(guān)注這幾根信號(hào)引腳名稱方向說(shuō)明VTref輸入J-Link 檢測(cè)目標(biāo)板電壓用于電平匹配GND-地線SWDIO雙向數(shù)據(jù)線對(duì)應(yīng) TMSSWCLK輸出時(shí)鐘線對(duì)應(yīng) TCKRESET輸出復(fù)位信號(hào)可接可不接接線口訣其實(shí)就一句VTref 接目標(biāo)板 3.3VSWDIO 接 SWDIOSWCLK 接 SWCLKGND 共地。很多連接不上問(wèn)題出在沒(méi)接 VTref導(dǎo)致 J-Link 不知道目標(biāo)電壓是多少電平匹配不工作。如果你用的是 10-pin 排針定義跟 20-pin 是兼容的只是去掉了大部分不用的 JTAG 信號(hào)。接好之后先用 J-Link Commander 驗(yàn)證JLink.exe命令提示符出現(xiàn)后輸入connect再選設(shè)備類型和接口如果能看到Static RAM Base Address: 0x20000000之類的信息說(shuō)明連接正常。常見(jiàn)錯(cuò)誤Cannot connect to target或No target connected第一反應(yīng)查接線第二反應(yīng)查目標(biāo)板供電第三反應(yīng)降低 SWD 速度試試比如從 4000kHz 降到 1000kHz。5.2 S32DS 啟動(dòng) GDB Server 超時(shí)的排查思路S32DS error in services launch sequence starting j-link gdb server timed out這個(gè)問(wèn)題主要出現(xiàn)在 NXP S32 Design StudioS32DS里用 J-Link 調(diào)試時(shí)Eclipse 生態(tài)的調(diào)試插件要啟動(dòng)一個(gè) J-Link GDB Server 進(jìn)程然后通過(guò) TCP 端口轉(zhuǎn)發(fā) GDB 和 J-Link 之間的通信。如果這個(gè)啟動(dòng)過(guò)程在限定的超時(shí)時(shí)間內(nèi)沒(méi)有完成就會(huì)報(bào)這個(gè)錯(cuò)。這個(gè)報(bào)錯(cuò)可以說(shuō)有四個(gè)最常見(jiàn)的誘因第一個(gè)是端口被占用。J-Link GDB Server 默認(rèn)監(jiān)聽(tīng)的是 2331 端口有的版本是 2332。如果你之前跑過(guò) JLinkGDBServer 或者別的調(diào)試會(huì)話沒(méi)有正常退出端口就還占著。檢查辦法netstat -ano | findstr 2331看到有 LISTENING 記錄直接到任務(wù)管理器里把對(duì)應(yīng) PID 的進(jìn)程結(jié)束掉。第二個(gè)是 J-Link 驅(qū)動(dòng)版本和 S32DS 自帶的 GDB Server 版本不匹配。S32DS 內(nèi)置的調(diào)試插件會(huì)調(diào)用它自己認(rèn)識(shí)的 JLinkGDBServer 版本如果你電腦上安裝了新版本的 J-Link 軟件插件卻還在找舊的執(zhí)行文件就容易發(fā)生啟動(dòng)失敗。這種情況去 S32DS 的調(diào)試配置里手動(dòng)指定 GDB Server 的可執(zhí)行文件路徑讓它指向當(dāng)前 J-Link 安裝目錄里的JLinkGDBServerCLExe.exe就能解決。第三個(gè)是接口參數(shù)不對(duì)。調(diào)試配置里如果選擇了 SWD但目標(biāo)板實(shí)際只接了 JTAG或者反過(guò)來(lái)GDB Server 啟動(dòng)時(shí)會(huì)卡在建立連接階段直到超時(shí)。檢查Debugger配置頁(yè)里的 Interface 設(shè)置確保跟實(shí)際接線一致。第四個(gè)是目標(biāo)板沒(méi)上電或復(fù)位電路有問(wèn)題。GDB Server 啟動(dòng)時(shí)會(huì)對(duì)目標(biāo)做一次連接檢測(cè)如果芯片沒(méi)反應(yīng)它不會(huì)立刻報(bào)錯(cuò)而是等超時(shí)。從 S32DS 的 Console 視圖里拉出 J-Link GDB Server 的完整日志看看連接階段的最后一句輸出是什么基本就能定位到哪一步卡住。我當(dāng)時(shí)排查這個(gè)問(wèn)題的順序是先 netstat 看端口再檢查 J-Link 驅(qū)動(dòng)版本然后用 J-Link Commander 單獨(dú)驗(yàn)證連接最后回到 S32DS 重新指定 GDB Server 路徑。整個(gè)流程十分鐘左右就能定位問(wèn)題。5.3 常見(jiàn)問(wèn)題速查表問(wèn)題現(xiàn)象可能原因解決方案J-Link 報(bào) Cannot connect to targetSWD 接線錯(cuò)誤VTref 接電壓、SWDIO/SWCLK 不可接反連接成功但 loadbin 失敗WorkRAMAddr 配置錯(cuò)誤改為目標(biāo)芯片空閑 RAM 區(qū)域燒錄時(shí) loader 加載失敗ELF 路徑錯(cuò)誤相對(duì)路徑在 XML 里寫相對(duì)于 J-Link 安裝目錄的路徑S32DS 啟動(dòng) GDB Server 超時(shí)端口 2331 被占用netstat 找 PID 并結(jié)束進(jìn)程Open Flash Loader 燒錄性能差ProgramPage 未做緩沖寫入按 Flash 頁(yè)大小整頁(yè)寫入避免逐字節(jié)寫Flasher 連接不上目標(biāo)板排線過(guò)長(zhǎng)、信號(hào)質(zhì)量差縮短線纜長(zhǎng)度降低速度檢查連接器焊接J-Trace 燒錄后 trace 異常loader RAM 與 trace buffer 沖突為 loader 單獨(dú)分配 RAM5.4 幾條個(gè)人經(jīng)驗(yàn)最后分享幾條我在實(shí)際項(xiàng)目中攢下來(lái)的經(jīng)驗(yàn)這些細(xì)節(jié)通常文檔里不會(huì)寫。第一Open Flash Loader 的 ELF 文件編譯時(shí)盡量關(guān)掉重定位選項(xiàng)讓代碼加載到固定地址。有些編譯器默認(rèn)生成位置無(wú)關(guān)代碼J-Link 加載起來(lái)雖然也能跑但在特定芯片上偶爾會(huì)有詭異問(wèn)題比如擦除到一半死機(jī)。固定地址編譯更像傳統(tǒng) MCU 固件行為可預(yù)期得多。第二loader 里的 Init 函數(shù)不要只配 Flash 控制器還要把 CPU 的時(shí)鐘、總線等待狀態(tài)一起考慮進(jìn)去。很多芯片 Flash 讀取有 wait state 要求loader 運(yùn)行在 RAM 上不涉及 Flash 讀但 ProgramPage 時(shí) Flash 控制器需要穩(wěn)定的時(shí)鐘如果你沒(méi)初始化好時(shí)鐘源寫入極不穩(wěn)定。最保險(xiǎn)的做法是在 Init 里顯式配置 Flash 編程所需的時(shí)鐘頻率。第三一定要保留 loader 源碼的版本管理。我見(jiàn)過(guò)有團(tuán)隊(duì)直接拿原廠給的 ELF 文件用結(jié)果芯片出了新版底層 Flash 指令時(shí)序變了原廠 ELF 不對(duì)又找不到當(dāng)初編譯的源碼只能重新逆向非常痛苦。從一開始就把 FlashLoader 工程納入 Git每次出板子版本都重建 loader產(chǎn)線燒錄的 ELF 文件和固件版本捆綁記錄能省掉很多后續(xù)麻煩。Open Flash Loader 這套體系讓我最滿意的一點(diǎn)就是它的開放性和可遷移性不管你是用 J-Link 做開發(fā)調(diào)試還是用 J-Trace 做深度跟蹤分析或者用 Flasher 做產(chǎn)線量產(chǎn)同一個(gè) loader 文件從頭用到底。配好第一個(gè)不支持的芯片之后后面再遇到任何冷門型號(hào)心里就有底了無(wú)非是拿手冊(cè)、寫 Flash 驅(qū)動(dòng)、編譯、驗(yàn)證這套流程走一遍。