5009a844a9
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。
89 lines
6.8 KiB
Markdown
89 lines
6.8 KiB
Markdown
---
|
||
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 容忍)。
|