2026/9/29 9:30:53

ST-Link烧写全链路避坑:从SWD接线到选项字节排障

ST-Link烧写全链路避坑:从SWD接线到选项字节排障 每次在群里看到有人贴出 No target connected 或者 Can not connect to target! 的截图我基本能猜到问题出在哪要么是 SWDIO 和 SWCLK 接反了要么是驱动装了个来路不明的版本要么是板子上的程序一上电就把 SWD 引脚复用成了普通 GPIO。ST-Link 烧写这件事说起来是嵌入式里最基础的一环但真正上手时踩的坑一点都不少——尤其是从买板子送的那个蓝色小 U 盘式调试器开始到用 STM32 ST-LINK Utility 或者 STM32CubeProgrammer 把固件写进 Flash中间任何一环出问题表现都是同一句话连不上。这篇东西不讲虚的就把 ST-Link 烧写这条链路从头到尾捋一遍硬件版本怎么选、STSW-LINK007 驱动怎么装干净、SWD 接线为什么是那四根、.hex 和 .bin 到底差在哪、选项字节动了会有什么后果、被读保护锁住之后怎么救、常见报错怎么一项项排查。写的都是我自己在小批量和样板调试时反复验证过的做法新手照着走能少绕半天路做过几年的人也可以在排障那部分找找对照。前提是你手上有一块 STM32 目标板、一个 ST-Link 调试器以及一台 Windows 电脑。1. 先搞清楚手里的 ST-Link 到底是哪一代1.1 V2、V2-1、V3 的差别不只是价格市面上能买到的 ST-Link 大致分三类。第一类是独立盒装的 ST-Link V2也就是那个蓝色塑料壳、一头 USB 一头 20 针 JTAG 座、或者简化成 10 根杜邦线引出的小板子几十块钱绝大多数个人玩家用的就是这个。第二类是板载的 V2-1比如 Nucleo 开发板上把调试器直接做进板子还额外带一个虚拟串口VCP和一个可拖拽烧写的 U 盘盘符把 .bin 文件直接拖进去就能烧非常方便。第三类是 ST-Link V3SET / V3MINI这是官方后来推的正代产品下载速度比 V2 快一个量级支持 SWO 高速跟踪还支持 1.65V 到 3.6V 的宽电压目标。选哪一代看你要干什么。只是偶尔烧烧自制小板子V2 足够了要做实时变量跟踪、性能分析、或者目标板跑 1.8V 电平就得考虑 V3。这里有一条血泪经验市面上大量的 V2 克隆版固件是不能随便在线升级的。有些工具检测到调试器固件版本旧会提示你升级一点确认运气不好就直接变砖——USB 能认出设备但连不上目标。克隆版的原则就是能用就别动它除非你手上有 ST 官方的正品或者确认该克隆版有可回滚的固件方案。我自己手上有个克隆 V2 用了六年从来没升过级一直很稳。1.2 为什么实战里几乎只用 SWD 而不用 JTAGST-Link 同时支持 JTAG 和 SWD 两套协议。JTAG 需要 TDI、TDO、TMS、TCK 四根信号线加上电源和地至少六根还要考虑 nTRSTSWD 只要 SWCLK、SWDIO 两根信号线加上 GND 和可选的目标 VREF、nRESET四根就能跑起来。物理连线少意味着排针小、走线短、干扰源少这在双层板甚至单面板上差距很明显。更关键的一点是引脚复用。STM32 的 JTAG 引脚PA13/PA14/PA15/PB3/PB4在复位后默认处于调试功能但程序里一旦把 GPIO 重映射打开JTAG 那几根就被抢走了而 SWD 的两根PA13 是 SWDIO、PA14 是 SWCLK在绝大多数配置下会保留。所以程序跑起来之后还想连SWD 的成功率高得多。JTAG 的优势在多器件菊花链和边界扫描测试做产线 ICT 或者多芯片联合调试才用得上日常开发没必要给自己加这个负担。1.3 ST-Link 能写的东西远比固件多很多人以为烧写就是把 .hex 写进主 Flash其实 ST-Link 通过调试口能碰到的区域有好几块主 Flash 存储区、选项字节区Option Bytes、OTP 区、备份寄存器以及通过外部加载算法去操作 SPI Flash 里的内容。主 Flash 是最常见的选项字节是最危险的因为里面装着读保护等级、写保护扇区、硬件看门狗配置、BOR 复位阈值、BOOT 相关配置改错一项就可能让芯片表现为烧进去了但不跑或者以后再也连不上。理解了这个分层后面的顺序就顺了先把连接打通再选对地址写数据最后才去动选项字节。反过来先动选项字节很容易把自己关在门外。2. 驱动和上位机工具一次配干净之后不用管2.1 STSW-LINK007 驱动装完应该看到什么STSW-LINK007 是 ST 官方的 ST-Link 驱动包装完之后在 Windows 设备管理器里应该能看到两个东西一个是 STMicroelectronics STLink dongle 或者 STLink USB Device另一个是 STLink Virtual COM Port后者只有 V2-1 及以后、或者支持虚拟串口的型号才有。如果只看到一个未知设备带黄色感叹号说明驱动没匹配上。Windows 10 之后的系统有一类很常见的坑系统自动把 ST-Link 认成了一个 WinUSB 设备设备管理器里看着正常但 ST-LINK Utility 打开后提示找不到设备。处理办法是在设备管理器里右键那个设备选择更新驱动手动浏览到驱动包目录指定安装或者在属性里确认设备类是不是 ST 自己的。装驱动时还有个小细节USB 线一定要用带数据线的市面上大量长得一模一样的线其实是纯充电线。我遇到过不下三次驱动装了三遍都没用最后换根线就好了。判断方法很简单换一个已知能用的 U 盘插同一根线如果不识别就是线的问题。2.2 STM32 ST-LINK Utility 和 STM32CubeProgrammer 该选哪个这两个都是 ST 官方上位机。STM32 ST-LINK Utility 是老工具免费、界面简陋但响应极快功能停在 v4.6 左右不再更新对 Win10 更新到某些版本之后的兼容性会打折扣。STM32CubeProgrammer 是现在的官方主推跨平台支持 ST-Link 和 UART 和 USB DFU 多种连接方式支持外部加载器CLI 脚本化能力也完整。我的建议是按场景分单板子点鼠标烧一两次Utility 更快更直接要做批量、要自动化、要跑在 CI 上、要用外部 Flash 算法直接上 CubeProgrammer 的 CLI。需要注意一点两个工具对驱动的态度不完全一样先装驱动包再装工具顺序别反否则工具可能装一套自己的驱动覆盖掉前面的导致另一个工具又找不到设备。如果两个都要装装完之后分别验证一次能不能连上目标出问题就回设备管理器手动指定驱动。2.3 Keil 和 IAR 里调用 ST-Link 的配置要点在 Keil MDK 里路径是 Options for Target → Debug → 选 ST-Link Debugger → 点 Settings。里面几个地方必须确认Connection 选 SW能读到 Device ID 说明物理链路通了Flash Download 选项卡里要勾上 Reset and Run烧完自动复位运行Programming Algorithm 里必须加对芯片对应的 Flash 算法。举例说 STM32F103C8 是 64K 的算法STM32F103ZE 选大容量 512K 的算法选错会直接报 Flash Download failed。还有一个很多人忽略的选项是 Verify Code Download勾上之后烧完会回读校验能提前发现供电不稳导致的写入错误。IAR 路径类似在 Project → Options → Debugger 里选 ST-LINKDownload 选项卡里勾 Verify download 和 Use flash loader。经验上Keil 的下载算法选择错误是初学者最高频的烧写失败来源之一而它跟硬件一点关系都没有。3. 接线与上电九成的连不上出在这一步3.1 SWD 四根线怎么接最小系统是什么样最小可用的 SWD 接线是四根调试器的 GND 接目标板 GNDSWDIO 接目标的 SWDIO一般是 PA13SWCLK 接目标的 SWCLK一般是 PA14然后是目标参考电压 VREF或者在调试器侧选 3.3V 输出给板子供电。加上 nRESET 就是五根强烈建议把这根也接上后面讲原因。这里必须提醒一件事V2 小板子上经常有一组丝印标着 SWIM 的引脚那是给 STM8 系列用的单线调试口不是 SWD。STM32 用 SWD接错引脚的表现是彻底连不上。另外 SWDIO 是双向的调试器侧和目标侧要有适当的上下拉很多自制板子省掉了这个电阻短线情况下没事线一长就开始随机丢包。如果你自己画板子SWDIO 加 10K 上拉到 3.3V、SWCLK 加 10K 下拉到地成本几分钱能省很多调试时间。3.2 供电、BOOT 引脚和复位三个最容易搞错的状态供电是第一个要理清的。ST-Link V2 的那一路 3.3V 输出电流能力很有限通常只有一百毫安左右接个空板子没问题接上带 WiFi 模块、继电器或者一堆 LED 的板子就会供电跌落表现出来就是能识别芯片但一烧就失败或者偶尔成功偶尔失败。我的习惯是目标板自己供电调试器只接 GND、SWDIO、SWCLK 和 nRESETVREF 那根用来做电平参考不拿来供电。这样既避免了电流不够也避免了调试器和板子上两个电源打架。BOOT 引脚是第二个。BOOT0 拉低从主 Flash 启动这是正常运行状态。如果 BOOT0 悬空、被上拉芯片可能跑到系统存储器里的出厂引导程序去你的程序根本没执行看着像烧写成功但不运行。用万用表量一下 BOOT0 对地的电压比看原理图靠谱因为虚焊和漏焊是常有的事。第三个是复位。STM32 的 NRST 引脚上一般挂一个 100nF 电容到地这个电容在调试器驱动复位的时候会形成一段 RC 延时太大或者质量差的电容会让调试器认为复位一直没释放从而连不上。遇到过一块板子死活连不上最后发现是 NRST 上并了个 10uF 的电容换成 100nF 立马就好了。3.3 线长和时钟频率一个必须会调的旋钮SWD 是同步串行接口时钟由调试器输出。CubeProgrammer 里默认频率是 4000kHzST-LINK Utility 里也有目标设置里的频率选项。线越长、干扰越大、目标板供电越弱高速就越容易出错。手边一根三十厘米的杜邦线跑 4MHz出现 No target connected 或者校验失败的几率非常高。处理办法就是把频率往下调先降到 1000kHz还不行就 500kHz一般都能连上。定位到问题之后如果是线的问题换短一点的线再往上调。我在自制的测试夹具上最常用的是 20 厘米以内的线配 1MHz稳定性和速度的平衡点比较舒服。顺便说一句这条旋钮也是区分真连不上和连得上但不稳的分水岭如果降频之后就能连上说明问题在信号完整性不用去怀疑芯片坏了。4. 一次完整的烧写流程图形界面和命令行两条路4.1 用 STM32CubeProgrammer CLI 做可复现的烧写先把命令行跑通因为它可复现、可记录、可放进脚本。核心命令如下。STM32_Programmer_CLI.exe -c portSWD freq1000 modenormal -w firmware.hex -v -rst拆开说-c是连接portSWD指定用 SWD 接口freq1000是 1MHz 的时钟这里的数字带单位习惯写成 1000kHzmodenormal表示正常连接如果目标程序会把 SWD 引脚复用掉就换成modehotplug也就是边复位边连接。-w后面跟要写的文件.hex自带地址工具会自己解析。-v表示写完回读校验这一步在批量场景里不能省。-rst表示跑完复位并让芯片运行不加的话芯片停在复位或者调试状态看起来像没跑起来。如果是要整片清干净再写或者要处理被保护的芯片用这条。STM32_Programmer_CLI.exe -c portSWD modehotplug -e all -ob RDP0xAA -w firmware.hex -v -rst-e all是全片擦除-ob RDP0xAA是把读保护降到 Level 0注意这个操作会顺带清空整片 Flash所以必须先备份。把这几条命令写成一个 .bat 文件双击就能烧班产几十块板子的时候能省掉大量重复点击。4.2 ST-LINK Utility 的点选流程和批量技巧如果只想点鼠标ST-LINK Utility 的流程是Target → Connect连上之后左下角会显示芯片型号和 Flash 大小接着 File → Open File 选固件然后 Target → Program Verify弹窗里默认会显示写入地址.hex不用改.bin必须手动填最后确认勾选项包括 Verify after programming 和 Reset after programming。Utility 里有个很好用的功能是 Device 菜单下的 Erase Chip 和 Option Bytes读保护相关的操作都在这里。另外它的 Target → Settings 里有 Connect Under Reset 勾选项遇到连不上的板子挨个试一遍通常有一个能通。4.3 hex、bin、elf 到底差在哪地址错了会怎样这三种格式的差别值得单独说清楚因为地址填错导致的烧写成功但程序不跑我见过太多次。格式是否自带地址典型来源烧写时要不要手动填地址.hex是Intel HEX 文本格式每条记录带地址Keil/IAR/GCC 输出不需要.bin否纯二进制镜像objcopy 转换产物必须填STM32 通常是 0x08000000.elf / .axf是带段地址和符号信息编译链接直接产出不需要工具能自动解析段.bin填错地址的典型症状有三种填到别的地址导致主程序区是空的芯片复位后跑不起来填到选项字节区0x1FFFF800 之类可能导致不可预期的行为填到 RAM 地址上断电就没了。所以拿到一个 .bin 文件第一件事是问清楚它的起始地址别想当然。EEPROM 数据、Bootloader 和 App 分离的工程地址更要对上App 的起始地址必须和 Bootloader 里的跳转地址一致差一个字都不行。5. 选项字节与读保护最容易被自己锁死的区域5.1 RDP 等级、写保护和 BOOT 配置的实际含义读保护RDP在 STM32 上一般是三个等级。Level 0 是0xAA完全不保护调试口随便读随便写。Level 1 是任何非0xAA的值效果是通过调试口读不到主 Flash 和备份 SRAM 的内容但程序正常运行这个等级是可以降回 Level 0 的代价是降级瞬间芯片会自动执行一次全片擦除数据全丢。Level 2 是0xCC永久锁死调试口彻底失效芯片不可逆只有出厂时给客户做防抄板的场景才用个人开发千万别碰。写保护WRP是按扇区或者按页粒度保护的被保护的扇区在擦除和写入时会报错。它的一个副作用是如果你只保护了部分扇区全片擦除也可能失败因为擦除命令覆盖到了受保护区域。遇到 Erase error 又确认过供电和接线去 Option Bytes 里看一眼 WRP 的配置位。BOOT 相关配置在有些系列里也存在选项字节中比如 nBOOT0、nBOOT1、BOOT_SEL 这几位的组合决定了上电时从哪里启动。改这些位之前先把当前值读出来截图或者抄在纸上改完不跑能立刻回滚。5.2 芯片被锁住之后怎么救回来Level 1 的救法就是全片擦除。图形界面里用 STM32CubeProgrammer 的连接设置Mode 选 Under reset然后在 Erasing Programming 里点 Full chip erase命令行就是前面那条带-e all和-ob RDP0xAA的命令。注意顺序先确认能连上Under reset 模式下能读到芯片 ID再做擦除。有些情况下连都连不上那就把 nRESET 接好、频率降到 500kHz、目标板独立供电、按住复位键点连接的瞬间松手多试几次基本能进去。这里有个一定要强调的点只要 RDP 还是 Level 1任何全片擦除都会把你原来的程序抹掉。所以如果手里那块板子上的固件没有源码或者没有备份动手之前先想清楚能不能承受这个损失。对于 Level 2官方的说法是没有任何办法恢复调试接口被永久关闭只能换芯片这一点没有例外。5.3 量产和小批量时的配置固化思路量产烧写最怕的不是烧不进去是烧进去的板子配置不一致。我的做法是先用一块样板把所有选项字节、Bootloader、App 三段都调通然后用 CubeProgrammer 把当前配置导出成一个 .ob 文件或者记下所有关键选项字节的值之后每一批都先烧这份配置再烧固件。命令行里可以用-ob参数一次性写入多个选项字节的值也可以先-ob displ把当前值打印出来跟基准对比。另一个实用技巧是给固件加上一个版本号和一个 CRC 校验区。烧完之后用-r参数把校验区读回来比对比单纯依赖-v的全片校验更省时间。因为这个原因我现在做小批量时基本都走命令行脚本把擦除、写选项字节、写固件、写序列号、回读校验串成一条流水线人只需要负责放板子和按键。6. 报错速查表和我踩过的那些坑6.1 常见报错对照表把最容易遇到的几种现象整理成一张表按这个顺序排查比盲目换板子效率高得多。现象或报错最可能的原因处理动作No ST-LINK detectedUSB 线是纯充电线、驱动异常、克隆版固件挂掉换数据线、重装 STSW-LINK007、换 USB 口No target connected / Can not connect to target接线错、目标板没供电、SWD 被复用、频率过高核对四根线、独立供电、Under reset 连接、降频到 500kHz能识别芯片但一烧就失败供电跌落、线太长、Flash 算法选错独立供电、缩短线、核对 Keil 里的下载算法Flash Download failed - Target DLL has been cancelled芯片型号选错、算法不匹配、选项字节有写保护核对器件型号、清 WRP 配置Verification failed供电不稳、Flash 写入不可靠、频率过高降频重试、检查电源纹波、换一块板子对照烧写成功但程序不跑BOOT0 状态错、.bin 地址填错、时钟配置失败量 BOOT0 电压、核对起始地址、检查晶振起振Device ID 读到 0x00000000 或读出的 ID 不匹配供电不足、复位电路 RC 太大、目标芯片是兼容型号独立供电、换小电容、用对应厂商工具6.2 几条不太被提到但很有用的经验第一条如果你怀疑硬件短路别急着换芯片。把万用表调到二极管档黑表笔接 GND、红表笔分别点 SWDIO 和 SWCLK正常情况下会有一个零点几伏的压降接近零说明对地短路接近无穷说明开路或者虚焊。这个方法三十秒就能定位是焊接问题还是配置问题。第二条很多国产兼容型号比如一些 GD、CKS 之类的替代品在 ST-Link 下会被认成 ID 不匹配或者干脆识别不出来但底层协议其实是兼容的。这时候的处理方式是用对应厂商的烧写工具或者在 ST-LINK Utility 里手动指定一个相近的 STM32 型号再尝试CubeProgrammer 的兼容性判断更严格认不出就是认不出。用这类芯片的项目最好提前把厂商自己的烧写工具也装好别等到产线上才发现。第三条调试器插在 USB 3.0 的蓝色口上偶尔会出现枚举不稳定、连接时断时续的现象尤其是一些老克隆版。换到 USB 2.0 口或者经过一个带供电的 Hub问题常常就消失了。这不是玄学是电气特性。第四条自制板子上的 SWD 排针强烈建议做五个脚并丝印标出方向并且把 nRESET 引出来。我在板子上留了一个明显的一号脚标记之后接错线的概率直接降到接近零插错插反这种事在赶进度的时候真的很容易发生。6.3 为什么串口 ISP 烧写经常失败最后还是回到 SWD串口 ISP 是一条不依赖调试器的路子把 BOOT0 拉高、BOOT1 拉低上电进系统存储器里的引导程序然后用串口工具把固件发进去。它的好处是不需要买调试器坏处是失败率确实高。常见的失败原因有几类USB 转 TTL 模块输出的是 5V 电平而目标板是 3.3V通信时好时坏波特率设得过高比如直接上 115200 甚至更高配合劣质线材就开始丢包BOOT0 的状态在上电瞬间没稳定下来芯片根本没进引导程序串口被别的软件占用工具打开端口失败还有一些板子靠 DTR/RTS 做自动复位时序转接板没引出这两根线就只能手动卡着时间点按复位。串口 ISP 还有一个根本性的短板它进不去调试口改不了选项字节出问题也没法单步。所以我自己的习惯是串口 ISP 只作为应急手段比如手上没有调试器、或者 SWD 排针焊坏了的时候用一下日常还是老老实实用 SWD。7. 换个角度看烧写工具其实是同一套心智模型7.1 不同平台烧写的共性做久了会发现不管是 ST-Link 烧 STM32还是 Zynq 平台上下载 PL 的 bitstream 和 PS 端的启动镜像或者 Rockchip 平台用 rkdevtool 单独烧写某个分区镜像比如 boot.img底层心智模型是同一套先建立一条到目标的物理链路调试口、USB、串口再选定目标存储介质和起始地址然后把镜像写进去并校验最后让目标从正确的地址启动。差别只在于链路类型和地址概念的表现形式。STM32 上是 Flash 起始 0x08000000Zynq 上要区分 PL 配置和 PS 的启动流程工具里要按顺序加载并复位Rockchip 平台上地址概念变成了分区表和分区名所以会出现只单独烧写 boot.img这种需求本质是不想动其他分区。理解了这层共性换个平台上手大概只需要半小时熟悉工具界面。7.2 一个反复被验证的原则先能读再谈写无论在哪个平台遇到烧写问题我第一条验证永远是能不能读到目标信息。ST-Link 场景下就是能不能读到芯片 ID 和 Flash 大小Rockchip 场景下就是能不能读到芯片型号和存储介质信息。读得到说明链路和权限都正常问题在写入参数上读不到问题在物理链路或者目标状态上。所有排查都从这一个判断分叉出去效率会高很多。很多人一上来就反复点下载结果在错误的假设里绕半天。8. 一点个人体会折腾 ST-Link 这些年我最大的感受是这东西的坑基本集中在电和时序两个词上跟软件配置相关的反而少。线太长了、供电不够、复位电容太大、频率太高这几个原因能覆盖我遇到的八成故障。所以我现在固定了一套排查顺序先换一根二十厘米以内的数据线再确认目标板独立供电然后降频到 1MHz 试连接最后才去看选项字节有没有被锁。这套顺序让平均定位时间从半小时压到了五分钟以内。另外分享一个小习惯我给自己每块调试器都贴了一小段标签写上V2-克隆-勿升级和购买日期出问题的时候能立刻知道手上这个是正品还是克隆版避免误操作。板子那侧则统一在 SWD 排针旁边留一个方形焊盘当一号脚标记。这些动作花不了几分钟但能省下的返工时间相当可观。