發(fā)燒錄調(diào)試全鏈路:從SWD到量產(chǎn)方案實(shí)戰(zhàn)指南)
嵌入式開(kāi)發(fā)這行干久了你會(huì)發(fā)現(xiàn)一個(gè)很有意思的現(xiàn)象寫(xiě)代碼的時(shí)間可能只占整個(gè)項(xiàng)目周期的三成剩下七成全耗在怎么把代碼弄進(jìn)板子里和弄進(jìn)去之后為什么不跑這兩件事上。尤其是剛?cè)胄械念^一兩年編譯通過(guò)那一刻的喜悅往往會(huì)被燒錄失敗的紅色報(bào)錯(cuò)瞬間澆滅。我見(jiàn)過(guò)太多人卡在Keil里編譯零錯(cuò)誤零警告點(diǎn)下載就是連不上目標(biāo)這種問(wèn)題上一卡就是一整天最后發(fā)現(xiàn)是調(diào)試器驅(qū)動(dòng)沒(méi)裝對(duì)或者復(fù)位模式選錯(cuò)了。這篇內(nèi)容我想把嵌入式開(kāi)發(fā)里燒錄、下載、仿真、調(diào)試這條鏈路徹底講透。不管你是剛拿到第一塊STM32開(kāi)發(fā)板的新手還是已經(jīng)用過(guò)J-Link、ST-Link、串口ISP多種方式的老手我都會(huì)從工具選型、接口原理、實(shí)操步驟、常見(jiàn)故障排查幾個(gè)維度展開(kāi)把那些文檔里不會(huì)寫(xiě)、但實(shí)際項(xiàng)目中一定會(huì)遇到的坑一個(gè)個(gè)拆開(kāi)講。核心關(guān)鍵詞就四個(gè)嵌入式軟件開(kāi)發(fā)、燒錄、仿真調(diào)試、工具。讀完你至少能搞清楚為什么有的板子用ST-Link能燒、用J-Link就不行為什么串口燒錄有時(shí)候要按住BOOT0有時(shí)候不用為什么仿真器能連上但一燒錄就報(bào)Flash Download failed。1. 燒錄這件事本質(zhì)上是三條物理鏈路在打架很多人把燒錄當(dāng)成一個(gè)動(dòng)作其實(shí)它背后至少涉及三條不同的物理鏈路搞清楚這三條鏈路的區(qū)別后面80%的故障你都能自己定位。1.1 調(diào)試接口鏈路SWD和JTAG到底差在哪SWDSerial Wire Debug和JTAG是ARM Cortex-M系列最常用的兩種調(diào)試接口。JTAG歷史更久標(biāo)準(zhǔn)是5根線(xiàn)TCK、TMS、TDI、TDO、TRST后來(lái)ARM把它精簡(jiǎn)成了SWD只用兩根線(xiàn)SWCLK和SWDIO就能實(shí)現(xiàn)同樣的調(diào)試和燒錄功能。為什么現(xiàn)在絕大多數(shù)項(xiàng)目都用SWD原因很直接引腳少。一個(gè)48腳的MCUJTAG占掉5個(gè)引腳SWD只占2個(gè)省下來(lái)的引腳可以拿去做GPIO或者接外設(shè)。而且SWD在高速下比JTAG更穩(wěn)定布線(xiàn)也簡(jiǎn)單兩根線(xiàn)走等長(zhǎng)就行。但SWD有個(gè)坑它和JTAG共用引腳。如果你在代碼里把SWCLK和SWDIO配置成了普通GPIO或者初始化成了其他復(fù)用功能那下次燒錄時(shí)調(diào)試器就找不到芯片了。這種情況我遇到過(guò)不止一次尤其是新手在寫(xiě)GPIO初始化的時(shí)候一不小心把PA13和PA14STM32的SWD引腳給重映射了結(jié)果就是芯片被鎖死只能用串口ISP或者BOOT0拉高的方式救回來(lái)。提示寫(xiě)GPIO初始化代碼時(shí)永遠(yuǎn)不要?jiǎng)覲A13SWDIO和PA14SWCLK除非你確定這個(gè)項(xiàng)目不再需要SWD調(diào)試。1.2 串口ISP鏈路為什么有時(shí)候要按住BOOT0串口ISPIn-System Programming是另一種常見(jiàn)的燒錄方式尤其在沒(méi)有調(diào)試器的情況下。它的原理是MCU內(nèi)部有一段出廠(chǎng)固化的Bootloader上電時(shí)會(huì)檢測(cè)BOOT0引腳的電平如果BOOT0為高電平就從系統(tǒng)存儲(chǔ)器啟動(dòng)執(zhí)行那段Bootloader等待串口發(fā)送固件數(shù)據(jù)。這就是為什么很多教程讓你按住BOOT0再按復(fù)位——目的是讓MCU進(jìn)入Bootloader模式。但有些板子不用按也能燒原因是它的BOOT0引腳通過(guò)電阻默認(rèn)拉高了或者電路設(shè)計(jì)上做了自動(dòng)控制。串口ISP的波特率選擇也有講究。STM32的出廠(chǎng)Bootloader對(duì)波特率容忍度比較高但也不是隨便設(shè)。我實(shí)測(cè)下來(lái)115200是最穩(wěn)的再高比如460800或者921600有些型號(hào)的Bootloader會(huì)丟包。如果你用的是CH340或者CP2102這類(lèi)USB轉(zhuǎn)串口芯片還要注意驅(qū)動(dòng)版本老版本驅(qū)動(dòng)在Win10/Win11上會(huì)出現(xiàn)串口打開(kāi)失敗或者燒錄到一半卡死的問(wèn)題。1.3 USB DFU鏈路被低估的燒錄方式USB DFUDevice Firmware Upgrade是STM32另一條燒錄路徑通過(guò)USB接口直接燒錄不需要額外的調(diào)試器。它的優(yōu)勢(shì)是速度快USB全速模式下能到1MB/s以上比串口ISP快得多。但缺點(diǎn)是進(jìn)入DFU模式的條件比較苛刻通常需要BOOT0拉高并且USB線(xiàn)接在特定的USB口上。DFU燒錄工具推薦用STM32CubeProgrammer它同時(shí)支持SWD、串口ISP、USB DFU、OTA等多種方式界面統(tǒng)一比早期的Flash Loader Demonstrator好用太多。而且它跨平臺(tái)Windows、Linux、macOS都能跑。燒錄方式所需硬件典型速度適用場(chǎng)景SWDST-Link/J-Link/DAPLink50-200KB/s日常開(kāi)發(fā)調(diào)試JTAGJ-Link/專(zhuān)用仿真器50-150KB/s多核調(diào)試、老芯片串口ISPUSB轉(zhuǎn)串口模塊10-50KB/s無(wú)調(diào)試器、量產(chǎn)USB DFUUSB線(xiàn)500KB-1MB/s快速燒錄、現(xiàn)場(chǎng)升級(jí)OTA無(wú)線(xiàn)模塊取決于網(wǎng)絡(luò)遠(yuǎn)程升級(jí)、已部署設(shè)備2. 調(diào)試器選型ST-Link、J-Link、DAPLink的真實(shí)差距調(diào)試器這東西便宜的十幾塊貴的上千塊差距到底在哪我用過(guò)市面上主流的幾種說(shuō)說(shuō)實(shí)際感受。2.1 ST-LinkSTM32開(kāi)發(fā)者的默認(rèn)選擇ST-Link是ST官方出的調(diào)試器原廠(chǎng)版本價(jià)格在100-200元之間淘寶上的山寨版只要20-30塊。山寨版能用嗎能用但有幾個(gè)問(wèn)題一是固件版本老不支持新出的STM32型號(hào)二是沒(méi)有隔離保護(hù)熱插拔容易燒三是SWD時(shí)序有偏差長(zhǎng)排線(xiàn)時(shí)容易連不上。原廠(chǎng)ST-Link V3有個(gè)很實(shí)用的功能虛擬串口。它把調(diào)試和串口二合一一根USB線(xiàn)搞定燒錄和串口打印桌面能清爽不少。V3還支持更高的SWD時(shí)鐘頻率燒大固件時(shí)能明顯感覺(jué)到速度差異。ST-Link的驅(qū)動(dòng)安裝是個(gè)老生常談的問(wèn)題。Windows 10之后系統(tǒng)會(huì)自動(dòng)裝一個(gè)通用驅(qū)動(dòng)但這個(gè)驅(qū)動(dòng)有時(shí)候和Keil、IAR配合不好表現(xiàn)為設(shè)備管理器里能看到ST-Link但I(xiàn)DE里就是連不上。解決辦法是手動(dòng)安裝ST官方驅(qū)動(dòng)或者用STM32CubeProgrammer先連一次它會(huì)自動(dòng)修復(fù)驅(qū)動(dòng)。2.2 J-Link貴有貴的道理J-Link是SEGGER出的原廠(chǎng)版本從幾百到幾千不等。它的優(yōu)勢(shì)在于支持芯片型號(hào)極多幾乎涵蓋所有ARM內(nèi)核MCU、燒錄速度快、固件更新勤、配套軟件J-Flash功能強(qiáng)大。J-Link有個(gè)OB版本On-Board是集成在開(kāi)發(fā)板上的簡(jiǎn)化版功能受限不能調(diào)試非授權(quán)芯片。如果你買(mǎi)的是淘寶上的J-Link OB要注意它可能只支持特定廠(chǎng)商的芯片換個(gè)品牌的板子就用不了。J-Link最讓我滿(mǎn)意的是它的RTTReal Time Transfer功能。傳統(tǒng)調(diào)試要看變量得停下來(lái)設(shè)斷點(diǎn)RTT可以在不中斷程序運(yùn)行的情況下打印日志速度比串口快幾個(gè)數(shù)量級(jí)。對(duì)于調(diào)試時(shí)序敏感的代碼這個(gè)功能簡(jiǎn)直是救命稻草。2.3 DAPLink開(kāi)源方案里的性?xún)r(jià)比之王DAPLink是ARM官方開(kāi)源的項(xiàng)目國(guó)內(nèi)很多開(kāi)發(fā)板比如正點(diǎn)原子、野火板載的調(diào)試器就是基于DAPLink做的。它的優(yōu)點(diǎn)是開(kāi)源、便宜、支持拖拽燒錄把固件拖到虛擬U盤(pán)里就完成燒錄。拖拽燒錄這個(gè)功能對(duì)新手特別友好不需要裝任何IDE把hex文件拖進(jìn)去就行。但缺點(diǎn)是速度慢而且不支持復(fù)雜的調(diào)試功能比如實(shí)時(shí)變量監(jiān)控、斷點(diǎn)條件設(shè)置等。DAPLink還有個(gè)隱藏問(wèn)題不同廠(chǎng)商的DAPLink固件版本差異很大有的支持SWD串口U盤(pán)三合一有的只有SWD。買(mǎi)之前一定要看清楚說(shuō)明。注意無(wú)論用哪種調(diào)試器SWDIO和SWCLK的排線(xiàn)盡量短最好在10cm以?xún)?nèi)。排線(xiàn)過(guò)長(zhǎng)會(huì)導(dǎo)致信號(hào)反射表現(xiàn)為有時(shí)能連上有時(shí)連不上這種間歇性故障最難排查。3. Keil環(huán)境下燒錄失敗的完整排查鏈路Keil里編譯成功卻怎么也燒錄不進(jìn)開(kāi)發(fā)板——這個(gè)問(wèn)題在搜索引擎里的搜索量常年居高不下。我把自己踩過(guò)的坑和幫別人排查的經(jīng)驗(yàn)整理成一條完整的排查鏈路按順序走一遍基本能覆蓋95%的情況。3.1 第一步確認(rèn)調(diào)試器本身是否被識(shí)別打開(kāi)設(shè)備管理器看調(diào)試器有沒(méi)有出現(xiàn)在通用串行總線(xiàn)設(shè)備或者端口下面。如果出現(xiàn)黃色感嘆號(hào)說(shuō)明驅(qū)動(dòng)有問(wèn)題。ST-Link需要裝ST-Link USB driverJ-Link需要裝J-Link driverDAPLink通常是免驅(qū)的HID設(shè)備。如果設(shè)備管理器里根本看不到調(diào)試器先換一根USB線(xiàn)。我遇到過(guò)好幾次問(wèn)題出在USB線(xiàn)只供電不傳數(shù)據(jù)。特別是那種很細(xì)的充電線(xiàn)十有八九沒(méi)有數(shù)據(jù)線(xiàn)芯。3.2 第二步確認(rèn)Keil里的調(diào)試器配置打開(kāi)Options for Target - Debug確認(rèn)選的是正確的調(diào)試器。這里有個(gè)容易忽略的點(diǎn)Keil里選的是ST-Link Debugger但旁邊的Settings里還要再選一次具體的調(diào)試器型號(hào)和接口SWD還是JTAG。我見(jiàn)過(guò)有人Debug頁(yè)選對(duì)了但Settings里Port選的是JTAG而板子上只接了SWD線(xiàn)自然連不上。Settings里的Reset選項(xiàng)也很關(guān)鍵。默認(rèn)是Normal但有些板子需要改成Connect under Reset才能連上。什么時(shí)候需要改當(dāng)你的代碼一上電就把SWD引腳復(fù)用成其他功能時(shí)調(diào)試器還沒(méi)來(lái)得及連接引腳就被搶走了。這時(shí)候用Connect under Reset調(diào)試器會(huì)先拉住復(fù)位在芯片啟動(dòng)前搶占SWD引腳。3.3 第三步檢查Flash Download配置Options for Target - Utilities - Settings這里要確認(rèn)兩件事一是Programming Algorithm里有沒(méi)有添加對(duì)應(yīng)芯片型號(hào)的Flash算法二是RAM for Algorithm的大小夠不夠。Flash算法不對(duì)是最常見(jiàn)的燒錄失敗原因之一。比如你用的是STM32F103C8T6但算法里選的是STM32F103RC的地址范圍對(duì)不上燒錄就會(huì)報(bào)Flash Download failed。Keil的算法列表里型號(hào)很多選的時(shí)候要看清楚Flash大小和頁(yè)大小。RAM for Algorithm默認(rèn)是0x10004KB對(duì)于大多數(shù)芯片夠用。但有些芯片的Flash算法需要更多RAM比如STM32H7系列可能需要改成0x2000甚至更大。如果這個(gè)值設(shè)小了燒錄時(shí)會(huì)報(bào)Algorithm RAM overflow。3.4 第四步排查芯片讀寫(xiě)保護(hù)如果前面三步都沒(méi)問(wèn)題但燒錄還是失敗很可能是芯片被讀了保護(hù)或者寫(xiě)了保護(hù)。STM32的讀保護(hù)RDP一旦開(kāi)啟調(diào)試器就無(wú)法通過(guò)SWD讀取Flash內(nèi)容燒錄也會(huì)被拒絕。解除讀保護(hù)的方法用STM32CubeProgrammer連接芯片在Option Bytes里把RDP等級(jí)改回Level 0。注意這個(gè)操作會(huì)全片擦除芯片里的程序會(huì)丟失。寫(xiě)保護(hù)WRP則是保護(hù)特定扇區(qū)不被寫(xiě)入同樣在Option Bytes里解除。還有一種情況是芯片進(jìn)入了死鎖狀態(tài)SWD完全無(wú)響應(yīng)。這時(shí)候可以嘗試用BOOT0拉高的方式從系統(tǒng)存儲(chǔ)器啟動(dòng)然后用串口ISP或者CubeProgrammer擦除芯片恢復(fù)SWD功能。故障現(xiàn)象可能原因排查方法設(shè)備管理器無(wú)調(diào)試器USB線(xiàn)、驅(qū)動(dòng)換線(xiàn)、重裝驅(qū)動(dòng)IDE里連不上調(diào)試器端口配置、復(fù)位模式檢查SWD/JTAG選擇、改Connect under Reset能連上但燒錄失敗Flash算法、RAM大小核對(duì)芯片型號(hào)、增大RAM for Algorithm燒錄報(bào)讀寫(xiě)保護(hù)RDP/WRP開(kāi)啟CubeProgrammer解除保護(hù)間歇性連接失敗排線(xiàn)過(guò)長(zhǎng)、時(shí)鐘太快縮短排線(xiàn)、降低SWD時(shí)鐘4. 仿真調(diào)試斷點(diǎn)之外你還能做什么很多人用調(diào)試器就只會(huì)設(shè)斷點(diǎn)、單步執(zhí)行、看變量。其實(shí)仿真調(diào)試能做的事情遠(yuǎn)不止這些用好這些功能排查問(wèn)題的效率能提升好幾倍。4.1 實(shí)時(shí)變量監(jiān)控Watch窗口的正確用法Watch窗口可以添加全局變量和局部變量程序運(yùn)行時(shí)實(shí)時(shí)刷新。但有個(gè)限制如果變量被編譯器優(yōu)化掉了比如加了volatile但沒(méi)實(shí)際使用Watch窗口里會(huì)顯示cannot evaluate。解決辦法是把優(yōu)化等級(jí)調(diào)低或者在變量定義前加volatile關(guān)鍵字。對(duì)于結(jié)構(gòu)體變量Watch窗口支持展開(kāi)查看每個(gè)成員。如果結(jié)構(gòu)體指針指向的是動(dòng)態(tài)分配的內(nèi)存需要先確認(rèn)指針本身有效否則展開(kāi)會(huì)報(bào)錯(cuò)。4.2 邏輯分析儀功能SWO和ETMSWOSerial Wire Output是SWD接口的第三根線(xiàn)可選可以輸出printf調(diào)試信息不需要占用串口。配置方法是在Keil的Debug - Settings - Trace里使能Trace設(shè)置Core Clock頻率然后在代碼里重定向printf到ITM_SendChar。ETMEmbedded Trace Macrocell是更高級(jí)的指令級(jí)追蹤能記錄程序執(zhí)行的每一條指令但需要芯片支持且調(diào)試器有對(duì)應(yīng)引腳。J-Link的高端型號(hào)支持ETMST-Link不支持。SWO的波特率設(shè)置要和Core Clock匹配否則輸出的都是亂碼。一般來(lái)說(shuō)SWO時(shí)鐘是Core Clock的1/4或者1/2具體看芯片手冊(cè)。4.3 條件斷點(diǎn)和數(shù)據(jù)斷點(diǎn)條件斷點(diǎn)是指滿(mǎn)足特定條件時(shí)才觸發(fā)的斷點(diǎn)比如當(dāng)i等于100時(shí)停下。在Keil里右鍵斷點(diǎn) - Condition輸入條件表達(dá)式即可。這個(gè)功能在排查數(shù)組越界、循環(huán)異常時(shí)特別有用。數(shù)據(jù)斷點(diǎn)Data Watchpoint是指當(dāng)某個(gè)內(nèi)存地址被讀寫(xiě)時(shí)觸發(fā)斷點(diǎn)。比如你懷疑某個(gè)指針被意外修改了可以對(duì)這個(gè)指針變量設(shè)數(shù)據(jù)斷點(diǎn)一旦它被寫(xiě)入就停下來(lái)直接定位到修改它的代碼行。數(shù)據(jù)斷點(diǎn)的數(shù)量有限Cortex-M3/M4通常只支持2-4個(gè)用的時(shí)候要省著點(diǎn)。4.4 寄存器查看和修改Debug - View - Registers可以查看CPU寄存器和外設(shè)寄存器的當(dāng)前值。外設(shè)寄存器是按模塊分組的比如GPIOA、USART1、TIM2等展開(kāi)就能看到每個(gè)寄存器的每一位。這個(gè)功能在排查外設(shè)不工作時(shí)特別有用。比如串口發(fā)不出數(shù)據(jù)先看USART1的CR1寄存器TXE和TC位有沒(méi)有置起來(lái)如果TXE一直是0說(shuō)明發(fā)送數(shù)據(jù)寄存器滿(mǎn)了可能是波特率配置不對(duì)或者時(shí)鐘沒(méi)使能。寄存器不僅可以看還可以直接修改。比如你想臨時(shí)把某個(gè)GPIO拉高直接在寄存器窗口里改ODR對(duì)應(yīng)的位就行不用重新編譯燒錄。這個(gè)技巧在硬件調(diào)試階段非常實(shí)用。5. 那些年我踩過(guò)的燒錄坑有些問(wèn)題文檔里不會(huì)寫(xiě)教程里不會(huì)講只有真正踩過(guò)才知道。這一章我把自己和身邊同事遇到過(guò)的典型坑整理出來(lái)希望能幫你省下幾個(gè)通宵。5.1 國(guó)產(chǎn)替代芯片的燒錄兼容性問(wèn)題這兩年國(guó)產(chǎn)MCU越來(lái)越多很多是Pin-to-Pin兼容STM32的。但兼容歸兼容燒錄環(huán)節(jié)經(jīng)常出問(wèn)題。我遇到過(guò)一款國(guó)產(chǎn)芯片用ST-Link能識(shí)別ID但燒錄到一半就報(bào)錯(cuò)換J-Link就正常。后來(lái)查資料發(fā)現(xiàn)這款芯片的Flash編程時(shí)序和STM32有細(xì)微差異ST-Link的固件沒(méi)有適配。還有的國(guó)產(chǎn)芯片Keil的器件支持包DFP里沒(méi)有對(duì)應(yīng)的Flash算法需要手動(dòng)添加廠(chǎng)商提供的算法文件。這個(gè)文件通常在廠(chǎng)商的SDK包里文件名類(lèi)似xxx_FLASH.FLM把它復(fù)制到Keil的ARM/Flash目錄下然后在Utilities里手動(dòng)添加。提示用國(guó)產(chǎn)芯片時(shí)優(yōu)先用廠(chǎng)商推薦的調(diào)試器和燒錄工具。很多廠(chǎng)商有自己的IDE或者燒錄軟件雖然界面丑但兼容性最好。5.2 低功耗模式下的燒錄失敗如果你的代碼里進(jìn)了Stop模式或者Standby模式調(diào)試器可能連不上芯片。因?yàn)榈凸哪J较耂WD引腳可能被關(guān)閉或者時(shí)鐘被停掉了。解決辦法有兩個(gè)一是用Connect under Reset讓調(diào)試器在芯片進(jìn)入低功耗之前搶占二是在代碼里加一個(gè)延時(shí)上電后先等幾秒再進(jìn)低功耗給調(diào)試器留出連接窗口。Standby模式更麻煩退出Standby相當(dāng)于一次復(fù)位所有RAM內(nèi)容丟失調(diào)試器也會(huì)斷開(kāi)。調(diào)試Standby模式下的代碼通常只能靠串口打印或者GPIO翻轉(zhuǎn)來(lái)觀(guān)察狀態(tài)。5.3 多芯片共用一個(gè)調(diào)試器有些項(xiàng)目一塊板子上有兩顆MCU比如一顆主控加一顆協(xié)處理。如果兩顆芯片的SWD線(xiàn)并聯(lián)在一起調(diào)試器會(huì)同時(shí)看到兩個(gè)ID導(dǎo)致連接混亂。正確的做法是用跳線(xiàn)帽或者模擬開(kāi)關(guān)把SWD線(xiàn)分開(kāi)調(diào)試哪顆就接哪顆。或者用支持多核調(diào)試的J-Link它可以分別連接不同的核。還有一種情況是板子上有多個(gè)相同的芯片比如兩顆STM32F103。這時(shí)候即使SWD線(xiàn)分開(kāi)Keil里也要配置不同的調(diào)試目標(biāo)否則會(huì)燒錯(cuò)芯片。5.4 固件加密和讀保護(hù)的實(shí)際影響產(chǎn)品量產(chǎn)時(shí)通常會(huì)開(kāi)啟讀保護(hù)防止固件被抄。但讀保護(hù)開(kāi)啟后調(diào)試器就無(wú)法再燒錄了除非先解除保護(hù)。這就帶來(lái)一個(gè)生產(chǎn)流程上的問(wèn)題產(chǎn)線(xiàn)上燒錄完固件后開(kāi)啟讀保護(hù)后續(xù)如果發(fā)現(xiàn)bug需要返修就得先解除保護(hù)而解除保護(hù)會(huì)擦除整個(gè)Flash。所以產(chǎn)線(xiàn)通常的做法是燒錄和開(kāi)保護(hù)分兩步燒錄用一個(gè)工位開(kāi)保護(hù)用另一個(gè)工位?;蛘哂弥С譄涢_(kāi)保護(hù)一次完成的工具比如J-Flash的Production Programming功能。5.5 燒錄文件格式的選擇常見(jiàn)的固件格式有hex、bin、elf、s19等。hex和s19帶地址信息bin是純二進(jìn)制不帶地址。燒錄時(shí)如果選錯(cuò)了格式比如把bin當(dāng)hex燒會(huì)報(bào)格式錯(cuò)誤把hex當(dāng)bin燒會(huì)從0地址開(kāi)始燒但hex里可能有多個(gè)不連續(xù)的地址段導(dǎo)致燒錄不完整。elf文件帶調(diào)試信息通常用于仿真調(diào)試不適合直接燒錄。量產(chǎn)燒錄一般用hex或者binhex更通用bin更小。Motorola S-records19格式在一些老芯片或者汽車(chē)電子里還在用它的結(jié)構(gòu)和hex類(lèi)似都是文本格式帶地址和校驗(yàn)。解析s19的時(shí)候要注意它的地址長(zhǎng)度可能是2字節(jié)、3字節(jié)或4字節(jié)取決于記錄類(lèi)型S1、S2、S3。6. 從開(kāi)發(fā)到量產(chǎn)燒錄方案的演進(jìn)個(gè)人開(kāi)發(fā)和量產(chǎn)燒錄需求完全不同。個(gè)人開(kāi)發(fā)追求方便量產(chǎn)追求效率和一致性。這一章說(shuō)說(shuō)不同階段該怎么選燒錄方案。6.1 開(kāi)發(fā)階段調(diào)試器IDE開(kāi)發(fā)階段最方便的就是調(diào)試器直接連IDE點(diǎn)一下下載按鈕就完成。Keil、IAR、STM32CubeIDE都支持這種方式。這個(gè)階段不用太在意燒錄速度因?yàn)橐惶炜赡芤簿蜔龓资?。但要注意一點(diǎn)開(kāi)發(fā)階段最好把讀保護(hù)關(guān)掉否則每次燒錄都要先擦除浪費(fèi)時(shí)間。等產(chǎn)品定型了再開(kāi)保護(hù)。6.2 小批量試產(chǎn)脫機(jī)燒錄器小批量試產(chǎn)幾十到幾百片的時(shí)候用電腦調(diào)試器的方式就有點(diǎn)慢了。這時(shí)候可以用脫機(jī)燒錄器比如J-Link的脫機(jī)模式或者專(zhuān)門(mén)的量產(chǎn)燒錄器。脫機(jī)燒錄器的原理是先把固件存到燒錄器內(nèi)部然后燒錄器獨(dú)立完成燒錄不需要電腦。操作員只需要把燒錄器接到板子上按一下按鈕就行。這種方式速度快而且不容易出錯(cuò)。6.3 大批量量產(chǎn)離線(xiàn)燒錄機(jī)大批量量產(chǎn)幾千片以上通常用離線(xiàn)燒錄機(jī)可以同時(shí)燒錄多片自動(dòng)上下料。這種設(shè)備價(jià)格不菲但效率極高適合工廠(chǎng)產(chǎn)線(xiàn)。離線(xiàn)燒錄機(jī)的核心是燒錄算法和治具。治具要保證接觸可靠燒錄算法要保證速度和穩(wěn)定性。有些燒錄機(jī)還支持燒錄后自動(dòng)校驗(yàn)和打標(biāo)整個(gè)流程全自動(dòng)化。6.4 OTA升級(jí)已部署設(shè)備的更新方案產(chǎn)品已經(jīng)部署到現(xiàn)場(chǎng)了不可能再拆開(kāi)燒錄這時(shí)候就需要OTAOver-The-Air升級(jí)。OTA的原理是設(shè)備通過(guò)無(wú)線(xiàn)網(wǎng)絡(luò)下載新固件然后自己擦寫(xiě)Flash完成升級(jí)。OTA的關(guān)鍵是Bootloader的設(shè)計(jì)。Bootloader要能接收新固件、校驗(yàn)完整性、擦寫(xiě)Flash、跳轉(zhuǎn)到新程序。還要考慮升級(jí)失敗的回滾機(jī)制比如保留舊固件新固件校驗(yàn)失敗就回滾。OTA的固件包通常要加密和簽名防止被篡改。加密用AES簽名用RSA或者ECC具體看安全等級(jí)要求。階段燒錄方案單次耗時(shí)適用規(guī)模開(kāi)發(fā)調(diào)試器IDE5-30秒1-10片小批量脫機(jī)燒錄器10-60秒10-500片大批量離線(xiàn)燒錄機(jī)5-20秒/片500片以上現(xiàn)場(chǎng)升級(jí)OTA取決于網(wǎng)絡(luò)已部署設(shè)備7. 工具鏈之外的幾個(gè)實(shí)用技巧最后分享幾個(gè)和燒錄調(diào)試相關(guān)的小技巧都是實(shí)際項(xiàng)目中總結(jié)出來(lái)的不一定系統(tǒng)但都管用。7.1 用腳本自動(dòng)化燒錄流程如果你經(jīng)常需要燒錄同一個(gè)固件到多塊板子可以寫(xiě)個(gè)腳本自動(dòng)化。J-Link提供了命令行工具JLinkExe支持腳本文件。比如寫(xiě)一個(gè)燒錄腳本# JLink燒錄腳本示例 device STM32F103C8 si SWD speed 4000 connect erase loadfile firmware.hex verify reset go exit然后命令行執(zhí)行JLinkExe -CommanderScript flash.jlink就能自動(dòng)完成燒錄。STM32CubeProgrammer也支持命令行模式參數(shù)類(lèi)似。7.2 串口燒錄的自動(dòng)化串口ISP燒錄也可以用腳本自動(dòng)化。STM32CubeProgrammer的命令行版本支持串口模式STM32_Programmer_CLI -c portCOM3 br115200 -w firmware.bin 0x08000000 -v -g 0x08000000這條命令的意思是連接COM3波特率115200寫(xiě)firmware.bin到0x08000000地址校驗(yàn)然后從0x08000000開(kāi)始運(yùn)行。自動(dòng)化燒錄的好處是減少人為操作失誤而且可以集成到CI/CD流程里每次代碼提交后自動(dòng)燒錄測(cè)試。7.3 固件版本管理量產(chǎn)的時(shí)候固件版本管理很重要。建議在固件里嵌入版本號(hào)燒錄后可以通過(guò)串口或者調(diào)試接口讀出來(lái)。版本號(hào)可以放在Flash的固定地址比如0x0800FFF0燒錄腳本自動(dòng)寫(xiě)入。還有一種做法是用編譯時(shí)間作為版本號(hào)每次編譯自動(dòng)生成。這樣能保證每個(gè)固件都是唯一的方便追溯。7.4 調(diào)試引腳的復(fù)用與保護(hù)前面提過(guò)SWD引腳被復(fù)用會(huì)導(dǎo)致連不上芯片。除了代碼里注意硬件設(shè)計(jì)上也可以做保護(hù)。比如在SWDIO和SWCLK上各串一個(gè)100歐姆的電阻即使引腳被復(fù)用成推挽輸出調(diào)試器也能通過(guò)電阻強(qiáng)行拉回電平爭(zhēng)取到連接窗口。但這個(gè)電阻不能太大否則會(huì)影響SWD信號(hào)質(zhì)量。100歐姆是經(jīng)驗(yàn)值實(shí)測(cè)下來(lái)既能保護(hù)又不影響通信。7.5 備用燒錄方案產(chǎn)品設(shè)計(jì)時(shí)最好預(yù)留至少兩種燒錄方式。比如主用SWD備用串口ISP。這樣萬(wàn)一SWD引腳被鎖死還能用串口救回來(lái)。串口ISP只需要TX、RX、GND三根線(xiàn)占用引腳少硬件成本幾乎為零。如果連串口都沒(méi)預(yù)留那就只能靠BOOT0拉高USB DFU了。但DFU需要USB接口有些小設(shè)備可能沒(méi)有USB。所以最保險(xiǎn)的還是預(yù)留串口。嵌入式開(kāi)發(fā)里燒錄調(diào)試這塊說(shuō)復(fù)雜也復(fù)雜說(shuō)簡(jiǎn)單也簡(jiǎn)單。核心就是搞清楚三條鏈路SWD、串口ISP、USB DFU的原理選對(duì)工具配好參數(shù)剩下的就是遇到問(wèn)題按排查鏈路一步步走。我個(gè)人的經(jīng)驗(yàn)是90%的燒錄問(wèn)題都出在三個(gè)地方驅(qū)動(dòng)沒(méi)裝對(duì)、Flash算法選錯(cuò)了、SWD引腳被復(fù)用了。把這三個(gè)點(diǎn)記住能省下大量折騰的時(shí)間。