diff --git a/.dsh/skills/new-machine-setup/SKILL.md b/.dsh/skills/new-machine-setup/SKILL.md index 53b90272..b5b73ed0 100644 --- a/.dsh/skills/new-machine-setup/SKILL.md +++ b/.dsh/skills/new-machine-setup/SKILL.md @@ -29,12 +29,12 @@ whenToUse: 换新机器/新克隆要把环境搭起来、构建或烧录报"环 ``` 语义统一:**显式设了但路径无效 = 立即报错不回退**;不设则走 PATH/自动发现。 3. **驱动**:CH340(调试串口)与 ST-Link 的 USB 驱动装好—— - `Get-PnpDevice -Class Ports` 能看到 COMx、`reset.bat list` 能看到探针 SN。 + `Get-PnpDevice -Class Ports` 能看到 COMx、`stlink_flash.py list` 能看到探针 SN。 4. **验收三连**(全绿才算环境就绪): ```powershell & '.venv\Scripts\python.exe' .dsh/skills/serial-assistant/scripts/serial_tool.py selftest # 23/23 PASS & '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py # exit 0 - & "MDK-ARM\reset.bat" list # 列出探针 + & '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py list # 列出探针 ``` ## 实测坑(本会话两次撞上) diff --git a/.dsh/skills/serial-boot-test/SKILL.md b/.dsh/skills/serial-boot-test/SKILL.md index 463bac5d..82de7a27 100644 --- a/.dsh/skills/serial-boot-test/SKILL.md +++ b/.dsh/skills/serial-boot-test/SKILL.md @@ -52,7 +52,7 @@ whenToUse: 需要向目标板烧录或复位后,用串口日志自动判定运 **先跑项目的构建**(本仓库 = `keil-build` skill,其它 Keil 项目照该 skill 套; 非 Keil 项目用项目自己的构建入口),确认 0 错误 0 警告后再进闭环。 档案里的 `flash_cmd`/`readback_cmd` 就是烧录层的入口命令 -(本仓库 = `stlink-flash` skill 的 `MDK-ARM\reset.bat flash` / `cmp {hex}`)。 +(本仓库 = `stlink-flash` skill 的 `stlink_flash.py flash` / `cmp {hex}`)。 ## 第二步:跑闭环 diff --git a/.dsh/skills/serial-boot-test/config.example.json b/.dsh/skills/serial-boot-test/config.example.json index 8d7e1bd4..4f2e7cdb 100644 --- a/.dsh/skills/serial-boot-test/config.example.json +++ b/.dsh/skills/serial-boot-test/config.example.json @@ -2,11 +2,11 @@ "portName": "COM6", "baudRate": 115200, - "flash_cmd": "MDK-ARM\\reset.bat flash", + "flash_cmd": ".venv\\Scripts\\python.exe .dsh\\skills\\stlink-flash\\scripts\\stlink_flash.py flash", "flash_timeout": 180, "hex": "MDK-ARM\\STM32F407-Demo\\STM32F407-Demo.hex", "fw_marker": "fw build: ", - "readback_cmd": "MDK-ARM\\reset.bat cmp {hex}", + "readback_cmd": ".venv\\Scripts\\python.exe .dsh\\skills\\stlink-flash\\scripts\\stlink_flash.py cmp {hex}", "readback_ok": "no difference found", "required": "App init OK;Network Init;net init: OK", diff --git a/.dsh/skills/serial-boot-test/scripts/run_boot_test.py b/.dsh/skills/serial-boot-test/scripts/run_boot_test.py index ac40c2b0..48aac463 100644 --- a/.dsh/skills/serial-boot-test/scripts/run_boot_test.py +++ b/.dsh/skills/serial-boot-test/scripts/run_boot_test.py @@ -138,7 +138,7 @@ def _split_cmd(cmd_str): 会给含空格的路径正确加引号。旧写法 `['cmd','/c', 串]` 在本仓库(目录名 `DTU Code` 含空格)会被 cmd 的 /c 引号规则玩坏——实测报 `'D:\Code\DTU' is not recognized`,回读校验被假判成"芯片内容不一致"。 - 路径本身含空格时把该段用引号包住(`"D:\some dir\reset.bat" flash`)。 + 路径本身含空格时把该段用引号包住(`"D:\some dir\flash_tool.bat" flash`)。 posix=False 是必须的:posix=True 会吃掉 Windows 路径里的反斜杠。 """ return [p.strip('"') for p in shlex.split(cmd_str, posix=False)] @@ -416,7 +416,7 @@ def main(argv=None): print("RUN_TEST_ERROR: no required markers (--required or 'required' in {})".format(CFG_FILE)) return 3 - # --flash-cmd 允许带参数(如 "MDK-ARM\reset.bat flash"):拆成 argv, + # --flash-cmd 允许带参数(如 "python flash_tool.py flash"):拆成 argv, # 存在性只查 exe 段(整串当文件名必然 missing,2026-10-10 实测) flash_argv = _split_cmd(args.flash_cmd) if args.flash_cmd else None diff --git a/.dsh/skills/stlink-flash/SKILL.md b/.dsh/skills/stlink-flash/SKILL.md index 13d98acb..868e8f9a 100644 --- a/.dsh/skills/stlink-flash/SKILL.md +++ b/.dsh/skills/stlink-flash/SKILL.md @@ -15,6 +15,7 @@ whenToUse: 需要向 STM32 目标烧录 .hex/.bin、只复位重启目标、校 & $PY ".dsh\skills\stlink-flash\scripts\stlink_flash.py" flash [hex] # 烧录 + -Rst -Run & $PY ".dsh\skills\stlink-flash\scripts\stlink_flash.py" cmp [hex] # 回读比对(会复位目标) & $PY ".dsh\skills\stlink-flash\scripts\stlink_flash.py" reset # 只复位运行 +& $PY ".dsh\skills\stlink-flash\scripts\stlink_flash.py" hard # nRST 100ms 脉冲(CLI 拒 RM= 时自动降级为复位) ``` 镜像缺省取项目档案 `hex`;ST-LINK_CLI 解析:`--cli` > 档案 `stlink_cli` > @@ -25,8 +26,11 @@ whenToUse: 需要向 STM32 目标烧录 .hex/.bin、只复位重启目标、校 ## 本仓库 -仓库原生入口 `MDK-ARM\reset.bat`(flash/cmp/halt/run/list 子命令)与本 skill 脚本 -语义一致,两者任选。环境变量 `DTU_STLINK_CLI`(未设回退 PATH;设了但无效 = 报错 exit 2)。 +**`@download` = 本 skill**(2026-10-10 起为仓库文档口径)。原 `MDK-ARM\reset.bat` +(`flash`/`cmp`/`halt`/`run`/`list` 子命令)已并入本 skill 的 +`flash/cmp/reset/hard/halt/run/list` 并于 **2026-10-10 删除**;`@build`/`@download` +两条旧批处理入口至此全部收敛到 skill(一个能力一个实现)。 +环境变量 `DTU_STLINK_CLI`(未设回退 PATH;设了但无效 = 报错 exit 2)。 ## 铁律与陷阱(实测教训) @@ -38,8 +42,9 @@ whenToUse: 需要向 STM32 目标烧录 .hex/.bin、只复位重启目标、校 不一致 = 本次运行作废。 - **`-CmpFile` 连接时会复位目标**:板子当场重打一遍开机日志——在自动闭环里必须排在 **串口日志采集之后**,否则开机日志被截断、启动锚点计数误判成"中途复位"。 -- **只重启不烧录**用无参 `-Rst -Run`;nRST 未接线的台架(3 线 SWD)这是唯一复位手段, - `-HardRst`/`RM=` 在部分 CLI 版本(v3.5.0 实测)不可用。 +- **只重启不烧录**用 `reset` 子命令(`-c SWD -Rst -Run`);nRST 未接线的台架(3 线 SWD) + 这是唯一复位手段——`hard`(`RM=Hrst -HardRst PULSE=100`)在部分 CLI 版本(v3.5.0 实测) + 被拒,本 skill 会打印 `RESET_NOTE` 并**自动降级**为这条系统复位(仍按降级结果给 rc)。 - 探针在位先 `list`;`Programming Complete` 但行为像旧固件 → 先怀疑缺 `-Rst -Run`, 再怀疑 hex 没重编(对比 hex 时间戳)。 - 完整复位语义/故障排查(本仓库):`docs/测试说明/ST-LINK_CLI_复位使用说明.md`。 @@ -48,5 +53,6 @@ whenToUse: 需要向 STM32 目标烧录 .hex/.bin、只复位重启目标、校 - 编译 = `keil-build` skill(先 0 错 0 警再烧)。 - `serial-boot-test` 档案里 `flash_cmd` = 本 skill 入口(如 - `"MDK-ARM\\reset.bat flash"`)、`readback_cmd` = `"MDK-ARM\\reset.bat cmp {hex}"`、 + `".venv\\Scripts\\python.exe .dsh\\skills\\stlink-flash\\scripts\\stlink_flash.py flash"`)、 + `readback_cmd` = `"... stlink_flash.py cmp {hex}"`、 `readback_ok` = `no difference found`——闭环脚本已保证"回读排在采集之后"。 diff --git a/.dsh/skills/stlink-flash/scripts/stlink_flash.py b/.dsh/skills/stlink-flash/scripts/stlink_flash.py index ef44c9b7..bd295d3b 100644 --- a/.dsh/skills/stlink-flash/scripts/stlink_flash.py +++ b/.dsh/skills/stlink-flash/scripts/stlink_flash.py @@ -7,6 +7,7 @@ python /scripts/stlink_flash.py flash [镜像.hex|.bin] # 烧录 + -Rst -Run python /scripts/stlink_flash.py cmp [镜像.hex|.bin] [--base 0x08000000] python /scripts/stlink_flash.py reset # 只复位运行 + python /scripts/stlink_flash.py hard # nRST 100ms 脉冲(CLI 拒 RM= 时自动降级为系统复位) python /scripts/stlink_flash.py halt | run 镜像缺省取项目档案 "hex"(解析顺序同下)。 @@ -20,6 +21,8 @@ ST-LINK_CLI 解析(命令行 > 档案 > 环境 > PATH): - cmp 成功判据 = 某行以 "No difference found" 开头(原样透传 CLI 输出, 上层 run_boot_test 的 readback_ok 默认值直接可用) - cmp 连接时会**复位目标**(板子重打开机日志)→ 自动闭环里必须排在日志采集之后 + - hard 复位 = `RM=Hrst -HardRst PULSE=100`;v3.5.0 CLI 拒 `RM=` → **自动降级为系统复位** + (打印 RESET_NOTE,仍按降级结果给 rc);本机 nRST 未接线时这条即唯一可用路径 退出码: 0=OK 1=探针/目标错误 2=CLI 未找到/无效 3=用法错误 """ @@ -105,7 +108,7 @@ def main(argv=None): pass ap = argparse.ArgumentParser(description="ST-LINK CLI flash/reset/readback (pure stdlib)") - ap.add_argument("command", choices=["list", "flash", "cmp", "reset", "halt", "run"]) + ap.add_argument("command", choices=["list", "flash", "cmp", "reset", "hard", "halt", "run"]) ap.add_argument("image", nargs="?", default=None, help="image file (.hex/.bin; default: config 'hex')") ap.add_argument("--cli", default=None, help="ST-LINK_CLI.exe path") @@ -122,7 +125,7 @@ def main(argv=None): cli, src = find_cli(args.cli, cfg) print("CLI: {} ({})".format(cli, src)) - if args.command in ("list", "reset", "halt", "run"): + if args.command in ("list", "reset", "hard", "halt", "run"): if args.image: print("NOTE: image argument ignored for '{}'".format(args.command)) timeout = args.timeout or 60 @@ -134,6 +137,18 @@ def main(argv=None): rc, _ = run_cli(cli, ["-c", "SWD", "-Rst", "-Run", "-Q"], timeout) print("STLINK_RC={}".format(rc)) return 0 if rc == 0 else 1 + if args.command == "hard": + print("RESET: nRST pulse 100ms (falls back to system reset if CLI lacks RM=)") + rc, _ = run_cli(cli, ["-c", "SWD", "RM=Hrst", "-HardRst", "PULSE=100", "-Q"], + timeout) + if rc != 0: + # v3.5.0 CLI 帮助与实现不符:RM= 被拒(Unknown debug protocol or option)。 + # 回退 = 与 `reset` 同款的系统复位 + 运行;本机 nRST 未接线时这就是唯一可用路径。 + print("RESET_NOTE: this ST-LINK_CLI rejects RM= (v3.5.0 known gap), " + "falling back to system reset") + rc, _ = run_cli(cli, ["-c", "SWD", "-Rst", "-Run", "-Q"], timeout) + print("STLINK_RC={}".format(rc)) + return 0 if rc == 0 else 1 if args.command == "halt": rc, _ = run_cli(cli, ["-c", "SWD", "-Rst", "-Halt"], timeout) print("STLINK_RC={}".format(rc)) diff --git a/AGENTS.md b/AGENTS.md index 16c632e0..46a93876 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,8 +19,8 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v - `@test` / `.dsh/skills/serial-boot-test/scripts/run_boot_test.py` 一键闭环(2026-09-20 起为纯 Python 标准库实现,替代 PowerShell 版;`& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py`):开串口+清日志 → 烧录(**`stlink-flash` skill**:`stlink_flash.py flash` = `-P -Rst -Run`;`flash_cmd` 默认取 `.serialtest/config.json`,本仓库已指向本 skill)→ **固件身份戳**(从刚烧进去的 hex 里抠 `fw build: