Files
STM32F4-Base/docs/测试说明/ST-LINK_CLI_复位使用说明.md
T
wandering1 d1e6bb4ba7 W5波+N-19收口:FTP鉴权落地、Trap25三连定案修复(N-30)、N-20/N-23/N-26
N-19 FTP 鉴权:
- lftpd_auth(USER/PASS 状态机 + 连续5次失败锁60s)+ SHA-256
  (user||pwd) 口令哈希;config.ini [ftp] 段 user/pwd_hash/write,
  出厂 admin/admin 在用有启动告警;lftpd_log.c 删除并入 lftpd_auth
- ftp_cfg 配置读写;台架 ftp_auth_bench.py 13/13

N-30 / Trap 25(CH395F_Trap_Records.md 四次定案全记录):
- 修复1 closed-with-data accept:客户端发完正常 FIN 后芯片按
  FUN_PARA(0x09) §5.52② 保留 Socket+RX 缓冲,旧代码把 CLOSED 一律
  relisten 自毁缓冲 → STOR 必挂 425;改为接受"已关但可读"连接排空
- 修复2 丢 CONNECT 中断探针 net_lost_connect_probe + last_peer_port
  幽灵甄别(拆链窗口握手完成但中断丢失,双信源去抖补 accept)
- 修复3 send_list/send_nlst 批量单发:背靠背 ~60B 小段毒化芯片 TX
  (芯片报 SEND_OK 但对端全丢),整份目录一次性写入
- 证伪存档:固定沉降/Socket 轮换冷却/listen 门控(台架 v7 矩阵)
- 台架工具 test/board/ch395f_reuse_bench.{c,h} + host 脚本存档
  (不注册编译;实验分支 n30-chip-bench 保留)

N-20:Error_Handler 死循环降级(记录+复位路径)
N-23:scripts/check_registration.py 双端注册反向校验(pre-commit)
N-26:GD5F NAND 直 DMA 调用方缓冲窗口断言

验证:BUILD_OK 0/0;ftp_regression 连跑 4 轮 11/11(修复前
LIST#4/#7 100% 挂、STOR#2 曾 100% 425);ftp_auth_bench 13/13;
@test 启动标记 PASS;ci_local L0+L0.5 全过;doc-links 通过。
登记簿 N-30 已销项。
2026-10-11 18:50:24 +08:00

18 KiB
Raw Blame History

ST-LINK_CLI 复位使用说明(v3.5.0.0 本机实测版)

依据:本机 ST-LINK Utility 4.5.0.0 自带 ST-LINK_CLI.exe(CLI 版本 v3.5.0.0,-h 全文已实测核对)+ ST 官方文档语义。 探针路径:经 DTU_STLINK_CLI 环境变量解析(本机设为标准安装位 C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe;未设时回退 PATH,stlink_flash.py 均可用) 2026-09-19 已上板实测(ST-LINK/V2,FW V2J37S7,SN 0B250D12A218303030303032;STM32F407ZGTx 目标,SWD)。 2026-09-20 复测(V0.1 板):烧写静默失败根因闭环(见 §2 ⑤ 与 §7)、完整启动闭环(见 §5)。 ⚠️ 本机接线:3 根线(SWDIO / SWCLK / GND),nRST 未接 → 能力边界见 §0,实测记录见 §5。 文中标注 ⓞ 的为"官方帮助/文档说法"与"本机实测"不一致处的更正。


0. 本机接线与能力边界(先读)

当前板(V0.1;09/19 上板实测时为 V2 板,接线相同)↔ ST-LINK/V2 只接了 3 根线:

线 目标端 探针端 状态
SWDIO SWD 数据 SWDIO ✅ 已接
SWCLK SWD 时钟 SWCLK ✅ 已接
GND 地 GND ✅ 已接
nRST 芯片复位脚 RESET ❌ 未接

由此得到本机能力矩阵:

能力 本机(3 线) 说明
软件系统复位(-Rst,SYSRESETREQ) ✅ 本机"重启板子"的唯一方式
停核/运行/单步/断点(-Halt/-Run/-Step/-SetBP) ✅ 调试用
内存/Flash 读写、擦除、校验(-r*/-w*/-P/-V/-ME/-SE/-CmpFile) ✅
不扰连接 / 低功耗唤醒 / 读电压 / 枚举探针(HOTPLUG/LPM/-TVolt/-List) ✅
nRST 引脚操作(-HardRst、RM=Hrst) ❌ 双重障碍:① nRST 未接线(无信号可驱动)② v3.5.0.0 CLI 拒识 RM=(ⓞ,见 §2③)
复位态连接(UR) ❌ 需要 nRST 接线才能"按住复位连接"

要点:

  • 日常"命令重启板子" = -c SWD -Rst -Run(软件系统复位)。对 STM32F4,SYSRESETREQ 会复位内核 + 几乎所有外设,与 nRST 硬复位的固件级效果等价(差别仅在 nRST 引脚本身不动、调试域保留)——3 线接线场景下这就是复位能力的上限,完全够用。
  • 需要 nRST 引脚级操作时(复位电路/上电时序验证、跑飞后的复位态连接救援)必须补第 4 根线:目标 nRST → 探针 RESET 脚。补线之后注意:本机 v3.5.0.0 CLI 仍不认 RM=(ⓞ),届时要走 ST-LINK Utility GUI、升级 ST-LINK Utility(新版 CLI)、或换 J-Link。
  • stlink_flash.py hard 已内置回退:本机永远回退到软件复位(exit 仍为 0),不会把脚本跑断;将来补线 + 升级 CLI 后自动升级为真 nRST 脉冲,无需改脚本。

1. 三种"复位"(核心概念)

种类 触发源 复位范围 CLI 表达 本机可用
硬件复位(nRST) 探针驱动目标 nRST 引脚 整片冷启动,最接近"重新上电" -HardRst [LOW/HIGH/PULSE=<ms>](配 RM=Hrst) ❌ nRST 未接线(且 CLI 不支持 RM=)
软件系统复位(SYSRESETREQ) 调试器写系统复位寄存器 内核 + 绝大多数外设(调试域保留) -Rst(默认模式即可) ✅ 本机唯一复位方式
内核复位(AirCore/VC) 内核复位信号 仅内核;外设保持运行 -c ... RM=Crst(连接时选择) ⓞ v3.5.0.0 CLI 拒识 RM=,本机不可用

2. 六个核心复位用法

① 复位并运行(重启板子,最常用)✅ 本机可用

ST-LINK_CLI -c SWD -Rst -Run

时序:连接(默认连接即停核)→ 系统复位 → 运行 → 板子从 Flash 引导重新跑固件。 这就是"命令控制板子重启",本机 3 线接线完全够用。

② 复位并停核(调试/检查用)✅ 本机可用

ⓞ 实测更正:v3.5.0.0 CLI 下 -Rst 之后核是运行状态(-SCore 回读 "Core is Running."),并不停核。要停核必须显式加 -Halt:

ST-LINK_CLI -c SWD -Rst -Halt

实测:停核成功,SP=0x2001E8B8(与向量表首字一致),PC=0x08004664——复位后核先运行了一段启动代码再被停住(软件系统复位不保持调试 halt,停点由 -Halt 下发时刻决定,不保证是复位向量)。 ⓞ 本机无 nRST 线 + CLI 不支持 RM=,"精确停在复位向量"在本机不可实现;停核读取命令必须与复位写在同一命令行:

ST-LINK_CLI -c SWD -Rst -Halt -SCore -CoreReg        :: 复位停核后读核状态 + 寄存器
ST-LINK_CLI -c SWD -Rst -Halt -R32 0x08000000 4      :: 停核后读向量表前 4 个字

ⓞ 一次性连接语义(实测):ST-LINK_CLI 是"连接→执行→断开"的一次式进程,会话结束(断开)时核自动恢复运行。因此 stlink_flash.py halt 单独调用只适合"复位后读状态"场景,断开后板子会继续运行;需要持续性 halt(GDB 调试/长时间断点)请走 GDBServer/IDE 路径。

③ 硬件复位:nRST 脉冲 ❌ 本机不可用(nRST 未接线)

:: 仅备查:需 nRST 接线 + 支持 RM= 的 CLI/GUI/J-Link
ST-LINK_CLI -c SWD RM=Hrst -HardRst PULSE=100

PULSE=100 意为 nRST 拉低 100ms 再释放(整片冷启动,等价于按复位键/重新上电)。 本机不可用的原因(双重障碍):

  1. nRST 线未接(3 线接线)——探针没有可驱动目标复位脚的信号;
  2. ⓞ v3.5.0.0 CLI 拒识 RM=:RM=Hrst/Srst/Crst 在 4 种语法排列下全部报错 [RM=Hrst]: Unknown debug protocol or option!(exit=1)——帮助文本与实现不符。

将来若补 nRST 线:ST-LINK GUI 可先做引脚级操作;要 CLI 化则升级 ST-LINK Utility 或换 J-Link。

④ nRST 电平保持序列 ❌ 本机不可用(nRST 未接线)

:: 仅备查:按住复位→释放,用于复位电路验证/上电过程观察
ST-LINK_CLI -c SWD RM=Hrst -HardRst LOW -HardRst HIGH

(-HardRst LOW 按住、-HardRst HIGH 释放;需 nRST 接线 + 支持 RM= 的工具。)

⑤ 烧写 + 复位 + 运行(完整固件更新)✅ 本机可用

ST-LINK_CLI -c SWD -P "MDK-ARM\STM32F407-Demo\STM32F407-Demo.hex" -Rst -Run
  • ⓞ .hex 直接支持已实测:1MB Intel HEX 编程耗时 6.5s,Programming Complete(远快于 UV4/CMSIS-DAP 路径);.bin 同理(fromelf --bin 可转,ARMCC 自带 C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe);.axf 直读未测,无需。
  • 加 -V 编程后校验、-Q 静默。
  • 与 stlink_flash.py flash 同源(都走 ST-LINK_CLI)。原 download.bat(UV4 -f 走 CMSIS-DAP)与 reset.bat 均已删除(2026-10-10),烧录/复位/回读统一由 stlink-flash skill 承载。
  • ⓞ 静默失败模式(2026-09-20 实测,代价最大的坑):省略结尾 -Rst -Run 的裸 -c SWD -P <文件> 仍报 Memory programmed in 1s 906ms / Programming Complete,但芯片 flash 不变(回读向量表 = 旧镜像)——目标核处于死循环/异常状态时,"Normal 连接、不复位"的会话写入不落地;同文件改用完整 -P <文件> -Rst -Run 即正常落地(6.5s / 1MB)。铁律:任何编程命令必须以 -Rst -Run 收尾;任何烧录之后必须 -CmpFile 全片回读校验(详见 §7)。

⑥ 不扰目标连接(HOTPLUG,运行中板子的只读检查)✅ 本机可用

ST-LINK_CLI -c SWD HOTPLUG -SCore                 :: 核状态(Running/Halted、PC)
ST-LINK_CLI -c SWD HOTPLUG -R32 0x08000000 4      :: 读运行中芯片的 Flash
ST-LINK_CLI -c SWD HOTPLUG -TVolt                 :: 读 VDD
ST-LINK_CLI -c SWD HOTPLUG -Dump 20000000 1000000 dump.bin   :: 转储 SRAM

HOTPLUG = 连接时不 halt、不 reset——对正在跑的板子做无副作用检查。

3. -c 连接参数全表

-c [ID=<id>/SN=<sn>] [JTAG/SWD [SWCLK=<f>]] [UR/HOTPLUG] [LPM] [RM=Hrst/Srst/Crst]
参数 含义 本机状态
SWD / JTAG 调试接口(本工程用 SWD;SWD 只需 2 根信号线,JTAG 需 4 根) ✅ 默认选 SWD
SWCLK=<f> SWD 时钟。⚠️ 帮助文字标"KHz"但官方示例写 SWCLK=5(若按 KHz 则慢到不可用),两处自相矛盾 ⓞ 先不传,用探针默认(本机实测自动协商到 4000K);连接慢/失败再小步试验
UR 在复位状态下连接(nRST 拉低期间完成连接) ❌ 需 nRST 接线(本机未接)
HOTPLUG 连接时不 halt、不 reset ✅
LPM 低功耗模式下进入调试(先唤醒目标) ✅
RM=Hrst/Srst/Crst 本次会话的复位机制:nRST 引脚 / 软件系统复位 / 仅内核 ⓞ v3.5.0.0 全部拒识,勿用
ID=<0..9> / SN=<串号> 多探针选择(默认 ID=0) ✅ 一机多板时用于指定

示例(多板场景):-c SN=0B250D12A218303030303032 SWD LPM

4. 核状态 / 内存 / Flash 辅助命令(复位前后验证链)

命令 作用
-SCore 核状态:Running/Halted + 程序计数器(复位后核对"停在哪")
-CoreReg 读核心寄存器组(SP/PC/xPSR 等)
-Halt / -Run [addr] 停核 / 运行(可从指定地址开始)
-Step 单步
-SetBP <address> / -ClrBP 设/清断点
-r8/-r16/-r32 <地址> <数量> 读内存(地址、数量均为十六进制)
-w8/-w32/-w64 <地址> <数据> 写内存
-Dump <地址> <大小> <文件> 内存转储到文件
-CmpFile <文件> [地址] 全片 Flash 与文件逐字节比对(2026-09-20 实测:No difference found = 真写入;v3.5.0.0 无 -Cksum 命令)。⚠ 连接即复位目标(2026-10-10 实测:比对瞬间板子重打一遍开机日志)→ 自动化里必须排在日志采集之后
-P <文件> [地址] [ske] [skpv] 编程(ske=跳擦除 skpv=跳校验)
-V [after_programming] 校验
-ME / -SE <扇区> 全片擦除 / 扇区擦除(⚠️ RDP≠0 时 -ME 会被拒)
-TVolt 目标 VDD 电压(⚠️ 需 VDD 感应脚接至目标;本机台架 3 线连接(SWDIO/SWCLK/GND)此脚未接,读数无效,供电判据以万用表实测为准)
-Q / -Log / -NoPrompt 静默 / 生成跟踪日志 / 免交互确认
-List 枚举所有已连接探针(固件版本 + 串号)

退出码:0=成功;2=未检测到探针(本机实测);其他非零=失败。

5. 本工程实战组合

A. 只重启不烧录(固件没变,重新验证启动/串口行为;配合 serial_tool)

& '.venv\Scripts\python.exe' .dsh/skills/serial-assistant/scripts/serial_tool.py open
& '.venv\Scripts\python.exe' .dsh/skills/serial-assistant/scripts/serial_tool.py clear
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py reset   # = ST-LINK_CLI -c SWD -Rst -Run -Q
# 等待开机完成后直接读日志文件校验标记:
Get-Content .dsh\skills\serial-assistant\scripts\state\serial.log -Tail 100

顺序关键:先开串口清日志,再复位,否则错过开机头几行(与 run_boot_test.py 的"采集先于烧录"原则一致)。 ⓞ 实测补充三条:

  1. 改过 .serialtest/config.json 端口后必须重启 daemon:daemon 在启动时缓存配置,改端口后 close + 杀旧进程再 open,否则一直按旧端口报 port not found;
  2. (已修,2026-10-10)旧版 wait-idle 在复位突发期会报 daemon unresponsive after auto-start: timed out:CLI 把超时误判成"daemon 不可达",顺手拉起一个绑不上 HTTP 口的实例再把命令撞一次超时(数据其实已落盘)。现 CLI 超时按 --max-ms 自动推导、超时只快速失败不再误拉起实例;
  3. 日志校验:.dsh/skills/serial-assistant/scripts/state/serial.log 用 Read/Grep 直接查最直观;serial_tool.py log --grep <标记> 现已可作判定依据(2026-10-10 修:旧实现先 --tail(默认 50)后 grep,开机标记必然查不到——这就是当年"实测 0 命中、语义存疑"的真根因)。

B. 完整烧写 + 运行:stlink-flash skill 的 stlink_flash.py flash [xxx.hex](= -c SWD -P <hex> -Rst -Run;09/19 实测 1MB ≈ 6.5s,09/20 复测 6.47s + 全片 -CmpFile 逐字节一致)。2026-10-10 起 CLI 路径即唯一烧录路径——原 download.bat 的 UV4 -f 与 reset.bat 均已删除。

B2. 回读校验:stlink_flash.py cmp [xxx.hex](= -c SWD -CmpFile <hex> 0x08000000,2026-10-10 加;默认对最新构建 hex)。判定看输出行首的 No difference found(This file is already downloaded 是同义提示)。⚠ 连接即复位目标:实测比对瞬间板子重打一遍开机日志 → 在自动化闭环里回读必须排在日志采集之后(run_boot_test.py 已按此顺序内置)。

C. 救援(板子起不来 / 疑似 Flash 问题)——本机 3 线接线的可行子集:

ST-LINK_CLI -c SWD LPM                      :: 若目标休眠/连不上,先试低功耗唤醒
ST-LINK_CLI -c SWD -ME                      :: 全片擦除(前提 RDP=0;RDP≠0 需先 -rOB 确认,RDP 解锁是专门流程)
ST-LINK_CLI -c SWD -P "MDK-ARM\STM32F407-Demo\STM32F407-Demo.hex" -Rst -Run

ⓞ 注意:UR(复位态连接)在本机不可用(nRST 未接线)——跑飞救援能力受限,能做的只有"正常连接 + LPM + 全擦重烧";若板子连 SWD 都握不上手,需先补 nRST 线。

D. 运行中检查:-c SWD HOTPLUG -SCore / -R32 / -TVolt(⚠️ 本机 3 线连接下读数无效,见命令表注记)/ -Dump。

用法(全部分支 exit=0 实测通过):

调用 行为 本机实际效果
stlink_flash.py reset -c SWD -Rst -Run ✅ 软件系统复位 + 运行(重启板子)
stlink_flash.py hard -c SWD RM=Hrst -HardRst PULSE=100,被拒则回退 ⓞ 本机 RM= 被拒 → 自动回退软件复位(打印 RESET_NOTE,exit=0);补 nRST 线 + 升级 CLI 后自动升级为真 nRST 脉冲
stlink_flash.py halt -c SWD -Rst -Halt ✅ 复位停核(一次性会话,读状态须同命令行附加;断开后核自动恢复运行)
stlink_flash.py run -c SWD -Run ✅ 恢复被停核的目标
stlink_flash.py list -List ✅ 枚举探针
stlink_flash.py flash [F] -c SWD -P F -Rst -Run(F 缺省 = 档案 hex = MDK-ARM\STM32F407-Demo\STM32F407-Demo.hex) ✅ 烧写 + 复位 + 运行(1MB ≈ 6.5s;2026-09-20 复测验证,见 §2 ⑤)
stlink_flash.py cmp [F] -c SWD -CmpFile F 0x08000000 ✅ 全片回读比对(No difference found = 真写入)

退出码:0=OK;1=探针/目标错误;2=CLI 未找到/无效;3=用法错误。 注意:档案(.serialtest/config.json)解析、DTU_STLINK_CLI 工具路径解析(未设回退 PATH;显式设了但无效 = 硬报错)、镜像缺省值均内置于脚本;stlink_flash.py 为纯标准库 Python,无原 bat 的引号/CRLF 行尾坑。

7. 故障排查速查

现象 排查
No ST-LINK detected!(exit=2) 探针没插/USB 未枚举/驱动问题。本机已装 STLinkWinUSB 驱动;stlink_flash.py list 复核;换 USB 口(避免前端_hub)
[RM=xxx]: Unknown debug protocol or option!(exit=1) ⓞ v3.5.0.0 CLI 不支持 RM=(帮助与实现不符);且本机 nRST 未接线——直接用软件复位 -Rst(stlink_flash.py reset)
连接失败 目标供电;SWDIO/SWCLK 接线(本机 3 线,勿依赖 nRST 辅助);芯片休眠 → 加 LPM;看门狗反复复位 → 提高连接速度(本机无 UR 可用);RDP 被锁 → 只能读有限信息
复位后程序没跑 读复位向量确认 Flash 有效:-R32 0x08000000 1(应指向 0x08xxxxxx,0xFFFFFFFF=空片);查 BOOT0 状态;看串口是否有输出
复位后卡死(串口日志中断在半路) ⓞ 2026-09-19 实测案例:-c SWD HOTPLUG -SCore -CoreReg 读 PC/寄存器定位卡点(案例:V2 引脚固件卡在 0x08000FA0 启动循环,见 §5)——先定位再下结论,勿直接怀疑探针
烧录报成功但芯片行为不变 ⓞ 先怀疑静默写入失败(2026-09-20 实测):命令缺 -Rst -Run(裸 -P 在目标核死循环/异常时不落地)或选项字节异常(RDP 字节非法,见 §3 与 §7)。处置:-CmpFile 全片比对/回读向量表首字 → 用 stlink_flash.py flash 重烧 → 再 -CmpFile 复核;勿直接怀疑探针/接线
daemon unresponsive after auto-start(serial_tool) ⓞ 复位后几秒内 daemon 忙于排空日志突发;稍等后直接读 state/serial.log 文件验证,勿反复重试
port not found: COMx (available: COMy)(serial_tool) ⓞ 端口重新枚举(板子重插常见):改 .serialtest/config.json → kill 旧 daemon 进程 → 重新 open(daemon 启动时缓存配置,不重启不生效)
log --grep 查不到明明存在的标记 ⓞ 该子命令实测不可靠(0 命中);改用直接读/Select-String 查 state/serial.log
SWD 通信不稳 不传 SWCLK 用默认时钟(本机实测 4MHz);检查长线/夹子接触
误改 option bytes -rOB 读回现状;-OB RDP=0 等回写后需再复位生效;RDP=2 会锁死调试+全片擦除,操作前务必确认
多板混淆 stlink_flash.py list 拿串号,-c SN=<串号> 指定