阶段 D 收口:P3 卫生六项 + S-2 boot_log 存档流程 + 登记簿销项

阶段 D(验证与卫生)离线可完成项收口;台架依赖项 D2/D5/D6 保留登记。

- D4 P3 卫生六项:
  - P3-1 cfg_file.c s_encode:STR 型 len==0 回绕(p_key->len - 1u)直接拒绝
  - P3-2 cfg_file_store_mcu.c:原子写临时名由 p_path 同目录推导(s_build_tmp_path)
  - P3-4 rs485.c:模块描述订正为实际实现(HAL_Delay(1),非 DWT µs)
  - P3-6 ch395f_get_socket_status:补 p_status NULL 检查
  - P3-8 build.md:退出码契约订正为 0/1/2 三档
  - P3-11 adc_task/rs485_task:注明"预留桩(未启用)"
- D3 S-2:新增 docs/测试说明/boot_log_data/(快照存档目录 + 流程),
  并在 测试开发标准流程.md §7.3 登记沉淀约定
- 登记簿销项:删 P3-1/2/4/6/8/11、S-2;阶段 D 表移除 D3/D4;
  §1 计数更新(P3 6→0、登记簿 10→9);§3 章节重排
  (登记簿→§3.2、专项→§3.3);清理 App/cfg/README.md 等对已销编号的引用
- 同步刷新内存快照:Flash 266,632 B / ROM 合计 267,372 B

验证:@build 0 错 0 警;cfg_file 主机单测 149/149;
pre-commit --all-files 17/17 通过。
This commit is contained in:
2026-10-05 10:15:53 +08:00
parent de1b50efe9
commit ad0fd53389
12 changed files with 129 additions and 48 deletions
@@ -36,10 +36,10 @@
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ER_IROM1 | 266,548 B (260.30 KB) | 1,048,576 B (1024 KB) | 25.4% |
| ER_IROM1 | 266,632 B (260.38 KB) | 1,048,576 B (1024 KB) | 25.4% |
| RW_IRAM1 | 84,960 B (82.97 KB) | 131,072 B (128 KB) | 64.8% |
| RW_CCM | 49,184 B (48.03 KB) | 65,280 B (64 KB) | 75.3% |
| **Flash (ROM 合计)** | **267,288 B (261.0 KB)** | 1,048,576 B (1024 KB) | **25.5%** |
| **Flash (ROM 合计)** | **267,372 B (261.1 KB)** | 1,048,576 B (1024 KB) | **25.5%** |
<!-- MEM_SNAPSHOT:END -->
各区的容量与常量来源:
+15 -30
View File
@@ -38,8 +38,7 @@
| 级别 | 数量 | 关键项 |
|---|---|---|
| **P1** | 1 (+1 收尾) | **P1-1 ADC 采样路径产品构建中死亡**;P1-10 测试固件构建实测闭环(主体已闭环,见 §3.1) |
| **P3** | 6 | 卫生项:P3-1/2/4/6/8/11,可随其他修改顺手处理 |
| 登记簿 | 10 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口);存储/日志:**S-1(defaultTask 栈余量 10%,需尽快处理)**、S-2(boot_log 存档)、S-3(USART1 TX-only 根治)、S-4(dhara 重试自旋)、S-5(可选全序列卷锁) |
| 登记簿 | 9 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口);存储/日志:**S-1(defaultTask 栈余量 10%,需尽快处理)**、S-3(USART1 TX-only 根治)、S-4(dhara 重试自旋)、S-5(可选全序列卷锁) |
| 测试/基础设施 | 5 | T-7(CI runner 未就绪)+ 测试架构专项 **S12**(断言宏)、**S1-c**(可选单测)、**A-4**(采集链路测试约束)、**A-5 残余**(CI 体积门禁盲区) |
> **网络侧另有 E-xx 未闭环项**(E-12/15/16/23/24/25/26/27/28/30/47/48/49/50/58/59/61,共 17 项)
@@ -92,8 +91,6 @@
| 序 | 任务 | 说明 |
|---|---|---|
| **D2** | N-3 L5 基线重锁 | 下次 Phase 13 窗口顺带做(低风险:阈值余量 >8×;**需 PC peer**) |
| **D3** | S-2 boot_log 快照存档流程 | 固化 `%TEMP%\opencode\boot_log_*.txt` 进 `docs/测试说明/` 存档目录 |
| **D4** | P3 卫生项 | P3-1/2/4/6/8/11(含 E-13 `test_parse_ip` 门控析取)顺手清理 |
| **D5** | **N-16 专项负向台架窗口** | A2/A4 负向场景:PHY 拔线(需断 DTU 侧/关受管交换机端口)、A2 芯片级 `net_init` 失败(SPI 故障注入)、A4 短写压测 |
| **D6** | **N-17 探针窗口心跳缺口** | 定位 `time_sync` 监听重建为何阻塞 NET/FTP/UI(~1s 缺口,余量仅 ~0.7s);评估缩短重建重试或让掉线路径不阻塞其它任务 |
@@ -106,7 +103,7 @@
【阶段 C 结构】 C1 pending 二期 ─ C3 日志管线(N-2/S-3) ─ C4 栈(S-1)
─ C5 收口 ─ C6 USART1 TX-only
↓
【阶段 D 常态】 D2 N-3 / D3 boot_log / D4 P3 / D5 N-16 负向 / D6 N-17 探针窗口
【阶段 D 常态】 D2 N-3 / D5 N-16 负向 / D6 N-17 探针窗口
```
---
@@ -129,18 +126,7 @@
- **剩余**:① CH395F 套件(`TEST_SUITE_CH395F`,HW 全阶段 / NET 层 7 配置)实际构建确认链接通过——PHASE5 三静态缓冲 3×4093B 仍在,理论余量足够但未实测;② `@test` 闭环;③ **不建议**扩 scatter 到 192KB(破坏既有克隆芯片兼容决策)。
- **置信度**:high(基线数据来自 2026-09-21 map;测试固件构建未复验)。
### 3.2 P3(未闭环 6 项)
| # | 位置 | 问题 |
|---|---|---|
| P3-1 | `App/cfg/cfg_file.c` `s_encode` | STR 型 `len==0` 时 slen 计算回绕(`if (slen >= p_key->len) slen = p_key->len - 1u;`) |
| P3-2 | `App/cfg/cfg_file_store_mcu.c` | 临时文件名硬编码 `/config.TMP`,忽略 `p_path` 参数 |
| P3-4 | `Drivers/BSP/RS485/rs485.c` | 文件头宣称 DWT µs 延时,实际用 `HAL_Delay(1)`(文档不一致) |
| P3-6 | `Drivers/BSP/CH395F/ch395f.c` `ch395f_get_socket_status` | `p_status` 无 NULL 检查 |
| P3-8 | `.opencode/command/build.md` | 退出码契约写 "2+ = 编译错误",`build.bat` 实际只有 0/1 两档(与 AGENTS.md 一致的是后者) |
| P3-11 | `App/task/adc_task.c` / `rs485_task.c` | 空桩无注释说明原因(建议注明"预留,未启用") |
### 3.3 登记簿(N-x / S-x / T-x)
### 3.2 登记簿(N-x / S-x / T-x)
**网络(CH395F / net 层)**
@@ -157,7 +143,6 @@
| # | 事项 | 发现 | 证据与现状 | 出处 |
|---|---|---|---|---|
| S-1 | defaultTask 静态最坏链余量贴线:`storage_bring_up → … → dhara GC → SPI` 链 | 2026-09-22;2026-10-04 重采升级 | **2026-10-04 重采(升级为需尽快处理)**:产品构建(`suite=NONE`)V5 30 min 真实负载实测 **3664B/4096(余量 432B = 10%)**,**已远低于 30% 判据**。处置:栈 4096→4608(CCM 堆余量可覆盖 +512B)或 GC 链缓冲局部削减;建议**提前到阶段 B 之前**处理 | 本文件 §2.2 C4 / §6 |
| S-2 | N-2 消化后,台架 20MB 串口日志截头会丢早期 [STACK] 水位行——跨构建的"前后"栈水位对照建议固化 boot_log 快照(`%TEMP%\opencode\boot_log_*.txt`)进 `docs/测试说明/` 存档目录 | 2026-09-22 | 流程项,无代码改动 | 本文件 N-2 佐证 |
| S-3 | **USART1 TX-only 结构根治(灭 ORE 僵尸机制)**——ORE 锁存在外设软复位后毫秒级重锁(PA10 悬空 + RX 使能),是 2026-10-02 台架"背靠背 drain 拉长主循环 → 喂狗节奏饥饿 → IWDG 误复位"的**机制根源**。现仅有缓解(单次 drain 250ms 预算 + 发送故障后 300ms 冷却),**未根治** | 2026-10-02(台架 gen-288) | **待办**:改 `.ioc` 令 USART1 为 TX-only → CubeMX 重生成 → 跑 `scripts/check_cubemx_survival.py`。结构性改动,需单开一轮并复跑台架闭环 | `子系统设计/控制台单写者日志设计说明.md` §12(含 O4) |
| S-4 | **dhara 重试自旋残留**——`try_recover()` 的 `DHARA_MAX_RETRIES`(8) 自旋在坏块密集时仍可能长时间占用 defaultTask(喂狗点) | 2026-10-02 | 低优先:现有 `vol_lock` + 喂狗节奏缓解;若台架再出"存储侧喂狗饥饿"再排期 | `Lib/dhara/map.c` |
| S-5 | **可选全序列卷锁**——现卷锁仅覆盖 `syslog` / `cfg` / `lftpd` 三条路径(`vol_lock_wait(0)` try 语义),其它潜在访问点(如 UI 读日志)未纳入 | 2026-10-02 | 待评估:先确认是否真有第二写者;无则关闭本项 | `App/fs/vol_lock.{c,h}` |
@@ -168,7 +153,7 @@
|---|---|---|---|---|---|
| T-7 | **CI runner 未就绪(部署前置)** | 中 | `.gitea/workflows/ci.yml` 已落地,但 CI 仅在 runner 就绪后才真正生效:① Gitea 实例 `[actions] ENABLED = true`;② 注册 Windows runner(labels 含 `windows`),装 Python 3.x / cppcheck / pre-commit / MSVC | runner 未就绪前,**提交前仍须在本地跑 `scripts/ci_local.py` 或 `pre-commit run --all-files` 自查**(L0 唯一保障,不能因"已配 CI"而放宽) | `.gitea/workflows/ci.yml`;`测试说明/测试开发标准流程.md` §9 |
### 3.4 测试与架构改进专项(S1x / A-x)
### 3.3 测试与架构改进专项(S1x / A-x)
> **编号约定**:**S1~S14 / T-1~T-5 / A-1~A-7** 是 2026-10-02 版复审的**条目编号**——编号**不随条目删除而回收**;
> 其他文档若引用这些编号,其证据见对应模块文档与 `git log`。已完成事项的证据沉淀:
@@ -180,12 +165,12 @@
| 编号 | 事项 | 状态 | 详述 |
|---|---|---|---|
| **S12** | 模块级轻量断言宏 | ⬜ 待做(第 4 波按需) | 3.4.1 |
| **S1-c** | `sys_log` / `time_sync` 主机侧单测 | ⬜ 可选(价值递减) | 3.4.2 |
| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ 待 B1/B2 落地时执行 | 3.4.3 |
| **A-5 残余** | CI 体积门禁盲区(`mem-numbers` 在 CI 被跳过) | ⬜ 未消除 | 3.4.4 |
| **S12** | 模块级轻量断言宏 | ⬜ 待做(第 4 波按需) | 3.3.1 |
| **S1-c** | `sys_log` / `time_sync` 主机侧单测 | ⬜ 可选(价值递减) | 3.3.2 |
| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ 待 B1/B2 落地时执行 | 3.3.3 |
| **A-5 残余** | CI 体积门禁盲区(`mem-numbers` 在 CI 被跳过) | ⬜ 未消除 | 3.3.4 |
#### 3.4.1 S12:模块级轻量断言宏 ⬜
#### 3.3.1 S12:模块级轻量断言宏 ⬜
**动机**:`configASSERT` 只覆盖 FreeRTOS 内部;自研代码的"不该发生"靠散落的 `if`。
@@ -211,7 +196,7 @@
**完成判据**:宏存在 + 生产构建 `@build` 0/0 且 `.map` 无新增符号;试点处有实际使用。
#### 3.4.2 S1-c(可选):`sys_log` / `time_sync` 主机侧单测 ⬜
#### 3.3.2 S1-c(可选):`sys_log` / `time_sync` 主机侧单测 ⬜
**范围**:`App/log/sys_log_mcu.c`(定长 64B 记录编解码;落盘部分需桩)、
`App/sync/time_sync.c`(协议帧编解码;与网络耦合,需先判定可解耦面)。
@@ -222,7 +207,7 @@
**完成判据**:`test/host/<模块>/run_unit_test.py` 退出码 0 + 挂 pre-commit 钩子。
#### 3.4.3 A-4:ADC / RS485 采集链路的测试可验证性约束 ⏸
#### 3.3.3 A-4:ADC / RS485 采集链路的测试可验证性约束 ⏸
**背景**:`adc_task.c` / `rs485_task.c` 仍是空桩,`App/protocol/` 只有 README 与 `.gitkeep`。
本项不是"缺陷",而是**对上游 B1 / B2 的设计约束**——应在动手前明确,否则后续无法补测。
@@ -238,7 +223,7 @@
**完成判据**:B1 / B2 设计文档体现上述三条;协议解析函数有对应 L0.5 单测。
#### 3.4.4 A-5 残余:CI 体积门禁盲区 ⬜
#### 3.3.4 A-5 残余:CI 体积门禁盲区 ⬜
**现状**:`mem-numbers` 钩子**在 CI 上被跳过**(CI 无 `.map`)→ **CI 不守体积门禁**。
S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 `CI配置指南.md` 声明,
@@ -258,7 +243,7 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在
## 4. 待确认(需手册/硬件/产品定义,暂不直接改码)
1. TPAFE5160 是否有自动扫描模式(决定 P1-1 定 P0 还是 P1)。
2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(关联 P1-1、P3-11;当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**)。
2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(关联 P1-1;当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**)。
3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)。
---
@@ -324,7 +309,7 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在
| 项 | 当前值(2026-10-04) | 出处 |
|---|---|---|
| 产品构建 Flash (ER_IROM1) | 265,940 B / 1024 KB(25.4%);ROM 合计 **266,676 B** | `.map` 受管快照 |
| 产品构建 Flash (ER_IROM1) | 266,632 B / 1024 KB(25.4%);ROM 合计 **267,372 B** | `.map` 受管快照 |
| 产品构建 RW_IRAM1 | **84,960 / 131,072 B(64.8%)** | `.map` 受管快照(`RAM使用分析与优化方案.md` §2.1) |
| 产品构建 RW_CCM | 49,184 / 65,280 B(75.3%) | 同上 |
| 实测堆 | free=8,664 / **min_ever=4,728 B** | V5 串口 `[STACK] heap` |
@@ -357,6 +342,6 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在
- 已闭环条目的**结论与证据沉淀进模块文档**,本文件不再重复。
- 编号一律**沿用且不回收**(P-x / N-x / S-x / T-x / S1x / A-x);`错误码传播审计.md` 的 E-xx 独立维护。
- 阶段 B 完成后重写 §1(届时 ADC/RS485 应从未闭环消失)。
- 新增发现按既有惯例分流:能立即修的进 §2(阶段 A/C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.3(登记簿)。
- 新增发现按既有惯例分流:能立即修的进 §2(阶段 C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.2(登记簿)。
- 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、`问题记录/错误码传播审计.md`(E-xx)、
`测试说明/实机测试实施指南.md`(执行流程)——三者均不在本文件合并范围。
+35
View File
@@ -0,0 +1,35 @@
# 启动日志(boot_log)存档
本目录保存 `@test`(`test/host/run_boot_test.py`)产出的**开机串口日志快照**,
用于**跨构建的栈 / 堆水位对照**(解析其中的 `[STACK]` 行)。
## 1. 为什么需要存档
- `@test` 默认把 boot_log 写到临时目录 `%TEMP%\opencode\boot_log_<时间戳>.txt`——**会被系统清理**;
- 台架长跑的 20MB 串口日志**截头会丢掉早期 `[STACK]` 水位行**(开机首次约 5s 后才报告);
- 两者叠加导致**无法事后回溯**"改代码前后"的栈水位变化。
因此凡涉及**栈 / 堆预算**的改动或**基线重采**,必须把该轮的 boot_log 快照固化到本目录。
## 2. 约定
| 项 | 规则 |
|---|---|
| 来源 | `& '.venv\Scripts\python.exe' test/host/run_boot_test.py`(默认 `--out-dir %TEMP%\opencode`,产出 `boot_log_<stamp>.txt` + `selftest_log_<stamp>.log`) |
| 命名 | `<日期>_<构建标识>_boot_log.txt`,例:`20261005_prod_none_boot_log.txt` |
| 构建标识 | 建议含:产品 / 测试套件(`prod_none` / `suite_ch395f` …)+ 负载(`idle` / `v5_30min` / `ftp_stress`) |
| 随文件登记 | 在下方 §3 清单登记日期、构建、负载、关键 `[STACK]` 水位(如 defaultTask 峰值) |
| 入库门槛 | **只存有对照价值的快照**——常规 `@test` 通过日志不必入库 |
## 3. 清单
| 日期 | 构建 / 负载 | 关键 `[STACK]` 水位 | 文件 |
|---|---|---|---|
| — | — | — | (待台架窗口补齐) |
## 4. 关联
- 沉淀约定:`../测试开发标准流程.md` §7.3
- 栈水位探针与基线:`../../内存管理/RAM使用分析与优化方案.md` §0.2 / §0.6
- 当前诊断基线:`../../待处理内容.md` §6
- 本流程立项:原 `../../待处理内容.md` S-2(2026-09-22 提出;2026-10-05 固化为本节流程后销项)
@@ -476,6 +476,7 @@ flowchart TD
| 代码变更影响判定标准 | 立即同步更新模块 Test_Guide,并登记该文档变更记录 |
| 有意改视觉 | 刷黄金参考 + 重生成目检 PNG + `UI_自动化测试流程.md` 变更记录登记 |
| 新增测试工具 / 新标记 | `自动化测试流程.md` 命令清单登记(§4.2) |
| 栈 / 堆预算相关改动或基线重采 | 把 `@test` 的 boot_log 快照(`%TEMP%\opencode\boot_log_*.txt`)存入 `docs/测试说明/boot_log_data/` 并在其 §3 清单登记(防临时目录被清理 / 长跑日志截头丢 `[STACK]` 行) |
> 文档与代码一体两面:**代码改了文档没同步 = 未完成**。