ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ST-LINK Utility 完全指南:从烧录到救砖的嵌入式开发利器

ST-LINK Utility 完全指南:从烧录到救砖的嵌入式开发利器

很多人手里握着 ST-Link,绝大多数时候只是拿来给 IDE 点一下“下载”按钮,芯片里是什么状态、Flash 里到底写了什么、板子被锁死了怎么救,一概不清楚。ST-LINK Utility 这个工具,恰恰就是解决这些“下载按钮之外”问题的。它在老工程师圈子里被戏称为“最后的救命稻草”,在新工程师手里却经常只被当作一个下载 hex 的替代品。这篇博文,我想把它的下载安装、完整使用流程、批量烧录和故障排查一次性讲透,希望对从事嵌入式开发、产线支持和售后维修的朋友都有点实际帮助。

1. 认识 ST-LINK Utility:没它的时候,你会在哪些场景卡住

1.1 它到底是什么,和 IDE 自带的烧录器区别在哪

ST-LINK Utility 是面向 STM32 全系列 Cortex-M 内核微控制器的桌面端编程工具。你可以把它理解成一个“独立于工程代码之外的 Flash 操作台”:它不关心你的源码,不参与编译,只负责和 ST-LINK 调试器通信,对芯片内部的 Flash、选项字节、OTP 区域做读写、擦除和校验。

IDE(比如旧版 Keil MDK 或 IAR)里自带的烧录功能,本质上也是调用 ST-LINK 的驱动库去操作 Flash,但它有一个前提:你必须有一个完整可编译的工程。假如你手上只有一个 hex/bin 文件、一段没有源码的固件、或者一块进度条卡在“Download”不动又不知道原因的开发板,IDE 就非常别扭。ST-LINK Utility 则完全绕开了工程体系,把芯片当成一个裸设备来操作,直接面对 Flash 的每一个字节。

另外一个容易忽略的区别是:IDE 的下载逻辑是“按扇区增量写入”,它只擦除有代码变化的区域;ST-LINK Utility 在做全片编程时,往往会执行更彻底的操作流程,这对排查一些“明明编译通过了,但程序行为很奇怪”的隐性 Flash 残留问题非常有帮助。很多同事在 Keil 里反复 Download 都搞不定的偶发故障,我让他们用 ST-LINK Utility 做一次全片擦除重新烧录,十有八九就正常了。原因很简单:IDE 的增量烧录不会把已经擦除的“空洞”或旧版本残留全部清干净,芯片里偶尔残留一些无用数据,可能导致中断向量表错乱或存储区重叠。

1.2 日常工作里真正需要它的几个场景

这不是一个需要“天天打开”的工具,但一旦出事,它就是那个能救场的。

  • 固件备份与比对:板子上的程序跑得好好的,但你手里没有源码或者不确定最新出货版本是不是这个,用 Utility 的 Read Back 功能把整片 Flash 读出来存成 bin 文件,再和另一个正常板子读出来的内容做比对,差异一目了然。
  • 板子被读写保护锁死:野外设备升级到一半断电、调试时误使能了 RDP(读保护)级别 1、或者 SWD 引脚被程序复用成了 GPIO,导致调试器连接不上。Utility 的“连接-全片擦除”路径是官方支持的标准自救流程。
  • 批量生产烧录:小批量产线不依赖 IDE 授权的情况下,Utility 的命令行模式配合批处理脚本,是低成本量产方案里很成熟的一种。几台电脑、一个 hex 文件、一根 ST-LINK,就能跑起一个简易烧录工位。
  • 查看芯片内部状态:想知道 Flash 有没有写满、某块地址区域存了什么配置、选项字节被改成了什么,IDE 是不会告诉你的。Utility 的内存窗口直接映射整个存储空间,全体一目了然。

可以说,凡是和“STM32 芯片 Flash 本身”有关的问题,它都管;凡是和“源码编译”有关的问题,它都不掺和。这个边界想清楚,你就知道什么时候该想起它。

1.3 和老伙计、新工具之间的横向对比

ST-LINK Utility 在官方产品序列里确实已经进入维护末期,官方主推的替代方案是 STM32CubeProgrammer。但“替代”不代表“立刻废弃”,很多场景下 Utility 仍然有不可替代的价值:

对比维度ST-LINK UtilitySTM32CubeProgrammer
界面简洁度非常简洁,点击即用功能丰富,菜单层级多
内存窗口可视化左侧树形映射+右侧窗口,直观偏底层,需要点选 Address 窗口
命令行批量.bat + ST-LINK_CLI,轻量Python/CubeProgrammer 更灵活
固件升级 ST-LINK老版本菜单里有独立入口新版独立升级程序
大 Flash 外部存储器支持部分外部 Flash 编程更完善
新芯片型号支持较老,对新系列支持有限跟随新片发布节奏

所以我的态度从来不是一刀切。如果你的芯片型号比较旧(F1/F4/F0 这些)、生产环境是 Windows XP/7、或者你不想为了一个 bin 文件下载几百 MB 的新工具,Utility 依然很顺手。如果你用的是新出的 G0/L4+系列,遇到型号不支持的情况,那还是老老实实用 STM32CubeProgrammer。工具不在新旧,在于你清不清楚它的边界。

2. 下载与安装:老工具也有讲究,千万别踩驱动坑

2.1 从哪里下载、选哪个版本

ST-LINK Utility 的官方下载渠道是 ST 官网的 TOOLS AND SOFTWARE 板块。注意一点:它的完整软件名是 “STM32 ST-LINK Utility”,别和 “ST-LINK/V2-1 固件升级程序” 搞混,这两个是不同的安装包。前者是主程序,后者是单独给 ST-LINK 硬件升级用的,默认会在前者安装时一并装好。

版本选择上,我建议直接选带 “_setup.exe” 的最新 Windows 版。老版本(比如 3.x 早期)对新款 ST-LINK/V2 的兼容性差,容易报告 “ ST-LINK firmware outdated” 然后拒绝连接。最新的 4.x 版本对新旧硬件兼容都不错,界面上没有翻天覆地的变化,操作习惯一致。

下载时留意你系统位数,虽然有兼容模式,但 64 位系统直接装 64 位版少很多麻烦。安装包体积不大,几十 MB 级别,不像新款 IDE 动辄上 GB,这也是它适合放在产线电脑上的重要原因。

2.2 安装过程中的关键勾选

安装向导一路 Next 基本没问题,但有三个细节值得留意:

第一,安装路径里绝对不要出现中文和空格。有同事装在D:\软件\ST Tools\下,结果命令行模式死活找不到ST-LINK_CLI.exe,最后发现是批处理脚本引号没写好,中文路径在 cmd 里编码不一致。工具本身不受影响,但命令行调用极其依赖路径纯净,统一用D:\STLink\这种最稳。

第二,驱动安装那一步。安装完成后通常会自动装好 ST-LINK 的 USB 驱动,但有些精简版系统或开启了驱动签名强制的机器会失败。你可以打开设备管理器看端口附近有没有 “ST-LINK dongle” 或者通用串行总线设备下面有没有感叹号。如果有感叹号,右键更新驱动,手动指向安装目录里的ST-LINK_USB_Driver文件夹即可,不需要额外去网上下载第三方驱动,否则容易被捆绑流氓软件。

第三,官方安装包默认会装一个 “ST-LINK Upgrade” 独立程序,保留它。后面 ST-LINK 硬件固件版本影响连接稳定性时,全靠它来升级,别为了节省桌面空间把它合掉。

2.3 硬件连接与识别检查

软件装好,接下来把 ST-LINK 插到电脑,用 SWD 四根线连目标板:SWDIO、SWCLK、GND,以及供电(如果板子没有独立电源)。这里有个非常反直觉的经验:很多连接失败不是线序问题,而是电压不匹配。

新款 ST-LINK/V2 的 SWD 接口有电平转换功能,但部分老款或山寨 ST-LINK 只支持 3.3V 目标板。如果你的板子是 5V 供电的外部传感器模块,或者目标芯片是 1.8V 内核的低功耗系列,SWDIO/SWCLK 的电平可能直接烧坏调试器或通讯异常。连接前先确认目标板供电范围和 ST-LINK 的电压跳线/模式说明。

连接后打开 Utility,界面上方的连接按钮会变成一个绿色圆点。如果显示 “Target is connected” 且左侧 RAM/Flash 区域出现地址映射,说明通路正常。若提示 “Can not connect to target”,大概率就是后面第 5 章要讲的问题,先别慌。

3. 五个最高频的使用场景,逐个手把手拆解

3.1 在线模式下载 hex/bin 文件

这是日常打开率最高的功能。工具栏上那个 “Open file” 按钮选择要下载的 hex 或 bin 文件,文件一经加载,右侧会显示目标地址和校验信息。hex 文件自带地址信息,工具会按照 hex 记录里的地址自动写入对应位置;bin 文件则是一片裸数据,你需要手动指定起始地址。大多数 F1 系列程序从0x08000000开始,不要填错,否则写入的位置不对,程序肯定跑不起来。

下载前建议养成一个习惯:先执行一次 Erase 操作,把整片 Flash 擦干净,再下载新固件。很多人为了省事点 “Download” 按钮让工具自动处理,确实它也会自动擦除必要的扇区,但在排查问题阶段,全片擦除能排除“旧代码残留”这个变量。下载过程中左下角状态栏会跳出File loaded successfully,接着是Programming...,再是Verification...,三步齐全才说明烧录完整,缺一不可。

这里分享一个我踩过很多次的坑:不要把 hex 文件当 bin 文件加载。hex 是文本格式,每一行都以冒号开头、带有地址和校验码;bin 是纯二进制。一旦你用 bin 方式加载 hex,起始地址全乱,工具会把它当裸数据写进你指定的地址,轻重则程序跑飞,重则把芯片配置区写坏。判断方法很简单:保险起见直接用 “Open file” 然后看一下右侧加载的起始地址是否以0x0800...开头,以及数据量是否和 hex 大小匹配。

3.2 读回 Flash 内容做备份和比对

想备份芯片里的固件,菜单栏选Target -> Read Back,你会看到一组地址范围选项。如果只是想读应用程序区,默认从当前 Flash 起点读到末尾即可,工具会把这部分内容加载进内存窗口。然后File -> Save File As,保存类型选 Binary(.bin)或 Intel HEX(.hex)。我建议保存成 hex 而不是 bin,原因在于 hex 自带地址映射,万一你下次想烧录回去,不用再猜起始地址。

读回之后想比对两块板子固件是否相同,最简单的方式是分别读两个板子的 bin,然后用支持二进制比对的编辑工具做 Hash 校验或者逐字节比对。有的同事喜欢直接在 Utility 里打开第二个文件,再和内存窗口比较,但界面比较工作量大了点。实际操作中我更常用命令行脚本做文件的 MD5 校验,产线上不同批次板子的固件一致性验证效率最高。比如读回固件后对 bin 文件算 MD5,和烧录前的原文件 MD5 比对,不一样就说明 Flash 里被改动过。

还有一个使用细节:读回操作会暂停 CPU 运行,如果你的板子上有其他外设在工作(比如电机正在转、显示屏正在刷新),Flash 读回期间 CPU 突然停止可能导致外设输出错误状态。遇到类似在线读回场景,务必把设备断电、进入待机状态再做。

3.3 全片擦除与选项字节管理

擦除操作在Target -> Erase Bulk。点击后工具会弹出一个确认框,提示整个 Flash 将会被擦除,确认后开始。这个操作会清空所有扇区,包括你在程序里自己写入的片内配置数据、参数存储区。因此全片擦除和全片读回一样,做之前先确认数据已经备份。

选项字节窗口在Target -> Option Bytes,打开后能看到几组关键配置:

  • 读保护级别RDP:0 是关闭保护,1 是禁止从调试接口读取 Flash,2 是最高保护且永久生效。
  • 写保护WRP:按扇区勾选,勾中的扇区无法通过调试接口和用户程序写入。
  • 看门狗强制选项:某些应用需要开启硬件看门狗无法关闭。
  • 启动配置BOOT:部分系列支持设置 boot 地址。

最危险的坑在这里:把 RDP 从 1 改成 0 会导致整片 Flash 被自动擦除,这是芯片保护机制规定的,不是工具 bug。也就是说,用 Utility 给一台设置了读保护的设备解除保护时,固件和 Flash 里的所有数据会一并清空。产线返修时,经常有同事以为只是修改选项字节,结果改完才发现板子成空片了。所以给带保护的设备解锁前,务必先确认固件已经备份,或者在解除保护后立刻重新烧录。另外,RDP 一旦设为级别 2,调试接口将被永久锁定,再也无法连接,这种情况任何软件都救不回来,只能更换芯片。所以选项字节窗口里设置 RDP 时一定要想清楚。

3.4 外部 Flash 烧录(补充场景)

需要操作外部 SPI NOR Flash 时,比如程序里有一个存储字库、图片、日志的外部 Flash 芯片,它挂在 STM32 的 SPI 接口上,而你想在量产前直接把字库烧进去。Utility 的External Memory Programming功能可以配合目标板上的引脚映射,通过 STM32 的 SPI 接口对外部 Flash 编程。这个功能在不同系列上的支持程度不一,旧工具对 F1/F4 支持相对完整。

这个功能的配置比较繁琐,需要在External Memory Loader里选择与芯片匹配的 loader 文件,loader 负责通过特定引脚组合收发 SPI 信号。实际操作中,如果你只是小批量烧录,我建议直接在程序里写一段 IAP 逻辑,把字库作为固件的一部分放在片内 Flash 末尾,然后由程序启动时搬运到外部 Flash,比折腾 External Loader 省心得多。只有当产量大、需要纯硬件操作时才值得花时间研究工具的外扩烧录功能。

3.5 给 ST-LINK 硬件本身升级固件

如果你插上 ST-LINK 后,Utility 顶部状态栏一直提示ST-LINK firmware outdated,或者连接过程中频繁断连,很可能是硬件固件版本过旧。打开ST-LINK Upgrade,先点 “Device Connect” 让它识别硬件,再点 “Yes” 进入升级模式,然后 “Upgrade” 开始刷写。升级过程中绝对不要断开 USB,也不要拔掉目标板连接,否则变砖风险不低。

升级完需要重新插拔一次 USB,确认固件版本号已变化。这个操作建议每隔半年做一次,ST-LINK 硬件固件更新通常是为了兼容新推出的芯片型号和修正通讯稳定性,不更新会严重影响新芯片的连接成功率。

4. 命令行模式:批量烧录与产线自动化的精髓

4.1 ST-LINK_CLI 的关键参数

ST-LINK Utility 的命令行程序叫ST-LINK_CLI.exe,位于安装目录下。它支持的参数和图形界面几乎一一对应。核心用法:

ST-LINK_CLI.exe -c SWD UR -p 固件.hex -v

分解一下:

  • -c SWD UR:连接配置。SWD指定使用 SWD 协议,UR表示连接 USB 接口的 ST-LINK(通用的-c指令模式)。
  • -p 固件.hex:编程文件名。支持 hex 和 bin,bin 文件需要额外的起始地址参数,比如-p data.bin 0x08000000。注意 bin 后面跟的是十六进制地址,不能带0x前缀?实际工具要求带0x,直接写0x08000000即可。
  • -v:烧录后执行校验。没有这个参数,烧录完不读回比对,产线如果开了省这一步,出问题的概率大增。校验带来的时间开销很小,但价值巨大,量产脚本里必须带上。

常用的其他参数还包括:

  • -me:全片擦除。
  • -r8 起始地址 长度 文件名:按字节读回 Flash 范围并存成 bin 文件。比如-r8 0x08000000 0x10000 dump.bin,表示从 0x08000000 开始读 0x10000 字节,保存为 dump.bin。
  • -a 起始地址:为 bin 文件指定编程起始地址。
  • -NoRst:编程后不复位芯片,有些板子复位电路异常时可以用这个参数临时绕过问题。

4.2 用批处理写一个简易产线烧录脚本

批量烧录场景,带宽和工位电脑性能有限,用图形界面一个个点比脚本效率低太多。下面这个批处理是我在产线常用的一个模板,配合 hex 文件即可跑起来:

@echo off set HEX_FILE=app.hex echo 正在连接 ST-LINK... ST-LINK_CLI.exe -c SWD UR if errorlevel 1 goto ERR_CONNECT echo 正在全片擦除... ST-LINK_CLI.exe -c SWD UR -me echo 正在烧录固件并校验... ST-LINK_CLI.exe -c SWD UR -p %HEX_FILE% -v if errorlevel 1 goto ERR_FLASH echo 烧录成功 pause exit /b 0 :ERR_CONNECT echo 连接失败,请检查 ST-LINK 和目标板连接 pause exit /b 1 :ERR_FLASH echo 烧录失败,请检查固件文件和芯片状态 pause exit /b 1

这里有三个重要的迭代心得:

第一,每次操作前都做一次连接检测。不要一上来就烧录,因为批量烧录时接触不良、目标板供电不稳是常态,提前探测能省掉大量返工。脚本里如果检测失败就停下来,让操作员人工检查,比自动重试更安全,避免反复烧录损坏 Flash 寿命。

第二,整片擦除 + 烧录 + 校验是黄金三板斧。量产环节不要为了省时间省略校验,烧录进去之后芯片跑起来是否正常或可以通过上电自检判断,但 Flash 内容是否完整只能靠逐字节比对,这一步是质量底线。

第三,脚本路径和文件编码一定要注意。批处理文件如果包含中文路径,务必存成 ANSI 编码,否则在 UTF-8 的 Windows 上会乱码报错。最简单的方式是路径全英文,脚本里也不写中文,只在回显信息上用英文。产线操作员看到的一律是烧录成功/失败,不需要保持中文。

4.3 读回脚本和校验技巧

有时产线需要抽检已经烧录的板子,下面的脚本会读回前 64KB 固件区并算 MD5:

ST-LINK_CLI.exe -c SWD UR -r8 0x08000000 0x10000 check.bin certutil -hashfile check.bin MD5 certutil -hashfile app.hex MD5

注意:app.hex 是十六进制格式,直接算 MD5 和 bin 不一样。要对比,需要把原始固件也转成 bin(可以用 Utility 图形界面打开 hex 后另存为 bin,或者用 hex2bin 小工具)。读回的 check.bin 才是纯二进制,和原始固件的 bin 版本做 MD5 比对才有意义。这部分细节虽然小,但足以让不熟悉文件格式差异的同事卡壳半天。

命令行模式的能力边界在这里:它不能处理需要图形交互的错误恢复流程,比如芯片读保护级别异常导致连接失败时,脚本只能报错,无法自动进入特殊恢复流程。产线方案要把这些特殊分支留给人工处理,脚本只覆盖“健康板子”的标准流程。

5. 连接失败的排查清单:从现象到根因

5.1 连接不上,按照这个顺序试

连接失败是最折磨人的问题。我把常见原因按照概率高低整理成一个排查顺序,纯操作经验,不按手册顺序:

步骤检查项成功率提升点
1目标板供电电压正常吗万用表测 VDD 和 GND,别默认“上电了”就是“供好电了”
2SWDIO/SWCLK/GND 三根线接对了吗示波器或万用表测 SWDIO 引脚是否有边沿变化
3芯片复位引脚有没有被外部拉低复位 IC 故障或手动复位按键卡死都会导致连接失败
4目标板有没有独立供电,地和 ST-LINK 共地了吗共地是 SWD 通讯成功的前提
5芯片是否上电后立刻进入低功耗模式低功耗模式下调试接口可能已经关闭,需在复位期间连接
6有没有其他程序占用 ST-LINK 的 USB 口关闭所有 IDE 调试会话,只留 Utility 一个主人
7芯片的 SWD 引脚是否被复用成了普通 GPIO使用连接时按住复位键再点 Connect 的骚操作
8芯片是否被设置了读保护 RDP 级别 1/2级别 1 可用全片擦除解除,级别 2 只能换芯片

其中第 7 条和第 8 条是嵌入式开发特有的高发问题。SWD 引脚被复用,通常发生在程序初始化阶段把 PA13/PA14(对应 SWDIO/SWCLK)设置为普通输出。这里有个我用得最多的“连接期间复位”操作:在连接对话框中把连接速度降到最慢,然后在点击 Connect 的同时按住目标板复位按键,保持复位状态下连接,再松开复位,让程序还没来得及执行引脚复用代码时就被调试器接管。具体到 Utility 界面,它没有像 IAR 那样提供专门的 connect-under-reset 勾选项,但你可以通过调整连接时序和复位操作达到类似效果。实际操作是先在Target -> Settings里把频率调低到几百 kHz,然后 按住板子复位键 -> 点击 Connect -> 松开复位键,成功率很高。

5.2 写保护、读保护和死锁恢复

“烧录时提示Cannot program the memory” 是最常见的下载失败弹窗。绝大多数情况是芯片被设置了写保护,或者之前的烧录中断导致 Flash 处于锁定状态。恢复方法分两步:

第一步,打开Target -> Option Bytes,查看写保护扇区是否打了勾。如果打了,取消勾选,点击 Apply。这里注意:修改写保护本身会先执行一次全片擦除,所以写保护的解除动作会清掉固件,属于正常行为,不是工具抽风。

第二步,如果解除写保护后仍报告无法编程,执行一次 全片擦除,再不行就检查电源稳定性。Flash 烧录瞬间电流消耗比运行大,劣质 USB 口或压降明显的杜邦线会导致写操作期间电压跌落,工具表现为编程中途失败。

读保护解除的恢复逻辑比较特殊:如果你遇到Read protection enabled这类提示,首先确认芯片当前是可以被识别的。识别得到的情况下,执行 全片擦除 会自动清除 RDP 级别 1,芯片恢复可读可写状态。本质原因是芯片底层把 RDP 降级和全片擦除绑定在一起,防止通过调试口暴力破解固件。级别 2 则不同,它一旦被设置,芯片将永久禁止调试接口访问,任何软件都无法再连接,只有通过修改芯片本身才能解锁——但那是另一个话题,普通开发者直接换新芯片即可。

5.3 选项字节被改乱后的自救流程

有人不小心把选项字节里的 BOR(掉电复位门槛)设成了过高的值,导致芯片一上电就锁死,代码还没跑就被复位,反复复位循环根本连不上。这种状态不要以为只能换芯片,还有一个技巧:

先把外部高速时钟或内部时钟的启动配置暂时改到 RAM 启动模式(BOOT 引脚或选项字节里的 BOOT 配置)。然后连接调试器,因为 RAM 不需要擦除,芯片可以从 RAM 区域启动,CPU 跑一个简单循环,调试接口就能正常连接。连接上之后再恢复正常启动模式,重新烧录。不过这招在不同的 STM32 系列上操作略有差异,部分新系列在选项字节完全损坏时这个办法也受限,真到了那一步只能靠 ISP 模式(如果有的话)恢复。

恢复选项字节的最稳妥操作是:在Target -> Option Bytes里把 RDP 级别恢复到默认 0、WRP 全部取消勾选、BOR 恢复默认值,然后点击 Apply。工具会一次性重新编程所有选项字节并触发芯片复位。做这个操作之前,务必拍下原来的选项字节配置,方便恢复到生产状态。

写在最后的经验

说了这么多,最后还是想啰嗦一句:ST-LINK Utility 这类工具,真正好用不是因为按钮多、界面炫,而是因为它对 Flash 操作的“可视”和“可控”程度高。很多工程师习惯把一切交给 IDE,遇到问题反而不明所以;用 Utility 做几次全片擦除、读回、比对之后,你会对芯片的存储结构、保护机制、启动流程有更深的理解。每次我帮新人排查板子,都会从连接时序、电源、读保护这三个维度入手,这套思路就是从这个工具上学来的。量产脚本里现在还在跑着 ST-LINK_CLI 的批处理,每次看到它稳定输出 “Programming” 和 “Verification” 成功,心里都很踏实。你要是手边正好有一块 STM32 板子,不妨试着用它读一次 Flash,再写一次 Flash,看完这个过程,你对“下载程序”这四个字的理解会完全不同。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进