Files
STM32F4-Base/docs/测试说明/实机测试实施指南.md
T
wandering1 2fd8a86490 refactor(注释): 把内部阶段代号 S4 与 S7 换成平实语言——查不到的代号不算可检索锚点
用户 2026-10-14 就定过这条(以后没人知道这种编码,要简单明确),这次把最后两处内部分层代号清干净:
· 串口自检判据里的 S7 → 直接写自检台账联合判定;用例追溯里的 S4 → 写用例追溯校验。
· 涉及烧录编排器与日志校验器的帮助文本、两份数据目录 README 的字段说明,以及看门狗、存储维护、
  实机测试、链路延迟四篇文档的同一处措辞。

判据没变,改的只是**读起来能不能查得到**:S7/S4 这类号在任何登记表里都查不到定义,注释里留着,
后来人只能靠问人——而这类内部分层代号正是当年编号失控的起点。门禁:doc-links 与 id-check 均 rc=0。
2026-10-27 14:16:26 +08:00

509 lines
42 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.
# 实机测试实施指南(On-Board Test Guide)
> **文档定位**:本文 = 上板(真机)测试的**执行流程**——按顺序执行。
> 每步给出「目的 → 判据(可观测、量化)→ 命令 → 状态(✅ 已闭环 / ⬜ 待执行)」。
> **已完成事项**(S7、A1~A4)的实施细节与证据**不在本文**,见对应模块文档(§10 状态与去向)。
> **前置铁律**:本文所有步骤**均在接上 MCU / 串口 / ST-LINK 之后**执行;
> 无实机时**只读本文,不执行任何烧录**。
> **上游**:`docs/任务规划/README.md`(统一登记簿:P-x / N·S·T-x /
> S1x·A-x / 阶段排序 / 诊断基线)·
> `子系统设计/看门狗设计说明.md`(§7 验证记录)。
> **约定**:本文事项完成后**先销上游登记**,再在文末变更记录留一行;
> 结论与证据沉淀进对应模块文档/问题记录(2026-10-02 台架窗口的完整取证链——
> IWDG PR/RLR 静默错配 / dhara resume 回滚 / ORE 僵尸通道——见 `看门狗设计说明.md` 2026-10-02 变更记录、
> `STM32F4-Base存储架构说明.md` §5.4.1、`控制台单写者日志设计说明.md` §12;修复已随 `930215f` 提交)。
---
## 1. 执行流程总览
台架窗口就绪后,**按下列顺序执行**(P0 → P1 → P2 → P3):
| 步骤 | 事项 | 状态 | 章节 |
|---|---|---|---|
| **步骤 1** | 环境预检(P0-A,每次上台架必跑) | 常设 | §2 |
| **步骤 2** | 产品 `@test` 闭环 + 自检结果判定(P0-B) | ✅ 已闭环 | §3 |
| **步骤 3** | IWDG 故障注入 V2/V4 + 长跑 V5(P1-A) | ✅ 已闭环 | §4 |
| **步骤 4** | 堆低水位告警实测(P1-B) | ✅ 已闭环 | §5 |
| **步骤 5** | GD5F 错误通道回归(P2-A) | ✅ 已闭环 | §6 |
| **步骤 6** | 网络稳定性与基线重锁(P2-B / 日志静默观察项 + L5 队列往返基线待重验) | ◐ 部分闭环(7.1/7.2 ✅;7.3 待 PC peer) | §7 |
| **步骤 7** | 工程卫生(P3 + 待核实项) | ✅ 已闭环 | §8 |
> **每步出口**:`@build` 0/0 → 一轮 `@test` PASS → ST-LINK 全片回读 `No difference found` →
> 上游登记销项 + 文末变更记录留痕。
>
> **参考**(非执行步骤):§9 执行注意(实测陷阱)· §10 已完成事项与证据去向 · §11 引用闭环。
---
## 2. 步骤 1:环境预检(P0-A,每次上台架前必跑)
> **目的**:避免"改动没问题、台架有问题"的误判(历史上多次把接线/权限问题误判为代码缺陷)。
| # | 检查 | 命令 | 通过判据 |
|---|---|---|---|
| A1 | 工作区干净 | `git status --short` | 无输出(或有明确待提交项) |
| A2 | 产品构建 0/0 | `& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py` | 末行 `BUILD_OK: 0 errors, 0 warnings` |
| A3 | 构建产物为**产品态** | 检查 `test/board/test_config.h` L30-33 | 四个 `TEST_SUITE_*` **全部注释** |
| A4 | `.map` 非测试态 | 看 `MDK-ARM/STM32F407-Demo/STM32F407-Demo.map` 的 `ER_IROM1` | 产品态基线随已接受的修复增长:262,100(初版)→ 262,836 B(10-02 第 1~6 轮台架)→ 264,284 B(第 7~9 轮台架)→ **264,936 B(当前,含 A2/A3/A4 补码)**;明显阶跃 ≈3.7KB 及以上(10-02 实测产品 262,836 → 套件 266,540)= 停在套件态 → 重跑 A2 |
| A5 | 全量静态门禁 | `pre-commit run --all-files` | **17/17 Passed**(2026-10-03 实测;含新增 `test-cppcheck`) |
| A6 | ST-LINK 探针可见 | `& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py list`(CLI 经 `DTU_STLINK_CLI` / PATH 解析) | 列出探针 SN `0B250D12A218303030303032` |
| A7 | 串口端口正确 | 检查 `.serialtest/config.json` 的 `portName` | 端口单一配置源 = 此文件(当前 COM6,2026-09-21 台架重插后由 COM7 变更);变更后先杀旧 daemon 再 `open` |
| A8 | 串口助手 daemon 可用 | `& '.venv\Scripts\python.exe' .dsh/skills/serial-assistant/scripts/serial_tool.py status` | 返回 JSON,`open: true/false` 可读 |
> ⚠️ **A4 的陷阱**(2026-10-02 实测):`@build` 是**增量**构建,`run_all_suites.py` 跑完
> 套件后 `.map` 会停在**测试套件体积**;仅还原 `test_config.h` 不够,**必须再编一次产品固件**
> (`run_all_suites.py` 已在 `finally` 内自动补这一步)。
**预检失败处置**:任一项 FAIL → **不上台架**,先修到全绿(避免"带病测试"浪费台架窗口)。
---
## 3. 步骤 2:产品 @test 闭环 + 自检结果判定(P0-B) · ✅ 已闭环
> S7 判定已落地并投用;A1~A4 已闭环。**实施细节与真机验证证据见 §10 状态与去向**,本节只给复跑命令与判据。
### 3.1 执行
`@test` 闭环除串口标记外,还判定设备侧自检结论(v1 只记故障、不记通过):
`selftest.log` **缺失 / 0 字节 → 无故障 → PASS**;`filesize/64 > 0`(任一 64B 定长记录)
= 有故障 → FAIL,并打印故障条目(时间戳 + 描述)便于定位。
```bash
# 一键闭环(selftest.log 自动 FTP 抓取;无故障记录 = PASS)
& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py --require-selftest-pass --device-ip 192.168.1.100
# 或手动联合判定(本轮串口日志 + selftest.log 本地副本)
& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/verify_log.py \
--log-path <本轮串口日志> \
--require-selftest-pass \
--selftest-log <下载的 selftest.log 本地副本>
# 判据:退出码 0;输出含 "[OK] selftest: no fault record"
```
### 3.2 自检项清单(S7 判定覆盖面,20 处)
> 来源:全库 `syslog_post(SYSLOG_SELFTEST, ...)` 调用点。**这是 S7 的判定覆盖面基准**。
| 文件 | 自检描述串 |
|---|---|
| `App/app/app_main.c` | `watchdog reset` / `clock chip fault` / `NAND fault` / `ADC fault` |
| `App/cfg/cfg_file.c` | `cfg heap alloc fail`(×3) / `cfg template write fail` / `cfg load oversized` / `cfg load read fail` / `cfg save read fail` / `cfg save overflow` / `cfg save write fail` / `cfg poll oversized` |
| `App/task/default_task.c` | `filesystem fault`(×2) / `storage fault`(×2) |
| `App/task/net_task.c` | `comms fault` / `net init fail` / `net reinit fail` |
**联动**:`syslog_post` 的两级自愈(L1 文件级重试 / L2 错误去重 `s_fault_reported[]`)
决定**持续故障只留第一条**——故 S7 判定"有记录即 FAIL"是**充分**的(不会被去重掩盖)。
---
## 4. 步骤 3:IWDG 故障注入与长跑(P1-A 收尾) · ✅ 已闭环
> **2026-10-03 台架结论**(实施细节与证据见 `子系统设计/看门狗设计说明.md` 变更记录):
> V2/V4/V5 三用例全部通过——V2(任务饿死)声明 stall 后 ≤2.5s `reset cause: IWDG`;V4(关中断死循环)每 ~4.9s 稳定 IWDG 复位(IWDG 独立于中断);V5(30 min 真实负载)**120/120 次 FTP 传输全 PASS、零 IWDG 复位**。
> **遗留观察**:V5 期间 44 次 stall 声明 100% 与 `e02_probe` 探针的 time_sync 30s 掉线+监听重建重合;隔离实验(仅 FTP 120s)**0 次 stall** → 探针场景专属,非一般负载误杀(已登记 `docs/任务规划/登记簿.md`)。
> 来源:`子系统设计/看门狗设计说明.md` §7 验证记录(原实施步骤已并入该文档文末变更记录)。
> 判定状态机与 IWDG 配置(PR/RLR 按设计值写入)已落地并经真机验证(2026-10-02,`930215f`,
> 见设计说明 2026-10-02 变更记录);故障注入 + 长跑验收结论见上文 2026-10-03 段落。
### 4.1 三个验收用例
| # | 用例 | 注入方法 | 通过判据 |
|---|---|---|---|
| **V2** | 任务饿死 | 临时在 `netTask` 循环插 `while(1);` | 800 ms 后串口 `[ERR] WATCHDOG: task stall mask=0x...`;≤2.5 s 复位;重启后 `[WD] reset cause=watchdog reset` |
| **V4** | 关中断死循环 | 临时插 `taskDISABLE_INTERRUPTS(); while(1);` | ≤2.5 s 复位(检验 IWDG **独立于中断**);`cause=watchdog reset` |
| **V5** | 长期不误杀(**核心验收项**) | FTP 大文件传输 + UI 菜单遍历 + 配置保存 + 网络重配 **≥30 min** | **零复位**(重点验证 `docs/子系统设计/看门狗设计说明.md` §4.3 白名单是否完备) |
> ⚠️ **V5 是核心验收项**:误杀比不杀更有害。必须在**真实业务负载**下跑足时长。
### 4.2 执行步骤
```bash
# --- V2/V4(故障注入,需临时改码)---
# 1) 基线:跑一轮产品 @test 确认无复位
& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py
# 2) 注入:按 `docs/子系统设计/看门狗设计说明.md` §7 在 netTask 循环插 while(1);(或 taskDISABLE_INTERRUPTS(); while(1);)
# —— 改完 @build,然后烧录
& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py
& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash MDK-ARM\STM32F407-Demo\STM32F407-Demo.hex
# 3) 抓串口日志,确认 [ERR] WATCHDOG task stall + 复位原因
# 4) 回读校验复位后镜像(ST-LINK_CLI 经 DTU_STLINK_CLI 解析,未设时回退 PATH,不写死路径)
$cli = if ($env:DTU_STLINK_CLI) { $env:DTU_STLINK_CLI } else { (Get-Command ST-LINK_CLI.exe).Source }
& $cli -c SWD -CmpFile MDK-ARM\STM32F407-Demo\STM32F407-Demo.hex 0x08000000
# 判据:No difference found
# 5) 撤销注入,@build 回产品态,再跑一轮 @test 确认正常
# --- V5(长跑,需真实负载)---
# 1) 用 test/host/ftp_speed_test.py / ftp_up_dl_test.py 持续传输大文件
& '.venv\Scripts\python.exe' test/host/ftp_speed_test.py
# 2) 同时人工/脚本遍历 UI 菜单 + 反复保存配置 + 触发网络重配
# 3) 持续 ≥30 min,全程串口记录
# 判据:零复位(日志无 "reset cause=watchdog reset");业务不中断
```
**风险/回滚**:
- 故障注入用例**会复位设备多次**——确认设备非在用/非已部署。
- 长跑涉及 NAND 写入(FTP 上传)**消耗 NAND 块**——若设备已接近容量上限,改用只读传输。
- ⚠️ **R5 风险**(`docs/子系统设计/看门狗设计说明.md` §9):NAND 擦写偶发超 800 ms 可能误复位——若 V5 出现偶发复位,
先按设计说明增大容忍次数或把存储操作改分段置位,**不要盲目放宽全局超时**。
---
## 5. 步骤 4:堆低水位告警实测(P1-B,S11) · ✅ 已闭环
> **2026-10-03 台架结论**:告警代码(`default_task.c` 的 `HEAP_LOW_WATER_B=3072` 门闩 + `[HEAP]` 告警 + syslog 自检)已落地;复用 §4.2 V5 窗口 30 min 长跑,**全程未触发**(`min_ever=4728 B` > 3072 B)→ 记录"当前负载下 min_ever 仍高于阈值"为基线,已更新 `内存管理/RAM使用分析与优化方案.md`。
**现状证据**:2026-10-03 上板复测 `free=8,688 / min_ever=3,712~4,728 B`
(两次开机,运行间波动 ≈1KB;初始 `configTOTAL_HEAP_SIZE` 48KB)——
**min_ever 下限已跌破 4KB**,余量不到 8%,新增任务/缓冲可能触发分配失败。
现有代码仅有周期性 `[STACK]` 报告(每周期打印 `heap free/min_ever`),**无阈值告警、不写自检记录**。
**待补代码**(约 15 行 + 1 个编译期常量,在 `defaultTask` 低频循环(LED 闪烁节拍)内):
检查 `xPortGetMinimumEverFreeHeapSize()`,低于阈值(建议 **3072 B**,低于 10-03 实测下限 3,712 B,防运行间波动误报)时
`DBG_ERROR("[HEAP] low water: %u B")` + 写 syslog selftest。
**判据**:台架长跑(复用 §4.2 V5 窗口)下,若发生低水位 → 串口出现告警行 + `selftest.log` 有记录;
若全程未触发 → 记录"当前负载下 min_ever 仍高于阈值"作为基线。
**执行步骤**:
```bash
# 1) 代码改动(约 15 行 + 1 个编译期常量)在 defaultTask 低频循环内
# 2) @build 0/0 后,与 §4.2 V5 长跑合并执行
# 3) 长跑结束读取 min_ever:
# - 串口 [HEAP] 告警行(若有)
# - 或 FTP 取 /log/selftest.log
# 4) 更新 docs/内存管理/RAM使用分析与优化方案.md 的 min_ever 基线
```
**成本/回滚**:约 15 行 + 零额外缓冲;阈值设编译期常量便于按新基线调整。
若长跑中频繁触发但系统正常 → 说明阈值偏紧,据实测值调整(不是缺陷)。
---
## 6. 步骤 5:GD5F 错误通道统一(P2-A,S9 = 上游 C2) · ✅ 已闭环
> **2026-10-03 台架结论**:四要素(分类/透传/分级/留痕)+ 返回类型统一 `int32_t` 已落地。
> 套件回归:`test/run_all_suites.py --suites gd5f` → **`=== GD5F2GQ5UE Tests: 16/16 PASSED (failed=0) ===`**(只读模式,4 个破坏性用例按设计跳过);编排器 `[GD5F] -> PASS`。
> **顺带修复(编排器缺陷,非本次代码引入)**:`run_all_suites.py` 原对所有套件统一 `--forbidden "HardFault;assert;[ERR]"`,而 GD5F 的 `TC-GD5F-704`(CCM 非 DMA 可达缓冲)会**预期**打出 `[ERR][NAND] RX DMA buffer not DMA-reachable ... fallback poll`(用例 PASS)→ GD5F 套件**永远被判 FAIL**(自 `2055de0` 起)。按 `verify_log.py` 的说明改为**按套件覆盖 `--forbidden`**(GD5F = `HardFault;assert`),修复后 PASS。
> **来源**:第二档 #1;
> `docs/产品需求/产品需求设计文档.md` §7.1(错误码通道四要素骨架,设计基线)。
**现状证据**:`ch395f.c`(1330 行) 与 `gd5f2gq5ue.c`(1496 行) 是同代驱动,但**只有 CH395F**
形成了"分类 + 传播 + 审计"完整体系;GD5F 错误处理散落各函数,`Trap_Records` 仅 198 行。
**统一错误通道四要素**(以 CH395F 为范式):
| 要素 | 内容 |
|---|---|
| ① **分类** | `wait_busy` 区分「超时 / 真故障 / 参数错」——不得混为一个返回码 |
| ② **透传** | 底层错误码逐层上报,不吞不猜(禁 `(void)ret`) |
| ③ **分级** | 可恢复(重试)/ 不可恢复(上报自检 + 降级)显式判定 |
| ④ **留痕** | 不可恢复项写 syslog selftest;可恢复项计数并在 UI/日志可见 |
| — | 返回类型统一 `int32_t` |
**实施顺序**(数据安全优先):
1. 先建**分类函数**(`gd5f_wait_busy` 内检查三次 HAL 调用)——所有下游判断的基础;
2. 再修**最危险的**:`gd5f_bbt_scan` 失败**放弃持久化**(保护好副本)——**数据安全优先**;
3. 补 **init 全链路检查 + 重试 1~2 次**;
4. 回读 **B0h 校验 ECC 使能**(bit4);
5. `gd5f2gq5ue_read` 的 raw 契约文档化或加 ECCS 检查;
6. 全程在 `GD5F2GQ5UE_Trap_Records.md` 留痕,同步 `GD5F2GQ5UE_Test_Guide.md`。
7. **RAM 预算**:新增错误分支**不得引入新的大缓冲**(先跑 `ram_report.py` 核算)。
**判据**:
- **错误通道审计项全部销项**;
- **GD5F 套件回归 PASS**:
```bash
# 套件回归(需实机)
& '.venv\Scripts\python.exe' test/run_all_suites.py --suite gd5f
# 判据:=== GD5F Tests: N/M PASSED (failed=0) === 且 N>0
# 只编译验证(离机,改动后随手跑)
& '.venv\Scripts\python.exe' test/run_all_suites.py --check-build
```
> ⚠️ **纪律**(呼应 `AGENTS.md` 铁律):自愈逻辑**严禁**把"名字/参数类错误码"
> (如 `FR_INVALID_NAME`)归入"卷损坏触发集"——`.fschk` 无限重格式化事故即此类(2026-09-20)。
> ⚠️ **破坏性用例**:GD5F 套件默认只跑只读;`ENABLE_DESTRUCTIVE_TESTS` 跑一次消耗一个 NAND 块
> (实测 95248→95200),**仅在产线首启或明确需要时打开**。
---
## 7. 步骤 6:网络稳定性与基线重锁(P2-B) · ◐ 部分闭环(7.1/7.2 已闭环;7.3 待 PC peer)
### 7.1 网络重建失败恢复(A2;实施细节见 `网络/Net层阻塞模型架构设计.md`,状态见 §10) · ✅ 正常路径已闭环
**判据**:拔插网线/改 IP 触发重建后——
- 失败路径**写 syslog 自检**(不再零日志);
- **30s 周期重试**,不自驻留死循环;
- 恢复后各 TCP 服务(FTP 21 等)**据代次号重建监听**,功能正常。
**验证手段**:`test/host/e02_probe.py`(网络探针)+ UI 网口设置页改 IP。
**2026-10-03 台架结论**:
- **正常路径 ✅**:V5 长跑(30 min,FTP 512 KB 上/下传)**120/120 PASS、零 IWDG 复位**,
网络重建后的 FTP/time_sync 服务据代次号重建监听、功能正常(证据 `/tmp/v5_soak_serial_20261003.log`)。
- **负向路径(拔线/芯片级 `net_init` 失败)**受**台架拓扑**限制(CH395↔交换机,
拔交换机侧线缆链路仍 UP;芯片级失败需 SPI 故障注入)→ 已登记 `docs/任务规划/登记簿.md` 条目「网络负向场景台架验证」
(① PHY 拔线负向 ② A2 `net_init` 失败分支 ③ A4 短写压测),需专项窗口。
### 7.2 日志静默观察项:49s 全系统日志静默复现与定位 · ✅ 判据②已满足 / 判据①未复现
**现状证据**(登记簿条目「日志静默观察项」):2026-09-22 台架实测,串口日志 **49s 无行**
(testTask/netTask/[STACK] 行全缺),期间 net 栈照常处理外部连接 → **日志管线停滞**,
队列满后各任务日志行被丢;系统功能不受损。
**判据与核实(2026-10-03)**:
- **判据②(队列满丢弃计数/告警)→ ✅ 代码已满足**:日志管线**已有**显式丢弃可观测性——
`App/log/console_log.c` 的 `s_con_drop` 计数 + 排空末尾 `[ERR] CONSOLE dropped %lu lines`
提示 + `dbg_console_dropped()` 访问器;`App/log/sys_log_mcu.c` 的队列满/preboot 满分别
打 `DBG_ERROR("queue full, drop: …")` / `("preboot full, drop: …")`。另 UART TX 卡滞
已由**僵尸通道自愈**覆盖(`con_uart_reinit()` + `[WARN] CONSOLE tx fault: UART reinit`,
`s_con_tx_fault` 计数)。**"现静默丢行、排障不可见"已不成立**。
- **判据①(复现 49s 并定位卡点)→ 未复现**:对 V5 30 min 长跑日志(6031 条带时间戳行)
做间隔分析,**最大静默 41s**(发生在**开机/烧录边界**,非运行期),**运行期无 49s 静默**。
运行期 >10s 的静默共 24 处,**全部**为 ~28s,且**均落在 `e02_probe` 的 time_sync 30s
挂起客户端窗口内**——与「探针窗口心跳缺口」同源(探针场景专属,非通用负载)。
- **结论**:49s 静默在当前固件 + V5 负载下**不复现**;可观测性缺口已由既有代码补齐。
日志静默观察项降级为**低风险**(保留登记,若再现则借 `[ERR] CONSOLE dropped` 计数定位)。
- **后续(2026-10-25,道F 批 2 合并评估)**:窗内静默的同源阻塞机制
(`drop_conn` 同步占用 netTask 400-600ms)已随「登记式拆链」修复
(`../网络/网络自愈架构设计.md` §4.6);日志静默观察项与日志单写者化的合并评估已完成,结论与「无源 vs
真停滞」判别口径落 `../子系统设计/控制台单写者日志设计说明.md` 文末附录——
再现静默先按三本账(`dbg_console_dropped/_tx_fault/_tx_timeout`)+ syslog 丢弃
账对照定性,再决定是否开卡;销项条件 = 探针窗口心跳缺口修复版 V5 复跑(e02_probe + FTP
≥30 min)运行期 `task stall` 与真停滞嫌疑静默段双零(2026-10-25 v1.1 起
`MISS start` 降级为诊断行不计销项——见下方判读工具与
`../子系统设计/看门狗设计说明.md` §6.1)。
- **判读工具 v1.1(2026-10-25 大窗判读 F1 起)**:
`'.venv/Scripts/python.exe' scripts/v5_log_gap_report.py <serial-assistant 日志路径>`
——自动列 `>10s` 静默段(`--gap-threshold-s` 可调),每段带判定(NO-SOURCE /
PROBE-WINDOW / BOOT-WINDOW / TRUE-STALL-SUSPECT)与贴边证据行。违规口径 =
`task stall` 行 >0 **或** 真停滞嫌疑段 >0;退出码 0=达标 / 1=违规 /
2=日志无有效时戳;`--json` 机读、`--report-only` 只出报告、`--selftest`
内嵌合成样例自检(无台架可跑)。**v1.1 变更(判读口径,先文档后脚本)**:
① `MISS start` 降级为**诊断行**(看门狗 v1.5 按位分账后它只是复合缺席边沿,
不代表停喂,`../子系统设计/看门狗设计说明.md` §6.1)——报告改出归因诊断:
开机良性 / 探针窗内 / 窗外运行期 + 窗外每分钟速率 top;v1.0 把运行期 MISS
计违规属收紧过头(2026-10-25 台架 70min 窗 1262 条经逐窗归因实为风暴复合边沿
与传输窗抖动),予以纠正;② `task stall` 行语义 = v1.5 起「同一任务 800ms
单串真停摆」(行文本不变,`../子系统设计/看门狗设计说明.md` §5.3),每行都是
真猎物;开机豁免口径(§9 第 8 条)保留、仅作用于 MISS 诊断分类。口径唯一
来源 = `../子系统设计/控制台单写者日志设计说明.md` 文末附录 + §9 第 8 条 +
看门狗设计说明——改口径先改文档再改脚本(自检断言会拦漂移)。
**执行步骤**:长跑(§4.2 V5)期间周期性打点 + 对照 `CH395F` 无关的 SD2506 侧日志判别卡点。
### 7.3 L5 队列往返基线待重验 · ⬜ 待 PC peer
**现状**:L5 基线(1223/988µs)属**分片时代**;L3 对该路径逐位不变 → 机制上无影响,
但严格重锁需跑一轮 Phase 13(**需 PC peer**)。
**判据**:Phase 13 窗口跑一轮,基线数值与阈值余量(>8×)对照,重锁数值。
**2026-10-03 台架**:本窗口**无 PC peer**,Phase 13 无法执行 → 保留待办(低风险:
阈值余量 >8×,机制上 L3 对该路径逐位不变)。
---
## 8. 步骤 7:工程卫生(P3) · ✅ 已闭环
> S5 / S4 落地(离机可做),待核实项已实机核实并修复。本节留复跑命令与判据。
### 8.1 S5:`test/` 代码宽松静态检查
**现状证据**:`test/` 完全豁免 pre-commit("自律"要求),而 `test/board/` 下 **6300+ 行 C 代码**
(实测 `.c`+`.h` 合计 6,313 行)**且编入固件**。曾出现 `s_rx_buf` 使用先于声明。
**目标**:抓 `test/board/` 固件测试代码的**真实缺陷**(未初始化/越界/空指针),
但不引入存量 style 噪音。
**执行步骤(先跑基线,离机可做)**:
```bash
# 1) 基线统计(不需实机)
cppcheck --enable=warning --error-exitcode=1 test/ 2>&1 | tee test_cppcheck_baseline.txt
# 2) 若存量可控(建议 <20 条)→ 加 test-cppcheck 钩子,只开 warning
# 3) 若存量较多 → 先建 suppress 清单(明确每条豁免理由),再挂钩子
# 4) 务必排除模拟器桩/第三方头(test/host/watchdog/stub/ 等)
```
**判据**:`test-cppcheck` 在 CI PASS;新增测试代码越界/未初始化被自动拦截。
> **注意**:若基线告警过多,**保持现状亦可接受**——此时应把该决策写明确("理由:存量 N 条")。
**结论(✅ 已闭环,2026-10-03)**:已加 `test-cppcheck` 钩子(`.pre-commit-config.yaml`
`id: test-cppcheck`,**仅开 `warning`、排除模拟器桩/第三方头**)。基线可控,
`pre-commit run test-cppcheck --all-files` **PASS**。新增 `test/board/` 代码的
未初始化/越界/空指针问题现由钩子自动拦截。
### 8.2 S4:用例追溯脚本
**现状**:文档声称 91 个 TC、代码有 222 个 `TEST_CHECK`(断言点数 > 用例数是正常的),
但**双向是否一一对应无人校验**。
**目标**:新增 `[计划] scripts/check_test_traceability.py`——
输入 `test/board/*_test_task.c` 的 TC 注释 + `docs/测试说明/*Test_Guide.md` 的 TC 编号;
输出 ① 文档有、代码无(未实现)② 代码有、文档无(未登记)。
**默认仅告警(warning),不阻断提交**(与 `doc-links` 演进路径一致)。
**判据**:一键列出双向差异清单;差异收敛后再考虑升为门禁。
**结论(✅ 已闭环,2026-10-03)**:`scripts/check_test_traceability.py` 已落地并跑通,
**默认仅告警(exit 0)、不阻断提交**。2026-10-26 重打:当前差异 **25 处**(文档有代码无 + 代码有文档无两向),
另有约 1,486 处属"代码有该号、号旁写着人话意图",按「代码即属主登记处」放过——**弱于文档的保证**,
对外举证仍需模块级说明。当年列出的孤儿号(GD5F 那三个 11xx、存储 06 号)已在 2026-10-26 清号批次
里从代码侧删号收口。差异清单可追踪,后续按需补登记;**暂不升门禁**(与 §8.2 目标一致)。
### 8.3 待核实项:`TEST_SUITE_SELECTED` 未含 `TEST_SUITE_RTC` · ✅ 已核实(非缺陷)
**原疑点**(`test/board/test_config.h`):派生标记 `TEST_SUITE_SELECTED` 只含
CH395F / STORAGE / GD5F,未含 RTC;怀疑 RTC 构建下 `testTask` 不被创建 → 套件不执行。
**2026-10-03 实机核实结论**:
- **`TEST_SUITE_SELECTED` 是死代码**:`grep -rn TEST_SUITE_SELECTED` 全仓**仅本文件有定义、
无任何使用点**。`Src/freertos.c` **无条件创建 `testTask`**;`test/board/test_config.c`
的 `start_test_task()` **直接按 `TEST_SUITE_RTC` 等宏分支**(不经 `TEST_SUITE_SELECTED`)。
→ "testTask 不被创建 → RTC 不执行"的推断**不成立**。
- **RTC 套件确实执行**:选 `TEST_SUITE_RTC` 构建烧录后,串口出现完整 RTC 输出
(`SD2506 test suite started` … `Phase 1 basic: 3/3 PASSED` … `Phase 2 API: 6/6 PASSED`)。
- **真正的缺口 = 缺套件级汇总行**:原 `sd2506_test_run()` 只打 Phase 级汇总,**没有**
`=== RTC Tests: N/M PASSED (failed=0) ===` → `run_all_suites.py --require-suite-summary "RTC Tests"`
判 **FAIL**(设备实际 12/12 全过)。属**判据缺口**,非设备缺陷。
**修复(2026-10-03)**:
1. `test/board/sd2506_test_task.c`:各 Phase 进入前**自清零**,末尾输出套件级
`=== RTC Tests: N/M PASSED (failed=0) ===`(复用 `SD2506_TEST_REPORT` 宏,格式与
`test_common.h` 统一)。顺带修正 Phase 级汇总行**累计**问题——原 Phase 2 显示的是
含 Phase 1 的累计值(9/9),现各阶段独立:Phase 1 = 3/3、Phase 2 = 6/6、套件级 = 9/9。
2. `test/board/test_config.h`:`TEST_SUITE_SELECTED` **补齐 RTC** 并注释其"当前无引用",
防止将来真有分支复用时重演"漏 RTC"。
**复跑命令**:`& '.venv\Scripts\python.exe' test/run_all_suites.py --suites RTC`
**判据**:`[RTC] -> PASS`、`VERDICT: PASS`,日志含 `=== RTC Tests: 9/9 PASSED (failed=0) ===`。
---
## 9. 执行注意:实测陷阱(2026-10-02 台架窗口,照做可少绕一天)
1. **写入"复位后消失"的两层原因**(窗口最大坑,根因均已修复,详见模块文档):
- **L1 dhara checkpoint 回滚**(`架构设计/STM32F4-Base存储架构说明.md` §5.4.1):环回绕后
`dhara_journal_resume()` 恢复旧 checkpoint,**之后写的一切整段丢弃**
(已修:epoch 锚点改比较两候选的新旧)。
- **L2 FTL 单页写回缓存**:一次 `disk_write` 里不满整页(2048 B)的写,在**写到另一个 LPN /
整页写 / `CTRL_SYNC`** 之前只存在于 RAM(`nand_ftl.c` 的 `s_cache_buf/s_cache_dirty`)。
但正常 `f_close` 就会走到 `CTRL_SYNC`(FatFs `sync_fs` → `disk_ioctl` → `ftl_flush_cache`),
所以**"写完即关"的路径(日志、配置保存)关文件即落盘,不必再"写另一个文件逼刷"**;会丢的
只有**写事务进行中**掉电/硬复位(含 IWDG 误复位)里最后那笔未跨页的写(≤512 B)——
FTP STOR 传输途中掉电就落在这一档(已登记观察;「写回缓存空闲 flush」于 2026-10-22 裁定暂不做,
缺的是"空闲/掉电前周期 flush",且本机无掉电检测硬件,掉电时点无法补救)。
→ 排查写入丢失时**先看开机日志的 head/tail/epoch**(`Map head=… tail=… epoch=…`,
纯内存字段、零 I/O):head 复位后倒退 = L1(resume 错);head 正常 = L2(缓存未刷)。
(旧口径"清台账/写证据后写另一个文件"的 flush 诱导属 L1 时代的产物:现码 `f_close` 自带
`CTRL_SYNC`,正常写完即关就不需要它;这条诱导只在 `f_close` 失败时才还有兜底意义。)
2. **FTP 路径**:lftpd 相对路径基准是**根目录**(`SIZE selftest.log` → 550),一律用
绝对路径 `/log/xxx`;`LIST /log` 实测列的是**根目录**内容(lftpd 怪癖)——查状态只用
`SIZE` / `RETR`。
3. **0 字节 STOR 的数据连接**存活期仅 ~10~50ms,短于芯片/网络层轮询粒度 → 芯片只见
`DISCONNECTED (chip tcp=0x00)` → accept 失败(425 或控制连接被重置);2026-10-02 实测客户端
`PASV→STOR` 间隔达 **11 s**(数据口 LISTEN 半开)。这是**与看门狗误复位不同的另一类
问题**(CH395F 数据通道);若修复后仍复现 425,转 §7.1 专项。
4. **串口采集铁律**:`open` → `clear` → 烧录/复位 → `wait-idle --timeout 90 --settle-ms 8000
--max-ms 45000` → **直接 Read/Grep `.dsh/skills/serial-assistant/scripts/state/serial.log`**
(`log --grep` 子命令不可信);daemon 残留 → `taskkill /F /PID <旧>` 后重新 `open`。
5. **只用 `.venv\Scripts\python.exe`**(PATH 里的 `python` 是 msys64);每次烧录后**必须**
ST-LINK 全片回读 `No difference found`。
6. **误复位会使台账 +1 条** `watchdog reset`:取证/修复期间台账只会增长,
属预期(清台账留到最后一次修复后的出口闭环)。
7. **ST-LINK_CLI 取证三硬知识**(完整用法见 `ST-LINK_CLI_复位使用说明.md`):
- `-R32` **不会 halt 内核**(`-CoreReg` 才 halt,实测约 30ms/次且可重复)→ 用 `-R32` 做
**无扰动**存活性采样,只在需要 PC 时用 `-CoreReg`(halt 期间 TIM7 ISR 不执行,
会让中断计数出现"假停顿",须用非 halt 读法甄别)。
- `-R32 <addr> <count>` 的 `count` 单位是**字节**(`-R32 0x1000FF00 16` 得 4 个字);
按字理解会把读取**静默截断**。
- `-W32 <addr> <data>` 的 `data` 按**十六进制**解析(写 `1249` 会变成 `0x1249`,
被 12 位 RLR 截断成 `0x249`=585);要写十进制 1249 得传 `0x4E1`。另 `IWDG->KR` 是
**只写**寄存器(读回恒 0),`-W32` 写 KR 必报 `Error!`——那是 ST-LINK 的写-回读
校验失败,**写入其实成功**。
- 现场改寄存器(如 IWDG PR/RLR 验证手段)须在**一次调用**内完成整段键序列
(解锁→参数→键锁)——分多次调用会超过看门狗超时、中途被复位;寄存器随复位丢失,
只能用于验证,不是修复。
8. **开机良性 `MISS start` 行**(2026-10-03 上板):看门狗抽样在**开机屏障等待期**偶见
UI 位单抽样缺席,每 episode 记一条裸 UART `MISS start snap=0x… req=0x… t=…`
(`task_watchdog.c` 的停摆起点标记,round-7 取证件)。实测每次开机 2 条
(t≈0.6s / t≈2.8s,snap 仅缺 UI 位),NET_READY 解除后立即恢复——**未达 800ms 停喂
阈值、不触发复位**,属分片心跳与 100ms 抽样边界的固有交错,非回归;
处置:见到该行不必恐慌,**连续**出现 `task stall` 行/复位才是真停摆。
9. **导航类自动化脚本默认零 ENTER**(2026-10-26 台架实证,task-41 收口;口径也见
`启动日志原子性复验流程.md`):装置维护的 **强制复归 / 清除记录 是两段式确认**——
第一次 ENTER 只把该行标成「确认?」,**第二次 ENTER 才真执行**(复归保护位并写 SOE /
清 SOE·运行·操作记录)。因此任何"认不出屏就按 ENTER 试一下"的回收逻辑,落到这两页上
等于**替操作员按下执行键**;更隐蔽的是它只在画面异常时才发作(新字库缺字、白框、状态行
变化——恰恰是回归最想抓的那几帧),平时零流量、改动时无声。 `scripts/board_ui_nav.py`
的两条硬闸与 `--selftest-quick` 里的 **7 条常驻用例**(假设备 + 内存空白帧 + 按键只记账,
**不连 7003、不开串口、不碰台架**,提交钩子 `uinav-selftest` 就跑这档)把它钉成回归:
① UNKNOWN 退避的 ENTER 上限 `BACKOFF_MAX_E`(政策钉死 ≤1,需要第二次就当场停机并 dump 帧,
报错文案点名执行类风险);② `EXEC_PAGE_IDS`(clear / reset)**默认拒绝下钻**且拒绝发生在
**任何键投出去之前**(真机实测:连轨迹文件都不生成),显式 `--allow-exec-pages` 才放行并打警告。
用例还钉住**两个常量本身**:上限被调到 2 以上、清单被清空、或默认值被翻成"允许"——
都必须在 `--selftest-quick` 里报红(这三条都用"故意改坏再跑"逐条证过能红,不是空跑)。
通用要求:**导航 = 移光标 + 取帧;ENTER 只能出现在明确、非执行类的用例步骤里**;
要看执行类页面的显示正确性,去模拟器黄金参考(那里没有真机后果)。
---
## 10. 已完成事项与证据去向
> 已完成事项的**实施细节与真机证据不在本文**,按下列去向查阅;本文只保留其复跑命令与判据。
| 事项 | 状态 | 实施细节 / 证据所在 |
|---|---|---|
| **S7** 自检结果判定 | ✅ 已落地并投用 | `测试说明/自动化测试流程.md`;提交 `4a4cd29` |
| **A1** `cfg_file` 堆分配改造 | ✅ 已闭环(含真机持久化) | `子系统设计/配置文件设计说明.md`(实施 v1.11 + 2026-10-03 真机验证记录 + 2026-10-04 独立复跑记录) |
| **A2** 网络重建失败恢复 | ✅ 已闭环(正常路径零回归;故障分支见「网络负向场景台架验证」) | `网络/Net层阻塞模型架构设计.md` |
| **A3** CH395F 字节命令超时 | ✅ 已闭环(正常路径零回归;故障分支待专项窗口) | — |
| **A4** `remo_send` 返回值 | ✅ 已闭环(正常路径零回归;推流压测待专项窗口) | — |
| 2026-10-02 台架取证链(IWDG PR/RLR 错配 / dhara resume 回滚 / ORE 僵尸通道) | ✅ 已修 | `子系统设计/看门狗设计说明.md` 2026-10-02 变更记录 · `架构设计/STM32F4-Base存储架构说明.md` §5.4.1 · `子系统设计/控制台单写者日志设计说明.md` §12;提交 `930215f` |
> **真机判定汇总**(2026-10-03,本机 MCU,新固件全闭环 `@test` PASS 7/7):A1 ✅ PASS(含配置持久化);
> A2/A3/A4 正常路径零回归;芯片级失败分支 / 短写 / 拔线负向场景记 `docs/任务规划/登记簿.md` 条目「网络负向场景台架验证」,待专项台架窗口。
---
## 11. 与既有文档的引用闭环
| 本文项 | 上游文档 | 下游落地文档 |
|---|---|---|
| S7 自检判定 | —(原复审项,已闭环 2026-10-02) | `测试说明/自动化测试流程.md`(参数已落地,`4a4cd29`) |
| V2/V4/V5 | `子系统设计/看门狗设计说明.md` §7 验证记录 | `子系统设计/看门狗设计说明.md` 变更记录(2026-10-03) |
| S11 堆告警 | —(原复审项,已闭环 2026-10-03) | `内存管理/RAM使用分析与优化方案.md`(基线更新) |
| S9 GD5F | —(第二档 #1) | `问题记录/GD5F2GQ5UE_Trap_Records.md`、`测试说明/GD5F2GQ5UE_Test_Guide.md` |
| 日志静默观察项 | `docs/任务规划/登记簿.md` | `网络/Net层阻塞模型架构设计.md`(头阻塞,历史编号) |
| 网络重建 | —(原台账项,已闭环 2026-10-02) | `网络/Net层阻塞模型架构设计.md` |
| S5/S4 | —(原复审项,已闭环 2026-10-03) | `测试说明/测试开发标准流程.md` |
| 模拟器差距 | `测试说明/模拟器差距清单.md` §3 决策规则 | 本文为"需回真机"项的执行面 |
> **模拟器差距清单 §3 的六条"必须回真机"规则**决定"哪些改动**必须在本规划内验证——
> 改动触及 `Drivers/BSP/` 寄存器时序 / 模拟器差距清单的硬件专属项 / 配置变更检测与回调 / 网络重建并发 / 启动段 / 内存预算,
> 一律在本文件找到对应批次。
---
## 变更记录
| 日期 | 变更 |
|---|---|
| 2026-10-27 | **§9 新增第 9 条「导航类自动化脚本默认零 ENTER」**(task-41):装置维护两页是两段式确认、第二次 ENTER 即真执行,故导航器禁止用 ENTER 从未知状态脱身;`scripts/board_ui_nav.py` 两条硬闸(`BACKOFF_MAX_E` ≤1 停机、`EXEC_PAGE_IDS` 默认拒绝且投键前即拒)做成 `--selftest-quick` 7 条常驻用例(假设备零注键,提交钩子跑这档),并钉住常量本身(上限调高 / 清单清空 / 默认翻成允许 → 报红,三条均实测能红) |
| 2026-10-03 | **步骤 5/6/7 闭环**:§6 GD5F 错误通道回归 PASS(`=== GD5F2GQ5UE Tests: 16/16 PASSED (failed=0) ===`;E-10/42/53/54/56/57 全部销项;顺带发现并修复编排器判据缺口——GD5F 的 TC-GD5F-704 故意触发 `[ERR]` 回落轮询,`run_all_suites.py` 改为**按套件**覆盖 `--forbidden`,与 `verify_log.py` 说明一致)→ §1/§6 改「✅ 已闭环」。§7 网络稳定性:**7.1 正常路径 ✅**(V5 120/120 FTP、零复位;负向路径转 `N-16`,台架拓扑受限);**7.2 N-2 ✅判据②/未复现判据①**(丢弃可观测性代码已有:`console_log.c` `s_con_drop`+`[ERR] CONSOLE dropped`、`sys_log_mcu.c` 队列满 `DBG_ERROR`、TX 僵尸通道自愈;V5 30 min 日志间隔分析最大静默 41s 且在开机边界、运行期 24 处 >10s 静默**全为 ~28s 且均在 `e02_probe` 窗口内**=N-17 同源)→ N-2 降级低风险观察项;**7.3 N-3 ⬜ 待 PC peer** → §1/§7 改「◐ 部分闭环」。§8 工程卫生:S5 `test-cppcheck` 钩子 PASS(仅 warning,排除模拟器桩);S4 `scripts/check_test_traceability.py` 落地并跑通(**30 处差异**,默认 warn-only);**待核实项 `TEST_SUITE_SELECTED` 实机核实 = 死代码**(全仓无使用点;`start_test_task()` 直接按宏分支,RTC 套件实际正常执行;真缺口 = 缺 `=== RTC Tests: N/M PASSED ===` 汇总行,已补 `test/board/sd2506_test_task.c` 并修正 Phase 级汇总累计问题;`test/board/test_config.h` 补齐 RTC 并注释"当前无引用")→ §1/§8 改「✅ 已闭环」 |
| 2026-10-03 | **步骤 3/4 闭环**:V2/V4/V5 台架验收通过(V2 任务饿死声明 stall 后 ≤2.5s `reset cause: IWDG`;V4 关中断死循环每 ~4.9s 稳定 IWDG 复位;V5 30 min / **120×FTP 全 PASS、零 IWDG 复位**)→ §1 总览与 §4 状态改「✅ 已闭环」,实施细节与证据移入 `子系统设计/看门狗设计说明.md` 变更记录。S11 堆告警代码落地、V5 全程未触发(`min_ever=4728 B` > 3072 B)→ §5 改「✅ 已闭环」,基线入 `内存管理/RAM使用分析与优化方案.md`。新登记 `待处理内容.md` **N-17**(V5 期间 44 次 stall 与 `e02_probe` 的 time_sync 30s 掉线+监听重建重合;隔离实验「仅 FTP 120s = 0 stall」证实探针场景专属) |
| 2026-10-03 | **重构为纯执行流程**:确立单一组织逻辑——本文 = **按顺序执行**的上板测试流程(步骤 1~7 + 状态标记),参考内容(§9 执行注意 / §10 已完成事项去向 / §11 引用闭环)后置。已完成事项(S7、A1~A4)的实施细节与真机证据**移出本文**,§10 只留「事项 → 去向」指针;§3 只留复跑命令与判据;§1「事项总览」改「执行流程总览」(步骤/状态列) |
| 2026-10-03 | **§3.2 去"待上板"框架**:A1~A4 均已落地并(A1 全项 / A2~A4 正常路径)经真机验证,删除"待上板事项(代码状态 2026-10-02 核对)"表述,改写为**客观事实记录**(列名改为「实施内容(已落地)」+「验证判据」);§1 总览 P0-B 状态由「待上板」改「✅ 已闭环」;抬头与 `docs/README.md` 索引同步为「真机验证状态」。残留事实(A2/A3/A4 故障分支 + A4 推流压测需专项窗口、N-16 拔线负向测试)仍如实保留 |
| 2026-10-02 | **更名**:`实机测试规划.md` → `实机测试实施指南.md`(与文档性质对齐——常设执行判据,非规划;引用面改造后仅剩 `docs/README.md` 索引 1 处,同步更新) |
| 2026-10-03 | **A2/A3/A4 实施 + 真机验证**:A2 = `net_task.c` 初始组网失败/重建失败 → 自检留痕 + 30s 周期重试(分片喂心跳,不自驻留);A3 = `ch395f.c` 3 处字节级 SPI 调用 `HAL_MAX_DELAY` → 100ms 有限超时 + 返回值检查 + 故障锁存 `ch395f_spi_byte_fault()`(首条记日志);A4 = `ui_net_sink.c` `remo_send` 校验 `net_send` 返回值,短写告警、连续 3 次失败阻断推送、新连接/网络重建解除(单连接模型不 `net_close` 数据 fd)。`@build` 0/0 + L0/L0.5 全绿 + 模拟器构建通过;上板 `@test` PASS 7/7:A1 判定 PASS(含 IP 改→复位→持久→可达闭环,原档已恢复)、A2/A3/A4 正常路径零回归;自检清单 18→20 处(`net init fail` / `net reinit fail`);上板新数据:min_ever 下限 3,712 B(S11 阈值建议改 3,072 B)、开机良性 `MISS start` 行新增陷阱 §9.8;拔线负向/短写压测记 `待处理内容.md` N-16 |
| 2026-10-02 | 初版:无 MCU 窗口建立。汇总 P0-A 环境预检 / P0-B `@test`+S7 / P1-A IWDG V2/V4/V5 / P1-B S11 / P2-A S9 / P2-B P1-8+N-2+N-3 / P3 S5+S4+待核实项,共 **7 批**。每项含现状证据 / 目标 / 判据(量化)/ 执行步骤(精确命令)/ 风险回滚。18 处自检调用点清单 + 模拟器差距清单 §3 决策规则交叉引用 |
| 2026-10-02 | **台架窗口执行交接**:新增 **§0.5**(P0-A 通过;S7 已落地并提交 `4a4cd29`;P0-B 唯一阻断 = 0 字节 STOR → IWDG 误复位(round 3~6 后仍 5/5 复现);round 1~6 修复集摘要;**round 7 纯取证埋点设计 + 判据表**;P0-B 出口闭环(含 FTL flush 诱导式清台账);设备/台账/本地证据快照;**7 条实测陷阱**);§2.1 标注 S7 已落地、命令形态已确认 |
| 2026-10-02 | **文档改造**(同 `本地工具路径环境变量方案.md` 思路):删除一次性台架窗口状态(原 §0.5——round 1~9 取证全过程、快照、未提交警告:结论已沉淀 `看门狗设计说明.md`/`STM32F4-Base存储架构说明.md` §5.4.1/`控制台单写者日志设计说明.md` §12,修复随 `930215f` 提交)与规划框架(预估耗时/阶段措辞),重组为执行判据说明——§1 事项总览 / §2 环境预检 / §3 `@test` 闭环+自检判定+A1~A4 项 / §4 IWDG 注入长跑 / §5 堆告警 / §6 GD5F 错误通道 / §7 网络基线 / §8 工程卫生 / §9 实测陷阱 / §10 引用闭环;A1~A4 代码状态按当日代码核对改写(A1 已落地 / A2 部分 / A3、A4 未补码);A4 基线更新 264,284 B、A7 端口更正 COM6;原 §0.5.x 的 8 处代码注释、`待处理内容.md` 3 行、`看门狗设计说明.md` 变更记录、`docs/README.md` 同步重指向模块文档 |