Files
STM32F4-Base/.dsh/skills/serial-boot-test/SKILL.md
T
wandering1 5009a844a9
CI / L0 静态门禁 (pre-commit) (push) Has been cancelled
CI / L0.5 主机侧单测 (MSVC) (push) Has been cancelled
收敛 reset.bat 到 stlink-flash skill 并删除该批处理
stlink_flash.py 新增 hard 子命令(-c SWD RM=Hrst -HardRst PULSE=100),
RM= 被 CLI 拒绝时自动降级为系统复位并打印 RESET_NOTE;至此 reset.bat 的
全部子命令(复位/hard/halt/run/list/flash/cmp)均已由 skill 覆盖。

删除 MDK-ARM/reset.bat(git rm)。@build/@download 两条旧批处理入口至此
全部收敛到 .dsh/skills/ 下的 skill,一个能力一个实现。

同步更新引用:AGENTS.md、README、MDK-ARM/README、7 篇 docs、4 个 skill
(stlink-flash/serial-boot-test/new-machine-setup 及 config.example.json)。

真机验证:hard 子命令 RM= 被拒 → RESET_NOTE → 回退系统复位 → STLINK_RC=0。
2026-10-10 16:41:46 +08:00

89 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: serial-boot-test
description: 嵌入式目标"烧录/复位 → 抓串口开机日志 → 标记校验"一键闭环。构建在 serial-assistant skill(串口采集层)之上,自带烧录测试编排器与日志标记校验器;项目差异全部收在 <项目根>/.serialtest/config.json,任何带调试串口的项目都能用。
whenToUse: 需要向目标板烧录或复位后,用串口日志自动判定运行是否正常(开机回归、固件身份校验、HardFault/FAIL 标记扫描、开机耗时测量),或需要交互式串口收发与日志回放时。
---
# serial-boot-test — 串口自动验证(判定层,构建在 serial-assistant 之上)
分层:**采集层 = 兄弟 skill `serial-assistant`**(常驻 daemon 串口助手),
本 skill 只负责**闭环编排 + 判定**。换项目时把 `serial-boot-test` 和
`serial-assistant` 两个文件夹一起拷进目标项目的 `.dsh/skills/`
(或 `.agents/skills/`),脚本不含任何仓库路径。
| 脚本 | 作用 |
|---|---|
| `.dsh/skills/serial-boot-test/scripts/run_boot_test.py` | 一键闭环:open+clear → 烧录 → wait-idle → 提取 boot log → 烧录回读校验 → 标记校验。串口助手按 `$DSH_SERIAL_TOOL` > 同目录 > `../serial-assistant/scripts/serial_tool.py` 解析 |
| `.dsh/skills/serial-boot-test/scripts/verify_log.py` | 对任意日志文件做标记校验(Required/Forbidden/锚点计数/顺序/耗时),可单独用 |
交互式串口操作(open/send/log/wait-idle/status 等)不属于本 skill——
**用 `serial-assistant` skill**。
## 前置条件
1. **解释器需装有 pyserial**(闭环经采集层脚本用串口)。优先用项目自己的 venv;
否则按 `serial-assistant` skill 的"前置条件"建专用 venv。
下文 `$PY` = 选定的解释器,`$SKILL` = `.dsh\skills\serial-boot-test`(项目根下相对路径)。
2. **所有命令都在项目根目录下运行**(cwd 决定配置源解析)。
## 第一步:项目档案(每个项目一次)
配置解析顺序:`$DSH_SERIAL_CONFIG` > `<cwd>/.serialtest/config.json` > `<cwd>/.opencode/serial_config.json`(旧位置,仅串口字段)。
若项目没有 `.serialtest/config.json`:**先从项目文档(AGENTS.md/README/测试文档)推断各字段,推断不了的问用户**,然后按 `config.example.json` 写一份。字段含义:
| 键 | 含义 | 缺省行为 |
|---|---|---|
| `portName` / `baudRate` | 串口 | 无 portName 直接 exit 3 |
| `flash_cmd` | 烧录命令(**必须含复位运行**,如 `-Rst -Run`;可带参数) | 空 = 不烧录,脚本提示人工复位板子 |
| `hex` | 刚构建的镜像(Intel HEX),供身份戳 + 回读比对 | 空 = 两项都跳过(WARN) |
| `fw_marker` | 固件身份戳前缀(固件里打印 `"<前缀>" __DATE__ " " __TIME__`) | 默认 `fw build: `;hex 里无此串只 WARN 不假判 |
| `readback_cmd` | 回读校验命令模板,`{hex}` = 镜像路径(引号自动加) | 空 = 跳过 |
| `readback_ok` | 回读成功判据(按行首匹配,大小写不敏感) | `no difference found` |
| `required` | 必须出现的标记(`;` 分隔,大小写敏感) | **空 = exit 3**(必须给) |
| `forbidden` | 禁止出现的模式(`;` 分隔,大小写不敏感) | `FAIL;ERROR;HardFault` |
| `boot_marker` | 一轮启动的锚点子串(如 `reset cause:`) | 空 = 锚点计数关闭 |
| `max_boot_count` | 锚点出现 0 次或 >N 次 = FAIL | 1(仅 boot_marker 非空时生效) |
| `done_marker` + `max_boot_ms` | 开机耗时口径与上限 | 空/0 = 只报告不判 |
| `settle_ms` / `max_wait_ms` / `first_wait_ms` | RX 静默判据 / 总超时 / 首字节超时 | 8000 / 30000 / 12000 |
| `require_order` / `expect_reset_cause` / `require_suite_summary` | 顺序校验 / 复位原因白名单 / 套件汇总行 | 空 = 关闭 |
| `require_selftest_pass` + `device_ip` | 设备侧自检台账联合判定(FTP 抓取) | 关闭 |
**先跑项目的构建**(本仓库 = `keil-build` skill,其它 Keil 项目照该 skill 套;
非 Keil 项目用项目自己的构建入口),确认 0 错误 0 警告后再进闭环。
档案里的 `flash_cmd`/`readback_cmd` 就是烧录层的入口命令
(本仓库 = `stlink-flash` skill 的 `stlink_flash.py flash` / `cmp {hex}`)。
## 第二步:跑闭环
```powershell
# cwd = 项目根目录
& $PY "$SKILL\scripts\run_boot_test.py"
# 临时覆盖:--port COM7 --required "..." --forbidden "..." --flash-cmd "..."
```
退出码:`0=PASS` / `1=FAIL`(标记缺失或命中)/ `2=采集或烧录错误`(含回读不一致,本次运行作废)/ `3=用法/预检错误`。
产物:boot log(每行带 `[+Nms]` 相对时基)写到 `%TEMP%\serial-boot-test\boot_log_<时间戳>.txt`(`--out-dir` 改,保留最近 20 份)。
## 第三步:判读与迭代
- **PASS** → 报告命中的标记与开机耗时。
- **FAIL** → `[MISS]`/`[HIT]` 行(Forbidden 命中带行号+内容)+ 日志尾部已给出;需要更多上下文直接 Read/Grep boot log 文件或 `status` 里 `log.path` 指向的 serial.log。修代码 → 重新构建 → 重跑闭环。
- **exit 2 `no_data`** → 板子全程零字节:查端口在位(`ports`)、板电、烧录命令是否真的复位了目标。
## 交互式串口调试(不跑闭环时)
用 **`serial-assistant` skill**(`ports/open/send/log/clear/wait-idle/status` 全套命令、
抓开机日志铁律、daemon 陷阱都在那边)。本 skill 不重复采集层用法。
## 陷阱(都是实测教训)
- **daemon 一台机只有一个**(HTTP 口 18765 独占绑定,由采集层 serial-assistant 管理)。改配置后必须 `restart`(daemon 启动时缓存配置)。若机器上还有旧 daemon,先 `status` 看 `daemon.version`(serial-assistant 版 = `1.1.0-skill`)确认归属,必要时 `stop` 后重开。
- **回读校验排在日志采集之后**:部分烧录工具(如 ST-LINK `-CmpFile`)连接时会复位目标,提前跑会截断开机日志。脚本已按此顺序,勿手工调换。
- **烧录命令必须让目标复位运行**(裸 `-P` 类写入在目标核死循环时不落地);写完镜像后 `fw build` 身份戳校验会揭穿"芯片还是旧镜像"。
- **`settle_ms` 必须大于固件的自然静默间隙**(常见 3~4s),默认 8000;日志被截断先调大它。
- **Required 标记宁少勿多**:先用启动锚点 + 少数里程碑标记;按用例临时覆盖 `--forbidden`(预期出现的 `[ERR]` 负路径用例)。
- **烧录与串口采集不冲突**:SWD 下载走探针、调试日志走 USB-serial(CH340 类),互不占用;烧录期间串口侧静默几秒属正常,不算 `no_data`(首字节门会兜住)。
- 中文/编码:脚本全程字节级处理,不受控制台代码页影响;配置文件存 UTF-8(BOM 容忍)。