test:@test 闭环迁移 PowerShell→Python(run_boot_test/verify_log 纯标准库,文档同步)

This commit is contained in:
2026-09-20 03:07:42 +08:00
parent 2375569f96
commit 8ae7a12016
18 changed files with 395 additions and 323 deletions
+2 -2
View File
@@ -249,8 +249,8 @@ flowchart TD
## 六、P3:MCU 验证
1. `@build` → **0 错误 0 警告**(AGENTS.md 强制;有警告看 `MDK-ARM/build_log.txt`)
2. `@test`(一键 `test/run_boot_test.ps1`):
- 采集窗口**先于烧录武装**(脚本 `-FlashCmd` 分支已保证顺序)
2. `@test`(一键 `test/run_boot_test.py`):
- 采集窗口**先于烧录武装**(脚本 `--flash-cmd` 已保证顺序)
- Required:`UI port init: OK;UI menu init: OK` + 本界面定制标记(按屏增补,如页头标题字样)
- Forbidden:`FAIL;ERROR;HardFault`
3. **真机目检**(用户执行,DTU-RemoteLCD @ TCP 7003):极性 / 边框 / 文字 / 选中态 / 滚动
@@ -279,7 +279,7 @@ ISR 余量:该任务运行期间可能被中断打断的最深中断链(SPI/
1. **RAM 预算台账**(本节模板落地为 `docs/内存管理/RAM预算台账.md`):记录每个 Region/缓冲/栈的计划值、实测值、责任人、变更历史;每次改内存相关代码必须更新
2. **AGENTS.md 增补**:新增任务/缓冲/栈前必须先查台账余量(把现有"内存预算紧张"条目升级为可执行 checklist:先跑 `ram_report.ps1`,算总账,再动手)
3. **pre-commit 门禁**(可选):钩子解析最新 map,RW_IRAM1 使用率 >92% 或 RW_IRAM2 超限 → 提交拦截并提示
4. **@test 扩展**:`verify_log.ps1` 增加可选 Required 标记 `"[MEM] heap free"`,把堆余量下限纳入自动化回归
4. **@test 扩展**:`verify_log.py` 增加可选 Required 标记 `"[MEM] heap free"`,把堆余量下限纳入自动化回归
5. **map diff 常态化**:每次 `@build` 后跑 `ram_report.ps1`,ZI 增量 >1KB 的改动必须在提交说明中解释
## 5. 预期效果
@@ -173,7 +173,7 @@ ST-LINK_CLI -c SWD HOTPLUG -Dump 20000000 1000000 dump.bin :: 转储 SRAM
Get-Content tools\serial_tool\state\serial.log -Tail 100
```
顺序关键:**先开串口清日志,再复位**,否则错过开机头几行(与 `run_boot_test.ps1` 的"采集先于烧录"原则一致)。
顺序关键:**先开串口清日志,再复位**,否则错过开机头几行(与 `run_boot_test.py` 的"采集先于烧录"原则一致)。
ⓞ 实测补充三条:
1. **改过 `serial_config.json` 端口后必须重启 daemon**:daemon 在启动时缓存配置,改端口后 `close` + 杀旧进程再 `open`,否则一直按旧端口报 `port not found`;
@@ -191,7 +191,7 @@ Select-String -Path 'tools\serial_tool\state\serial.log' -Pattern 'App init OK'
| `timeout` | `--max-ms` 到了仍在持续吐数据 | false |
- **`--settle-ms` 默认 8000 不是随便定的**:本工程 boot 任务间有 3~4s 自然静默间隙,判据小于它会把开机日志截断。
- @test 流程(`run_boot_test.ps1`)用它作为"烧录后日志收齐"的判据。
- @test 流程(`run_boot_test.py`)用它作为"烧录后日志收齐"的判据。
### 3.9 `start` / `stop` / `restart` — daemon 生命周期
@@ -274,7 +274,7 @@ Select-String -Path 'tools\serial_tool\state\serial.log' -Pattern 'App init OK'
... serial_tool.py log --tail 0 # 取本轮全量 → 人眼/脚本检查标记
```
自动化版本 = `test/run_boot_test.ps1`(同一序列 + 烧录 + 标记校验,见 `自动化测试流程.md`)。
自动化版本 = `test/run_boot_test.py`(同一序列 + 烧录 + 标记校验,见 `自动化测试流程.md`)。
### 5.3 长时运行监控
@@ -326,7 +326,7 @@ Get-Content 'tools\serial_tool\state\daemon.log' -Tail 30 # ② daemon 自身
| 日志里出现 `HEX:…` 行 | 该段字节不是 UTF-8/GBK 文本(二进制流/乱码) | 正常回退行为,按 hex 对照协议解析 |
| `state: error` + `error: read: …` | 读串口出错/拔线 | daemon 仍活着;重插后 `open` 即恢复(自动 1.5s 退避) |
| 改了 `serial_tool.py` 行为没变 | 运行中的 daemon 还是旧代码 | `… serial_tool.py restart` |
| 开机日志"缺尾巴"(如缺 `Network Init`) | `--settle-ms` 太小,在 boot 自然静默间隙就收尾了 | 用默认 8000(`run_boot_test.ps1` 已内置) |
| 开机日志"缺尾巴"(如缺 `Network Init`) | `--settle-ms` 太小,在 boot 自然静默间隙就收尾了 | 用默认 8000(`run_boot_test.py` 已内置) |
| 旧日志"丢了" | 20MB 截头丢的是**文件头** | 查旧内容要看尾部;重要轮次开始前先 `clear` 分代 |
## 8. 常见问题
@@ -45,7 +45,7 @@ Python 重写一并解决:依赖收敛到仓库 `.venv + pyserial`(任意机
| R8 | 日志 20MB 上限,超限**原地截头**保留尾部 10MB(不重开端口/不 rename) | P0 | 补充(用户确认) |
| R9 | 开端口不翻转 DTR/RTS(防 STM32 自动复位电路误复位),可配置 | P0 | 补充 |
| R10 | 串口读错/拔线 → daemon 存活,state=error,可重开;daemon 被杀可自恢复 | P0 | 补充 |
| R11 | @test 集成:`run_boot_test.ps1` 采集步改写 + `verify_log.ps1` 兼容 + 旧文档/配置迁移 | P0 | 用户场景 |
| R11 | @test 集成:`run_boot_test.py` 采集步改写 + `verify_log.py` 兼容 + 旧文档/配置迁移 | P0 | 用户场景 |
| R12 | `send`(TX 进日志)、`log --tail/--grep`、`start/stop/restart`、`selftest` 无头自检 | P1 | 补充 |
## 3. 总体方案
@@ -175,7 +175,7 @@ flowchart LR
## 7. 集成与迁移(@test 切换)
### 7.1 新 @test 流程(`run_boot_test.ps1` 采集步改写,退出码约定不变:0/1/2/3)
### 7.1 新 @test 流程(`run_boot_test.py` 采集步改写,退出码约定不变:0/1/2/3)
```mermaid
flowchart LR
@@ -183,11 +183,11 @@ flowchart LR
B --> C["MDK-ARM\download.bat(ST-Link 烧录+复位,端口全程打开)"]
C --> D["wait-idle:rx 静默 8s(-SettleMs)或超时 30s(-MaxWaitMs)"]
D --> E["提取本代际 [RX] 行,剥 [RX] 时间戳前缀 → boot txt"]
E --> F["verify_log.ps1(标记匹配,脚本不动)"]
E --> F["verify_log.py(标记匹配)"]
```
- 对比旧流程:6 个采集窗口参数 + JSON 解析 + EOF 重试 **全部删除**;采集 = 端口常开 + 读文件
- `verify_log.ps1` 无需修改(剥前缀后与现有纯文本契约一致)
- `verify_log.py` 与纯文本日志契约一致(2026-09-20 随 @test 迁移 Python,判定语义不变)
- 参数保留:`-Port` `-BaudRate` `-FlashCmd` `-Required` `-Forbidden` `-OutDir`;删除 `-DurationMs` 等窗口参数,新增 `-SettleMs`(静默判据,**默认 8000**——boot 任务间有 3~4s 自然静默间隙,2000 会截断)`-MaxWaitMs`(默认 30000)
### 7.2 配套变更清单
@@ -235,7 +235,7 @@ flowchart LR
| S2 | daemon 核心:HTTP 服务 + 串口读线程 + 行日志写(含 clear/截头/DTR 策略) | `tools/serial_tool/serial_tool.py`(daemon 部分) | `start→status→send→stop` 手动走通 ✅ |
| S3 | CLI 全子命令 + 自动拉起 + 超时契约 + `selftest` | serial_tool.py(CLI 部分) | `selftest` 0=PASS + 命令走查 ✅ |
| S4 | 验收 A1–A6、A8 | 测试通过记录 | A1–A5/A8 PASS ✅(本机无 CH340,A6 待硬件) |
| S5 | @test 集成:`run_boot_test.ps1` 采集步改写 + 参数收敛 | run_boot_test.ps1 | 负路径(端口缺失→exit 2)+ 假烧录全链路 + verify 正/负判定 ✅;**A7 正路径待 CH340 接入** |
| S5 | @test 集成:`run_boot_test.py` 采集步改写 + 参数收敛 | run_boot_test.py | 负路径(端口缺失→exit 2)+ 假烧录全链路 + verify 正/负判定 ✅;**A7 正路径待 CH340 接入** |
| S6 | 文档/配置迁移(§7.2 全清单) | docs + 配置 | 全库 grep 无 serial-mcp-server 残留引用(本文 §12 工具历史除外) ✅ |
提交:全部完成后单提交(pre-commit 门禁;纯宿主侧 Python,不涉及 Keil 构建)。
@@ -185,15 +185,15 @@ static void phaseN_run(void) {
| 工具 | 位置 | 作用 |
|---|---|---|
| Python 串口助手(serial_tool) | `tools/serial_tool/serial_tool.py`(.venv + pyserial) | 常驻 daemon + 薄 CLI:列端口 / 开关 / 收发 / 全量日志 / wait-idle |
| `test/run_boot_test.ps1` | `test/` | 一键闭环:采集 → 烧录 → 提取日志 → 校验 |
| `test/verify_log.ps1` | `test/` | 日志标记校验(Required / Forbidden → PASS / FAIL) |
| `test/run_boot_test.py` | `test/` | 一键闭环:采集 → 烧录 → 提取日志 → 校验 |
| `test/verify_log.py` | `test/` | 日志标记校验(Required / Forbidden → PASS / FAIL) |
| `.opencode/serial_config.json` | 仓库 | **串口端口单一配置源**(当前 COM6 / 115200);换端口只改这个文件 |
| `test/ftp_*.py`(4 个)/ `ch395f_socket_test.py` / `time_sync_server.py` | `test/` | PC 端交互测试工具(FTP 客户端 / socket 回显 / 对时推送) |
| `simulator/tests/*.py`(4 个) | `simulator/tests/` | LVGL 模拟器回归脚本(见 §5) |
### 4.2 新工具约定
- **PowerShell 脚本必须纯 ASCII**(编码铁律:会读写中文源码的脚本不得含非 ASCII,见 `run_boot_test.ps1` 头注);
- **test/ 自动化脚本为纯 Python 标准库**(2026-09-20 由 PowerShell 迁移:绕开控制台代码页/执行策略陷阱,全部 I/O 显式 UTF-8/字节级处理;`requirements.txt` 仍须纯 ASCII——pip 按 GBK 代码页解码);
- **Python 统一用仓库 `.venv`**;第三方依赖必须进 `requirements.txt`(纯 ASCII);
- 落位:板端交互工具 → `test/`;模拟器回归 → `simulator/tests/`;
- 新工具引入新的"通过标记"时,必须登记到 §6.2 标记表,供 `@test` 闭环复用。
@@ -241,7 +241,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
```mermaid
flowchart TD
A[代码改完] --> B["G1 @build(0 错 0 警,否则修复重编)"]
B --> C["run_boot_test.ps1:烧录前武装采集(等 first-byte)"]
B --> C["run_boot_test.py:烧录前武装采集(daemon 全量日志兜底)"]
C --> D["@download 烧录(Reset & Run 触发重启)"]
D --> E[提取日志 + verify_log 标记校验]
E -->|exit 0| F["PASS → G3(UI 改动)→ L3 上机目检 → 提交"]
@@ -263,7 +263,7 @@ flowchart TD
### 6.3 三条铁律
1. **采集必须先于烧录武装** —— 开串口 + clear 在烧录前完成(daemon 常驻全量日志兜底,不会漏字节;`run_boot_test.ps1` 已保证顺序);
1. **采集必须先于烧录武装** —— 开串口 + clear 在烧录前完成(daemon 常驻全量日志兜底,不会漏字节;`run_boot_test.py` 已保证顺序);
2. **端口以 `.opencode/serial_config.json` 为准** —— 每次连接前先读它;
3. **静默判据覆盖时间窗** —— `-SettleMs=8000`(覆盖 boot ~3-4s 自然静默间隙)、`-MaxWaitMs=30000`(整体超时兜底);
@@ -333,7 +333,7 @@ flowchart LR
| `storage_test.h` / `storage_test_task.c` | STORAGE 套件:FTL + FatFS 集成(TC-STO-01~04)+ 恢复测试 |
| `gd5f_test.h` / `gd5f_test_task.c` | GD5F 套件:NAND 驱动 10 阶段 |
| `sd2506_test.h` / `sd2506_test_task.c` | RTC 套件:SD2506 RTC 2 阶段组 |
| `run_boot_test.ps1` / `verify_log.ps1` + `serial_tool` | 自动化闭环三件套(ps1 纯 ASCII / Python 仓库内置) |
| `run_boot_test.py` / `verify_log.py` + `serial_tool` | 自动化闭环三件套(纯 Python 标准库 / 仓库内置) |
| `ftp_test.py` / `ftp_capture.py` / `ftp_up_dl_test.py` / `ftp_speed_test.py` | FTP PC 端测试工具 |
| `ch395f_socket_test.py` | CH395F PC 端 socket 回显 / 大文件传输工具 |
| `time_sync_server.py` | 对时推送 PC 端服务器 |
@@ -58,7 +58,7 @@
| 项 | 说明 |
|---|---|
| `@test` 标记 | 套件结尾汇总行(如 `=== Storage Tests:`)或阶段标题行;**必须与串口实际输出逐字一致**(`verify_log.ps1` 子串匹配) |
| `@test` 标记 | 套件结尾汇总行(如 `=== Storage Tests:`)或阶段标题行;**必须与串口实际输出逐字一致**(`verify_log.py` 子串匹配) |
| 禁止模式 | 默认 `FAIL;ERROR;HardFault;assert`,可按模块增补 |
| PC 端脚本 | `test/*.py` 工具清单与调用方式 |
| 门禁层级 | L1(板端套件)/ L2(串口标记 + 模拟器回归)/ L3(人工目检),见 `测试开发标准流程.md` §1 |
@@ -201,7 +201,7 @@ DP-{NN}
| 通道 | 判定方 | 适用 |
|---|---|---|
| 串口日志标记 | `@test` / `verify_log.ps1` 子串匹配 | 启动序列、阶段标题行、关键事件 |
| 串口日志标记 | `@test` / `verify_log.py` 子串匹配 | 启动序列、阶段标题行、关键事件 |
| 返回值 / 寄存器 / 数据 | 板端 `XXX_TEST_CHECK` 断言 | 驱动命令、协议交互、数据完整性 |
| 像素参考 | LVGL 模拟器回归(`simulator/tests/`) | UI 渲染、字体、样式 |
| 内存池水位 | 模拟器池基线 / 往返常量 | LVGL 对象泄漏、结构漂移 |
+6 -6
View File
@@ -10,7 +10,7 @@
├─ Step 0 预检 .venv + serial_tool(selftest/ports 确认 COM)
├─ Step 1 构建验证 MDK-ARM/build.bat (0 错误 0 警告才继续)
├─ Step 2 烧录 + 采集(一条命令编排:开串口 + 清日志 → 烧录 → wait-idle → 提取)
│ test/run_boot_test.ps1 (内置 serial_tool + download.bat + verify_log.ps1)
│ test/run_boot_test.py (内置 serial_tool + download.bat + verify_log.py)
├─ Step 3 判定:
│ PASS → 报告,结束
│ FAIL → 依据 [MISS]/[HIT] + 日志尾部,修改代码后回到 Step 1
@@ -23,15 +23,15 @@
| `@build` | `.opencode/command/build.md` | 仅编译验证(0 错误 0 警告) |
| `@download` | `.opencode/command/download.md` | 编译并烧录(ST-Link) |
| `@test` | `.opencode/command/test.md` | 完整闭环:build → capture+download → verify → iterate |
| `test/run_boot_test.ps1` | `test/run_boot_test.ps1` | **一键闭环**:open + clear → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 `[RX]` → verify,退出码 0=PASS/1=FAIL/2=采集或烧录错误/3=用法错误 |
| `test/run_boot_test.py` | `test/run_boot_test.py` | **一键闭环**:open + clear → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 `[RX]` → verify,退出码 0=PASS/1=FAIL/2=采集或烧录错误/3=用法错误 |
| `tools/serial_tool/serial_tool.py` | `tools/serial_tool/` | Python 串口助手(常驻 daemon + 薄 CLI):ports/open/send/status/log/clear/wait-idle/selftest;全量日志 `state/serial.log`(20MB 自动截头) |
| `test/verify_log.ps1` | `test/verify_log.ps1` | 对日志做标记校验,输出 PASS/FAIL 并返回退出码 |
| `test/verify_log.py` | `test/verify_log.py` | 对日志做标记校验,输出 PASS/FAIL 并返回退出码 |
## 判定标准
- **构建**:`@build` 退出码 0(0 错误 0 警告),否则不进入硬件环节。
- **烧录**:`@download` 退出码 0(`run_boot_test.ps1` 内部调用)。
- **日志**:`verify_log.ps1` 退出码
- **烧录**:`@download` 退出码 0(`run_boot_test.py` 内部调用)。
- **日志**:`verify_log.py` 退出码
- `0` = PASS:所有 `-Required` 标记均出现,且无 `-Forbidden` 模式命中
- `1` = FAIL:存在缺失标记(`[MISS]`)或违规模式(`[HIT]`)
- `2` = 日志文件不可读
@@ -54,7 +54,7 @@
| `selftest` FAIL / `ModuleNotFoundError: pyserial` | venv 未建或依赖缺失:按 AGENTS.md「Python 环境」重建 `.venv` + `pip install -r requirements.txt` |
| daemon 无响应 / 自动拉起失败 | 查 `tools/serial_tool/state/daemon.log`;`serial_tool.py restart` 重建 daemon;检查 COM 是否被其他程序占用 |
| 抓到日志缺 `Network Init` | `-SettleMs` 太小(boot 任务间有 ~3-4s 自然静默间隙),用默认 8000ms |
| 烧录后无数据(`no_data`) | 开串口 + clear 必须在烧录**前**完成(`run_boot_test.ps1` 已保证);核对 COM 号、板子供电,看 `state/serial.log` 有无 SYS 异常行 |
| 烧录后无数据(`no_data`) | 开串口 + clear 必须在烧录**前**完成(`run_boot_test.py` 已保证);核对 COM 号、板子供电,看 `state/serial.log` 有无 SYS 异常行 |
| 端口被占用(`port busy`) | 先 `serial_tool.py close` 或 `restart`;检查其他程序占用;Keil ST-Link 不占 COM |
| 日志中无 UI 相关输出 | 见下节「UI 自动化」 |
+2 -2
View File
@@ -27,7 +27,7 @@
### P0-1 配置引擎临时缓冲用 C 库 malloc(MicroLIB C 堆仅 512 B)→ 真机配置加载/保存必然失败 ✅ 已修复(2026-09-18)
- **位置**:`App/cfg_file.c` 修复前 `:485`(读缓冲 4,097B)/ `:522`(模板输出 5,120B)/ `:1038`(外科保存 Pass1 副本 ≤4,097B)/ `:1050`(保存输出 5,120B);根因参数在 `MDK-ARM/startup_stm32f407xx.s:43` `Heap_Size EQU 0x200`
- **证据**(静态三重,可独立复核):① `.map`(2026-09-16)`0x2001e878 - 0x00000200 Zero RW HEAP` 且 `__heap_limit = 0x2001ea78` → **C 库堆总量 = 0x200 = 512 B**;② 交叉引用 `cfg_file.o(i.s_load_file)` / `(i.s_write_template)` / `(i.cfg_file_save)` `refers to malloc.o(i.malloc)`,请求量 4,097 / 5,120 B,且全仓库无 `pvPortMalloc` retarget;③ `.lnp` 带 `--library_type=microlib`,MicroLIB 堆为固定区不可外扩。调用链:`Src/freertos.c:234 net_cfg_load()` → `Drivers/BSP/NETCFG/net_cfg.c:146 cfg_file_load()` → `s_load_file()` → `malloc`。
- **影响**:真机上配置文件**读不进也写不出**——上电加载回落工厂默认(192.168.1.100/24)、首启出厂模板生成失败、UI 保存与外科保存全部失败;日志签名 `read: malloc 4097B FAIL` / `template: malloc 5120B FAIL` / `load: file read FAIL, factory defaults kept`。**PC 模拟器走宿主 CRT 堆(MB 级)完全正常** → 双端行为分裂,双端 0 错 0 警也照不出来(`--cfgtest` PASS 亦不能证伪)。`test/verify_log.ps1` Forbidden 含 `FAIL`,一次 `@test` 即可捕获。
- **影响**:真机上配置文件**读不进也写不出**——上电加载回落工厂默认(192.168.1.100/24)、首启出厂模板生成失败、UI 保存与外科保存全部失败;日志签名 `read: malloc 4097B FAIL` / `template: malloc 5120B FAIL` / `load: file read FAIL, factory defaults kept`。**PC 模拟器走宿主 CRT 堆(MB 级)完全正常** → 双端行为分裂,双端 0 错 0 警也照不出来(`--cfgtest` PASS 亦不能证伪)。`test/verify_log.py` Forbidden 含 `FAIL`,一次 `@test` 即可捕获。
- **修复**(2026-09-18 实际实施):① `cfg_file_store` 后端新增 `cfg_store_alloc` / `cfg_store_free` / `cfg_store_heap_free` 三件套——MCU 端 = `pvPortMalloc`/`vPortFree`(取 FreeRTOS 堆 49,152B,与 `lftpd_io.c` 既有模式一致),模拟器端 = `malloc`/`free`;共享核心 `cfg_file.c` 内 C 库分配符号清零,双端仍可同源编译;② 新增编译期堆峰值预算 `CFG_HEAP_BUDGET = 10,240B`(typedef 负数组实现,ARMCC 5 C99 无 `_Static_assert`)——放大 `CFG_FILE_MAX_LEN`/`CFG_OUT_MAX` 会先编译失败,而不是退化为真机运行期失败;③ 四条失败路径(加载读失败 / 模板写失败 / 保存分配失败 / 保存写盘失败)补 `syslog_post(SYSLOG_SELFTEST, …)`,失败进自检记录页而非只留一行串口;`load: OK` 行附带 `heap free` 实测值;④ 文件头"属主任务"注释 netTask → defaultTask(P1-3 遗留漂移)。
- **未采用方案**:静态缓冲(4,097 + 5,120 = 9,217B,当时 SRAM1 仅余 4,488B 放不下,须先做 CCM 迁移);调大 MicroLIB `Heap_Size`/加 `--heap`(只是把"必然失败"变成"够大就侥幸",且该堆无碎片与水位观测)。**流式读写(免整文件驻留内存,+≈1.2KB 即可彻底摆脱暂态堆)列为后续改进项**,见《项目审查与优化建议报告》§4.4.1。
- **验证**:MCU `@build` 0 错 0 警;map 复核 `malloc.o` 不再参与链接、`Removing startup_stm32f407xx.o(HEAP), (512 bytes)` → 静态区 126,584 → **126,064 B**(余 4,488 → **5,008 B**),并新增 `cfg_file.o → cfg_file_store_mcu.o(cfg_store_alloc) → heap_4.o(pvPortMalloc)`;模拟器重建 0 警 + `lvgl_sim.exe --cfgtest` **PASS**(加载 523B → 外部编辑沉降重载 → 外科保存注释/值无损)。**待补**:真机 `@test` 一次,确认 `load: OK` 出现且 Forbidden `FAIL` 零命中。
@@ -161,7 +161,7 @@
- `Drivers/BSP/UI/ui_net_sink.c`:代次号重建监听、逐字节失步重同步、`RM_MAX_RX_PAYLOAD` 长度防护齐全。
- FatFS 卷归属:产品构建单卷拥有者 = defaultTask 的 `f_mount` 实例,lftpd 复用不另 mount;`FF_FS_REENTRANT=1` ✓。
- CH395F trap 修复在位:Trap 01(listen 顺序)、Trap 10(xTaskNotify)、Trap 11(单连接 accept)、Trap 20(send 分块 `NET_SEND_CHUNK_MAX`)均核验存在。
- 宿主侧:`test/verify_log.ps1`、`test/run_boot_test.ps1`、`test/time_sync_server.py`(伪 epoch 与时区处理注释完备)、`tools/menu_gen/gen_menu.py`(自带校验:拒 Tab/缩进非整倍数/节点 >255)、`tools/serial_tool/`(近期已验证)均健康。
- 宿主侧:`test/verify_log.py`、`test/run_boot_test.py`、`test/time_sync_server.py`(伪 epoch 与时区处理注释完备)、`tools/menu_gen/gen_menu.py`(自带校验:拒 Tab/缩进非整倍数/节点 >255)、`tools/serial_tool/`(近期已验证)均健康。
## 待确认(需手册/硬件/产品定义,暂不直接改码)
+2 -2
View File
@@ -149,7 +149,7 @@ python tools/font_gen/extract_cn.py # 任意 python3:
|---|---|---|
| Python 串口助手 | `tools/serial_tool/serial_tool.py`(仓库内置,.venv + pyserial) | 常驻 daemon + 薄 CLI + 全量日志文件;无需单独安装,`pip install -r requirements.txt` 即就绪 |
| 调试串口 | USART1(PA9 TX / PA10 RX),115200 8N1 | **端口单一配置源 `.opencode/serial_config.json`**(本机 COM6);换端口只改这个文件 |
| 一键测试 | `test\run_boot_test.ps1`(即 `@test`) | 开串口 + 清日志 → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 → 标记校验;默认端口取 `serial_config.json` / 115200,退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法错误 |
| 一键测试 | `test\run_boot_test.py`(即 `@test`,`& '.venv\Scripts\python.exe' test/run_boot_test.py`) | 开串口 + 清日志 → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 → 标记校验;默认端口取 `serial_config.json` / 115200,退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法错误 |
> 采集 = 端口常开 + daemon 全量日志(`tools/serial_tool/state/serial.log`),无采集窗口/first-byte/EOF 重试仪式。
> 命令契约与陷阱见 `docs/测试说明/串口助手设计说明.md`、`docs/测试说明/自动化测试流程.md`。
@@ -381,7 +381,7 @@ pre-commit run --all-files
|---|---|
| 下载方式 | `& "MDK-ARM\download.bat"`(Keil 命令行:烧写 + Reset & Run) |
| 下载器 | 工程已配 `UL2CM3` 调试驱动 + `STM32F4xx_1024` Flash 算法;**物理下载器按现场选择**(本机为 ST-Link——不占 COM 口,可与串口调试并存);新机器在 Keil `Options for Target → Debug → Settings` 选择与硬件一致的驱动 |
| 调试日志 | USART1 115200;抓开机日志必须**先武装采集再复位**(`test/run_boot_test.ps1 -FlashCmd` 已保证顺序) |
| 调试日志 | USART1 115200;抓开机日志必须**先武装采集再复位**(`test/run_boot_test.py --flash-cmd` 已保证顺序) |
### 3.5 功能配置开关