diff --git a/docs/README.md b/docs/README.md index 6b12f72a..cd25f292 100644 --- a/docs/README.md +++ b/docs/README.md @@ -31,7 +31,7 @@ docs/ ``` > ⚠️ `docs/芯片手册/`(约 120 MB / 1754 张图)为**只读外部输入资料**,与代码演进无关; -> 后续按《项目审查与优化建议报告》D-1 建议拆分独立仓库或降采样(见 `问题记录/项目审查与优化建议报告.md`)。 +> 后续按原报告 D-1 建议拆分独立仓库或降采样(登记簿 **N-29**,已决策暂不处理)。 --- @@ -220,10 +220,12 @@ docs/ ### 9.1 评审报告 -| 文档 | 内容 | -|---|---| -| [`问题记录/项目审查与优化建议报告.md`](问题记录/项目审查与优化建议报告.md) | 项目全景审查:文档/代码/架构/可靠性问题清单(未闭环项:D-1、N-xx、Px-xx;**已修复项按「修复即销项」删除**,去处见其变更记录)——**体系层评审报告,非待办池**(待办见 `任务规划/README.md`) | - +> 体系层评审报告《项目审查与优化建议报告》(原在 `问题记录/`)已于 **2026-10-25 删除**—— +> 大部分内容已闭环,留着的只有历史快照与重复清单。结论的去处: +> 未闭环项 → [`任务规划/登记簿.md`](任务规划/登记簿.md);内存与 Flash 结论(含整簇暂缓的**重开条件**) +> → [`内存管理/RAM使用分析与优化方案.md`](内存管理/RAM使用分析与优化方案.md) §2.5 / §2.6.4 / §4; +> UI 侧硬约束 → [`UI设计/UI_设计架构.md`](UI设计/UI_设计架构.md) §1.4; +> 六个自有编号族 → [`编号规范.md`](编号规范.md) §4.3(属主文档已删,存量冻结)。 ### 9.2 环境与部署 | 文档 | 内容 | @@ -259,8 +261,8 @@ docs/ ## 11. 已知文档问题(待清理) -> 来源:《项目审查与优化建议报告》D-3/D-7(两条已销项,正文已移入 [`文档规范.md`](文档规范.md) 与 pre-commit 门禁)。 -> **D-3 / D-6 / D-7 已处理完毕**(2026-09-25):全库链接存在性检查通过(66 文档 0 失效)、任务表与 +> 来源:原报告 D-3/D-7(两条已销项,正文已移入 [`文档规范.md`](文档规范.md) 与 pre-commit 门禁)。 +> **原报告 D-3 / D-6 / D-7 已处理完毕**(2026-09-25):全库链接存在性检查通过(66 文档 0 失效)、任务表与 > `Src/freertos.c` 一致、文档规范已建立。下表保留**仍需跟踪**的项。 | 问题 | 位置 | 说明 | @@ -271,7 +273,7 @@ docs/ | ~~缺一致性门禁~~ | — | ✅ 已落地(2026-09-25/26,D-7 三档齐):`scripts/check_doc_links.py`(存在性)+ `scripts/gen_task_table.py`(数值)+ `scripts/check_mem_numbers.py`(体积),接入 pre-commit `doc-links` / `task-table` / `mem-numbers` 钩子 | | ~~`docs/文档规范.md` 未创建~~ | — | ✅ 已创建(2026-09-25):[`文档规范.md`](文档规范.md) | -> 未闭环的文档类问题见 [`问题记录/项目审查与优化建议报告.md`](问题记录/项目审查与优化建议报告.md) §3.1(体量)与 §3.3/§3.4(**仅剩 D-1 仓库膨胀**,登记簿 N-29 已决策暂不处理)。 +> 未闭环的文档类问题**只剩原报告 D-1 仓库膨胀**(登记簿 **N-29**,已决策暂不处理)。 --- @@ -296,4 +298,4 @@ docs/ | 2026-09-25 | D-7 文档-代码一致性门禁 | 新建 `scripts/check_doc_links.py`(链接存在性,含行内代码豁免/就近状态词/`[计划]` 标记)、`scripts/gen_task_table.py`(任务表由 `Src/freertos.c` 生成/校验,锚点 `TASK_TABLE:BEGIN/END`);接入 pre-commit `doc-links`/`task-table` 钩子;全库 66 文档 0 失效 | | 2026-09-26 | D-7 体积档落地 | 新建 `scripts/check_mem_numbers.py`(内存/Flash 数字以 `.map` 为事实源,锚点 `MEM_SNAPSHOT:BEGIN/END` + 陈旧散句数字扫描);接入 pre-commit `mem-numbers` 钩子;上线即抓出 6 处真实失真(RW_IRAM1 82,048→87,040、ROM 249,432→262,660 等) | | 2026-09-25 | 新建 `文档规范.md` | 正式确立文档体系规范(目录命名/编码换行/链接形态/门禁/结构/写作约定);补入本索引 §7.1b | -| 2026-10-04 | 待办文档合并 + 报告归档 | 4 份待办文档(`待处理内容.md` / `项目审计改进清单.md` / `下一步任务规划.md` / `测试与架构改进建议.md`)合并为**统一待办登记簿** `待处理内容.md`;`项目审查与优化建议报告.md` 移入 `问题记录/`,删除 `审查记录/` 目录;全仓库引用同步 | +| 2026-10-04 | 待办文档合并 + 报告归档 | 4 份待办文档(`待处理内容.md` / `项目审计改进清单.md` / `下一步任务规划.md` / `测试与架构改进建议.md`)合并为**统一待办登记簿** `待处理内容.md`;《项目审查与优化建议报告》移入 `问题记录/`,删除 `审查记录/` 目录;全仓库引用同步(该报告 2026-10-25 已删除,内容并入登记簿与模块文档) | diff --git a/docs/产品需求/产品需求设计文档.md b/docs/产品需求/产品需求设计文档.md index dc17c75f..fe193476 100644 --- a/docs/产品需求/产品需求设计文档.md +++ b/docs/产品需求/产品需求设计文档.md @@ -52,7 +52,7 @@ | 甲方 / 产品 | §2 产品概述 → §5 功能需求 → §9 待实现项与路线图 → §10 验收判据 | | 开发 | 全文;深入时按 §11 指向各模块设计文档 | | 测试 / 验证 | §5、§6、§7、§10 + `docs/测试说明/` | -| 评审 | §2、§7、§8、§9 + [`docs/问题记录/项目审查与优化建议报告.md`](../../docs/问题记录/项目审查与优化建议报告.md) | +| 评审 | §2、§7、§8、§9 | --- @@ -864,7 +864,6 @@ cfg-file-unit-test、test-suite-switch、gitlint。 | 部署环境 | [`docs/环境与部署/项目部署环境要求.md`](../../docs/环境与部署/项目部署环境要求.md) | | 硬件网表 | [`docs/硬件平台/V0.1_网表详细分析报告.md`](../../docs/硬件平台/V0.1_网表详细分析报告.md) | | 待办登记簿 | [`docs/任务规划/README.md`](../任务规划/README.md) | -| 体系层评审报告 | [`docs/问题记录/项目审查与优化建议报告.md`](../../docs/问题记录/项目审查与优化建议报告.md) | | 实机测试指南 | [`docs/测试说明/实机测试实施指南.md`](../../docs/测试说明/实机测试实施指南.md) | | 测试标准流程 | [`docs/测试说明/测试开发标准流程.md`](../../docs/测试说明/测试开发标准流程.md) | | RAM 预算与优化 | [`docs/内存管理/RAM使用分析与优化方案.md`](../../docs/内存管理/RAM使用分析与优化方案.md) | diff --git a/docs/任务规划/README.md b/docs/任务规划/README.md index 7969d83a..1874812a 100644 --- a/docs/任务规划/README.md +++ b/docs/任务规划/README.md @@ -24,8 +24,7 @@ > 已闭环项的**结论与证据沉淀进对应模块文档/问题记录**,本文件夹不再重复。 > **消化即销项**:事项修复/关闭后,直接删除对应条目,并同步清理其它文档对本编号的引用。 > -> **不在本文件夹范围**:`../问题记录/项目审查与优化建议报告.md`(体系层评审报告)、 -> `../测试说明/实机测试实施指南.md`(执行流程)。 +> **不在本文件夹范围**:`../测试说明/实机测试实施指南.md`(执行流程)。 --- @@ -39,7 +38,7 @@ | `S1~S14` / `A-1~A-7` | 2026-10-02 复审的测试充分性与架构专项 | 编号**不回收** | | `E-xx` | 错误码传播审计发现(**历史族**) | 属主文档已于 2026-10-15 删除;编号冻结(`docs/编号规范.md` §4.1 / §4.3),存量引用仅作历史指称,新发现一律 `DEF` | | `B` 前缀 | 功能主线排期条目 `B0`~`B10`(见 §2) | 存量冻结、不再新增。原 `C`(结构债)/ `D`(验证窗口)两族 **2026-10-25 废止**,条目改语义名——它们与 UI 设计约束、设计决策记录同字母不同义 | -| 报告 `N-x`/`R-x`/`F-x`/`S-x`/`U-x`/`D-x` | `项目审查与优化建议报告.md` **自有编号** | ⚠ **与本登记簿同名不同义**(报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架)→ **引用一律带文档名**。其未闭环项 2026-10-11 并入本登记簿(新编 `N-19`~`N-29` + U 簇,出处列保留报告编号) | +| 报告 `N-x`/`R-x`/`F-x`/`S-x`/`U-x`/`D-x` | 《项目审查与优化建议报告》**自有编号**(**该报告 2026-10-25 已删除**) | ⚠ 曾与本登记簿**同名不同义**(报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架)。其未闭环项已于 2026-10-11 并入本登记簿(`N-19`~`N-29` + U 簇),**现存引用只是历史指称,不再新增** | > ⚠ **为什么 2026-10-14 改用语义标识**(一条实测失效案例):原规则写着"编号**不回收**",但 > 销项 = **删行**,删完仓库里就不留任何痕迹——登记簿 `N-31`(2026-10-11 的 Phase 7 复跑项) @@ -65,7 +64,7 @@ | 硬件 | 1 | N-18(V0.2 改版项) | | 测试 / 基础设施 | 5 | T-7(CI 远端两 job 闭环 + 第二机交叉验证)· S12(断言宏)· A-4(采集链路测试约束,RS485 侧随 B2 暂缓)· A-5 残余(CI 体积门禁盲区)· 串口助手 A6/A7 补验(待 CH340) | | UI | 1 | U5 页面落地(**未排期**,最早在「数据可信」M4 之后) | -| **暂缓** | 2 簇 | **B2 RS-485 整簇**(`暂缓-RS485.md`)· **N-27 内存优化簇剩余**(R-2 后半 / R-3 / R-4 / R-6;重开条件见 `../问题记录/项目审查与优化建议报告.md` §5.3)。⚠ 已落地的 R-9 与 `mem-budget` 门禁/台账/趋势**不回退** | +| **暂缓** | 2 簇 | **B2 RS-485 整簇**(`暂缓-RS485.md`)· **N-27 内存优化簇剩余**(R-2 后半 / R-3 / R-4 / R-6;重开条件见 `../内存管理/RAM使用分析与优化方案.md` §4)。⚠ 已落地的 R-9 与 `mem-budget` 门禁/台账/趋势**不回退** | | **数据可信**(当前波次) | 1 簇 · **14 张卡** | 已知电压注入验证 · 端子变比确认 · 通道标定系数与折算 · 标定落盘 · 未标定即闭锁 · 下游三常数重定 · 量纲回归 · 遥测快照 200 ms · 运行参数段 · 频率点绑定(详表 `数据可信.md`) | > **网络侧 E-xx 存量项**(历史编号族,属主文档已于 2026-10-15 删除,编号冻结见 @@ -77,7 +76,7 @@ ### 1.1 结构性判断(排序依据) 1. **功能主线优先(用户决定 2026-10-12)**:把"采集→相量→保护→上送"链路收口到"台架闭环 + 功能面完整 + 可送检"。前两项已达成,「采集保护收尾」只剩 M3 送检(`采集保护收尾.md`)。**RS-485 对下采集(B2)暂缓**(`暂缓-RS485.md`),主线不等它。 -2. **内存预算红线已机械化**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势基线 → `docs/内存管理/RAM预算台账.md`。**R-2 后半与 R-3 / R-4 / R-6 整簇暂缓**(CCM 只剩 **7,904 B**,重开条件见 `../问题记录/项目审查与优化建议报告.md` §5.3)——**门禁与台账继续常开,它们正是"何时该重开"的传感器**。 +2. **内存预算红线已机械化**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势基线 → `docs/内存管理/RAM预算台账.md`。**R-2 后半与 R-3 / R-4 / R-6 整簇暂缓**(CCM 只剩 **7,904 B**,重开条件见 `../内存管理/RAM使用分析与优化方案.md` §4)——**门禁与台账继续常开,它们正是"何时该重开"的传感器**。 3. **验证债仅剩窗口性事项**(L5 基线重锁 / A2-A4 负向台架 / 探针窗口心跳 / 串口助手补验 + P1-10 收尾),不单独排期、逢窗口顺手做。 --- @@ -85,7 +84,7 @@ ## 2. 统一推进顺序(全项目唯一权威) > **本节是全项目所有工作流唯一的权威顺序**:`产品需求设计文档.md` §9.2、`../算法/继电保护功能复现规划.md`、 -> `项目审查与优化建议报告.md` §0.3 中的路线图均为局部视图,**顺序变更只改本节,其它文档只留指针**。 +> 各模块文档里的路线图均为局部视图,**顺序变更只改本节,其它文档只留指针**。 > 排序原则:**安全风险 > 产品功能主线 > 数据正确性 > 预算/结构债 > 验证常态 > UI 扩展 > 仓库决策**(当前无未闭环安全项)。 > 波内详表在挂接文件里(`采集保护收尾.md` / `排期详述.md` / `暂缓-RS485.md`),但**波次增删与先后只改 §2.0**。 @@ -99,7 +98,7 @@ |---|---|---| | **采集保护收尾** | **只剩 M3 送检**(B10,Fixed Date)——任务卡与判据见 `采集保护收尾.md` | 收口目标"台架闭环 + 功能面完整 + 可送检"的前两项已达成;**真约束只剩送检窗口**,窗口一到全道让路、窗口前 2 日特性冻结 | | **数据可信**(当前) | **通道标定 → 遥测链 → 运行参数**:M4 系数与量纲 / M5 遥测链 / M6 运行参数与点表;14 张卡与事实基线见 `数据可信.md` | **用户决定(2026-10-23):下一步做通道标定,先于 UI 页面与结构债**。它是唯一"改一处、全链受益"的入口(`App/task/adc_task.c:335` 是码值→工程量的唯一位置),也是「UI 扩展」页面与 104 遥测的共同前置——先做页面则 `ui_data_feed` 组装的码值帧要返工。本波紧随「采集保护收尾」,排在「预算与内存」「结构债」之前。⚠ 2026-10-23 补记:ADC 至今**从未采过已知电压**(连极性都没验过,见 `数据可信.md` §2.6),故第一张卡是"已知电压注入验证"——只需一块万用表,不需要信号源/示波器,是开工的第一刀 | -| **预算与内存** | ⏸ **整簇暂缓**:R-2 后半(缩堆 56→32 KB → 29.5 KB 迁 CCM)· R-3 · R-4 · R-6;R-5 已判定不可行 | **不再排期**:没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测。重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3 | +| **预算与内存** | ⏸ **整簇暂缓**:R-2 后半(缩堆 56→32 KB → 29.5 KB 迁 CCM)· R-3 · R-4 · R-6;R-5 已判定不可行 | **不再排期**:没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测。重开条件 → `../内存管理/RAM使用分析与优化方案.md` §4 | | **结构债** | **USART1 改为只发不收 → 日志管线与 S8 合并评估 → net 层跨上下文收口 → 注册校验白名单清理 → 写回 flush / 性能语义簇 / 空 TU**(详表 `排期详述.md` §1) | 无紧急,按性价比排:USART1 那条灭 IWDG 误复位的机制根源;net 层收口体量大、验证重,放后 | | **验证常态** | P1-10 收尾 · T-7 CI · L5 基线重锁 · A2/A4 负向台架 · 探针窗口心跳 · 串口助手 A6/A7 · S12 · A-5(详表 `排期详述.md` §2) | 窗口性,逢机顺带,不单独排期 | | **UI 扩展** | **U5 页面落地**——27 是目标数不是差集(现存 7 个页面实现;27 个空叶子已归并为 7 模块 + 2 项前置能力) | **未排期**(2026-10-20 用户裁定暂缓)。地基已齐(U1~U4 落地、`ui-golden` 与字符集差集检查已挂 pre-commit),新增一页 = 3 处人工 + 1 条生成器命令。**最早在「数据可信」的 M4 之后开工**——`ui_data` / `ui_data_feed` 需要真数据(`数据可信.md` §10)。逐页规格见 `../UI设计/页面扩充详细方案.md` | @@ -117,7 +116,7 @@ 关键路径: 量程口径 → 标定模块 → 落盘 → 未标定即闭锁 → 量纲回归 「UI 扩展」可在 M4 后开工 ↓ -预算与内存 ⏸ 整簇暂缓(重开条件见 项目审查与优化建议报告 §5.3) +预算与内存 ⏸ 整簇暂缓(重开条件见 `../内存管理/RAM使用分析与优化方案.md` §4) ↓ 结构债 USART1 只发不收 → 日志管线与 S8 → net 层收口 → 白名单清理 → 写回/性能/空TU ↓ @@ -144,7 +143,6 @@ UI 扩展 U5 页面落地(未排期,最早「数据可信」M4 之后 - **引用审查报告编号一律带文档名**(报告 N-16 ≠ 登记簿 N-16、报告 S-3 ≠ 登记簿 S-3); 报告并轨项用本登记簿新编号(N-19~N-29 + U 簇),出处列保留报告编号。 - **§2 是全项目唯一的推进顺序权威**:`产品需求设计文档.md` 等文档中的路线图只留指针,顺序变更只改 §2.0(详表文件跟着挪,不改顺序)。 -- **暂缓不是销项**:条目仍在簿,只是不占波次。有独立清单文件的(`暂缓-RS485.md` = B2)重启或关闭时更新该文件与 §1/§2.0;**只在原处标注的**(N-27 内存优化簇,2026-10-15 用户裁定,理由与重开条件挂在 `../问题记录/项目审查与优化建议报告.md` §5.3)重启时改 `登记簿.md` 该行 + 本文件 §1/§2.0 三处。 +- **暂缓不是销项**:条目仍在簿,只是不占波次。有独立清单文件的(`暂缓-RS485.md` = B2)重启或关闭时更新该文件与 §1/§2.0;**只在原处标注的**(N-27 内存优化簇,2026-10-15 用户裁定,理由与重开条件在 `../内存管理/RAM使用分析与优化方案.md` §4)重启时改 `登记簿.md` 该行 + 本文件 §1/§2.0 三处。 - 新增发现按既有惯例分流:能立即修的进 §2 波次(结构债);需排期的进 `登记簿.md` / `测试与架构专项.md` 对应编号空间;跨版本观察的进 `登记簿.md`。 -- 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、 - `测试说明/实机测试实施指南.md`(执行流程)——两者均不在本文件夹合并范围。 +- 上游引用关系:`测试说明/实机测试实施指南.md`(执行流程)——不在本文件夹合并范围。 diff --git a/docs/任务规划/并行分道方案.md b/docs/任务规划/并行分道方案.md index dea5607d..469d86b8 100644 --- a/docs/任务规划/并行分道方案.md +++ b/docs/任务规划/并行分道方案.md @@ -178,7 +178,7 @@ | **串口助手 A6/A7 补验** | 无码(需 CH340) | **台架道** | 待硬件 | | B10 送检(标准源 + 第三方主站) | 无码 | **外部窗口** | Fixed Date | | T-7 CI runner | 外部基础设施 | **外部** | 待 runner | -| N-30 relisten 收口 / `docs/问题记录/项目审查与优化建议报告.md` 的 F-5(N-28 簇)/ N-29 `.git` / N-18 V0.2 / N-27 内存簇 / B2 RS-485 / 开入开出 / 录波 | — | **不排** | — | +| N-30 relisten 收口 / 原报告 F-5 空 TU(N-28 簇)/ N-29 `.git` / N-18 V0.2 / N-27 内存簇 / B2 RS-485 / 开入开出 / 录波 | — | **不排** | — | --- @@ -339,11 +339,11 @@ $WT = ".dsh\skills\task-worktree\scripts\task_worktree.py" | 项 | 状态 | 重开条件 | |---|---|---| | B2 RS-485 整簇(含 E-49/E-50、A-4 RS485 侧、N-25 DE 项、待确认-3) | ⏸ 用户决定 2026-10-12 暂缓 | 见 `docs/任务规划/暂缓-RS485.md` | -| N-27 内存优化簇剩余(`docs/问题记录/项目审查与优化建议报告.md` 的 R-2 后半 / R-3 / R-4 / R-6) | ⏸ 用户裁定 2026-10-15 | `docs/问题记录/项目审查与优化建议报告.md` §5.3 | +| N-27 内存优化簇剩余(原报告 R-2 后半 / R-3 / R-4 / R-6) | ⏸ 用户裁定 2026-10-15 | `docs/内存管理/RAM使用分析与优化方案.md` §4 | | N-29 `.git` 233 MB | 决策:登记观察 | 推送/协作前重评 | | N-18 V0.2 硬件改版 | 下一版硬件 | 硬件改版立项 | | N-30 relisten 收口 | 观察(原语版实测回退) | 三条语义前置满足后 | -| `docs/问题记录/项目审查与优化建议报告.md` 的 F-5 空 TU(N-28 簇) | 观察 | 有全量构建耗时痛点时 | +| 原报告 F-5 空 TU(N-28 簇) | 观察 | 有全量构建耗时痛点时 | | T-7 CI runner | 外部基础设施 | runner 就绪 | | 串口助手 A6/A7 补验 | 待硬件 | CH340 到位 | | 开入/开出固件、故障录波 + 104 文件传输 | 独立立项 | 产品定义 / 单独立项 | diff --git a/docs/任务规划/登记簿.md b/docs/任务规划/登记簿.md index d9c61d3d..4cc831e3 100644 --- a/docs/任务规划/登记簿.md +++ b/docs/任务规划/登记簿.md @@ -44,8 +44,8 @@ |---|---|---|---|---|---| | N-22 | 写回缓存无空闲/掉电强制 flush(整页写与换页已 flush) | 写回窗口内掉电丢最近日志/配置写 | defaultTask 空闲 N ms flush | 结构债 | 报告 N-14 | | N-23 残余 | **KNOWN_GAPS 白名单清理**——现存唯一缺口 = `App/task/rs485_task.c`(E-59 门禁下刻意不接线,随 B2 暂缓,见 `暂缓-RS485.md`) | 白名单不清 = "写了不编译"盲区仍在 | 随 B2 一并出白名单(`--strict` 供审计复跑) | 结构债 | 报告 N-06 残余 | -| N-25 | 性能/资源建议簇:PASV 每次新建监听;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(**DE 项随 B2 暂缓,见 `暂缓-RS485.md`**) | 次级性能/语义一致性 | 逐项见 `../问题记录/项目审查与优化建议报告.md` §4.2/§4.7,随窗口评估 | 结构债 | 报告 N-09/PHY/P3-x/rs485 | -| N-27 | **内存优化簇剩余**:R-2 后半(缩堆 56→32 KB → 迁 CCM)· R-3 · R-4 · R-6 | ⏸ **整簇暂缓**(2026-10-15 用户裁定):没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测。⚠ 代价落在"以后加任务 / 抬栈 / 加堆"那一刻——CCM 只剩 7,904 B、FreeRTOS 堆 `min_ever` 8,464 B,届时 `mem-budget` 会先报警 | 重开条件见 `../问题记录/项目审查与优化建议报告.md` §5.3。⚠ **R-5 已判定不可行**(CMSIS-RTOS2 `freertos_os2.h` 有 `#if (configMAX_PRIORITIES != 56) #error`,改小直接编译失败),不再列入 | **暂缓** | 报告 R-2 剩余/R-3/R-4/R-6/§5.5 | +| N-25 | 性能/资源建议簇:PASV 每次新建监听;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(**DE 项随 B2 暂缓,见 `暂缓-RS485.md`**) | 次级性能/语义一致性 | 随窗口评估,逐项机理见 `../网络/Net层阻塞模型架构设计.md` 与 `Drivers/BSP/NET/README.md` | 结构债 | 报告 N-09/PHY/P3-x/rs485(报告已删,仅作历史指称) | +| N-27 | **内存优化簇剩余**:原报告 R-2 后半(缩堆 56→32 KB → 迁 CCM)· R-3 · R-4 · R-6 | ⏸ **整簇暂缓**(2026-10-15 用户裁定):没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测。⚠ 代价落在"以后加任务 / 抬栈 / 加堆"那一刻——CCM 只剩 7,904 B、FreeRTOS 堆 `min_ever` 8,464 B,届时 `mem-budget` 会先报警 | 重开条件见 `../内存管理/RAM使用分析与优化方案.md` §4。⚠ **原报告 R-5 已判定不可行**(CMSIS-RTOS2 `freertos_os2.h` 有 `#if (configMAX_PRIORITIES != 56) #error`,改小直接编译失败),不再列入 | **暂缓** | 报告 R-2 剩余/R-3/R-4/R-6/§5.5 | | N-28 | **报告 F-5:uvprojx 里 127 个空 TU**(201 个 LVGL `.c` 中 127 个 `.map` 零产出) | 增量构建实测 4~5 s、远程 CI 刻意不跑 `@build` → **非产品指标**;报告原"编译时长 −40%"无基线记录 | 🟡 观察:等有实测的全量构建耗时痛点再做——用 Keil 原生 `0`(可逆)而非删条目,且排在任何 `lv_conf.h` 改动之后;动手前先补一次全量构建计时做基线 | 结构债 | 报告 F-5 | | N-29 | **仓库膨胀**:`.git` **233 MB**(2026-10-25 实测)+ 手册图片 36.3 MB(受控文件合计仅 79.3 MB,`.git` 已是它的 3 倍) | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**(三项都不解决历史膨胀)。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评 | **仓库决策** | 报告 D-1 | | U 簇 | **U5 页面落地**——⚠ "27 页"是目标数、不是差集:现存 **7 个页面实现**(`ui_page_ac/dc/device_info/net_cfg/password/runlog/selftest.c`,`ui_page_registry.c` 是生成物不算页面),27 个空叶子已归并为 **7 模块 + 2 项前置能力**(`../UI设计/页面补齐规划.md`) | 地基已齐(U1~U4 已落地;`ui-golden` 与 UI 字符集差集检查均已挂 pre-commit),新增一页 = 3 处人工 + 1 条生成器命令;缺的是产品定义与真数据 | **未排期**(2026-10-20 用户裁定暂缓);最早在「数据可信」M4 之后开工——`ui_data` / `ui_data_feed` 组装的是码值帧,先做会返工(`数据可信.md` §10)。逐页规格:`../UI设计/页面扩充详细方案.md` | UI 扩展 | `../UI设计/页面补齐规划.md` | diff --git a/docs/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index c9868611..ba7cac7a 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -157,6 +157,15 @@ C2 dhara 失败类 +84;RO 另 +208,全是 C2 的失败类名表)→ `ER_IR 小项:FF_FS_TINY=0(每打开文件 512B 扇区窗,§4.1.5 可改 1)、`ui_net_sink` PC 远程显示缓冲常驻 6.4KB(产品构建可加开关关闭,§4.1.5);lftpd 栈局部变量 ✅ 2026-09-21 已静态化(§4.1.4)。 +**2026-10-22 复评补充(按「常驻 vs 动态」切,与上表的「可回收性」视角互补)**: + +1. **静态大头是"缓冲常驻"**:`lv_mem_core_builtin.o` 16,384 + `lftpd.o` 7,724 + `ui_net_sink.o` 6,746 + + `ui_port.o` 6,408 + `nand_ftl.o` 6,200 = **43,462 B,占 `RW_IRAM1` 的 58%**。要动 `RW_IRAM1` 只能动这五块。 +2. **动态面只有一个**:所有任务栈 + TCB + 队列都在 `heap_4` 里,而堆在 CCM → **栈的余量问题就是 CCM 的 + 余量问题**。这就是红线从 SRAM1 迁到 CCM 的机制原因,也是"缩堆"必须先过 `stack_report.py` 的原因。 +3. **栈深的主因是日志与配置写链,不是算法本体**:`s_append` 每调用点 **216 B** 栈 + 配置原子写链 + (`cfg_store_write_atomic → f_rename`)把 defaultTask 推到 **3,024 B**。补日志要按调用点计费。 + ### 2.6 堆 / LVGL 池 / C 库 / Flash 明细 #### 2.6.1 FreeRTOS 堆(56 KB;2026-09-21 已迁 CCM `RW_CCM`) @@ -221,6 +230,12 @@ C2 dhara 失败类 +84;RO 另 +208,全是 C2 的失败类名表)→ `ER_IR > 验证:ui-verify 五步全过——**11 页内容黄金参考在裁剪前生成、裁剪后逐字节一致**,菜单 8 状态像素一致,LVGL 池水位 5,440 → 5,368 B(−72 B,样式表更小,一次性残留仍 80 B);`@build` 0 错 0 警;`@test` 真机 PASS。详见 `../UI设计/UI_设计架构.md` §4.1.4 第 10 条。 > **长效防复发**:已建门禁 `scripts/check_lv_conf_sync.py`(pre-commit 钩子 `lv-conf-sync`)——比对两份 `lv_conf.h` 的**生效值**(未定义则取 `lv_conf_internal.h` 兜底默认),并抓无效宏名与重复定义;首次跑揪出两端共 26 个 9.3 不存在的选项、3 处重复定义、10 项靠默认值隐式生效的开关,已清理(本次清理对镜像体积中性)。详解见 `docs/门禁说明/lv-conf-sync.md`(含四类判定、端专属白名单与首次落地实测)。 +> ⚠ **MicroLIB 的 `_fp_digits` 与双精度 helper(约 1,018 B)删不掉,别再去搜 `%f`**:全库 `%f` 命中 **0**, +> 这 1 KB 是 `snprintf` 的固有依赖——`printfa.o` 的 `_printf_core` 无条件引用 `_fp_digits`,只要用 +> `snprintf` 就带得进来。**能修的是根因侧**:`App/algo/prot_set.h` 的两个 Q10 宏曾写成 `double`, +> 2026-10-22 改单精度后 `Code` −332 B、5 个 helper(`dflti`/`d2f`/`f2d`/`dfixi`/`fepilogue` 共 300 B)消失, +> 且数值逐位等价(穷举 42 个字面量 + `int32` 全域 ÷1024 往返 4.49×10⁶ 例零差异)。 + ![Flash 布局](../images/内存布局_FLASH.svg) > 2026-09-11 快照的模块级分解(LVGL ~72 KB / 应用+UI ~47 KB / FatFS+dhara ~11 KB / CH395F ~10 KB / HAL ~9 KB / C 库 ~4.3 KB / FreeRTOS ~4.6 KB)见 `data/ram_report_20260911.md`;重跑 `scripts/ram_report.py` 即得当前分解。 @@ -253,8 +268,21 @@ C2 dhara 失败类 +84;RO 另 +208,全是 C2 的失败类名表)→ `ER_IR > - **保持常开**:阶段 0 的测量能力 + 阶段 3 的长效机制(`mem-budget` 92% 门禁、`RAM预算台账.md` 受管区、`ram_baseline.tsv` 趋势、`[STACK]` 水位与 `stack_report.py` / `ram_report.py`)。它们已落地、零维护成本,且正是"何时该重开优化"的传感器。 > - **已落地的优化不回退**:§4.1.1 LVGL 池 40→16 KB(✅ 2026-10-15,SRAM1 74.9% → **56.1%**)、§4.1.4 lftpd 大栈局部变量改静态(✅ 2026-09-21)。 > - **整簇暂缓、不再排期**:§4.1.2 启用 CCM 承载 UI 侧缓冲、§4.1.3 任务栈按实测缩减、§4.2.2 缩减 `configTOTAL_HEAP_SIZE`、§4.2.3 任务/队列全静态化,以及把池进一步试到 8 KB。 +> - ⚠ **"UI 侧缓冲进 CCM"要分两种,别一概而论**:**LVGL 内存池**是纯 CPU 访问 → 可以进 CCM; +> 而**帧缓冲 `g_ui_fbuf` / 绘制缓冲 / `ui_net_sink` 推流缓冲**由 **DMA2** 取数 → **必须留在 SRAM**, +> 搬进 CCM(CPU 专属,DMA 不可达)的后果是 DMA 静默读到错数据,不是报错。 > -> **暂缓理由与重开条件** → `../问题记录/项目审查与优化建议报告.md` §5.3。一句话:**当前没有功能在等这块预算**,而搬迁要动 scatter、要逐条过 DMA 可达性清单(违例是静默传错不是报错)、缩堆还得上板复测 `min_ever`——收益不抵风险与工时。下面各节**保留作重开时的实施依据,不代表现在要做**。 +> **暂缓理由与重开条件**(**本节是唯一权威**,其它文档只留指针): +> +> 暂缓理由一句话:**当前没有功能在等这块预算**,而搬迁要动 scatter、要逐条过 DMA 可达性清单 +> (违例是**静默传错**不是报错)、缩堆还得上板复测 `min_ever`——收益不抵风险与工时。 +> +> **重开条件(满足任一条才谈搬迁/缩堆)**: +> ① 出现"必须新增 **>8 KB** RAM"的功能且产品要它; +> ② `min_ever` **跌破 4 KB**(碎片或峰值失控——此时应**先削峰值**,不是搬家); +> ③ **CCM 撞墙**导致新任务建不起来。 +> +> 下面各节**保留作重开时的实施依据,不代表现在要做**。 ### 阶段 0:建立测量能力(先做,1~2 天) @@ -575,7 +603,7 @@ ISR 余量:该任务运行期间可能被中断打断的最深中断链(SPI/ > 已落地项(不再计入预期):§4.1.2 堆迁 CCM(2026-09-21)、§4.1.4 lftpd 静态化、§4.2.1 lftpd `malloc`→`pvPortMalloc`(2026-09-10)。 > 估算假设:LVGL 池缩到 16KB(8KB 未验证)且迁 CCM;`ui_net_sink` 产品构建关闭;`ui_port` 帧缓冲 + BBT 位图迁 CCM;堆缩 48K→32K。落地顺序与每步验证见 §6。 > -> ⏸ **2026-10-15 用户裁定:本表"目标"列所依赖的搬迁与缩堆整簇暂缓**(理由与重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3)。已落地部分只有 **1.1 池 40→16 KB**(SRAM1 实测 **73,568 B / 56.1%**,余 57,504 B)与 1.4;本表保留作重开时的收益测算依据,**当前实际水位以 `RAM预算台账.md` 受管区为准**,不要拿本表"目标"列当现状。 +> ⏸ **2026-10-15 用户裁定:本表"目标"列所依赖的搬迁与缩堆整簇暂缓**(理由与重开条件 → 本文档 §4)。已落地部分只有 **1.1 池 40→16 KB**(SRAM1 实测 **73,568 B / 56.1%**,余 57,504 B)与 1.4;本表保留作重开时的收益测算依据,**当前实际水位以 `RAM预算台账.md` 受管区为准**,不要拿本表"目标"列当现状。 ## 6. 实施顺序与验证 diff --git a/docs/内存管理/RAM预算台账.md b/docs/内存管理/RAM预算台账.md index acac7511..2a5cf342 100644 --- a/docs/内存管理/RAM预算台账.md +++ b/docs/内存管理/RAM预算台账.md @@ -1,7 +1,7 @@ # RAM 预算台账(配额 · 趋势 · 门禁) > **定位**:`docs/内存管理/RAM使用分析与优化方案.md` §8.2 模板与 -> `docs/问题记录/项目审查与优化建议报告.md` §5.5 三件套的**落地件**(2026-10-12,登记簿 N-27 前半)。 +> 内存治理三件套的**落地件**(2026-10-12,登记簿 N-27 前半)。 > 回答三个问题:**每个子系统还能用多少 RAM**(配额)、**总量趋势往哪走**(基线 TSV)、 > **超了怎么拦**(92% 门禁)。 > @@ -33,7 +33,7 @@ - **门禁**:pre-commit `mem-budget` 钩子(`scripts/ram_baseline.py --gate`)—— RW_IRAM1 / RW_CCM 任一 >92% 即拦提交,并打印 Top-10 RW+ZI 对象定位增量; 无 `.map` 时自适应跳过(CI 盲区登记在 `docs/任务规划/测试与架构专项.md` A-5 残余)。 -- **阈值依据**:92% 由 2026-09 体系评审提出、2026-10-12 落地为门禁(提出时的报告条目已随销项删除,闭环说明见 `docs/问题记录/项目审查与优化建议报告.md` §5.5)——留 ~8% 给突发缓冲与栈抬升, +- **阈值依据**:92% 由 2026-09 体系评审提出、2026-10-12 落地为门禁(提出时的报告条目已随销项删除,闭环说明见 `RAM使用分析与优化方案.md` §4 阶段 3「长效机制」与本文)——留 ~8% 给突发缓冲与栈抬升, 触线即触发排期,而不是静默逼近溢出。 - **软提醒**(不拦提交):tsv 末行落后于 `.map`(忘跑 `--update`)、`.map` 早于最新源码(忘 `@build`)。 - **子系统归集为参考值**:按对象名前缀归集(口径见 §2),合计与区域总量可差几十字节 @@ -59,7 +59,7 @@ UI 16 KB / RTOS 堆 56 KB / 应用 8 KB**。归集口径(按 `.map` 对象名 - **UI ⚠ 超配额 = 已知长期挂账,不是新增违规**:LVGL 池 16 KB(R-9 已于 2026-10-15 落地,由 40 KB 收缩)+ 帧/远显缓冲 ≈12.8 KB,实测 30,412 B。配额 16 KB 描述的是 **R-2 把 UI 侧缓冲迁进 CCM 之后的目标态**, 而 **R-2 后半已按用户裁定 2026-10-15 整簇暂缓**(`docs/任务规划/README.md` §2「预算与内存」已标暂缓)→ - **这条 ⚠ 会长期挂着**,判读时按已知挂账处理,别每轮当新问题追;重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3。 + **这条 ⚠ 会长期挂着**,判读时按已知挂账处理,别每轮当新问题追;重开条件 → `RAM使用分析与优化方案.md` §4。 - **RTOS 堆 = 配额本身**:56 KB 即 `configTOTAL_HEAP_SIZE`(2026-10-12 B5 由 48 KB 扩容,见 §6; `heap_4.o` 另含 32 B 元数据,不计超);**改堆 = 改配额**,必须先过本文件 §6 登记。 - **应用 ⚠ 小幅超**:8 KB 为报告规划值;2026-10-10 栈整改把 3 处 `FIL` 从栈搬进 BSS @@ -73,7 +73,7 @@ UI 16 KB / RTOS 堆 56 KB / 应用 8 KB**。归集口径(按 `.map` 对象名 | CCM 容量 | `RW_CCM` Max 见受管区 | scatter `RW_CCM`;**仅 CPU 可达,DMA 不可达**(RM0090 §3.1.1) | | 现占用 | 仅 FreeRTOS 堆 `heap_4`(56 KB,2026-09-21 迁入;2026-10-12 B5 扩容 48→56 KB) | 其余候选全部仍在 SRAM1 | | 现余量 | 受管区 RW_CCM 容量 − 占用 = **7,904 B** | **不够** R-2 后半的 UI 侧待迁体量(R-9 后 **29,570 B**)——⏸ 该搬迁已暂缓,见下行 | -| R-2 后半解锁链 | ⏸ **整簇暂缓(用户裁定 2026-10-15)**,本行保留作重开时的现状基线:① **R-9 ✅ 2026-10-15**:`LV_MEM_SIZE` 40→16 KB → 待迁体量 54,146 → **29,570 B**(SRAM1 74.9% → **56.1%**,实测池峰值 6,568 B)→ ② ~~现在卡在这一步~~:堆 56→32 KB(`docs/内存管理/RAM使用分析与优化方案.md` §4.2.2(阶段 2 第 2 项"缩堆"),再腾 24 KB;⚠ 2026-10-12 B5 反向扩容至 56 KB——9 任务栈 + 队列实测需要,缩回 32 KB 前必须重跑 `stack_report.py` + 上板 min_ever 复测)→ ③ CCM 余 ≈31.9 KB ≥ 29,570 B → 迁入 | **暂缓期间不启动**;重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3。**若重开,顺序不可颠倒**;每步前后跑 `stack_report.py` / `ram_report.py`(铁律) | +| R-2 后半解锁链 | ⏸ **整簇暂缓(用户裁定 2026-10-15)**,本行保留作重开时的现状基线:① **R-9 ✅ 2026-10-15**:`LV_MEM_SIZE` 40→16 KB → 待迁体量 54,146 → **29,570 B**(SRAM1 74.9% → **56.1%**,实测池峰值 6,568 B)→ ② ~~现在卡在这一步~~:堆 56→32 KB(`docs/内存管理/RAM使用分析与优化方案.md` §4.2.2(阶段 2 第 2 项"缩堆"),再腾 24 KB;⚠ 2026-10-12 B5 反向扩容至 56 KB——9 任务栈 + 队列实测需要,缩回 32 KB 前必须重跑 `stack_report.py` + 上板 min_ever 复测)→ ③ CCM 余 ≈31.9 KB ≥ 29,570 B → 迁入 | **暂缓期间不启动**;重开条件 → `RAM使用分析与优化方案.md` §4。**若重开,顺序不可颠倒**;每步前后跑 `stack_report.py` / `ram_report.py`(铁律) | | 迁入前置 | 目标缓冲必须过 DMA 可达性清单(`内存内容分配策略.md`) | 违例 = 静默传错(N-11 同类坑);克隆芯片 CCM 可靠性风险见 `docs/内存管理/RAM使用分析与优化方案.md` §7 | ## 4. 趋势基线(`scripts/ram_baseline.tsv`) @@ -93,6 +93,6 @@ UI 16 KB / RTOS 堆 56 KB / 应用 8 KB**。归集口径(按 `.map` 对象名 | 日期 | 变更 | 原因 / 出处 | |---|---|---| -| 2026-10-12 | 建档:三件套落地(本台账 + `scripts/ram_baseline.py` + `scripts/ram_baseline.tsv` + pre-commit `mem-budget` 钩子) | 登记簿 N-27 前半;`docs/问题记录/项目审查与优化建议报告.md` §5.5 | +| 2026-10-12 | 建档:三件套落地(本台账 + `scripts/ram_baseline.py` + `scripts/ram_baseline.tsv` + pre-commit `mem-budget` 钩子) | 登记簿 N-27 前半 | | 2026-10-12 | **RTOS 堆配额 48 KB → 56 KB**(`QUOTAS` 同步) | B5 protectTask 立项:iec104Task(2.5KB)+protectTask(2KB)+TCB 入堆后 48KB 池 min_ever 预估跌破 3,072 B 告警线 → `.ioc` L1 参数 `configTOTAL_HEAP_SIZE` 49152→57344(CCM 水位 75.3%→87.9%,仍 <92% 门禁;CCM 空闲降至 ≈8 KB)。连带影响见 §3 R-2 后半链注记 | | 2026-10-12 | **任务栈 +1536 B(堆内用量,配额 56 KB 不变)**:defaultTask 1024→1280 words(+1024 B)、timeSyncTask 512→640 words(+512 B);产品任务栈合计 37,632→39,168 B | 登记簿 N-33 栈收口:B7 定值持久化把 defaultTask 静态链推到 3016 B(余 1080 < 30% 线)、timeSyncTask 链 1264 B(余 784 < ISR 底线 1024);B6 台架背书 min_ever=10000 → 抬后实测 `heap free=16400 / min_ever=8464`(与预算 −1536 完全吻合,>3072 告警线);`stack_report` 9 任务 0 FAIL + `@test` PASS,见 `RAM使用分析与优化方案.md` §1.4 | diff --git a/docs/内存管理/存储栈RAM优化调研.md b/docs/内存管理/存储栈RAM优化调研.md index 8f3894b5..cf7c9664 100644 --- a/docs/内存管理/存储栈RAM优化调研.md +++ b/docs/内存管理/存储栈RAM优化调研.md @@ -4,7 +4,7 @@ > 数据来源:`data/ram_report_20260921.md`(.map 静态占用)+ 逐行代码核验(`nand_ftl.c` / `gd5f2gq5ue.c` / `Lib/dhara` / `Lib/FatFs/ffconf.h` / `lftpd*`) > 定位:`RAM使用分析与优化方案.md` 的存储专项补充;优化项编号 P0/P1/P2,与 `docs/内存管理/RAM使用分析与优化方案.md` §6 的 S 序号在"规划"一节对齐 > v1.1 清理(2026-09-21 同日):移除已落地的 P0-1 BBT 页缓冲收缩(−1,776B,commit `be1a30a`)与编程回读校验整体移除的实施记录(详见 GD5F TRAP-GD5F-05),以及过期逐模块基线表;仅保留未实施项与回归要求 -> ⏸ **实施状态(用户裁定 2026-10-15)**:本文**全部未实施项整簇暂缓、不再排期**——P0-2 页缓冲合并(= 报告 R-3)、P1-5 ①② 迁 CCM、以及依赖"堆 48K→32K"的第三步。当前没有功能在等这块预算,而搬迁要逐条过 DMA 可达性清单(违例是静默传错不是报错)。**保持常开**的是测量与门禁面(`ram_report.py` / `stack_report.py` / `mem-budget` 92% 门禁 / 台账 / 趋势)。理由与重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3;本文保留作重开时的实施依据,**不代表现在要做**。 +> ⏸ **实施状态(用户裁定 2026-10-15)**:本文**全部未实施项整簇暂缓、不再排期**——P0-2 页缓冲合并(= 报告 R-3)、P1-5 ①② 迁 CCM、以及依赖"堆 48K→32K"的第三步。当前没有功能在等这块预算,而搬迁要逐条过 DMA 可达性清单(违例是静默传错不是报错)。**保持常开**的是测量与门禁面(`ram_report.py` / `stack_report.py` / `mem-budget` 92% 门禁 / 台账 / 趋势)。理由与重开条件 → `RAM使用分析与优化方案.md` §4;本文保留作重开时的实施依据,**不代表现在要做**。 ## 1. 现状约束(不变,是下述全部方案的依据) @@ -51,11 +51,11 @@ ## 5. 页缓冲可合并性论证(2026-10-23) > 本节的来源:`Drivers/BSP/GD5F2GQ5UE/nand_ftl.c` 原注释声称"页缓冲三块不可合并的评估见报告", -> 而 `../问题记录/项目审查与优化建议报告.md` 里只有一行"中 / 暂缓",**论证从来没写过**——本节补上 +> 而原评审报告(2026-10-25 已删除)里只有一行"中 / 暂缓",**论证从来没写过**——本节补上 > (该注释已在本轮改为指向本节)。 > 结论:**三块不能合并**(最坏路径上同时存活,合并后的失败形态是**静默数据损坏**,不是报错); > 可削减的只有 `s_copy_buf` 一块,上限 −2,048 B,而**收益落点不是红线区** → -> `docs/问题记录/项目审查与优化建议报告.md` N-15 由"待评估"改为"**已评估、判定不做**", +> 原报告的 N-15 由"待评估"改为"**已评估、判定不做**"(报告已删除,结论以本节为准), > 与本文件 §2 那两条残余方案一起留在暂缓簇里。 ### 5.1 6,216 B 的构成(`.map` 实证) @@ -68,7 +68,7 @@ | `s_map` / `s_nand` / 3 个标量 | 56 + 8 + 8 | 0x2000667C 起 | dhara 状态与缓存标志 | — | `nand_ftl.o` 合计 **6,216 B = RW 16 + ZI 6,200**,其中三块页缓冲 6,144 B 占 **98.8%**。 -`../问题记录/项目审查与优化建议报告.md` §5.2 的 Top-5 表用 ZI 口径写 6,200,与本节的 6,216 差的就是那 16 B 的 RW,两处不矛盾。 +原报告 §5.2 的 Top-5 表用 ZI 口径写 6,200,与本节的 6,216 差的就是那 16 B 的 RW,两处不矛盾。 ### 5.2 三块同时存活的证据链(最坏路径) @@ -122,7 +122,7 @@ 而任务栈本身就在 CCM。 结论:**页缓冲合并这条线的收益没有消费者**。这正是 2026-10-15 整簇暂缓的机制原因,本节只是把它从"判断" -补成了"论证"——所以暂缓不变,重开仍按 `../问题记录/项目审查与优化建议报告.md` §5.3 的三条条件。 +补成了"论证"——所以暂缓不变,重开仍按 `RAM使用分析与优化方案.md` §4 的三条条件。 ### 5.6 复现 diff --git a/docs/子系统设计/看门狗设计说明.md b/docs/子系统设计/看门狗设计说明.md index 22a148aa..b55a540f 100644 --- a/docs/子系统设计/看门狗设计说明.md +++ b/docs/子系统设计/看门狗设计说明.md @@ -12,7 +12,7 @@ > [`../测试说明/实机测试实施指南.md`](../测试说明/实机测试实施指南.md)(故障注入台架流程)、 > [`../架构设计/项目启动顺序管理.md`](../架构设计/项目启动顺序管理.md)(启动时序与就绪屏障)、 > [`../测试说明/ST-LINK_CLI_复位使用说明.md`](../测试说明/ST-LINK_CLI_复位使用说明.md)(复位语义)、 -> [`../问题记录/项目审查与优化建议报告.md`](../问题记录/项目审查与优化建议报告.md)(N-03 的立项出处;该条已修复并按「修复即销项」从报告删除,**完整记录即本文**) +> 《项目审查与优化建议报告》(N-03 的立项出处;该条已修复并按「修复即销项」从报告删除,**完整记录即本文**;报告本身 2026-10-25 已删除) --- @@ -646,7 +646,7 @@ enter/exit 段还能读出"此刻仍在段内已多久"——**永久阻塞的 | `Inc/FreeRTOSConfig.h:165` | `configASSERT` → `vApplicationAssertFailed` | | `App/task/net_task.c` / `default_task.c` / `sync/time_sync.c` / `NET/lftpd/*` / `GD5F2GQ5UE/gd5f2gq5ue.c` | 心跳与喂狗埋点(见 §5.5) | -> 立项时(2026-09-29)的"仓库里根本没有 IWDG 驱动"一类取证已随实施失效,不再列出;当时的原始登记在《项目审查与优化建议报告》§4.1,已随「修复即销项」删除——**取证与实施记录以本文为准**。 +> 立项时(2026-09-29)的"仓库里根本没有 IWDG 驱动"一类取证已随实施失效,不再列出;当时的原始登记在《项目审查与优化建议报告》§4.1(该报告 2026-10-25 已删除),已随「修复即销项」删除——**取证与实施记录以本文为准**。 ## 附录 B:备选方案取舍记录 diff --git a/docs/子系统设计/配置文件设计说明.md b/docs/子系统设计/配置文件设计说明.md index 09a59a99..97a6e387 100644 --- a/docs/子系统设计/配置文件设计说明.md +++ b/docs/子系统设计/配置文件设计说明.md @@ -456,7 +456,7 @@ void adc_cfg_init(void) **P0-1(2026-09-18)实现纠偏**:本表原设计即"暂态走堆",但实现落在 C 库 `malloc` 上——本机工具链为 **MicroLIB**,其 C 堆只有 `Heap_Size = 0x200`(512 B),真机上 4 处 KB 级分配**必然返回 NULL**,症状是"配置读不到 → 静默回落工厂默认值"(模拟器用宿主 CRT 堆,故两端表现不一致)。现全部改走 `cfg_store_alloc`;map 复核:`malloc.o` 不再参与链接,`Removing startup_stm32f407xx.o(HEAP), (512 bytes)` → **静态区反而净增 512 B 余量**。 -**结论**:配置引擎自身不需要内存优化专项;但 9,217 B 暂态峰值已占 FreeRTOS 堆空闲的一半以上,且与 lftpd 的每命令分配共存——**流式读写(免整文件驻留内存)仍列为后续优化项**,方案见本文 §6.2/§8 与《项目审查与优化建议报告》§5.3(原报告 §4.4.1 已随 N-01 修复按销项删除,完整记录沉淀在本文)。 +**结论**:配置引擎自身不需要内存优化专项;但 9,217 B 暂态峰值已占 FreeRTOS 堆空闲的一半以上,且与 lftpd 的每命令分配共存——**流式读写(免整文件驻留内存)仍列为后续优化项**,方案见本文 §6.2/§8(原报告 §4.4.1 已随 N-01 修复按销项删除,完整记录沉淀在本文)。 ## 9. 兼容与迁移 diff --git a/docs/测试说明/主机单测覆盖率口径.md b/docs/测试说明/主机单测覆盖率口径.md index 0e32fdec..b72975e5 100644 --- a/docs/测试说明/主机单测覆盖率口径.md +++ b/docs/测试说明/主机单测覆盖率口径.md @@ -8,8 +8,7 @@ > **基线台账**:[`scripts/test_coverage_baseline.json`](../../scripts/test_coverage_baseline.json) > **关联文档**: > [`测试开发标准流程.md`](测试开发标准流程.md)(L0~L3 分层与门禁决策表)、 -> [`../问题记录/项目审查与优化建议报告.md`](../问题记录/项目审查与优化建议报告.md) §4.8(本文关闭它的空白 ①) -> 与 [`../问题记录/项目审查与优化建议报告.md`](../问题记录/项目审查与优化建议报告.md) §5.5 第 5 条的前半、[`../代码规范/pre-commit使用说明.md`](../代码规范/pre-commit使用说明.md)(钩子通用机制) +> [`../代码规范/pre-commit使用说明.md`](../代码规范/pre-commit使用说明.md)(钩子通用机制) --- @@ -735,7 +734,7 @@ uint16_t ch395f_link_change_count(void); | 日期 | 说明 | |---|---| -| 2026-10-23 | 新建。落地 `scripts/check_test_coverage.py` 与 `scripts/test_coverage_baseline.json`:首次实测 16 套全通过,并集 2552/2893 行(88.2%)、函数 193/207(93.2%),在测 19 文件 / 未触及 125 文件。同步销项 `docs/问题记录/项目审查与优化建议报告.md` §4.8 空白 ①(覆盖率口径)与 §5.5 第 5 条前半、§0.1 / §0.4 / §7 对应行;`malloc(` 正则那条**同日也落地**(`coding-standard` CODE-RULE-20,见 `docs/门禁说明/coding-standard.md`)。**同日补 §2.1**:用户问「为什么不用 GCC」,实测本机 WSL2 Ubuntu 有 gcc/gcov 15.2.0,16 套单测在 gcc 下**全部编过且全绿**、`gcov -b -c` 确实给出分支覆盖(`nand_ftl.c` 分支 41.40%)——但换编译器=换分母(`sha256.c` gcc 105 行 vs MSVC 114 行),故默认通道不变。 | +| 2026-10-23 | 新建。落地 `scripts/check_test_coverage.py` 与 `scripts/test_coverage_baseline.json`:首次实测 16 套全通过,并集 2552/2893 行(88.2%)、函数 193/207(93.2%),在测 19 文件 / 未触及 125 文件。同步销项原评审报告的 §4.8 空白 ①(覆盖率口径)与 §5.5 第 5 条前半、§0.1 / §0.4 / §7 对应行;`malloc(` 正则那条**同日也落地**(`coding-standard` CODE-RULE-20,见 `docs/门禁说明/coding-standard.md`)。**同日补 §2.1**:用户问「为什么不用 GCC」,实测本机 WSL2 Ubuntu 有 gcc/gcov 15.2.0,16 套单测在 gcc 下**全部编过且全绿**、`gcov -b -c` 确实给出分支覆盖(`nand_ftl.c` 分支 41.40%)——但换编译器=换分母(`sha256.c` gcc 105 行 vs MSVC 114 行),故默认通道不变。 | | 2026-10-23 | **用户裁定:本仓只留 MSVC 一条覆盖率通道**,不建 gcc/WSL 第二条("后面可能引入更多问题")。实测数据与三条代价保留在 §2.1 当决策依据,§7 第 1 条把分支覆盖改记为**已接受缺口**,§8 下一步删掉"建通道"并写明重开该裁定的前提(必须先答"两份分母怎么对齐")。脚本与基线**不受影响**,仍是 `mscoverage` 一条路 | | 2026-10-23 | **P1 第①批落地**(net_cfg / ftp_cfg / prot_set_store / task_prof 四个模块,104 条断言): 套件 16→20、`files_tested` 19→23、分母 2,893→3,163;照出并修掉 `net_cfg` 的 WAIT 契约违背与 diff --git a/docs/环境与部署/项目部署环境要求.md b/docs/环境与部署/项目部署环境要求.md index 49eaadee..7f0d8b90 100644 --- a/docs/环境与部署/项目部署环境要求.md +++ b/docs/环境与部署/项目部署环境要求.md @@ -503,7 +503,7 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级 | 资源 | 已用 | 总量 | 利用率 | 余量 | 红线说明 | |---|---|---|---|---|---| -| Flash(`ER_IROM1` = Code + RO) | 232,536 B(227.09 KB) | 1 MB | 22.2% | ≈804 KB | **充裕**:产品需求无 OTA / 双镜像预算,Flash 不是卡点;死代码裁剪簇已收口 → `docs/问题记录/项目审查与优化建议报告.md` §5.4 | +| Flash(`ER_IROM1` = Code + RO) | 232,536 B(227.09 KB) | 1 MB | 22.2% | ≈804 KB | **充裕**:产品需求无 OTA / 双镜像预算,Flash 不是卡点;死代码裁剪簇已收口 → `docs/内存管理/RAM使用分析与优化方案.md` §2.6.4 | | 主 SRAM1(静态区;FreeRTOS 堆已迁 CCM) | 75,264 B(73.5 KB) | 128 KB | 57.4% | 55,808 B | 已不紧张——2026-10-11 堆迁 CCM 与 2026-10-15 `LV_MEM_SIZE` 40→16 KB 两步的结果 | | CCM(`RW_CCM` 段) | 57,376 B(56.0 KB) | 65,280 B | **87.9%** | **7,904 B** | **当前真正的红线**:加任务 / 抬栈 / 加堆会先在这里撞墙;`mem-budget` 钩子在 92% 拦提交 | diff --git a/docs/编号规范.md b/docs/编号规范.md index 9267e7b1..87d64cc3 100644 --- a/docs/编号规范.md +++ b/docs/编号规范.md @@ -18,7 +18,7 @@ |---|---| | 2026-09-21 错误码传播审计 | `E-xx`、缺陷模式 `P1~P9`、严重度 `P0~P2` | | 2026-09-15/09-21 代码审计 | `P0-x` ~ `P3-x`(严重度直接进编号) | -| 2026-09 项目审查与优化建议报告 | `N-xx`、`D-x`、`S-x`、`R-x`、`F-x`、`U1~U5` | +| 2026-09 项目审查与优化建议报告(**2026-10-25 已删除**) | `N-xx`、`D-x`、`S-x`、`R-x`、`F-x`、`U1~U5`(六族属主文档已删,存量冻结作历史指称) | | 台架与长期观察 | `N-x`、`S-x`、`T-x`、`gen`、`round`、`V2/V4/V5` | | 2026-10-02 复审 | `S1~S14`、`A-1~A-7` | | 任务规划 | `W`、`B\d`、`C\d`、`D\d`、`M\d` | @@ -201,7 +201,7 @@ | 冻结对象 | 处置 | |---|---| | `E-` | 冻结于 `E-63`;引用照旧,**禁止新增**;门禁拒绝游标之外的新 E 号 | -| `docs/问题记录/项目审查与优化建议报告.md` 自造的 `N-xx`/`D-x`/`S-x`/`R-x`/`F-x`/`U1~U5` | 报告是历史基线,**不回改**;引用一律紧邻文档名;未闭环项已并轨进 `N-19~N-29`,出处列保留报告编号 | +| 《项目审查与优化建议报告》自造的 `N-xx`/`D-x`/`S-x`/`R-x`/`F-x`/`U1~U5`(**该报告 2026-10-25 已删除**) | 报告是历史基线,**不回改**;引用一律紧邻文档名;未闭环项已并轨进 `N-19~N-29`,出处列保留报告编号。六族在 `id_registry.json` 里 `owner_docs` 已清空、`check_dangling` 关闭(§4.3) | | `docs/问题记录/CH395F_Trap_Records.md` 2026-10-11 审计的 `A1~A6`/`B1~B10` | 该表是审计快照(条目已修复或推翻),**冻结**;新发现进 `DEF`;引用紧邻文档名 | | `P0-x`~`P3-x` | 在册项迁 `DEF`;已闭环项留在历史文档,走别名表 | | `Task #32` 等会话临时号 | **禁止入册**;现存引用(`Src/main.c`、`Drivers/BSP/UI/ui_net_sink.c` 的 `I-1/I-2`)改写为可解析形式或就地展开成事实描述 | @@ -217,6 +217,56 @@ | 图元 id | `README.md` 架构图 Mermaid 节点 `A1`/`B1`/`C1`/`D2` | 改描述性 id(`net`/`sto`/`ui`),避免与条目字面撞名 | | 运行时计数 | 网络代次号 `net_get_generation()` | 代码概念;与台架 `GEN` 是两回事,文档里须写全"网络代次号" | +### 4.5 报告自有编号族登记处(属主文档 2026-10-25 已删,本表是唯一登记处) + +> 《项目审查与优化建议报告》(原 `docs/问题记录/项目审查与优化建议报告.md`)已于 **2026-10-25 删除**, +> 但它自造的 6 个编号族(`N-xx` / `D-x` / `S-x` / `R-x` / `F-x` / `U1~U5`)在全仓仍有大量**历史指称**。 +> 本节承接原报告 §9 的登记职责,`scripts/id_registry.json` 里这 6 族的 `owner_docs` 就指向本节。 +> +> - 六族**一律冻结**:不再新增号,新条目用语义标识(§3.3)。 +> - 引用时仍**必须紧邻文档名或「报告」字样**(`原报告 N-14`、`报告 F-5`)——它们与登记簿的 +> `N-x` / `S-x` / `D-x` **同字母不同义**(原报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架)。 +> - 未闭环项早已并轨到 `docs/任务规划/登记簿.md` 的 `N-19`~`N-29` 与 U 簇,出处列保留报告编号。 +> +> **⚠ 本节的登记处身份只恢复「可判定比例」,不构成定义集。** 规范正文混着大量写法示例 +> (`N-99`、`S1`、`N-31`),若让本节进定义集会同时打穿两条判定:裸形 `S1` 被判成 `S-1` 漏连字符、 +> 本节表里的 `S-3` 与登记簿 S-3 被判重复定义。因此 `check_ids.py` 对 `snapshot_only` 族另设 +> `_def_owners`(剔除规范正文)——本表是**存档**,悬空/撞号/裸形一律不拿它当依据。 +> +> **⚠ 11 个已死号另有别名登记**(`scripts/id_aliases.json`,`status: void`):`N-03b` / `N-10` / `N-11` / +> `N-12` / `N-13` / `N-20` / `N-21` / `N-24` / `N-26` / `S-1` / `S-2`。它们被代码注释与文档广泛引用 +> (`nand_port_test.c`、`sys_log_mcu.c`、`nand_ftl.c`、`gd5f2gq5ue.h` 等约 110 处),原先是靠"报告里 +> 顺带提过一句"才算有定义——报告一删就集体悬空。别名表逐条写明它们现在详述于哪篇文档,这也正是 +> 原报告「去处表」的内容。其中 `N-21` / `S-1` / `S-2` **一号两义**(登记簿与原报告各有一个), +> 别名注记里已分别标明。 + + +| 号 | 事项 | 状态 | 现在详述于 | +|---|---|---|---| +| N-01 | 配置引擎整文件驻留 | ✅ 已修(流式列为后续项) | `docs/子系统设计/配置文件设计说明.md` §6.2/§8 | +| N-02 / N-03 / N-03a / N-03b / N-03c | 存储与日志取证类条目 | ✅ 已闭环 | `docs/架构设计/STM32F4-Base存储架构说明.md` §10.1 | +| N-06 | 注册白名单与 `--strict` | 🟡 残余随 B2 | 登记簿 N-23 残余 | +| N-07 / N-08 | 网络自愈与卷锁 | ✅ 已闭环 | `docs/网络/网络自愈架构设计.md` §4.10 | +| **N-09** | `NET_MAX_SOCKETS`/PHY/PASV 三项网络债 | ❌ 在策 | `docs/任务规划/登记簿.md` N-25 | +| N-10 ~ N-13 | 主机侧 nand/dhara 移植层单测动因 | ✅ 已建 | `test/host/nand_port/`(第 16 个单测钩子) | +| **N-14** | FTL 写回缓存无空闲/掉电强制 flush | ⏸ 暂缓 | `docs/任务规划/登记簿.md` N-22 | +| **N-15** | `nand_ftl` 三块 2 KB 页缓冲未合并 | 🟡 **观察项(2026-10-23 判定不做)** | `docs/内存管理/存储栈RAM优化调研.md` §5、登记簿 N-25 | +| N-16 / N-17 | 台架窗口项(task stall 归因等) | 🟡 待窗口 | 登记簿 N-16/N-17 | +| **N-18** | V0.1 双转换器无共同采样触发 | ❌ 待 V0.2 | `AGENTS.md` 硬件引脚节 | +| N-19 ~ N-21 | 时钟/对时与已销项条目 | ✅ 已闭环 | `git log`(该报告已删) | +| **D-1** | 外部资料与工程文档同仓同树 | ❌ 暂不处理 | `docs/任务规划/登记簿.md` N-29 | +| D-2 ~ D-7 | 文档治理条目(链接/同源/编号/BOM 等) | ✅ 多数已制度化为钩子 | `docs/文档规范.md` | +| D-9 | 文档面残余观察 | 🟡 观察 | 本节即定义位 | +| **S-1** | 分层反向依赖(BSP include App 的头) | 🟡 已止住恶化(存量 6 条基线待还,新增被 `layer-deps` 拦) | `docs/门禁说明/layer-deps.md`(存量 6 条基线) | +| **S-2** | 跨模块裸 `extern` | ✅ **已闭环 2026-10-22**(24 处手写全消;两类本就不算债见 §0.4) | `git log`;契约见 `App/task/task_handles.h`、`gd5f_spi1_notify_*`、`net_msg_queue_adopt` | +| **S-4** | `app_cfg.h` 未接线占位开关 | ✅ **已闭环 2026-10-22**(4 个零消费点宏删除) | `App/app/app_cfg.h` 修改记录 v1.2;口径同步见 `docs/环境与部署/项目部署环境要求.md` §3.2/§3.5、`docs/产品需求/产品需求设计文档.md`、`docs/任务规划/排期详述.md` C5 | +| **S-3** | `.ioc` 侧 USART1 配置 | ❌ 在策 | 登记簿 S-3 | +| **S-5** | 统一 `bsp_err_t` 错误码与超时命名约定 + **返回值不得裸丢弃** | 🟡 主体已落地(2026-10-23:契约 + `bsp-err` 四规则 + RS485/SD2506/TPAFE 收编 + GD5F 改名 + dhara 三类码 + `consume-result` 照出 37 条丢弃 + ECC 回读校验;基线 19 → 1 → 38) | `docs/代码规范/pre-commit使用说明.md` §2.27、`STM32F4-Base存储架构说明.md` §10.4、`Drivers/BSP/bsp_err.h` | +| R-1 ~ R-9 | 内存优化项(R-9 已落地、R-5 判定不可行、其余随簇暂缓) | 见 `docs/内存管理/RAM使用分析与优化方案.md` §4 | `docs/内存管理/RAM使用分析与优化方案.md` §4、`docs/内存管理/RAM预算台账.md` §3 | +| F-1 / F-2 / F-3 | LVGL 死代码裁剪,省 64,576 B | ✅ 已落地 2026-10-11 | `docs/内存管理/RAM使用分析与优化方案.md` §2.6.4 | +| **F-4 / F-5 / F-6** | Flash 双精度与死代码簇 | ✅/🟡/❌ 见 `docs/内存管理/RAM使用分析与优化方案.md` §2.6.4 | `App/algo/prot_set.h` 注释 | +| U1 ~ U5 | UI 标准化簇 | 见 `docs/UI设计/UI_设计架构.md` §1.4;排期见 `docs/任务规划/README.md` §2.0「UI 扩展」 | + --- ## 5. 分配、引用、销项规则(强制) @@ -401,7 +451,7 @@ git grep -n '<旧字面量>' # 零残留 |---|---| | 扫描文件 | 536 个(`git ls-files` 减去 §8 排除清单) | | 编号字面量出现 | 8271 处 | -| **可判定比例基线** | **82.6%**(6840 / 8271 = 82.70%,批 1 改名后重打,存进 `id_registry.json` 时**下取整到 0.1pp**——用 `round()` 会让 82.34 进位成 82.3 再反过来把自己判死,实测踩过;比较容差 0.1pp) | +| **可判定比例基线** | **84.0%**(8747 / 10410 = 84.02%,2026-10-25 删报告 + 补登 11 条已死号别名后重打;存进 `id_registry.json` 时**下取整到 0.1pp**——用 `round()` 会让 82.34 进位成 82.3 再反过来把自己判死,实测踩过;比较容差 0.1pp) | | 校验 1 未登记前缀 | 0 处 | | 校验 2 形态不合规 | 396 处(**批 1 已从 417 降到 396**:裸形 `S`/`T` 类 71 → 50。剩余大头:真无模块码 `TC-nnn` 181 处 / 5 文件、数字模块码 `TC-104-nnn` 23 处(§6 表里模块码是 `I104`,非数字)、`DP-01`~`DP-04` 22 处、`Task #nn` 33 处、`Trap 空格形`+`陷阱 中文形` 43 处、`gen/round` 36 处、大写后缀 31 处) | | 校验 3 悬空引用 | 错误 626 / 告警 223(scoped 别名收编旧号后 −16)(错误集中在 `TC-PS-*`/`TC-PE-*`/`TC-AH-*`/`TC-FR-*`/`TC-SOE-*`——**主机侧单测有码无文档**,正是 §7.2 列的"缺文档 = 追溯断链") | @@ -533,7 +583,7 @@ git grep -n '<旧字面量>' # 零残留 | **1-① 小族** | `RC`/`PAT`/`GEN`/`RUN`/`MS`/`GAP`/`SC`/`OQ`/`RSK`/`DR`/`TRAP`/`ST`/`UL`/`LAT`/`CS` + Mermaid 节点 id + 孤儿处置 | 每批:dry-run 通读 → 落盘 → `git grep` 零残留 → `check_doc_links --all` → `@build` 0/0 → `ci_local.py` | 中 | | **1-② 大族** | `N` 补零 + `S`/`T` 并入;`WI` ← `B`/`C`/`D`/`W1-0`/`S1x`/`A-x`/`R-x`/`F-x`/`U-x`;测试分层 `L0~L3` → `T0~T3`(**最大机械批次**,`L0.5` 一词全库百余处) | 同上,逐族一个 commit | **高** | | **1-③ 缺陷族** | `DEF` ← `P0-x`~`P3-x` 在册项;报告历史编号补齐紧邻文档名;档位词规则落地;别名表与游标定稿 | 同上 | 中 | -| **2 门禁** | ✅ **已落地(2026-10-20,warn-only)**:`scripts/check_ids.py` + `id-check` 钩子 + `scripts/id_registry.json` / `scripts/id_aliases.json`;`check_test_traceability.py` 已收编(正则补齐 + 纳入 7 篇「单元测试说明.md」与 `test/host/` 一侧) | 全库告警清零后 entry 加 `--strict` 转拦提交;可判定比例基线 **82.6%** 已入档(批 1 改名后由 82.3% 抬升)(§8.1,写在 `id_registry.json` 里,跌破即失败) | 中(首轮确实暴露出 626 处真悬空 + 416 处形态违规 + 269 处未紧邻文档名,见 §8.1) | +| **2 门禁** | ✅ **已落地(2026-10-20,warn-only)**:`scripts/check_ids.py` + `id-check` 钩子 + `scripts/id_registry.json` / `scripts/id_aliases.json`;`check_test_traceability.py` 已收编(正则补齐 + 纳入 7 篇「单元测试说明.md」与 `test/host/` 一侧) | 全库告警清零后 entry 加 `--strict` 转拦提交;可判定比例基线 **84.0%** 已入档(批 1 改名后由 82.3% 抬升,2026-10-25 删报告后由 82.6% 抬到 84.0%)(§8.1,写在 `id_registry.json` 里,跌破即失败) | 中(首轮确实暴露出 626 处真悬空 + 416 处形态违规 + 269 处未紧邻文档名,见 §8.1) | 每阶段结束停下等指令再提交(`AGENTS.md` 边界:commit/push 须明确指示)。 diff --git a/docs/门禁说明/bsp-err.md b/docs/门禁说明/bsp-err.md index f99801a6..05b0f7fe 100644 --- a/docs/门禁说明/bsp-err.md +++ b/docs/门禁说明/bsp-err.md @@ -7,7 +7,7 @@ `language: system`、`pass_filenames: false`)。 - 规则脚本:`scripts/check_bsp_err.py`(纯标准库;文件头就是规则正文)。 - 约定正文:`Drivers/BSP/bsp_err.h`(**header-only,无 `.c`** → 不占体积、不需双端注册)。 -- 背景与整改史:`docs/问题记录/项目审查与优化建议报告.md` §0.4 与 §9 的 S-5 行。 +- 背景与整改史:S-5 条目的完整记录已随审查报告删除,现存依据 = 登记簿 **S-5** 行与 `Drivers/BSP/bsp_err.h`。 ## 1. 它在查什么 diff --git a/docs/门禁说明/id-check.md b/docs/门禁说明/id-check.md index 8660cee3..b51d5915 100644 --- a/docs/门禁说明/id-check.md +++ b/docs/门禁说明/id-check.md @@ -33,10 +33,17 @@ - **本次实测拦下过我自己两次**:一次是"字母加数字"自造号(校验 1),一次是引用某个跨文档 编号时没紧邻文档名(校验 6)——两次都是提交前门直接报,说明它在真起作用。 - 校验 8 是唯一的"趋势"闸门:它不要求号变少,只要求**解释能力不许退化**(新增不可判定的字面量会让比例下跌 → 失败)。 +- **`owner_docs` ≠ 定义集**(2026-10-25 起):族可以"有登记处"却"没有定义位"。判可判定只看 + `owner_docs` 是否解析出真实文件;而悬空(校验 3)/ 撞号(校验 4)/ 裸形(校验 2)/ 紧邻(校验 6) + 一律只看 `_def_owners`。两者仅在一种情形下不同:**`snapshot_only` 族的登记处挂在规范正文** + (`docs/编号规范.md` §4.5 那种冻结存档表)。规范里混着大量写法示例(`N-99`、`S1`、`N-31`), + 若拿它当定义集会立刻误伤——实测裸形 `S1` 被判成 `S-1` 漏连字符 238 条、表里 `S-3` 与登记簿 S-3 + 被判重复定义。所以这类族的 `_def_owners` 为空,等价于"属主已删、只有存档"。 + 代价要认清:这类族的号**不会再被校验 3 兜住**,新增引用只能靠别名表或人工核。 ## 3. 触发面 -- 扫描面以 git 清单为准。当前一次实跑:**551 个文件、编号字面量 8868 处**。 +- 扫描面以 git 清单为准。当前一次实跑:**696 个文件、编号字面量 10410 处**。 - **排除**:`Lib/`、`Middlewares/`、HAL/CMSIS、`docs/芯片手册/`、`docs/硬件平台/`。 最后一个是关键:硬件文档里的**元器件位号 `U1`/`C12`/`R3`/`L5`/`D7`** 与我们的编号字面 同形,不整体排除就会大量误报(脚本里另有一套位号识别,但仍**没有解除这两个目录的语料排除**)。 @@ -92,7 +99,7 @@ - 存量:`scripts/id_known_backlog.json`(指纹级);**只减不增**,收紧用 `--prune-backlog`。 - 别名:`scripts/id_aliases.json`(旧字面量 → 现行字面量)——号改名走 `scripts/rename_ids.py`, 它会显式写别名条目,**绝不全局查找替换**。 -- 比例基线:`id_registry.json` 的 `decidable_ratio_baseline`(实跑当前 82.85%,基线 82.6%、容差 0.1pp)。 +- 比例基线:`id_registry.json` 的 `decidable_ratio_baseline`(实跑当前 84.02%,基线 84.0%、容差 0.1pp)。 ## 8. 改这个门禁本身 @@ -105,4 +112,5 @@ | 日期 | 变更 | |---|---| +| 2026-10-25 | 补「`owner_docs` ≠ 定义集」口径(§2 末条):`snapshot_only` 族的登记处挂在规范正文时,`_def_owners` 为空 → 只恢复可判定、不参与悬空/撞号/裸形/紧邻。基线 82.6% → **84.0%**(删《项目审查与优化建议报告》+ 补登 11 条已死号别名后重打,实测 84.02%、696 文件 / 10410 字面量) | | 2026-10-23 | 首篇逐项文档(数据为当日实跑:551 文件 / 8868 字面量 / 台账 640 处 / 可判定 82.85%) | diff --git a/docs/门禁说明/lv-conf-sync.md b/docs/门禁说明/lv-conf-sync.md index f0d94196..8ed917ec 100644 --- a/docs/门禁说明/lv-conf-sync.md +++ b/docs/门禁说明/lv-conf-sync.md @@ -4,7 +4,7 @@ > "文件里写了什么"。不一致时最直接的伤害是:**像素回归跑的不是固件真正编译的那套特性**。 - 配置:`entry: python scripts/check_lv_conf_sync.py`、`pass_filenames: false`;2026-10-11 加, - 与 Flash 死代码裁剪那一簇同批落地(背景见 `docs/问题记录/项目审查与优化建议报告.md`)。 + 与 Flash 死代码裁剪那一簇同批落地(背景见 `docs/内存管理/RAM使用分析与优化方案.md` §2.6.4)。 ## 1. 它在查什么 diff --git a/docs/门禁说明/mem-numbers.md b/docs/门禁说明/mem-numbers.md index 9c800080..5dbb2aef 100644 --- a/docs/门禁说明/mem-numbers.md +++ b/docs/门禁说明/mem-numbers.md @@ -1,7 +1,7 @@ # `mem-numbers` — 文档里的内存 / Flash 数字是否与 `.map` 一致 > 一句话:它让**"照文档推算内存余量"这件事仍然成立**。事实源是 Keil 的 `.map`,不是文档作者的记忆。 -> 属于审查报告"文档数字一致性"三档里的**体积档**(档号见 `docs/问题记录/项目审查与优化建议报告.md`)。 +> 属于"文档数字一致性"三档里的**体积档**(三档口径见 `docs/文档规范.md`)。 - 配置:`entry: python scripts/check_mem_numbers.py --scan`、`pass_filenames: false`、 `files:` 覆盖 `docs/内存管理/*.md` 与相关脚本/文档改动面。 diff --git a/docs/门禁说明/task-table.md b/docs/门禁说明/task-table.md index 099f38ae..9eee4838 100644 --- a/docs/门禁说明/task-table.md +++ b/docs/门禁说明/task-table.md @@ -2,7 +2,7 @@ > 一句话:任务名 / 栈字数 / 优先级这三列**不许手抄**,事实源是 `Src/freertos.c`。 -- 归属:审查报告"文档与源码一致性"里的任务表档(`docs/问题记录/项目审查与优化建议报告.md`)。 +- 归属:"文档与源码一致性"里的任务表档(口径见 `docs/文档规范.md`)。 - 配置:`entry: python scripts/gen_task_table.py --check`、`pass_filenames: false`、 `files: ^(README\.md|AGENTS\.md|Src/freertos\.c)$`。 diff --git a/docs/问题记录/GD5F2GQ5UE_Trap_Records.md b/docs/问题记录/GD5F2GQ5UE_Trap_Records.md index 0fbce713..512b410d 100644 --- a/docs/问题记录/GD5F2GQ5UE_Trap_Records.md +++ b/docs/问题记录/GD5F2GQ5UE_Trap_Records.md @@ -234,7 +234,7 @@ if (ok) { ## TRAP-GD5F-07 — dhara 移植层:`is_free` 只看页首 + HAL 无几何校验(已修复,2026-10-15) -**发现时间**:2026-10-15(`项目审查与优化建议报告.md` N-12 / N-13 复核,登记簿原 N-21) +**发现时间**:2026-10-15(原审查报告 N-12 / N-13 复核,登记簿原 N-21;该报告 2026-10-25 已删除) **现象 / 机制**(两个独立缺陷,同一层): diff --git a/docs/问题记录/项目审查与优化建议报告.md b/docs/问题记录/项目审查与优化建议报告.md deleted file mode 100644 index 74004c49..00000000 --- a/docs/问题记录/项目审查与优化建议报告.md +++ /dev/null @@ -1,700 +0,0 @@ -# STM32F4-Base 项目审查与优化建议报告 - -> 版本 **v3.0** 2026-10-22(v2.x 2026-09-11 起多次增量修订) -> -> **本版是全量重写**:按 2026-10-22 的仓库重新取数审计,已闭环条目、失效数字与已完成的规划正文(六维 -> 评分旧表、UI 8 人日方案正文、波次交付物清单)整段删除。**刻意保留三层**:结论层(§0~§7)、**编号族 -> 登记处(§9,`check_ids.py` 的属主登记处,删了就断门禁)**、变更记录与销项去处(文末,按项目纪律冻结)。 -> -> ⚠ 待办**顺序的唯一权威** = [`../任务规划/README.md`](../任务规划/README.md) §2;本文只留"评审快照 + -> 证据 + 为什么这样判",不另立排期,避免两份清单漂开(本版重写就是因为旧 §0.4 与登记簿漂开了)。 - -## 0. 执行摘要 - -### 0.1 六维评分(2026-10-22 复评) - -| 维度 | 评级 | 今天的实测依据 | 相比 2026-10-15 的变化 | -|---|---|---|---| -| 结构与分层 | 🟢 良好 | 单向依赖未被破坏;双端注册反向校验 PASS;326 个编译单元全部可追溯 | 无退化 | -| 文档与治理 | 🟢 良好 | 39 个提交钩子 + 16 套主机单测;工程 md 91 份;`doc-links` 全库 0 问题 | 新增 `编号门禁增量拦截` 与内存快照回填常态化 | -| 内存与 Flash | 🟡 可控但已换位置 | SRAM1 **57.4%**(余 55,808 B)、Flash **22.1%**、**CCM 87.9%(余 7,904 B)** | **红线从 SRAM1 迁到 CCM**(堆 2026-10-11 迁 CCM + 池 40→16 KB 后 SRAM1 已宽松) | -| 可靠性与自恢复 | 🟢 良好 | 4 个 Fault 全采集现场;IWDG 五面 `required_mask`;复位原因与 `[STACK]` 水位常开 | 台架复跑持续 PASS(今日真机 708 ms 起网、无 `[ERR]`/Fault) | -| 测试与验证 | 🟡 半办 | 16 套主机单测 + `ui-golden`/`font-charset` 入门禁;TC 双向追溯 593∶271 交集 265; **§5.5 两条补强已全部落地**(2026-10-23:覆盖率口径 `../测试说明/主机单测覆盖率口径.md` + `malloc(` 正则 `coding-standard` CODE-RULE-20) | 覆盖率**未挂 pre-commit**(口径文档 §8 三条理由);**分支覆盖已裁定不做** (§2.1 决策记录)→ 现在真正的半办是**覆盖面**:首登照出 **125 个生产源文件从未进过任何主机单测** | -| UI 标准化 | 🟢 基本落地 | `ui_tokens.h`(L0 令牌)+ `ui_page_registry.c`(描述符注册表)+ 7 个内容页 + 两枚 UI 钩子 | **U1/U3/U4 从"未做"变为已落地**;U2 只有 `ui_w_records` 一个组件 | - -### 0.3 主线建议(2026-10-22) - -1. **最大功能缺口仍是 RS-485 采集未接线**(B2 按用户决策冻结);接线前必须先过 E-59 门禁—— - `rs485.c` 仍有 3 处 `HAL_Delay`(E-49 超时拉 DE、E-50 单缓冲撕裂未修)。 -2. **CCM 是当下唯一预算红线**(余 7,904 B)。加任务 / 抬栈 / 加堆都会先在这里撞墙;`mem-budget` - 92% 钩子会先报警。SRAM1 与 Flash 都已不是卡点。 -3. **结构性内存优化整簇暂缓**(R-2 后半 / R-3 / R-4 / R-6,用户裁定 2026-10-15),治理面常开; - 重开条件见 §5.3。今天又收口一项:**F-4 判定不做、F-6 已落地、F-5 降级观察**(§5.4)。 -4. **补面两条已全部落地(2026-10-23)**:覆盖率口径(`../测试说明/主机单测覆盖率口径.md`)+ - 堆禁令机器拦截(`coding-standard` **CODE-RULE-20**,§5.5 第 5 条)。**剩下的量在覆盖面**:覆盖率首登 - 照出 **47 个 `.c`(9,657 有效代码行)+ 78 个 `.h` 从未进过任何主机单测编译单元**(`net_socket.c` 1,251 行最大)。 - 建桩比把在测的 19 个文件从 88% 推到 95% 值钱得多,但**不是 125 个都该做**:优先级与"刻意不做"的清单已按逐文件 - 画像写好 → `../测试说明/主机单测覆盖率口径.md` §9(P1 13 个 / 2,617 行、P2 5 个 / 2,226 行、P3 29 个 / 4,814 行不做)。 -5. **仓库体积重心在外部资料**(`docs/芯片手册` 717 文件 / 39.5 MB,占 docs 的 87%;`.git` 248 MB), - 见 §3.3 D-1 与登记簿 N-29——已决策暂不处理,但**推送/对外协作前必须重评**。 - -## 0.4 未闭环清单(2026-10-22 复评) - -> 只列**仍未闭环**项,已修项按「修复即销项」删除(去处见文末)。逐项细节以 -> [`../任务规划/登记簿.md`](../任务规划/登记簿.md) 为准,本表是评审快照(图例:❌ 未办 / 🟡 半办 / -> ⏸ 暂缓 / 🟡 观察)。 - -| 类别 | 编号(登记簿) | 今天的现状 | 下一步 | -|---|---|---|---| -| 功能缺口 | RS-485 采集(B2) | `rs485.c` 3 处 `HAL_Delay` 未修 → E-59 挡住 `rs485_task` | 待用户排期;先修 E-49/E-50 再谈接线 | -| 硬件改版 | **N-18** | V0.1 把 8 路电气量分给两片转换器(无共同采样触发,跨转换器相位/功率不可用) | V0.2 全接 TPAFE;V0.1 上禁做矢量运算 | -| 内存 RAM | R-2 剩余 / R-3 / R-4 / R-6 ⏸(N-27) | 待迁体量 29,570 B,而 CCM 只剩 7,904 B → 搬迁已无空间收益 | 暂缓;重开条件 §5.3 | -| 内存 RAM | N-14 🟡(N-22) | FTL 单页写回缓存无空闲/掉电强制 flush(整页写与换页已 flush,`f_close` 经 `CTRL_SYNC` 已落盘) | 用户裁定 2026-10-22 暂不做;残余窗口只是"单条记录" | -| Flash | **F-5 🟡 观察项**(N-28) | uvprojx 201 个 LVGL `.c` 里 **127 个空 TU**;增量构建 4~5 s、CI 不跑 `@build` | 有实测全量耗时痛点再做,用 `` | -| 结构 | **S-1 已止住恶化**(2026-10-22 上门禁) | 不是"命名错位",是真实的 **BSP→App 反向 include**,精确口径 **8 个文件 9 处**(上一版写"7 文件 15 处"也不准,已按 `check_layer_deps.py` 判定重算):`cfg_file.h`×2(NETCFG)、`vol_lock.h`×1(lftpd_io)、`sys_log.h`×3(UI 两处 + `ui_w_records.h`);`console_log.h` / `sys_clock.h` / `sha256.h` 三个横切叶子头已**显式豁免**。**运行时的属主纪律本来就没破**(UI 只投递 `net_cfg_save_request()`,写盘在 defaultTask),要修的只是静态方向 | **门禁已落地**(`layer-deps` + `scripts/check_layer_deps.py`:存量 6 条基线只减不增、新增当场 FAIL,落地时做过故意违规自证)。剩下的才是反转:把 `cfg_file_*` 直接调用换成注入的 ops(NETCFG 已有 `net_cfg_set_save_req_cb` 先例);**目录搬迁仍暂缓**(远程 CI 不跑 `@build`,兜底未成立) | -| ~~结构 S-2~~ ✅ **已闭环销项 2026-10-22** | 该修的 24 处手写跨模块裸 `extern` **全部消完**:2 处与 `Inc/spi.h`/`Inc/i2c.h` 重复 → 改 include;19 处任务句柄与属性 → `App/task/task_handles.h`;1 处 `main.c` 函数内 `g_rcc_csr_latched` → `App/app/app_main.h`; -`ch395f.c:177` 的 `g_spi1_dma_done` → 标志收回 GD5F 内部 `static`,改由 `gd5f_spi1_notify_done()` / `notify_error()` 契约转调;最后一处 `net_socket.c:77` 的 -`netMsgQueueHandle` → 句柄改为 net_socket 私有 `static s_net_msg_queue`,由 `Src/freertos.c` 的 `USER CODE BEGIN RTOS_QUEUES` 区在队列创建后立刻 -`net_msg_queue_adopt()` 绑定(创建点不能外移——`osKernelInitialize()` 之前的创建类 API 会杀死启动;**故意不新建第二个队列**:那会白占 CCM 里 8×`net_msg_t` -的堆空间,而 CCM 正是当前红线)。**两类从来不算债**:`stm32f4xx_it.c:241-256` 是 CubeMX「External variables」生成块;`:183/195/207/220` 是 `__asm` Handler -里的汇编标签引用(ARMCC `__asm` 取不到 C 数据符号)。 | 无(后续由 `layer-deps` 与 `cubemx-survival` 两条门禁守着不回退:新增 `net-msgq-adopt` 存活项) | -| 驱动规范 | **S-5 🟡 主体已落地**(2026-10-23:契约 + 门禁 + RS485/SD2506/TPAFE 收编 + GD5F 改名 + dhara 三类码) | 我原先写的"无统一错误码"**不准**,实测是 **六套并存**:0/−1(SD2506、NETCFG、nand_ftl)、自研枚举 `CH395F_STATUS_*`、**芯片寄存器原生码** `CH395F_ERR_*`(与前一套同模块并存)、`HAL_StatusTypeDef`(`rs485.h` 曾直接暴露)、`bool`,外加第三方 dhara 出参 `dhara_error_t` 与 FatFs `FRESULT`。超时侧是**同形两义**:`SD2506_I2C_TIMEOUT_MS` 带单位后缀而 `GD5F_SPI_TIMEOUT 100` 不带(**逐行核过:它也是毫秒**,我先前记成"自旋圈数"是错的)、`GD5F/TPAFE5160_BUSY_TIMEOUT = -2` 其实是**返回码**;`osWaitForever` 与 `HAL_MAX_DELAY` **同为 0xFFFFFFFFU**(值同域不同,跨层转手不报错也不变慢)。真正值钱的不是码名,是"**能不能重试**"以前只写在个别注释里 | `Drivers/BSP/bsp_err.h`(header-only,含 `BSP_ERR_CAN_RETRY`)+ `bsp-err` 钩子(**四条检查**:`err-type` / `timeout-name` / `return-doc` / `consume-result`;基线 19 → 1 → **38**,其中 `consume-result` 上线又暴露 37 条存量丢弃);已收编 **RS485(HAL 枚举不再外泄)/ SD2506(11 个公共 API,I2C 超时终于归成可重试)/ TPAFE5160(含 E-44 的 FRSTDATA → `BSP_ERR_NO_DEVICE`)**,GD5F 的 `GD5F_BUSY_TIMEOUT` 改名 `GD5F_WAIT_EXPIRED` 消掉同形两义,FTL 坍缩点按 **ECC / 预算耗尽 / 完整性** 三类就地分类并打可读日志(§10.4)。`net_*` BSD 层与 `tpafe5160_snapshot()` 三态按裁定**不纳入**。**已修第一处静默降级**(2026-10-23):`gd5f2gq5ue_bbt_rebuild()` 的 ECC 关闭/恢复不再裸丢弃,并补 E-10 同款**回读 -B0h 验 `ECC_EN`**——原先那两行的注释自己写着"否则后续 I/O 在无 ECC 下运行",风险却正落在它下面那行。 -**待还**:GD5F 私有码集整体收编(169 处、含板级套件 48 处,需真机 + 套件回归)、C4 失败类快照(让卷 -健康探针按类分支)、`bool ui_content_page_open()` 一条(需改签名 + 处理 3 个调用点,与还注释不是一档事)、 -**37 条丢弃点的收编**(已入基线只减不增)、**"host 侧失败也标坏块"的策略修正**(`dhara_nand_erase`/`dhara_nand_prog` -把 host 侧 SPI 失败与 DMA 等待超时也标成坏块,而 dhara 只在 `DHARA_E_BAD_BLOCK` 才 retire;改它得先定 -"host 侧失败给哪个码",见变更记录) | -| 网络 | N-09 / PHY ❌(N-25) | `NET_MAX_SOCKETS` 仍为 8(与单连接复用语义不符);PHY 强制 100M 无自协商回退;PASV 每次新建监听 | 见 §4.2;随 N-25 一并处置 | -| 存储 | N-15 🟡 **观察项**(N-25) | `nand_ftl.o` 静态 6,216 B = 三块 2 KB 页缓冲 6,144 B + dhara 状态 72 B;**已论证三块不可合并**——GC 撞上脏页回写时三块同时持有活数据,合并后的失败形态是静默错数据 | **判定不做**(2026-10-23):可削减的只有 `s_copy_buf`(−1,536 / −2,048 B),而收益落点 `RW_IRAM1` 余 55,808 B、红线在 CCM → 论证见 `../内存管理/存储栈RAM优化调研.md` §5 | -| 存储/日志 | P2-10 ❌(N-25) | 卷锁现有 5 个使用者(配置原子写 / 日志 / SOE / lftpd_io / defaultTask),容量轮转删除与 UI 读并发仍未全覆盖 | 登记簿 S-5 面(卷锁覆盖面) | -| 仓库 | D-1 ❌(N-29) | jpg 707 个 / 37.3 MB;`docs` 45.3 MB 里芯片手册占 39.5 MB;`.git` **248 MB** | 降采样 / 拆 submodule / LFS 三选一 + 历史重写;已决策暂不做 | -| UI | U2 残余(U 簇) | 组件库只有 `ui_w_records.c/h` 一个;其余仍是页内自绘 | 按产品需求决定要不要继续抽组件 | -| ~~测试~~ ✅ **两条全部闭环 2026-10-23**(覆盖率口径 + 堆禁令 CODE-RULE-20) | 覆盖率:`scripts/check_test_coverage.py` + 基线 `scripts/test_coverage_baseline.json`(口径与**盲区**见 `../测试说明/主机单测覆盖率口径.md`)——首登 16 套并集 2552/2893 行(88.2%)、**未触及 125 个文件 = 47 个 `.c`(9,657 行)+ 78 个 `.h`(2,182 行,多为声明/宏)**, -| 待办池是那 47 个 `.c`;分批与「刻意不做」见 `../测试说明/主机单测覆盖率口径.md` §9。堆禁令:`check_coding_standard.py` **CODE-RULE-20**(硬拦截、零基线;唯一豁免 = `simulator/sim/cfg_file_store_sim.c` -| 的平台分配后端宿主侧实现,见 `../门禁说明/coding-standard.md` §7) | 无(残余三项**已归口或已裁定**:覆盖率挂 -| pre-commit 的前置写在口径文档 §8;分支覆盖**不做**(§2.1 决策);扩大覆盖面按 §0.3 第 4 条) | -| CI | T-7 ❌ | 远程 CI 只跑本机一台 runner,且不跑 `@build` | 保持现状即可;扩机器前重读 `docs/CI/README.md` | - -## 1. 审查方法与证据基线 - -### 1.1 数据源(本版全部结论的出处) - -- 体量:`MDK-ARM/STM32F407-Demo/STM32F407-Demo.map`(2026-10-22 `@build`)→ `data/ram_report_20261022.md` -- 栈:`STM32F407-Demo.htm`(静态调用图)+ 同日真机 `[STACK]` 心跳 → `data/stack_report_20261022.md` -- 仓库:`git ls-files` 逐个 `stat`(必须 `-z`,否则中文名被控制台代码页破坏) -- 门禁:`.pre-commit-config.yaml`(39 个 `- id:`)+ 各钩子今日实跑输出 -- 待办:`docs/任务规划/登记簿.md`(在策 18 条)与 `docs/任务规划/README.md` §2 - -### 1.2 复现命令(本报告所有数字可重跑) - -```powershell -# 1) 三区水位 + Top-10 RW+ZI -& '.venv\Scripts\python.exe' scripts/ram_report.py MDK-ARM/STM32F407-Demo/STM32F407-Demo.map -o docs/内存管理/data/ram_report_<日期>.md -# 2) 每任务栈:静态最坏链 × 真机 [STACK] 水位 -& '.venv\Scripts\python.exe' scripts/stack_report.py -i MDK-ARM/STM32F407-Demo/STM32F407-Demo.htm -s .dsh/skills/serial-assistant/scripts/state/serial.log -o docs/内存管理/data/stack_report_<日期>.md -# 3) MicroLIB C 堆(应为 0x200 = 512 B) -& 'tools\grep_binaries\find.exe' -E 'Heap_Size +EQU' startup_stm32f407xx.s # 或直接 git grep Heap_Size -- Src -# 4) 仓库体量:逐文件字节(-z 防中文名破坏) -git ls-files -z | xargs -0 stat -c '%s' -# 5) 门禁全量自查(不含 @build) -& '.venv\Scripts\python.exe' scripts/ci_local.py -``` - -### 1.3 口径定义 - -| 名词 | 口径 | -|---|---| -| Flash 占用 | `Code + RO-data` = `ER_IROM1` = **232,536 B(22.2%)**;`ROM 合计` 再加 `RW` 初始化表 = 233,724 B(22.3%) | -| SRAM 占用 | `RW_IRAM1`(DMA 可达区)与 `RW_CCM`(仅 CPU)分开计,二者不可互换(规则 R2/R3) | -| 最坏栈 | `max(armlink 静态调用图深度, 真机 [STACK] 高水位)`;判定线 `余量 ≥ max(1024 B ISR, 配置×30%)` | -| 编译单元 | uvprojx 的 `` 计数(今日 **326 个 `.c`**,其中 LVGL 201);"自研 `.c`" 另按目录口径 114 个 | -| 工程文档 | `docs/` 的 `.md` 105 份,其中 `docs/芯片手册` 14 份为外部资料 → 工程侧 **91 份** | - -## 2. 项目结构合理性 - -### 2.1 规模与分布(2026-10-22 实测) - -| 顶层 | 入库文件 | 字节 | 说明 | -|---|---|---|---| -| `docs/` | 881 | 45.3 MB | **全仓最大目录**,其中 `芯片手册` 717 文件 / 39.5 MB(外部资料,见 D-1) | -| `Lib/` | 1,036 | 21.3 MB | lvgl + FatFs + dhara(只读,本地补丁须文档登记) | -| `Drivers/` | 192 | 8.9 MB | 手写 BSP(含 `UI` 42 文件、`NET`、`CH395F`、`GD5F2GQ5UE`) | -| `App/` | 74 | 629 KB | 应用层 L1~L3 + 任务编排 + 配置/日志/卷锁 | -| 全仓 | **2,498** | **80.0 MB** | `.git` 248 MB(D-1/N-29 的关注点在这里) | - -### 2.2 分层与依赖方向 - -单向依赖(业务 → UI/基础服务 → 中间件 → BSP → HAL/RTOS)在今天的抽查里**未被破坏**:算法落 -`App/algo/`(L1 `adc_input`/`adc_health`、L2 `sample_ring`/`phasor`、L2.5 `freq`、L3 `prot_set`/`prot_elm`), -任务侧只做消费与编排。三处"属主唯一"约束仍是硬规矩:日志唯一写者 = defaultTask、配置引擎属主 = -defaultTask、`net_*` 只在 netTask 串行执行。 - -### 2.3 双构建清单对齐 - -`registration-check`(反向校验 + UI 页面描述符接线)今日实跑 PASS:uvprojx 与 `simulator/CMakeLists.txt -` 无单侧缺项。**新增信息**:uvprojx 里 201 个 LVGL `.c` 有 **127 个在 `.map` 中零产出**(空 TU), -它不影响镜像只影响全量重编 → 判为观察项(§5.4 F-5),不是缺陷。 - -### 2.4 根目录卫生 - -根目录 37 项。本机产物均**未入库**且已被忽略:`sim_config.ini`、`sim_run.log`、`sim_selftest.log`、 -`ci-artifacts/`、`.workbuddy-ai/`、`tmp_save.bin`(由 `*.bin` 规则命中,属**顺带**忽略而非显式声明—— -改名即失守,建议显式登记)。入库的两个 `ui_cn_chars.txt` / `ui_menu_tree.txt` 是字模提取与菜单树清单, -与生成器一一对应,可接受。**没有发现散落的临时脚本或裸备份文件。** - -### 2.5 结构结论 - -结构本身不是当前风险源;风险集中在 §0.4 的语义层错位(S-1/S-2/S-4/S-5)与体积面(D-1)。 - -## 3. 文档分布合理性 - -### 3.1 体量画像(2026-10-22) - -- `docs/` = 881 文件 / 45.3 MB;其中 `docs/芯片手册` **717 文件 / 39.5 MB(87%)**,`.jpg` 全库 707 张 / 37.3 MB -- 工程 md **91** 份(外部资料 md 14 份,最大单份 `STM32F4xx参考手册_V18英文版_1-1000.md` = 40,239 行) -- `docs/images` 23 文件 / 2.0 MB——**全部由 `tools/arch_diagram/gen_*.py` 生成**,脚本与产物一并入库 - -### 3.2 已制度化、应保留的做法 - -- 数字同源:内存快照由 `check_mem_numbers.py --write` 写受管区,人只写判读文字 -- 章节同源:任务表由 `gen_task_table.py` 生成;配图由生成器出;引用图由 `tools/refgraph` 出 -- 引用可校验:`doc-links --sections-strict`(今日全库 146 文档 0 问题,章节引用 2,513 处、可判定 59%) -- 编号可校验:`id-check` 增量拦截(存量 650 指纹豁免,可判定 **82.98%** ≥ 基线 82.6%) - -### 3.3 问题清单 - -#### D-1(P1)外部资料与工程文档同仓同树(登记簿 N-29) - -今天实测:`docs/芯片手册` 717 文件 / **39.5 MB**(占 docs 87%),全仓 80 MB 的一半;`.git` **248 MB**。 -影响:clone / 备份 / worktree 开空间 / 对外交付的体积都被外部资料决定,且历史里删不掉。 -三个选项:① 图片降采样(一次性、可保留可读性)② 拆 submodule(干净但要改所有引用路径) -③ Git LFS(要服务端配合)。任一条都要配一次 `git filter-repo` 历史重写才真正减小 `.git`。 -**当前状态:已决策暂不处理**(本机单 runner、内网协作,痛点未爆发);**触发重评的条件** = 对外交付 / -新机器 clone 明显变慢 / 需要双 remote。 - -### 3.4 文档结论 - -文档制度是本项目最强的一面,但**同一事实的多份副本仍会漂**——本版重写正是这件事的第三次实证 -(旧 §0.4 未闭环清单与登记簿漂开)。因此本版把"待办清单"降级为快照 + 指向,**权威只留登记簿**。 -同类教训同日还有两例:`项目部署环境要求.md` 的任务栈副本表(已删表改指针)、 -`RAM使用分析与优化方案.md` 的阶段子项与顶层章节同号撞面(已改层级编号 `4.阶段.项`)。 - -## 4. 功能模块设计评审(现状复核) - -> 写法变更:本节不再重述设计(设计有专属文档),只记"今天复核到的状态 + 仍在册的问题 + 证据"。 - -### 4.1 启动与任务框架 - -9 任务、就绪屏障四位(`osFlagsNoClear`)、内核前模式均已固化在 `docs/架构设计/项目启动顺序管理.md`; -`Src/freertos.c` 584 行(含 USER CODE 区手写 ISR 节拍)。原"仓库里没有 IWDG 驱动"等立项取证已随实施 -失效,取证归 `docs/子系统设计/看门狗设计说明.md`。 - -### 4.2 网络子系统(CH395F + BSD 抽象层) - -`net_socket.c` 3,120 行 + 拆出的 `net_pending.c`(挂起 recv,真机专属);错误码经任务通知值回传; -单连接复用 + `auto_relisten` 语义已文档化。**仍在册**(N-25):`NET_MAX_SOCKETS = 8` 与单连接语义不符、 -PHY 强制 100M 无自协商回退、PASV 每次新建监听。 - -### 4.3 存储子系统(GD5F + dhara + FatFs) - -链路:GD5F SPI NAND → dhara FTL → FatFs → `/log`、`/config.ini`、FTP 根。**今天澄清的一处旧口径**: -`f_close → f_sync → sync_fs → disk_ioctl(CTRL_SYNC) → ftl_flush_cache()` 已把写回缓存落盘, -所以"必须写另一个文件才能逼出脏页"不成立(旧报告与源码注释都这么写,已改)。2026-10-02 那次 -"复位后整段丢失"的根因是 dhara resume 锚错 checkpoint,不是缓存未刷 → `../架构设计/STM32F4-Base存储架构说明.md` §5.4.1。 -残余风险 = 单次写事务中途掉电(登记簿 N-22,用户裁定暂不做)。 - -### 4.4 配置引擎(`App/cfg/cfg_file.c`,1,358 行) - -defaultTask 单属主;原子写经卷锁;旧档迁移已删除。**仍列为后续项**:9,217 B 暂态峰值(整文件驻留), -流式读写的方案与验收在 `docs/子系统设计/配置文件设计说明.md` §6.2/§8。 - -### 4.5 日志子系统(`App/log/sys_log_mcu.c`,751 行) - -64 B 定长记录、双文件轮转、`[ERR]` 与 Fault 现场同通道。成本模型未变:**每条 `DBG_*` 约 90 B Flash + -216 B 栈**(调用点内联行缓冲),所以"补日志"要按调用点计费(§5.2)。 - -### 4.6 UI 子系统 - -今天的真实形态:`ui_tokens.h`(69 行,L0 令牌层)+ `ui_page_registry.c`(描述符注册表,取代手写 `case`) -+ 7 个内容页(`ui_page_ac/dc/device_info/runlog/selftest/net_cfg/password`)+ 组件仅 `ui_w_records`。 -回归面已进门禁:`ui-golden`(`scripts/check_ui_golden.py`,菜单 8 状态 + 内容页黄金参考)与 -`font-charset`(字符集差集)。**新增一页的实际成本**:轻页 40~71 行(ac/dc/device_info/runlog/selftest), -重页 275~370 行(password/net_cfg 含表单交互)——旧报告"新增一页 ≤30 行"的验收目标**未达**,但接线 -处数已从三处降到"页面文件 + 注册表一行"。 - -### 4.7 外设驱动 - -`ch395f.c` 1,777 行(SPI 分频必须 8,PCB 约束);TPAFE 走临界区原子快照(旧 `get_buf/data_ready` 已删); -片内 ADC1 上电自校准手写;`rs485.c` 仍有 3 处 `HAL_Delay`(E-49/E-50)→ E-59 门禁仍在挡消费者接线。 - -### 4.8 测试体系 - -- 主机侧 **16 套**单测(提交门禁实跑);板级 `test/board/` 19 文件、套件开关互斥受 `test-suite-switch` 管 -- TC 双向追溯:代码侧 593 号 / 文档侧 271 号 / 交集 265,差异 13 处(当前仅告警,未升门禁) -- **两处空白已全部闭合(2026-10-23)**:① 覆盖率口径 → `scripts/check_test_coverage.py`(mscoverage 动态 - 插桩 + Cobertura 并集)+ 基线 `scripts/test_coverage_baseline.json`;口径 / 工具链实测 / **九条盲区**见 - `../测试说明/主机单测覆盖率口径.md`(首登 2552/2893 行、19 文件在测、**未触及 125 文件**)。 - ② C 库堆禁令 → `check_coding_standard.py` **CODE-RULE-20**(拦 `malloc/calloc/realloc/strdup/strndup/ - free/aligned_alloc(`;硬拦截、零基线;唯一豁免 = 平台分配后端的宿主侧实现 - `simulator/sim/cfg_file_store_sim.c`,见 `../门禁说明/coding-standard.md` §7)。禁令本身的事实源仍是 - AGENTS.md 平台约束与 `../内存管理/RAM使用分析与优化方案.md` §4.2.1——**为什么非得机器拦**:MicroLIB - 的 C 堆只有 512 B,而**模拟器(宿主 CRT 堆)完全正常、照不出来**——配置引擎 2026-09-18 的堆分配纠偏 - (4 处 KB 级 `malloc` 落错堆)与 lftpd 的 `malloc` 隐患都是**先上线才发现**的那类 -- 破坏性套件(`ENABLE_DESTRUCTIVE_TESTS`)有**持久代价**(NAND 坏块记账不可逆),默认关闭是正确设计 - -## 5. 内存与 Flash(2026-10-22 实测收口) - -### 5.1 实测基线 - -| 指标 | 2026-10-23 | 2026-10-15 | 说明 | -|---|---|---|---| -| `Code` | 213,676 B | 213,520 B | 10-23 S-5 全波 +212:契约试点 +48、C3 SD2506 迁移 +44、C1 GD5F/TPAFE 收编 +36、C2 dhara 失败类 +84(RO 另 +208 = 失败类名表);ECC 回读校验(恢复构建路径)+28(见变更记录:该函数在产品镜像里被链接器 Removing,28 B 非它带来);10-22 当日累计:F-6 −332、SPI 回调 +16、消息队列 +32、FTP 日志级别 +28(RO 另 +72)、LIST 满块续发 +172 | -| `ER_IROM1`(Code+RO) | **232,508 B / 22.2%** | 232,280 B / 22.2% | 余 ≈803 KB;**RAM 三项 10-23 零增量** | -| `RW_IRAM1` | **75,264 B / 57.4%**(余 55,808) | 73,568 B / 56.1% | 增量来自 B5/B8 功能码 | -| `RW_CCM` | **57,376 B / 87.9%**(余 7,904) | 57,376 B / 87.9% | **当前唯一红线** | -| FreeRTOS 堆 | 56 KB(57,344 B)@CCM;实测 `free=15,800` / `min_ever=8,464` | 同 | 2026-10-22 真机 | -| 任务栈 | **9/9 PASS**(最深 defaultTask 静态 3,024/5,120,余 40%) | 8/8 PASS | `data/stack_report_20261022.md` | -| LVGL 池 | 16 KB;实测峰值 6,568 B(40%)、菜单基线 4,784 B | 同 | 2026-10-15 由 40 KB 收缩 | - -### 5.2 结构性诊断(三条,仍然成立) - -1. **静态大头是"缓冲常驻"**:`lv_mem_core_builtin.o` 16,384 + `lftpd.o` 7,724 + `ui_net_sink.o` 6,746 + - `ui_port.o` 6,408 + `nand_ftl.o` 6,200 = 43,462 B,占 `RW_IRAM1` 的 58%(今日 Top-5 实测)。 -2. **动态面只有一个**:所有任务栈 + TCB + 队列都在 `heap_4` 里,堆在 CCM → **栈的余量问题就是 CCM 的 - 余量问题**,这就是红线迁到 CCM 的机制原因。 -3. **栈深的主因是日志与配置写链**,不是算法本体:`s_append` 每调用点 216 B 栈 + 配置原子写链 - (`cfg_store_write_atomic → f_rename`)把 defaultTask 推到 3,024 B。 - -### 5.3 RAM 优化路线(收益 / 风险 / 优先级) - -| 项 | 原收益 | 今天判定 | -|---|---|---| -| **R-9** LVGL 池 40→16 KB | 24,576 B | ✅ 已落地 2026-10-15(SRAM1 74.9%→56.1%),不回退 | -| R-2 后半 待迁缓冲进 CCM | ≈29.6 KB | ⏸ **暂缓**——CCM 只剩 7,904 B,搬不动也无收益 | -| R-3 页缓冲合并 / R-4 UI 帧副本 / R-6 栈静态化 | 中 | ⏸ 暂缓(N-27) | -| R-5 提高 `LV_MEM_SIZE` 上限换性能 | — | ❌ 已判定不可行(单色 160×160 用不到) | - -> **重开条件(满足任一条才谈搬迁/缩堆)**:① 出现"必须新增 >8 KB RAM"的功能且产品要它;② `min_ever` -> 跌破 4 KB(碎片或峰值失控,此时应先削峰值而非搬家);③ CCM 撞墙导致新任务建不起来。 -> 搬迁要动 scatter、逐条过 DMA 可达性清单(违例是**静默传错**不是报错),缩堆还得上板复测——收益不抵风险。 - -### 5.4 Flash 优化(2026-10-22 收口:F-6 已落地、F-4 判定不做、F-5 降级观察项) - -> 动手前逐条对 `.map` 与源码复核,结论:**旧报告三项里两项建议不成立、一处归因错误**(字节数全对)。 - -| 项 | 原估收益 | 实测复核 | 状态与结论 | -|---|---|---|---| -| **F-4** 关未用绘制子模块 | ≈10 KB | 五项字节数逐字节仍准(10,060 B),但**无一项有开关**:`lv_draw_sw.c` 的 `execute_drawing()` 无条件 switch 引用全部 task 类型;唯一总开关 `LV_DRAW_SW_COMPLEX` 被主界面"浅 V"3 px 粗斜腿依赖(2026-09-03 已实测失败并两端固化 =1)。原"mask/grad 是文字必经路径"证伪:字形走 blend 层 `mask_buf` | ❌ **判定不做**(要打补丁才谈得上,上限 ≈16 KB 换 1.6% Flash,不值) | -| **F-5** 清 uvprojx 空条目 | 编译时长 −40% | 201 个 LVGL `.c` / 127 个空 TU;增量构建 4~5 s,空 TU 只在全量重建或改 `lv_conf.h` 时重编,**远程 CI 刻意不跑 `@build`**;−40% 无基线记录 | 🟡 **降级观察项**;真要做用 Keil 原生 `0`(可逆),且排在任何 `lv_conf.h` 改动之后 | -| **F-6** 双精度软浮点 | ≈1 KB | **归因错**:全库 0 处 `%f`;剩余 `dadd/dmul/ddiv/depilogue/dfixul` 1,018 B 锁在 MicroLIB `printfa.o` 的 `_printf_core → _fp_digits`,只要用 `snprintf` 就删不掉。但**根因侧确有可修点**:`App/algo/prot_set.h` 两个 Q10 宏写成 `double` | ✅ **已落地 2026-10-22**:改单精度 → `@build` −332 B、5 个 helper(300 B)消失;数值逐位等价(穷举 42 个字面量 + int32 全域 ÷1024 往返 4.49×10⁶ 例零差异);真机 `@test` PASS | - -**当前可回收 Flash = 0 B**(F-4/F-6 已定论,图片链同理不打补丁)。LVGL 仍占镜像 **37.8%** -(87,706 / 232,536 B)——这是"用 LVGL 画单色菜单"的结构性代价,F-1/F-2/F-3 已省掉 64,576 B。 - -### 5.5 内存治理长效机制(常开,不受暂缓影响) - -1. 每次 `@build` 后 `scripts/ram_baseline.py --update`,再 `--write` 回填台账受管区;`--gate` 判 92% -2. `check_mem_numbers.py --scan/--write`:文档里的内存数字一律由 `.map` 反查,禁止手填 -3. 改栈 / 加大局部变量前后各跑一次 `stack_report.py`(静态 × 真机 `[STACK]`) -4. 子系统配额与 CCM 台账 → `../内存管理/RAM预算台账.md`;趋势 → `scripts/ram_baseline.tsv` -5. **两条补强已全部落地(2026-10-23)**:`malloc(` 正则 = `check_coding_standard.py` **CODE-RULE-20** - (硬拦截、零基线,判据与豁免见 `../门禁说明/coding-standard.md` §1/§7)。 - 另一条「覆盖率口径」✅ **已落地 2026-10-23** → `../测试说明/主机单测覆盖率口径.md`(口径 / 基线 / 盲区 - 一处写完,此处不复述)。⚠ 它落地的是**行与函数**覆盖,**分支覆盖本机拿不到**(无 gcc,MSVC 14.51 - 已无 `/coverage`)——「覆盖到哪些分支」这一半**已裁定不补**(不为它引入第二套工具链,见 - `../测试说明/主机单测覆盖率口径.md` §2.1),当前补偿 = TC 双向追溯 + 用例显式列边界值 - -## 6. UI 界面标准化:从方案到已落地 - -### 6.1 现状(U1~U5 复核) - -| 项 | 旧状态(2026-10-15) | 今天 | 证据 | -|---|---|---|---| -| U1 令牌层 | ❌ 未建 | ✅ 已落地 | `Drivers/BSP/UI/ui_tokens.h`(69 行,L0) | -| U2 组件库 | ❌ 未建 | 🟡 仅 1 个组件 | `ui_w_records.c/h`;其余仍是页内自绘 | -| U3 页注册表 | ❌ 手写 `case` | ✅ 已落地 | `ui_page_registry.c`(`content_page_def_t` 描述符)+ 7 页 | -| U4 回归门禁 | 🟡 未挂 pre-commit | ✅ 已挂 | `ui-golden`(菜单 8 状态 + 内容页)、`font-charset` | -| U5 页面扩展 | 27 页未落地 | 🟡 按需求推进 | 现 7 页(含网络配置与改密两重页) | - -### 6.2 新增一个页面要走多少步(今天实测) - -四步:① 新建 `ui_page_.c`(轻页 40~71 行)② 在 `ui_page_registry.c` 加一条描述符 ③ 菜单表挂节点 -④ 跑 `ui-golden` 更新黄金参考 + `@build`。旧流程里的"改 `ui_task.c` 手写 case"已不存在。 -**未达项**:验收目标"≤30 行/页"——最省的 `ui_page_dc.c` 也要 40 行。 - -### 6.3 已完成部分的记录去处 - -原"8 人日方案"正文(四层架构设问、逐日排期、27 页清单)已随落地删除;现行做法与约束只在两处详述: -`../UI设计/UI_设计架构.md`(分层、令牌、双端同步、陷阱表)与 `../UI设计/UI_自动化测试流程.md`(回归与 -黄金参考);历史决策与验收证据见本文**变更记录**(2026-10-15「UI 扩展」三行)与 `../UI设计/菜单页面设计.md`。 - -### 6.4 UI 侧的内存纪律(写进规范,勿再试探) - -1. 1bpp 单色:绘制缓冲 160×160/8 = 3,200 B/份,多缓冲每加一份都算进 `RW_IRAM1`(DMA 必须在 SRAM) -2. `LV_MEM_SIZE` 现为 16 KB;实测峰值 6,568 B(40%)→ **再降到 8 KB 前必须先看这个水位** -3. 字符集:新增中文必须过 `font-charset`,缺字 = 白框(静默视觉缺陷) -4. UI 侧缓冲**不得进 CCM**(DMA2 不可达);`ui_net_sink` 推流缓冲常驻 6.4 KB,产品构建可加开关 -5. 字体与像素改动 = 视觉回归范围,必须走 `ui-verify` skill 的五步 - -### 6.5 实施顺序(历史,已执行完) - -「UI 扩展」簇按 U4 → U1 → U3 → U2 的顺序执行完毕(U2 停在"够用即止"),顺序与理由见 §6.1 与变更记录 -2026-10-15 三行;不再另存排期。 - -## 7. 统一改进路线图(不另立权威) - -| 波次 | 本报告条目(今天状态) | 备注 | -|---|---|---| -| ~~预算与内存~~ ⏸ | R-9 ✅ / R-2 后半、R-3、R-4、R-6 暂缓 | 暂缓期间无验收动作,观测照常 | -| 结构债 | N-14 ⏸、F-5 🟡、S-1/S-2/S-4/S-5、N-25 | `--strict` 已默认;S-5 契约/门禁已落地并收编三模块,`consume-result` 已把"丢弃返回值"纳入机械检查(基线 19→1→38;剩 GD5F 码集收编、C4 快照、37 条丢弃点、标坏策略) | -| 验证常态 | ~~覆盖率~~ ✅、~~`malloc` 正则~~ ✅(均 2026-10-23)、TC 差异 13 处升门禁 | 剩 TC 一条 | -| UI 扩展 | U2 残余、U5 页量 | 随产品需求,不再单列专项 | -| 仓库决策 | D-1(N-29) | 已决策暂不处理;对外交付前重评 | - -## 附录 A 关键证据索引(2026-10-22) - -| 结论 | 证据位置 | -|---|---| -| 三区水位与 Top-10 静态大头 | `../内存管理/data/ram_report_20261022.md` §1/§2/§3 | -| 9 任务栈判定 | `../内存管理/data/stack_report_20261022.md` | -| F-4 关不掉 | `Lib/lvgl/src/draw/sw/lv_draw_sw.c`(`execute_drawing()`)+ 两份 `lv_conf.h` 的 `LV_DRAW_SW_COMPLEX` 注释 + `Drivers/BSP/UI/ui_deco.c` | -| F-6 已落地与等价性 | `App/algo/prot_set.h` Q10 宏注释;`MDK-ARM/STM32F407-Demo.map` 交叉引用区(`refers to mf_w.l(d*.o)`) | -| `snprintf` 必带 `_fp_digits` | 全库 `%f` 命中 0;`mc_w.l(printfa.o)` 交叉引用 | -| 任务栈配置唯一来源 | `Src/freertos.c` + `README.md`/`AGENTS.md` 的 `TASK_TABLE` 受管块 | -| UI 落地形态 | `Drivers/BSP/UI/ui_tokens.h`、`ui_page_registry.c`、`ui_w_records.c`、`scripts/check_ui_golden.py` | -| 外部资料体积 | `git ls-files docs/芯片手册`(717 文件)+ `du -sm .git`(248 MB) | - -## 附录 C 确认「无需改动」的设计(避免后续误改) - -1. **MicroLIB 的 `_fp_digits` 及其双精度 helper(1,018 B)**——不是"忘了清 `%f`",是 `snprintf` 的固有 - 依赖;删不掉,别再去搜 `%f`。 -2. **`LV_DRAW_SW_COMPLEX = 1`**——2026-09-03 与 2026-10-22 两次实测:关掉后"浅 V"两腿不渲染。 -3. **FTL 单页写回缓存**(N-14/N-22)——`f_close` 已经 `CTRL_SYNC` 落盘,为"单条记录"加空闲/掉电强制 - flush 属过度设计。 -4. **uvprojx 的 127 个空 LVGL TU**(F-5)——不影响镜像与增量时长,删条目反而破坏"改 `lv_conf.h` 全量 - 重编"的一致性。 -5. **CH395F SPI 分频 = 8**、**ADC1 走 DMA2 Stream4**、**TIM3 做 1 kHz 节拍源**——都是 PCB/硬件约束, - 不是可调优参数。 -6. **就绪屏障位用 `osFlagsNoClear`**——曾被默认消费行为坑到 FTP 静默不监听。 -7. **`ui_page_registry` 描述符注册表**——已取代手写 `case`,不要再退回分发式写法。 - -## 9. 编号族登记处(**冻结**,`check_ids.py` 的属主登记处) - -> 本文是下列 6 个族的属主登记处(`scripts/id_registry.json`,`check_dangling=true`),其它文档以 -> 「报告 N-14」「报告 F-4/F-5/F-6」「报告 D-1」「报告 R-2/R-3」式写法引用它们。**删除本节会让 -> 编号门禁报"定义缺失"并拦住提交**。新增条目一律改用**语义短语**、不再发新号(`../任务规划/README.md` §0 -> 的用户裁定);本节只保留存量号的最终状态。 - -| 号 | 事项 | 状态 | 现在详述于 | -|---|---|---|---| -| N-01 | 配置引擎整文件驻留 | ✅ 已修(流式列为后续项) | `../子系统设计/配置文件设计说明.md` §6.2/§8 | -| N-02 / N-03 / N-03a / N-03b / N-03c | 存储与日志取证类条目 | ✅ 已闭环 | 存储架构说明 §10.1、本文变更记录 | -| N-06 | 注册白名单与 `--strict` | 🟡 残余随 B2 | 登记簿 N-23 残余 | -| N-07 / N-08 | 网络自愈与卷锁 | ✅ 已闭环 | `../网络/网络自愈架构设计.md` §4.10 | -| **N-09** | `NET_MAX_SOCKETS`/PHY/PASV 三项网络债 | ❌ 在策 | 本文 §4.2、登记簿 N-25 | -| N-10 ~ N-13 | 主机侧 nand/dhara 移植层单测动因 | ✅ 已建 | `test/host/nand_port/`(第 16 个单测钩子) | -| **N-14** | FTL 写回缓存无空闲/掉电强制 flush | ⏸ 暂缓 | 本文 §4.3、登记簿 N-22 | -| **N-15** | `nand_ftl` 三块 2 KB 页缓冲未合并 | 🟡 **观察项(2026-10-23 判定不做)** | `../内存管理/存储栈RAM优化调研.md` §5、登记簿 N-25 | -| N-16 / N-17 | 台架窗口项(task stall 归因等) | 🟡 待窗口 | 登记簿 N-16/N-17 | -| **N-18** | V0.1 双转换器无共同采样触发 | ❌ 待 V0.2 | 本文 §0.3、AGENTS 硬件引脚节 | -| N-19 ~ N-21 | 时钟/对时与已销项条目 | ✅ 已闭环 | 本文变更记录与去处表 | -| **D-1** | 外部资料与工程文档同仓同树 | ❌ 暂不处理 | 本文 §3.3、登记簿 N-29 | -| D-2 ~ D-7 | 文档治理条目(链接/同源/编号/BOM 等) | ✅ 多数已制度化为钩子 | 本文 §3.2、`../文档规范.md` | -| D-9 | 文档面残余观察 | 🟡 观察 | 本节即定义位 | -| **S-1** | 分层反向依赖(BSP include App 的头) | 🟡 已止住恶化(存量 6 条基线待还,新增被 `layer-deps` 拦) | 本文 §0.4、登记簿 C5 | -| **S-2** | 跨模块裸 `extern` | ✅ **已闭环 2026-10-22**(24 处手写全消;两类本就不算债见 §0.4) | 本文变更记录 2026-10-22 三行;契约见 `App/task/task_handles.h`、`gd5f_spi1_notify_*`、`net_msg_queue_adopt` | -| **S-4** | `app_cfg.h` 未接线占位开关 | ✅ **已闭环 2026-10-22**(4 个零消费点宏删除) | `App/app/app_cfg.h` 修改记录 v1.2;口径同步见 `../环境与部署/项目部署环境要求.md` §3.2/§3.5、`../产品需求/产品需求设计文档.md`、`../任务规划/排期详述.md` C5 | -| **S-3** | `.ioc` 侧 USART1 配置 | ❌ 在策 | 登记簿 S-3 | -| **S-5** | 统一 `bsp_err_t` 错误码与超时命名约定 + **返回值不得裸丢弃** | 🟡 主体已落地(2026-10-23:契约 + `bsp-err` 四规则 + RS485/SD2506/TPAFE 收编 + GD5F 改名 + dhara 三类码 + `consume-result` 照出 37 条丢弃 + ECC 回读校验;基线 19 → 1 → 38) | 本文 §0.4、`pre-commit使用说明.md` §2.27、`STM32F4-Base存储架构说明.md` §10.4、`Drivers/BSP/bsp_err.h` | -| R-1 ~ R-9 | 内存优化项(R-9 已落地、R-5 判定不可行、其余随簇暂缓) | 见 §5.3 | 本文 §5.3、`../内存管理/RAM预算台账.md` | -| F-1 / F-2 / F-3 | LVGL 死代码裁剪,省 64,576 B | ✅ 已落地 2026-10-11 | `../内存管理/RAM使用分析与优化方案.md` §2.6.4 | -| **F-4 / F-5 / F-6** | Flash 双精度与死代码簇 | ✅/🟡/❌ 见 §5.4 | 本文 §5.4、`App/algo/prot_set.h` 注释 | -| U1 ~ U5 | UI 标准化簇 | 见 §6.1 | 本文 §6.1、`../UI设计/UI_设计架构.md` | - - -## 变更记录 - -| 日期 | 类型 | 说明 | -|------|------|------| -| 2026-09-18 | 初版 | 全量审查;基线 `HEAD = 2d0ec35`、`.map` 链接于 2026-09-16;产出 N-01..N-18 / D-1..D-7 / S-1..S-5 / R-1..R-9 / F-1..F-6 / U1..U5 编号体系 | -| 2026-10-11 | 实施 + 销项:F-1/F-2/F-3 | 两份 `lv_conf.h` 对齐同一特性子集 → 省 64,576 B;验证链(`@build` / ui-verify / `@test`)与对象级对照见 `../内存管理/RAM使用分析与优化方案.md` §2.6.4 | -| **2026-10-15** | **登记簿同步销项** | 本报告的 N-03c / N-11 对应登记簿 **N-20 / N-26** 两行已按「完成即销项」从 `../任务规划/登记簿.md` §5 删除(并清 `../任务规划/README.md` §1/§2 与 `排期详述.md` §1 的引用,「结构债」链由 6 项减为 5 项、结构/健壮性计数 9→7)。删除前补齐去处记录:`../子系统设计/看门狗设计说明.md` §4.4 新增 `Error_Handler` 统一降级一节、`../内存管理/内存内容分配策略.md` §4 R2 补编译期窗口断言与启动期自检两层 + §8 落点索引两行。同批订正登记簿三处过时内容:N-23 残余去掉已删除的 `lftpd_log.c`、N-25 去掉已删除的 `NET_RECV_TIMEOUT_MS`、N-27 剔除不可行的 R-5 并把 CCM 余量改为实测 7,904 B、N-29 的 `.git` 由 149 MB 订正为实测 235.3 MB | -| **2026-10-15** | **执行本报告条目:R-9 落地并销项** | `LV_MEM_SIZE` 40→16 KB(`Lib/lv_conf.h` + `simulator/lv_conf.h` 同步,`lv-conf-sync` 生效值比对 PASS)。**依据**:池水位门禁实测菜单基线 5,368 B / 开页-关页往返 5,448 B / 最重页面峰值 6,568 B。**验证**:`@build` 0 错 0 警,ZI 精确 −24,576 B → SRAM1 98,144/74.9% → **73,568/56.1%(余 57,504 B)**,CCM 不变;PC 侧 11 页黄金参考逐字节 10/11 一致、往返池水位 5,448 B 未变(唯一差异 `netcfg_save` 经 40 KB A/B 复测确认与本次改动无关,真因见下一行)。**连带改写**:§0.2 Top3 第 2 条、§0.3 主线一、§0.4 内存两行、§5.1 基线表(追 2026-10-15 `.map`)、§5.2 诊断 1(瓶颈由 SRAM1 换到 CCM)、§5.3(R-9 行删除、R-2 收益改 −29,570 B)、§6.4 池容量行;同步 `../内存管理/RAM使用分析与优化方案.md`、`../内存管理/RAM预算台账.md` §3、`../UI设计/UI_设计架构.md`、`../UI设计/UI_界面制作流程.md`、`../UI设计/LVGL模拟器部署与使用说明.md`、`simulator/README.md`、`../产品需求/产品需求设计文档.md`。**真机复跑 ✅**:`@test` PASS(`fw build: Oct 15 2026 07:31:34`,无 `[ERR]`/Fault,开机 622 ms 到 `net init: OK`),`menu build done: used=3192` = 建池后 15,020 B 的 21%。台账受管区与内存快照区已 `--write` 回填 → `mem-budget` / `mem-numbers` 两钩子转绿 | -| **2026-10-15** | **修 `netcfg_save` 假失败:回归改为自洽运行** | 上一条那个"唯一差异"查到真因,**不是代码回归**:`--cfgtest` 的 E-01 场景 2 伪造一份 4000 B 纯注释配置档并断言"拒写后原文件不动",**连通过路径也不删除它**;留在工作目录后每次运行都被加载 → 外科手术保存要在 4000 B 注释后补写受管段 → 输出必超 `CFG_FILE_MAX_LEN` → 引擎**按设计拒写** → 保存行显示 `ERR`。修三处:`simulator/main.c` 给 `--cfgtest` 加外壳(无论成败一律删除伪造档)、`check_menu_rows.py` 与 `check_content_pages.py` 改在**空临时目录**里跑(`cwd=tmp`)、脚本里已作废的 `sim_netcfg.bin` 兼容清理改为只提示不删除。修后 **11/11 页 + 往返池水位 5,448 B 全过,未刷任何黄金参考**(参考本来就是对的)。排查口径 → `../UI设计/UI_自动化测试流程.md` §五 | -| **2026-10-15** | **补漏:§0.1 六维评分与口径/附录数字追平 R-9 后状态** | 前面那条只改了 §0.2/§0.3/§0.4/§5.x,**漏掉 §0.1、§1 术语表、附录 A 证据表**(用户指出):① 内存使用行仍写"54,146 B 仍在 SRAM1 / SRAM1 74.9% / 须先 R-9"→ 改为 SRAM1 **56.1%(余 57,504 B)**、瓶颈收敛到 CCM 单点、只差"缩堆"一步,评级 **B → B+**(理由:SRAM1 由卡点变富裕,治理三件套与观测齐备;扣分项换成 CCM 单点 + C 堆无机械检查)② Flash `231,036` → **`231,084`**(§0.1 / §1 术语表 / §6.4 三处),并修掉术语表里 `ROM = 231,324 B` 这个**算术错**(`Code + RO + RW` 实为 **232,196 B**)③ RAM 占用定义 `98,144 / 74.9%` → **`73,568 / 56.1%`** ④ 附录 A 证据行改 `RW_IRAM1 Size: 0x00011f60`、余量 57,504 B ⑤ 文档分布 **88 篇 / 31,416 行 → 87 篇 / 30,781 行**、§3.1 体量表受控文件 **2,466 / 79.3 MB → 2,465 / 79.2 MB**(均随 `错误码传播审计.md` 删除,−1 篇 / −635 行;同表 `docs/` **56.9 MB**、手册图片 **703 张 / 36.3 MB** 复核未变)⑥ §0.1/§0.2/§0.4 与附录的复核日期统一标 **2026-10-15**,最近复核行的 `HEAD` 改指 `a7f5265` 并注明"后续文档与模拟器侧提交不影响固件",避免每提交一次就过期 | -| **2026-10-15** | **裁定:内存优化簇整簇暂缓** | 用户判定"把 LVGL 池与 UI 帧缓冲(现 ≈29.6 KB)搬进 CCM 作为后续功能预算来源"这个决定不合适,内存优化的事先放一放。据此:§0.2 **Top 3 → Top 2**(R-2 剩余移出名列,表下加一条 ⏸ 说明);§0.3 主线一由"把内存从卡死变富裕"改写为"**这条线到此为止**";§0.4 两条内存条目 🟡/❌ → **⏸ 暂缓**;§5.1 结论段与 §5.2 诊断 1 补"不代表现在要动";**§5.3 加暂缓横幅**(三条理由 + 保留常开的治理面 + 三条重开条件),R-2 / R-3 / R-4 / R-6 优先级列一律 ~~P1/P2~~ → **⏸ 暂缓**。**已落地的 R-9 不回退**(−24,576 B 是净收益且已台架验收);`mem-budget` 92% 门禁、预算台账、趋势基线、栈/堆观测**全部保留常开**——它们是传感器,不是优化动作。同步 `../任务规划/登记簿.md` N-27、`../任务规划/README.md`「预算与内存」、`../内存管理/RAM预算台账.md` §3、`../内存管理/RAM使用分析与优化方案.md` 阶段 1.2 / 2 | -| **2026-10-15** | **执行本报告条目:N-12 / N-13 / N-16 落地并销项** | **N-12**:`dhara_nand_is_free()` 改整页扫描(栈上 64 B 分块、页首命中即早退,成本与旧实现同价)。**N-13:本报告原建议经核对不成立,已按实际契约改修**——本仓裁剪版 dhara 既没有 `DHARA_NO_PAGE`(哨兵实为 `DHARA_PAGE_NONE`,`journal.h:46`)也没有 `DHARA_E_UNSUPPORTED`(`error.h:20-31` 枚举里没有,照抄直接编译失败),且 `map.c` 三处 `dhara_journal_copy` 调用点各自已挡掉哨兵(`map.c:260`、`:434`+`:440`、`:242`);真风险是**移植层零上界校验**(越界页号被地址位截断成真实页 → 静默读写错页),故改为六个 HAL 入口统一几何上界守卫 + `DHARA_E_CORRUPT_MAP`(不能用 `BAD_BLOCK`:`journal.c:904` 会据此标坏块;不能用 `RECOVER`:`map.c:275` 会据此启动回收)。**N-16**:写侧一次排空合并成"每文件一次 open/write/close"(≤8 条 = 512 B 静态缓冲;**掉电语义不变**——批次仍在同一次 drain 内 close,close 回写目录项这个不同 LPN 会逼出 FTL 单页写回缓存;失败尾部回投队列,条目不丢);读侧 8 条滑动窗口 + 写者代数失效(API 与 UI 零改动)。**刻意不批量**:`sys_log_evidence()` 的 `wdev.log` 仍逐条落盘——取证路径要求立刻进 NAND 并靠 flush 诱导逼出脏页。**验证**:`@build` 0 错 0 警(Code 212,344→**213,536**、ZI 129,880→**131,520**,+1,640 B 全为静态缓冲,不吃栈);`@test` PASS 且**台架 journal 恢复点与修复前同轨**(`sectors used` 恒 14,094、`Map head` 每轮 +128 单调推进、`epoch` 稳定 3 → 整页 `is_free` 未改变恢复语义、无双编程);`stack_report.py` 9 个任务全 PASS(defaultTask 静态最坏链 3,024 B / 余 40%,实测峰值 2,164 B / 余 57%);新增主机侧移植层单测 `test/host/nand_port/`(假芯片 + 旧算法对照用例)。实施记录 → `../架构设计/STM32F4-Base存储架构说明.md` §5.3、`../子系统设计/运行与自检记录设计说明.md` §4.4/§4.5 | -| **2026-10-15** | **删除 §0.2「未闭环问题」小节** | Top 2 修复销项后该节只剩指针与暂缓说明,而三条内容都已在别处**单点详述**:未闭环清单 → §0.4;内存簇暂缓 → §0.3 主线一与 §5.3 横幅;Top 2 修复证据 → 上一条变更记录与文末「已销项条目的记录去处」。按 `../文档规范.md`「同一事实只在一处详述」删除,不留空壳。**§0.3 / §0.4 编号保持不变、不重排**——`../任务规划/README.md` §2 前言引用本报告 §0.3,本报告内部另有 §0.4 交叉引用,重排会全断(与本表 2026-10-14 行第 ⑤ 条"报告自有编号不回改、不重排"同一口径)。文首「销项状态」行的指针由「§0.2 / §0.4」改为「§0.4」 | -| **2026-10-15** | **删除 §0.3 主线建议第 1 条("内存这条线到此为止")** | 该条是同日暂缓裁定的**复述层**,同一事实已有三处单点详述:§0.4 内存两行(⏸ 暂缓)、§5.3 暂缓横幅(三条理由 + 保留常开的治理面 + 重开条件)、登记簿 N-27 与 `../内存管理/` 两份文档的横幅。按 `../文档规范.md`「同一事实只在一处详述」删复述、留权威。⚠ 上一条变更记录里"内存簇暂缓 → §0.3 主线一"这个去处**自此失效,以本行为准**(变更记录本身不改,它是历史)。§0.3 现只剩 UI 一条主线;标题「两条主线建议」→「主线建议」,**§0.3 编号不变**(`../任务规划/README.md` §2 前言引用的是编号不是标题) | -| **2026-10-15** | **启动「UI 扩展」标准化簇**(用户裁定,覆盖 2026-10-11 的「本轮不排期」) | §0.3 删掉内存主线后只剩 UI 这一条,随即启动。已按 §6.5 的 U1~U5 拆成 5 个工作包上共享任务板,第一波 **U1 令牌层 ∥ U4 门禁补强** 两名成员并行(写范围严格不相交:U1 只写 `Drivers/BSP/UI/` + `App/task/ui_task.c`,U4 只写 `scripts/` + 门禁与规范文档)。**并行度的真实约束不是任务数量,而是注册文件**:新增 `.c` 必须改 `uvprojx` + `CMakeLists.txt` 两个共享文件,同工作树两人同改必互相踩,故 U3(生成器/注册表)是必须串行的一段,U2/U5 排在它后面——U5 的页面批量要等 U3 把注册自动化之后才谈得上并行。同步 §6.5 注与本表「UI 扩展」行;`../任务规划/README.md` §2.0「UI 扩展」行同步。另修正交付物清单:移植层单测拟名 `test/host/dhara/` 实际落地为 `test/host/nand_port/`,状态 ❌ → ✅ | -| **2026-10-15** | **§6 顶部加"建议栏不可照抄"总警示** | 启动「UI 扩展」后按 §6 执行 U1/U3/U4,**四次证伪**:① §6.3 要新建 `UI_SCREEN_W/H` 而 `ui_port.h:21-22` 早有同名宏;② `LV_COLOR_BLACK/WHITE` 在 LVGL 9.3 不存在**且极性反了**(墨色实为 white),照抄先编译失败、改完整屏反色;③ "27 页未落地"是**目标页数**、现存 `ui_page_*.c` 实测 7 个;④ 生成器草图漏掉**密码页非节点绑定**。另有 L0 清单 9 条取值错,明细在 §6.3 更正块。**不再逐条打补丁**,改为节顶立总口径:动手前逐条 grep 对代码核、不符一律以代码为准、差集必须回报不得静默修正;并明确**"发现"栏可信、"建议"栏不可照抄**。同一规律在 §4 的 N-13(`DHARA_E_UNSUPPORTED` 不存在)已复现,故这不是 UI 章节局部问题,而是"建议"这一体裁的通病 → 后续任务卡须显式写"报告建议值不可直接采用" | -| **2026-10-15** | **「UI 扩展」第一波落地:U1 + U3 验证通过并回填现状表** | Lead 亲自验证(成员被模型路由变更连续打断,最终停用):`@build` **0 错 0 警**;golden **菜单 8 状态全像素 + 内容页 11 页逐字节一致**、池水位 **5368 / 5448 B 与 U1 基线相同**、参考图 sha256 **差异 0 条**(证明无人用 `--update` 刷基线);`registration-check`(含第 ④ 类"页面必须被表引用")与 `font-charset` **Passed**;`ER_IROM1` **232,052 B**(较已提交 HEAD −228 B)、`RW_IRAM1` **75,232 B 零增量**;对 38 个在途修改文件逐个核对 **BOM / CRLF / U+FFFD 全部与 HEAD 一致**。**单位成本实测**(临时页 `zzprobe` 绑到 `遥信量` 叶子 → 只跑生成器 → 带页 `@build` 0/0 → 注册表出现 `{5u, &ui_page_zzprobe_desc}` → 回滚后 6 个产出文件的 `zzprobe` 残留计数均为 0、重编回基线)得出 **新增一页 = 3 处人工(新 `.c` + 新 `.h` + 树那一行加 ` #page=<名>`)+ 1 条生成器命令,手工编辑注册文件 0 处**,并确认生成器 `registered` / `pruned` **双向对账**(不只增、也减)。据此修正 §0.1 UI 行(B → **B+**)、§6.1「内容页」与「设计令牌」两行、§6.5 U3 行;并把 §6.5 U4 从我上一版**误写的 3/3 改回 2/3**(golden 两脚本至今未挂 pre-commit,"脚本已存在"≠"已进自动门禁");§6.5 U3 原口径"8 处降到 1 处"改为**真实 3 处**。**"分三笔提交"计划作废**:U1 与 U3 改同一批文件、文件内交叠,硬切会产生不可编译的中间态,改为整波一笔 | -| **2026-10-20** | **补上 U4 缺的第三件:golden 像素回归入提交门禁(35→36 钩子)** | 先实测成本再定形态:改一个 UI 源文件后「增量重编模拟器 + 两条 golden」合计 **2~4 秒**,支持走自动门禁(若实测要几分钟,正确做法是明确不挂、改为文档化人工门禁——一个逼人 `--no-verify` 的门禁等于没有门禁)。新增 `scripts/check_ui_golden.py` 包装器(**有意忽略 argv 并 `pass_filenames: false`**:两条 golden 按整棵菜单树 + 全量参考图工作,不接受文件参数),新钩子 `ui-golden` 的 `files:` 覆盖 UI 源 + `ui_task.{c,h}` + 模拟器 tests/sim/src + `lv_conf.h` + 包装器与本配置文件自身。 -⚠ **端到端验的是钩子不是脚本**:干净树连跑 3 次 `rc=0` 全 Passed;注入 `ui_page_dc.c` 的 `.top_y +5` → **钩子 Failed** 并点名 `[dc] FAIL 与参考页不一致(1882 px 差异)`;还原后 `git diff` 干净、`simulator/tests/ref` 的 `git status` 为空(**全程未用 `--update` 刷基线**)。诚实记录一次瑕疵:首次实测在连续注入/还原的紧邻重建之间偶发失败一次,疑似 MSBuild 节点争用,已把"单次失败先复跑、连续两次才当真、不许直接绕过"写进钩子注释。 -据此 §6.5 U4 由 **2/3 → 3/3**(这次是"真进了自动门禁",不是"脚本存在")、§6.1 golden 行转 ✅、§0.1 UI 行缺口描述更新、`AGENTS.md` 钩子数与文末索引 35→36、`pre-commit使用说明.md` 概览计数同步。**「UI 扩展」剩余**:U2 合并两页记录、U5 落地目标页(须先对齐"目标页 vs 现存 7 个 `ui_page_*.c`"差集)。 -| **2026-10-22** | **v3.0 全量重写:删过时条目 + 按今天的仓库重新审计**(用户裁定"过时的都删除,重新写") | 旧正文按今天的实测重取数重判:六维评分旧表、UI「8 人日方案」正文、波次交付物清单、以及所有已闭环条目整段删除;**697 → 436 行**(−37%)。 -**重写依据(全部当日实测,不再引用旧数字)**:镜像 `ER_IROM1` 231,768 B / 22.1%(Code 213,188)、`RW_IRAM1` 75,264 B / 57.4%(余 55,808)、`RW_CCM` 57,376 B / **87.9%(余 7,904)**、堆 `min_ever` 8,464 B、任务栈 9/9 PASS(`data/ram_report_20261022.md`、`data/stack_report_20261022.md`);仓库 2,498 文件 / 80.0 MB、`.git` 248 MB、`docs/芯片手册` 717 文件 / 39.5 MB 占 docs 87%;37 个钩子、16 套主机单测、TC 593∶271 交集 265。 -**改判的三条旧结论**:① §6 的 U1/U3/U4 原写「❌ 未建」,实际已落地(`ui_tokens.h` 69 行、`ui_page_registry.c` 描述符注册表、`ui-golden`+`font-charset` 两枚钩子);U2 只有 `ui_w_records` 一个组件;"27 页未落地"实为 7 页。② "新增一页 ≤30 行"目标**未达**(最省 40 行),如实记为未达项。③ §0.4 与登记簿已漂开 → 本版把待办清单降级为**快照 + 指向登记簿**,权威只留一处。 -**刻意保留的三层**(删了会出事):§9 **编号族登记处**——本文是 `id_registry.json` 里 `N-RPT`/`D-RPT`/`S-RPT`/`R-RPT`(游标 R-9)/`F-RPT`/`U-RPT`(游标 U5) 六族的属主登记处,且外部存在「报告 N-14」「报告 F-4/F-5/F-6」「报告 D-1」「报告 R-2/R-3」式紧邻引用与 `check_dangling`,删定义位即触发编号门禁;§1.2/§1.3 方法与口径(数字可重跑);文末**变更记录 + 已销项去处表**原样冻结保留(52 行)。被外部点名的锚点(`§0.3`/`§3.1`/`§4.1`/`§4.2`/`§4.3`/`§5.3`×9/`§5.4`/`§5.5`×4/`§6.2`/`§6.3`/`§6.5`)逐个保留,**68 处入站引用零改动**。 -**门禁**:`check_doc_links.py --all --sections-strict` → 146 文档 0 问题(章节引用 2,499、可判定 1,483);`check_ids.py --strict` 增量拦截通过、**存量债 650 → 641(−9)**、可判定比例 82.98% → **82.79%**(仍高于基线 82.6%,但缓冲从 0.38pp 缩到 0.19pp——删掉的那批引用 99% 是可判定的,属预期副作用);`mem-numbers` / `ram_baseline --gate` / `task-table` / `cubemx-survival` 全 0。字节卫生:BOM 无 / CR 0 / U+FFFD 0 / 无行尾空格 / LF 结尾。 | -| **2026-10-22** | **S-2 收尾:`netMsgQueueHandle` 收进 net_socket 内部——该族 24 处手写裸 extern 全部清零** | 最后一步。队列对象仍由 CubeMX 在 -`MX_FREERTOS_Init()` 创建(**创建点不可外移**:`osKernelInitialize()` 之前的任何创建类 API 会杀死启动, -docs/架构设计/项目启动顺序管理.md),改为创建后立刻在 `Src/freertos.c` 的 `USER CODE BEGIN RTOS_QUEUES` 区 -调用 `net_msg_queue_adopt(netMsgQueueHandle)` 把句柄交给本模块;net_socket 内改为 `static s_net_msg_queue` -(21 处引用改名),BSP 对该全局变量的裸 `extern` 消失,`netMsgQueueHandle` 现在只出现在生成文件自己的两处。 | -| | **两个刻意的设计决定**:① **不新建第二个队列**——那会白占 CCM 堆里 8 × `net_msg_t` 的空间,而 CCM 是当下 -87.9% 的红线;所以选"创建后绑定"而不是"自建队列 + 删 .ioc 里的队列"(后者还要 CubeMX 重生成,属 Ask-first)。 -② `adopt()` **拒绝重复绑定并保留首次句柄**——真出现两处绑定时,静默换句柄会让已入队的请求留在旧队列里永不处理, -拒掉第二个反而更容易暴露。绑定前的判空是真实防线:丢这一行的后果是"所有 net_* 请求被丢弃、网络全线静默不通", -不是崩溃。 | -| | **防回退**:`check_cubemx_survival.py` 新增存活项 `net-msgq-adopt`(region `RTOS_QUEUES`,must_contain -`net_msg_queue_adopt`),易失清单 **29 → 30 项全部到位**;基线已重建。 | -| | **体量**:`Code` 213,204 → **213,236 B(+32)**、`ER_IROM1` **231,816 B(22.1%)**;`RW +4 / ZI −4` → -`RW_IRAM1` 恒 **75,264 B(57.4%)**、`RW_CCM` 恒 **57,376 B(87.9%)**、`RW+ZI` 总量 132,688 B **不变**。 | -| | **验证**:`@build` 0 错 0 警告;`@test` PASS(624 ms 到 `net init: OK`、i104 已监听、无 `[ERR]`/Fault、 -`heap free=15800 min_ever=8464` 逐项不变——证明没有多占一个队列);**另做真机 FTP 控制通道往返**:220 → -`USER admin` 331 → `PASS admin` **230** → `PWD` 257 → `TYPE I` 200 → `QUIT` 221,每条命令都是一次过队列的 -net_recv/net_send → 绑定路径在真机走通;`.map` 里 `freertos.o(MX_FREERTOS_Init) refers to -net_socket.o(i.net_msg_queue_adopt)` 证明镜像确实含该行。 | -| | **顺带揪出一条测试工具漂移(未修,等定夺)**:`test/host/ftp_up_dl_test.py:123/126` 仍写死 -`USER anonymous` / `PASS test@test.com`,而设备自 N-19(2026-10-11)起按 `/config.ini [ftp]` 校验 -admin/admin(SHA-256 `pwd_hash`)→ 该脚本**必然登录失败**;它是手工工具、不在任何 pre-commit 钩子里,所以 -一直没人发现,而 `../测试说明/FTP_Test_Guide.md` 把它列为推荐入口。建议:加 `--user/--password` -(默认 admin/admin),并顺手把 `ftp_speed_test.py` 一起核。 | -| | 数字联动照做:两份 `data/` 快照重跑、`ram_baseline --update/--write`、`check_mem_numbers --write`、FLASH 与 -任务栈两张配图重算重生成(逐文本复查越界 = 0)、本文 §1.3/§5.1/§5.4 与部署文档 §3.3 同步;§0.4 的 S-2 行按 -「完成即销项」改写、§9 拆出 S-2 行标 ✅。 | -| **2026-10-23** | **执行 §5.5 第 5 条后半:C 库堆禁令变成机器拦截**(§4.8 空白 ②,CODE-RULE-20) | 按本文件 §8 的既有纪律**先全库普查再动手**:`coding-standard` 钩子范围内 C/H 共 **151 个文件**,`malloc` 族只命中 -| | | `simulator/sim/cfg_file_store_sim.c` 两行(`cfg_store_alloc`/`cfg_store_free` = 平台分配后端的**宿主侧实现**, -| | | 设计依据写在 `../子系统设计/配置文件设计说明.md` 的"MCU 端 = pvPortMalloc、模拟器端 = 宿主 CRT")——**不是漏网**, -| | | 所以零基线、直接硬拦截;豁免走脚本里的 `HEAP_ALLOC_ALLOWLIST`(**文件路径 + 函数名**双条件),刻意不做目录级豁免: -| | | 下次谁要碰 C 堆就得往那张表加一行,评审看得见。判据 = 掩码后文本上匹配 `\b(malloc|calloc|realloc|strdup|strndup| -| | | free|aligned_alloc)\s*(\(`:大小写敏感 ⇒ `pvPortMalloc`/`vPortFree` 不误报;词边界 ⇒ `dhara_nand_is_free(`、`buf_free(` -| | | 不误报;注释与字符串里写 `malloc` 不报。**自证**:临时样例三处(`malloc/calloc/free`)各报一次、五种陷阱形态全部不报; -| | | `pre-commit run coding-standard --all-files` 实测 **Passed**(= 全库零存量)。 -| | | **顺带消掉一处自相矛盾**:规范 V1.0 §6.1 的示例自己写着 `malloc`/`free`(通用 C 模板遗留),已在其下方加 -| | | 「本仓例外,别照抄」批注并把事实源指向 AGENTS.md 平台约束;`docs/门禁说明/mem-budget.md` 里"这条纪律只靠评审" -| | | 的旧说法同步更正。AGENTS.md 平台约束条加"已机器拦截"一句。**本轮零 `.c/.h` 改动**(只动门禁脚本与文档), -| | | 未跑 `@build`、未占 build/bench 锁;详解归 `../门禁说明/coding-standard.md`(本处不复述判据) | -| **2026-10-23** | **执行 §5.5 第 5 条前半:覆盖率口径落地并销项**(§4.8 空白 ①) | 新增 `scripts/check_test_coverage.py`(纯标准库)+ 基线台账 `scripts/test_coverage_baseline.json`。**工具链是实测出来的、不是查到的**:本机 PATH 上 gcc/gcov/clang/llvm-cov/lcov/gcovr **全无**;`cl /coverage`、`/fsanitize=coverage` 在 MSVC 14.51 已被砍——**只报 `warning D9002 忽略未知选项`,然后照常编译成功**(拿它做覆盖率=静默假数据,比报错更坏);`Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe`(17.0)的 `collect`/`analyze`/`instrument` 一律只打印「用法: CodeCoverage 」。最终走 **mscoverage(`Microsoft.CodeCoverage.Console.exe` 18.x)`collect -f cobertura`** 的**加载期动态插桩**,并实测它**原样透传子进程退出码**(子进程 `return 3` → `collect` 也返回 3)→ 于是「插桩运行下仍必须 PASS」可以当硬条件用。 | -| | | **口径**:只算 `App/**` 与 `Drivers/BSP/**` 的行/函数、多套单测取**并集**、生成物(文件头写「自动生成 / 请勿手改」)不进分母、分母一律来自插桩报告**不猜行数**;配置零复制——脚本 import 各运行器的 `TestBuild`、开关取 `unit_test_harness._BASE_FLAGS`,只追加 `/Zi /Od` 与 `/link /INCREMENTAL:NO`,发现规则与 L0.5 同一条 `test/host/**/run_unit_test.py`,**不会漂出第二套口径**。 | -| | | **首登数字(2026-10-23)**:16 套全通过,并集 2552/2893 行(88.2%)、193/207 函数(93.2%)、19 个生产文件在测,**未触及 125 个生产源文件 / 约 11,839 行**(`net_socket.c` 1,251 行最大)——最后一栏才是这套口径真正照出来的东西。**门禁自证**:人为抬高基线后,行 / 函数 / 总计三条回退路径都如期报 REGRESS 且退出码 1;`--module` 子集运行不会假报总计回退(首版就会,已修)。**刻意未挂 pre-commit**:三条理由与可直接粘的 YAML 片段写在 `../测试说明/主机单测覆盖率口径.md` §8,接线者照 §8 落地即可。 | -| | | **同日另一半也落地**(§4.8 空白 ②):`check_coding_standard.py` 加 **CODE-RULE-20** 禁 C 库堆分配, -| | | 硬拦截零基线(全库普查 151 个 C/H 只有 `cfg_file_store_sim.c` 两行命中 = 平台后端的宿主侧实现, -| | | 点名进 `HEAP_ALLOC_ALLOWLIST`,刻意不做目录级豁免);规范 §6.1 示例自己写着 `malloc/free` 的 -| | | 自相矛盾也同日加了"本仓禁止"批注。**只剩分支覆盖**一条。分支覆盖**不是拿不到**:同日被用户问住后复测,本机 WSL2 Ubuntu 有 gcc/gcov 15.2.0,16 套单测在 gcc 下**全部编过且全绿**、`gcov -b -c` 出分支数据(`nand_ftl.c` 分支至少走过一次 41.40%);但换编译器就是换分母(`sha256.c` gcc 105 行 vs MSVC 114 行)→ **用户裁定只保留 MSVC 一条通道**(多一套工具链=多一套分母 +多一本台账 + 多一个"这台机器有没有 WSL"的未决项),分支覆盖**记为已接受缺口**、不是待办。实测表与决策依据见 `../测试说明/主机单测覆盖率口径.md` §2.1。本轮只加 `.py`/`.json`/`.md`,无 `.c/.h` 改动,不重跑 `@build`;文档面动 §0.1 / §0.4 / §4.8 / §5.5 / §7 与 `docs/README.md` 索引各一处。 | -| **2026-10-23** | **术语迁移**:`bsp-err` 的四项检查从 `R1/R2/R3/R4` 改成语义标签 | 用户一句「R4 -| | 到底是什么」问出来的。这四个号**是我自己造的**,而 `R1~R8` 在本仓是"专项风险"的裸形编号 -| | (`id_registry.json` 已登记那一族,保护规划 `R1~R8`、看门狗 `R1~R7` 的风险表都在用),`R-2` -| | 还是内存优化项——**同一裸形四种意思**。最刺人的是:**编号门禁不会报这种撞法**,因为 -| | `docs/编号规范.md` §4.3 已把这些裸形声明为"同号不同义"、走 `collides_with` 白名单,于是机器一路 -| | 放行、人完全看不懂。 -| | 同一天里我给这批缺陷起的"字母加数字"自造号被门禁当场拦下,而这套代号却一路绿灯——说明白名单 -| | 挡的是"事故"、不是"可读性"。 -| | 新名(同时是基线键的第二字段):`err-type` 错误通道不外泄 / `timeout-name` 超时宏不取负值 / -| | `return-doc` 公开函数必须写返回值 / `consume-result` 返回值不得裸丢弃。改名**不动任何检查行为**: -| | 脚本里规则码与基线键一起换(38 条键的字段同步替换,换完 `--emit-baseline` 复核仍是 38/38/0, -| | 中途不跑 `--prune`,否则会把改名误读成"全部还清 + 全部新账");现状类文档(AGENTS、§2.27、 -| | `bsp_err.h`、本报告 §0.4/§9/附录 A)全部改用新名,**已提交的变更记录行里的老名按冻结历史不回改**, -| | 以 `docs/代码规范/pre-commit使用说明.md` §2.27 的对照行为准。 | -| **2026-10-23** | **S-5 第三波**:给 `bsp-err` 加 **R4(返回值不得裸丢弃)**,并修掉它照出来的第一处 -| | ECC 静默降级 | 用户裁定"B 按你说的进行"(先上 R4,再修最小最值的那处)。R4 之所以必须自己做,是两条实测 -| | 负结果:`warn_unused_result` 在 ARMCC v5 不生效;cppcheck 按本仓 `--enable` 跑同一文件,对 14 处丢弃 -| | `HAL_SPI_*` **一条不报**(它还假定 `gd5f_read_status(&status)` 会写出参,而失败路径根本不写)。上线即照出 -| | **37 条存量丢弃**:`gd5f2gq5ue.c` 29(14 处 HAL + 15 处自家原语)、`net_socket.c` 8、`ui_net_sink.c` 4(`net_close`)、 -| | `rs485.c` 2、`nand_ftl.c` 1——按增量拦截老规矩**入基线只减不增**(覆盖面扩大新暴露的历史债,不是新增违规)。 -| | **R4 自身被修三次**:① 首版漏判 `foo(); /* 注释 */` 这种**行尾带注释**的裸调用(正则 `\s*$` 卡死),而那 -| | 恰是最常见的"带说明的丢弃"→ 补可选注释分支并做 6 条自检;② 把 `net_set_errno` 八处误判成丢弃(它是 setter, -| | 返回的 int 是状态回声不是调用成败)→ **按真实反例收窄规则**(谓词 + setter 豁免),不塞基线洗掉;③ 名单 -| | 只从**头文件**取,`gd5f_set_feature` 这类 **static** 原语整个在视野外——而上面那处 ECC 丢弃恰恰是 static、靠人工才发现 -| | → 名单扩到 `.c` 内 static 定义,补完立刻又照出 `gd5f_bbt_save#1`(运行时标坏后 BBT 落盘结果被丢弃 = 记账 -| | 可能没持久化;已入基线记为待还,本步不动行为)。 -| | **这处为什么值得修**:`bbt_rebuild` 注释写着"无论扫描成败都须恢复 ECC,否则后续 I/O 在无 ECC 下运行", -| | 而它下面 `gd5f_set_feature(0xB0,…)` + `gd5f_wait_busy(100)` **返回值全丢**:SPI 一抖 ECC 就保持关闭,且 -| | `gd5f_check_ecc()` 在 ECC 关闭时恒读"无错"——整条链再无信号。补法复用 init 路径的 **E-10**(写完回读 B0h 验 -| | `ECC_EN`,"写了但没生效"与写失败同罪),并把"关 ECC 失败"改成**立即中止**(此时 ECC 仍开着,是安全侧; -| | 继续扫反而会在 ECC 语义下读 spare、把厂标好块误判成坏块,"重建 BBT"变成制造坏块)。 -| | **一条定位纠正(差点把修复记大)**:查链接映射发现 `Removing gd5f2gq5ue.o(i.gd5f2gq5ue_bbt_rebuild), -| | (604 bytes)`——**该函数在产品镜像里根本没被链接**(产品构建无调用者),只由 `ENABLE_STORAGE_RECOVERY_TESTS` -| | 的**恢复构建**经 testTask 调用。所以本次修的是**恢复流程自身的安全**(跑恢复时若 ECC 没恢复,设备会带着 -| | "已恢复"的结论在无保护状态下继续跑),不是现场日常路径;相应地镜像 `Code` 的 +28 B 也**不是**它带来的(未逐字节 -| | 追,线索是 `gd5f_private_get_feature` 由单调用点变多调用点、内联决策可能变化)。因此验证不能只跑产品构建: -| | 临时打开 `TEST_SUITE_STORAGE` + `ENABLE_STORAGE_RECOVERY_TESTS` 编一次(**0 错 0 警告且该函数不再出现在 -| | Removing 列表**),随即还原两处开关并重编产品构建核对(`test/board` 无残留差异)。 -| | 验证:`@build` 0 错 0 警告,`Code` 213,648 → **213,676**、RO 18,860、`ER_IROM1` **232,536 B / 22.2%**(ROM -| | 合计 233,724 B);`ram_report` 重生成 + `ram_baseline.py --update` + 配图常量同步(`mem-numbers` Passed); -| | `@test` **PASS**(到 `net init: OK` 682 ms、`[ERR]` 0);R4 两处**探针实证**(临时加一条裸调用 → 立刻成为 -| | 新增并 RC=1;还原 → 38/38/0);`--prune` 点名本次还掉的 2 条已删;受影响文件钩子全 Passed。 -| **2026-10-23** | **S-5 还债:`bsp-err` 基线 19 → 1**,并修掉门禁自己的一处误判口径 | 用户裁定先还 A(清存量)再调查 B。**16 条缺「返回值:」全部补齐**:`gd5f2gq5ue.h` 九个 SPI 原语 -(`wait_busy`/`write_enable`/`read_status`/`page_read`/`read_from_cache`/`program_load`/`program_exec`/ -`block_erase`/`check_ecc`)逐条写全 函数功能/入口参数/返回值/限定条件/函数说明,**并把每个函数 -能返回哪些码写死在注释里**(哪一个是"可重试"的 `GD5F_WAIT_EXPIRED`、哪一个是器件自认坏块的 -`P_FAIL`/`E_FAIL`);`nand_ftl.h` 从零散三行补成带模块头的完整注释,并**明写"`nand_ftl_init()` -的 -1 抹掉了失败类"**——分类目前只在失败点进日志,要按类分支需要 C4 快照(现无消费者故未做), -同时警告"不得把 -1 解读成卷坏了可以重格式化"(E-31 的教训)。 -`ui_menu_tab.h` 五个表查询 API 由行尾短注释升级为完整块(含"越界返回 false 是保守取只读"、 -"宁可按一张错表拒绝显示也不要按它导航"这类判断依据);该文件**带 BOM,Edit 后已按原样补回** -(AGENTS 铁律:丢 BOM → ARMCC 按 CP936 解码 → 中文报 #870-D)。 | -| | **门禁自身的误判口径也修了,而且这是本轮最该记的一条**:R3 原本要求注释块里出现字面"返回值", -而规范 V1.0 允许列对齐写法「**返 回 值:**」。后果是双重的——① 合规写法被判违规;② 反向更糟: -`gd5f_write_enable`/`gd5f_read_status` 两条**早就"通过"了**,原因竟是它们的**函数说明**里顺口写了 -"返回值"三个字,而不是真的有一行返回值说明。**一条会因为散文里出现关键词而放行的规则,等于在 -奖励运气**。修法是在块内**忽略空格**后再匹配关键词(规范允许的排版不是违规),并在注释里写明 -为什么不许把"必须不空格"写进规则。基线随之从表面 15 条回到真实 16 条缺说明,再一并补齐。 | -| | **刻意没做的最后一条**:`bool ui_content_page_open()` 留在基线里。它和"补注释"不是一档事—— -要改签名(`bsp_err_t`)、要处理 **3 个调用点**(`ui_menu.c:138/192/196`,**今天三处全部丢弃返回值**, -即"按 ENTER 开页失败是静默的"这件事现在没人知道)、UI 三个文件都带 BOM、且 UI 源码**双端编译** -(模拟器同份),验证面是"重新构建模拟器 + 像素回归 + 真机进菜单逐个页"。这不是还债,是独立一波改动。 -顺带查出的这一条(开页失败静默)比签名统一更值得修。 | -| | 验证:`@build` **0 错 0 警告且 `Program Size` 与上一笔逐字段相同**(`Code` 213,648、RO 18,860、 -RW 1,188、ZI 131,500)——证明本笔确为纯注释,故**不跑 `@test`**(无任何指令变化,跑它没有新信息); -受影响文件的 14 个钩子全 Passed(含 `ui-golden` 像素回归、`cppcheck`、编码规范、`bsp-err` 1/1/0); -`check_doc_links --all --sections-strict` 147 篇 0 问题;字节卫生复核:UI 头 BOM 仍在、无 CR、无 U+FFFD。 | -| | **顺手更正我自己写进文档的一条错话**(这类"听着很顺但没核"的说法最危险):我在 S-5 各条里把 -`GD5F_SPI_TIMEOUT 100` 记成"**自旋圈数**(改分频时长会变)"。这次逐行核它的 12 处用法,**全部是 -HAL_* 超时参数或 `HAL_GetTick()` 差值 → 它也是毫秒**。真问题降级为"**单位没写进名字**(缺 `_MS` -后缀),读代码必须回实现查单位",而不是"换个 CPU 就悄悄变慢"。`osWaitForever` 与 `HAL_MAX_DELAY` -同为 0xFFFFFFFFU、以及"`*_BUSY_TIMEOUT = -2` 是返回码"两条**仍然成立**(前者已核头文件,后者已改)。 -本行以上那些**已提交的变更记录行仍写着旧说法**——按 §8.1 冻结历史不回改,更正以本行为准; -现状描述类条目(§0.4、`bsp_err.h`、`pre-commit使用说明.md` §2.27、脚本文件头)已全部改准。 | -| **2026-10-23** | **S-5 第二波:C3 SD2506 整模块收编 + C1 GD5F/TPAFE 同形两义 + C2 dhara 失败类**(用户指定顺序 C3 → C1 → C2) | **C3**:`sd2506.h` 三枚私有宏(`SD2506_OK/ERROR/I2C_ERROR`)**删除而不是留别名**(留别名 = 新代码还能继续用旧形状,等于把迁移洗掉),11 个公共 API + 6 个内部 helper 改 `bsp_err_t`;新增 `sd2506_err_from_hal()`,**把 I2C 超时从"和没人应答同一个 −2"里拆出来归成 `BSP_ERR_TIMEOUT`(可重试)**——SD2506 是启动链第一站、I2C1 上电时序敏感,这是本波最实在的一处语义改善; -`sd2506_init` 的 charge 寄存器**回读校验不符**原返 `SD2506_ERROR`(参数类)→ 改归 `BSP_ERR_IO`。连带迁移 `App`(`sys_clock.c`、`app_main.c`)、板级 RTC 套件、 -主机单测(`test/host/sys_clock/` 桩 + `run_unit_test.py` 补 `Drivers/BSP` include 路径)→ **单测 100/100**。 | -| | **C1**:GD5F 的 `GD5F_BUSY_TIMEOUT` 改名 `GD5F_WAIT_EXPIRED`(**值 −2 不变**,纯消"名字叫 TIMEOUT 其实是返回码"),GD5F 私有码集**整体**收编**没做**——169 处引用里 48 处在板级套件、 -还要动 Trap 记录用词,得单独一波配真机回归,不夹带。TPAFE5160 收编(23 处):`BUSY_TIMEOUT → BSP_ERR_TIMEOUT`、`ERROR → BSP_ERR_PARAM`(**同值 −1,行为零变化**)、 -`FRSTDATA_ERR → BSP_ERR_NO_DEVICE`(E-44 的本义就是"芯片没驱动 DB 总线",归到**器件无响应**比留在私有 −3 有用,且避开与 `BSP_ERR_TIMEOUT` 撞值)。 -**`tpafe5160_snapshot()` 刻意不套成败码**:它 1=有新帧 / 0=无新帧 / −1=参数错,**0 不是错误**,是"这一拍没有新数据",强行收编会把慢消费者的正常路径变成失败。 | -| | **也纠我第二次写错的一条**:我在 `bsp_err.h` 里断言"本层只有 `net_*` 一族把数量与错误挤在同一返回值"——`snapshot`/`adc_input_poll` 就是第二族,已把两族都写明并各注原因。 | -| | **C2**:FTL 坍缩点(`ftl_flush_cache`/`ftl_read_page`)不再把 dhara 失败压成 `GD5F_ERROR`,按处置差异分三类并**就地**打日志(最早同时知道 LPN 与原始码的位置):`ECC/TOO_BAD → -BSP_ERR_CRC`(页级,重试/换页)、`JOURNAL_FULL/MAP_FULL → BSP_ERR_NO_SPACE`(**块池见底,重格式化只是把问题推回去**)、其余 `→ BSP_ERR_IO`(完整性,保卷 + -上报,不许自愈重格式化)——与 **E-31** 是同一条纪律的两端。可读名用自建短表:**本仓 dhara 没有编 `error.c`,`dhara_strerror()` 会直接链接失败**。`disk_read`/`disk_write` -仍回 `RES_ERROR`(那是 FatFs 契约),要让 defaultTask 卷健康探针**按类分支**还差一个跨调用存活的快照 → **C4 待还**。口径 → `存储架构说明.md` §10.4。 | -| | **又一次"凭猜测就会改错代码"的自查**:我一度认定 `DBG_ERROR("... err=%d", err)` 是把结构体塞进 varargs 的格式 bug,准备顺手修——**核过 `Lib/dhara/error.h`:`dhara_error_t` -是 `enum`(标量)**,那行日志本来就合法。若没核实,我会把一条正常日志"修"成访问 `err.type` 而编译失败或语义错。 | -| | **验收(这一波有真验证面,和 RS485 试点不同)**:`@build` **0 错 0 警告**(`Code` 213,648、RO 18,860、`ER_IROM1` **232,508 B / 22.2%**、**RAM 三项零增量**);`@test` -PASS(681 ms)且逐条读到被改模块的锚点:`SD2506 init: OK (ret=0)` + ID/时间/温度/电池四条读回正常、`ADC init: OK`、`NAND init: OK`、`Map resumed: 14094/97504`、 -`adc=20803→28875` 帧计数持续递增(**证明 snapshot 三态语义没被改坏**)、`[ERR]/Fault/FAIL` 0 条;主机单测 100/100;`bsp-err` 基线 **19 → 17**、`--prune` 干净; -`doc-links --all --sections-strict` 147 篇 0 问题;`layer-deps`、`id-check --strict`、`mem-numbers`、`mem-budget`、`task-table`、`ui-golden`、`registration-check` 全过。 | -| | 口径与数字联动:`TPAFE5160/README.md`、`GD5F2GQ5UE_Test_Guide.md`、`GD5F2GQ5UE_Trap_Records.md`(旧名均留痕,便于对旧日志);`存储架构说明.md` **新增 §10.4**; -`AGENTS.md` 与 `pre-commit使用说明.md` §2.27 的基线计数 19 → 17;配图桶按 .map 对象级增量大改(**dhara/FTL 10,931 → 11,222 = +291 全在 `nand_ftl.o`**、应用代码/UI -+36 在 `app_main.o`、其余散量入"其他"7,557,桶和 = `Code+RO` 断言通过);`ram_baseline`/`check_mem_numbers --write`/`ram_report_20261023.md` 快照与本文 -§1.3/§5.1/§5.4、部署文档 §3.3 数字全部同步。**TPAFE5160/GD5F 两个对象的 Code 增量实测为 0**(纯改名,不产生一条指令)——这也是"改名不该被当成性能风险"的实证。 | -| **2026-10-23** | **S-5 起步:BSP 错误码契约 + `bsp-err` 门禁 + RS485 试点**(钩子 38 → **39**) | 先纠本报告自己:原文「无统一错误码/超时/重试约定」**不准**,实测是**六套并存**——0/−1(SD2506、NETCFG、nand_ftl)、自研枚举 `CH395F_STATUS_*`、芯片寄存器原生码 `CH395F_ERR_*`(与前一套同模块并存)、`HAL_StatusTypeDef`(`rs485.h` 曾直接外泄)、`bool`, -再加第三方 dhara 的出参 `dhara_error_t` 与 FatFs 的 `FRESULT`。超时侧是**同形两义**:`SD2506_I2C_TIMEOUT_MS 100`/`CH395F_SPI_BYTE_TIMEOUT_MS 100U` 是毫秒,`GD5F_SPI_TIMEOUT 100` 是 -**自旋圈数**(改 SPI 分频或换主频,时长跟着变且无人报警),`GD5F_BUSY_TIMEOUT` / `TPAFE5160_BUSY_TIMEOUT = -2` 其实是**返回码**;`osWaitForever` 与 `HAL_MAX_DELAY` **同为 0xFFFFFFFFU** -(值同域不同 → 跨层转手既不报错也不变慢)。**契约真正值钱的是把「能不能重试」提到公共层**: -以前它只写在个别注释里(`gd5f2gq5ue.c`:「GD5F_BUSY_TIMEOUT(-2) - 超时(可重试)」), -语义在、跨模块不可判定。 | -| | 新增 `Drivers/BSP/bsp_err.h`——**header-only、无 `.c`**(不占体积、不需双端注册):`0=BSP_OK`、 -11 个负值码、`BSP_ERR_CAN_RETRY(e)`、`BSP_WAIT_NONE/FOREVER/MS` 与边界纪律。边界纪律明确三件事: -第三方码**就地映射不改名**(改名等于伪造语义);**`net_*` BSD 兼容层不纳入**(用户裁定:调用方 -要的就是「返回字节数 + 每任务 errno 槽」那个形状,模拟器 Winsock 后端同形状);**lftpd 按第三方 -排除**(它的 226/425/450/550 是 FTP 协议码,不是内部错误码)。 | -| | **也纠我自己写错的一条**:我一度在 `bsp_err.h` 里把 `gd5f2gq5ue_read/write/erase` 当「计数或错误挤 -同一返回值」的反例——**核过实现与头注释,它们是「0=成功、其它=错误码」**,本层真正的 count-or-error -只有 `net_*`(已裁定不纳入)。原文已改正,并把「数量走出参」降级为**面向新 API 的原则**。 | -| | **试点 = RS485**:`rs485_transmit` / `rs485_receive_start` 不再外泄 `HAL_StatusTypeDef`,改 `bsp_err_t` -+ 模块内 `static rs485_err_from_hal()` 映射(HAL 码不出模块),顺带补 `p_handle` 判空。 -`@build` **0 错 0 警告**(`Code` 213,436 → **213,484,+48 B**;RO 不变、**RAM 一字未动**)、`@test` -PASS(702 ms)。**诚实标注**:这两个函数当前**没有生产调用点**(B2 冻结未接线),所以 `@test` -只证明「没破坏启动」,**不证明新错误码在运行时被正确使用**——下一个试点该挑在启动链上的模块 -(建议 SD2506,41 处调用点)。 | -| | **门禁 `bsp-err`**(`scripts/check_bsp_err.py`,三条规则:R1 不得拿 `HAL_StatusTypeDef`/`bool` 当错误 -通道、R2 `*_TIMEOUT` 宏不得取负值、R3 非 void 公开 API 必须有「返回值:」)。**规则改窄而不是 -拿基线洗规则**:第一版把 7 个正当谓词(`ui_..._is_active` / `has_children`)误判成违规,遂加 -`is_/has_/can_/valid` 白名单。存量 **19 条**钉基线、只减不增(两个 `*_BUSY_TIMEOUT = -2`、一个 -`bool ui_content_page_open()`、16 个缺注释)。**当场自证**:临时埋 3 条违规 → `命中 22(在册 19 / -新增 3)`、**RC=1**,三条规则各自点名并给出路;删掉探针 → `19/19/新增 0`、RC=0。 | -| | **一条实测负结果**(值得记):`__attribute__((warn_unused_result))` **在 ARMCC v5 上不生效**—— -属性挂上、调用点裸调不接返回值,构建仍 0 错 0 警告(第一次实验我误用 `(void)`,那本就是「故意 -丢弃」的写法,重做了一次)。所以「返回值必须被消费」只能靠门禁脚本 + 书写约定「故意丢弃必须 -写 `(void)`」。 | -| | **pre-commit 的坑**:钩子跑之前会 **stash 未暂存改动**——我先把配置 `git add` 了但没加 rs485, -钩子看到的树里 rs485 还是 `HAL_StatusTypeDef`,于是**假报警 2 条**。口径:改代码 + 同时更新基线 -时,**先把改动 `git add` 再跑钩子**。已写进 `pre-commit使用说明.md` §2.27。 | -| | 口径同步:`AGENTS.md`(钩子数 + 枚举 + 索引行)、`pre-commit使用说明.md`(新增 §2.27 + 计数 + -脚本清单行)、`并行任务工作树方案.md`、本文 §0.1/§0.4/§7 与 §9 的 S-5 行。数字联动(`ram_baseline ---update/--write`、`check_mem_numbers --write`、FLASH 配图常量、本文 §1.3/§5.1/§5.4 与部署文档 §3.3) -随本波提交一并做。**待还**:两个 `*_BUSY_TIMEOUT = -2` 改名(波及板级套件与 Trap 记录用词,需真机 -+ 套件回归)、FTL 坍缩点拆三类码(ECC / 介质 / 映射层坏块预算,让上层能区分「重试 / 标坏块 / -别再 mkfs」)、其余模块逐个迁移。 | -| **2026-10-22** | **S-1 只做「防扩大」那一半:新增 `layer-deps` 分层方向门禁**(推荐清单第 5 步拆分执行,钩子 37 → **38**) | 上一轮的结论是「反转暂缓、门禁现在就该上」,这次照做。 -为什么门禁比搬迁值钱:AGENTS 与分层图早就写着「六层单向依赖」,可从来没有机械检查——于是同一件事的记载从 2026-09 的 -「NETCFG 一处」漂到今天的「8 文件 9 处」,全靠人读代码才发现。边界的静默腐蚀只能靠门禁止住。 | -| | **机制(与 `id-check` 的增量拦截同构)**:`scripts/check_layer_deps.py` 扫 `Drivers/BSP/**.{c,h}` 的 include,按 `App/**` -头索引解析反向边,分三类——ALLOW 永久豁免 3 条横切叶子头(`console_log.h` 日志后端 / `sys_clock.h` 时间源 / -`sha256.h` 纯算法,任何层都要用、不依赖上层服务);BASELINE 钉住存量 6 条(`cfg_file.h`×2、`vol_lock.h`×1、 -`sys_log.h`×3);**新出现的组合直接 FAIL**。基线只减不增(脚本没有 `--write`),`--prune` 在某条还清时点名「可删」, -于是「还欠几条」成为可见进度。挂 `files: ^Drivers/BSP/`、`pass_filenames: false`(要跨文件建索引,恒扫全库)。 | -| | **当场自证**:落地时临时给 `Drivers/BSP/RS485/rs485.c` 加一行 `#include "cfg_file.h"` → 钩子当场 FAIL 并点名该文件与该头 -(退出码 1),删掉后转绿。**没被触发过的门禁等于没有门禁。** | -| | **反转(5a)仍暂缓**:没有功能在等它,且要过「改 IP 免重启生效」整条真机链,留给下次真动 NETCFG/UI 时顺带做 -(N-25 网络项、U5 页面扩展都会碰到)。目录搬迁(5b)同样暂缓:uvprojx 326 条 + IncludePath + CMakeLists + 42 个 UI 文件 -+ 全库引用改写,收益只是「目录名好看」,而远程 CI 仍不跑 `@build`。 | -| | **口径同步**:钩子数 37 → 38 共 6 处(`AGENTS.md` 两处、`docs/代码规范/pre-commit使用说明.md` 两处含新增 §2.26、 -`并行任务工作树方案.md`、本文 §0.1/§1.1);`项目架构总览.md` §1 分层原则处补「此方向已机械检查」。§0.4 的 S-1 计数由 -「7 文件 15 处」更正为脚本口径的 **8 文件 9 处**。本轮只加脚本 + 配置 + 文档,无 `.c/.h` 改动,故不重跑 `@build`。 | -| **2026-10-22** | **S-2 第三步:SPI1 完成标志的回调归属拆清**(推荐清单第 4a 步) | 问题不是风格:HAL 的 SPI 完成/错误回调 -是**全局唯一符号**,全工程只能有一份实现,当前由 CH395F 代管并按 `hspi->Instance` 分发——于是 GD5F 的 -`g_spi1_dma_done` 被 CH395F 跨模块裸 `extern` 直接写,**GD5F 出错时的"释放等待者"寄居在别人的 .c 里**。 -谁哪天做"CH395F 清理",把那两个 `else if (SPI1)` 分支当无关代码删掉:**编译零报错**,GD5F 的 DMA 等待 -在出错时只能干等 `GD5F_SPI_TIMEOUT` 兜底。 -| | **改法(时序一字不动,只换所有权)**:标志收为 GD5F 文件内 `static s_spi1_dma_done`;GD5F 导出 -`gd5f_spi1_notify_done()` / `gd5f_spi1_notify_error()`(头文件里写明"SPI1 分支必须转调这两个函数"); -CH395F 删掉裸 `extern`、include `gd5f2gq5ue.h`、两个 SPI1 分支改为转调并就地注明"勿删"。 -`HAL_SPI_AbortCpltCallback`(`HAL_SPI_DMAStop()` 会触发)仍无人实现,**本次刻意不做**——它会改变中止 -语义,属真机专项,当前超时兜底可用。 -| | **体量代价**:`ch395f.o` −8 B、`gd5f2gq5ue.o` +24 B → `Code` 213,188 → **213,204 B(+16 B)**, -RO/RW/ZI 全部不变,`ER_IROM1` 231,768 → **231,784 B(22.1%)**。16 B 换一个静默失效类,划算。 -数字联动一并做掉:`data/ram_report_20261022.md`、`data/stack_report_20261022.md` 重跑;`ram_baseline ---update/--write`;`check_mem_numbers --write`;三张配图常量更新后重新生成(逐文本按字号与锚点复查 -越界 = **0**);本文 §1.3/§5.1/§5.4 与 `docs/环境与部署/项目部署环境要求.md` §3.3 的 Flash 数字同步。 -| | **真机验证 `@test` PASS**:无 `[ERR]`/Fault,复位原因 software;`[STACK] heap free=15800 -min_ever=8464`**与改前逐项相同**;各任务实测峰值 default 2152 / net 1116 / ftp 764 / ui 4052 / -timesync 616 / adc 952 / iec104 540 / protect 624,**静态最坏链全部未变**(3024/1912/1456/4052/1264/ -1320/1456/872)→ 9/9 PASS。⚠ 记录一条读数陷阱:测试脚本打印的"boot to net init: OK = 7,907 ms"是 -采集窗口锚点造成的度量偏差,真机日志里 `boot: syslog init OK → net init: OK` 实测 ≈699 ms,与改 -前一致,**不是性能回退**。 | -| **2026-10-22** | **S-2 第二步:19 处任务句柄裸 extern 收拢成引用契约**(推荐清单第 3 步) | 新建 `App/task/task_handles.h`——**只有声明、没有 `.c`**:头文件不需要双端注册,`../App/task` 本来就在 uvprojx 的 `` 里,所以这一步零构建面。`default_task.c:52-69` 的 18 行 + `adc_task.c:125` 的 1 行局部 extern 全部删除改 include(栈水位表本体仍留在 `default_task.c`);同批把 `Src/main.c` 函数内的 `extern volatile uint32_t g_rcc_csr_latched;` 移进 `App/app/app_main.h`(该文件 `main.c` 本来就 include), -USER CODE 区内只留「读 RCC_CSR → 写 RMVF 清除」两句、顺序约束的原注释保留。**价值**:原先每加一个任务都得记得往 `default_task.c` 再抄两行 extern,抄漏一行 = 读别人的栈(静默);现在只有一个改动点,且 CubeMX 若把句柄改名会在链接期报错而不是静默通过。**镜像逐项体积不变**(`Code=213,188 RO=18,580 RW=1,184 ZI=131,504`,`@build` 0 错 0 警告)证明行为中性。`check_cubemx_survival.py` 对这次有意的 USER CODE 区改动报「漂移」,已按其文档流程 `--write`重建基线(`.cubemx_survival_baseline.json` 仅 1 行变化),`--check` 复跑通过、易失清单 29 项全部到位;顺带把 §0.4 的 S-2 口径改成精确分类:**手写该修 24 处(已消 22)+ CubeMX 生成块 16 条(不算债)+ `__asm` 汇编标签 4 条(合法例外)**——上一版「25 处」混了这三类。 | -| **2026-10-22** | **结构债 S-4 闭环 + S-2 第一步(用户批准「先只跑 1+2」)** | **S-4**:删除 `App/app/app_cfg.h` 里 4 个**零消费点**宏(`APP_NET_ENABLE`/`APP_ADC_ENABLE`/`APP_RS485_ENABLE`/`APP_SYS_TIME_SRC`),文件降格为「决策占位说明」——修改记录 v1.2 写明为什么删与将来怎么接回;并去掉 `app_main.c` 里只为它存在的 include。留「看着能裁剪、其实不生效」的宏比不留更糟:它不产生任何编译期效果,却让评审误信模块可裁剪;此前为了说明它,AGENTS 之外还得在 6 处文档各写一句「未接线占位,别当开关用」。同步改口径 **17 处**:`App/app/README.md`、`App/README.md`、根 `README.md`、`项目架构总览.md`、`项目部署环境要求.md`(§3.2 两行 + 配置表一行)、`产品需求设计文档.md`(B0 结论 + 配置表)、`基线与待确认.md`、`排期详述.md` C5、`登记簿.md` N-23 残余、`RAM使用分析与优化方案.md` 三处。 -| | **顺带纠出另一个不存在的宏**:`RAM使用分析与优化方案.md` 把 `APP_CCM_ENABLE` 写成「加在 `App/app/app_cfg.h`」,实际从来没有落地(全库仅该文档提及)——已就地标注「未实现,重开本簇时一起落地」,避免下一个读者以为 CCM 有回退开关。 -| | **S-2 第一步(实测纠偏)**:删掉 `gd5f2gq5ue.c:47`、`sd2506.c:20` 两处与 `Inc/spi.h`/`Inc/i2c.h` 重复的 `extern`,GD5F 改 `#include "spi.h"`(沿用 `ch395f.c:22` 的既有做法)。**镜像逐字节不变**:`Code=213,188 RO=18,580 RW=1,184 ZI=131,504` 与改动前完全相同,`@build` 0 错 0 警告 → 证明这两步是行为中性的。同时把 §0.4/§9 的旧口径换成实测值:**S-2 不是 4 处而是 25 处**(`App/task/default_task.c:52-69` 一次就有 18 行;`stm32f4xx_it.c` 的 `fault_entry_hard` 属 ARMCC `__asm` 合法例外,不该「修」),**S-1 不是语义错位而是真实反向依赖**(NETCFG include `App/cfg/cfg_file.h` 10 处 + UI 3 个文件)。**这两个旧数字是我 v3.0 重写时沿用未测,一并认错。** SPI 回调归属这条隐患(CH395F 替 GD5F 释放错误路径)目前只在本文 §0.4 留了痕,**尚未进登记簿**——要不要立项等你定。 | -| **2026-10-22** | **执行 §5.4:F-6 落地、F-4 判定不做、F-5 降级观察项**(登记簿 N-28 同步改写) | 动手前逐条对 `.map` 与源码核(本报告"建议栏不可照抄"总口径的又一次复现——三处误判全部出在**建议栏**,"发现"栏字节数全对)。**F-6 ✅**:`App/algo/prot_set.h` 两个 Q10 宏去掉显式 `(double)`、`1024.0`→`1024.0f` → `@build` 0 错 0 警、Code 213,520→**213,188(−332 B)**;`.map` 中 `dflti`、`d2f`、`f2d`、`dfixi`、`fepilogue` 共 300 B 消失,自研侧不再引用任何双精度 helper。**原报告"来自 `printf` 的 `%f`"是误判**:全库 0 处 `%f`,剩余 `dadd`+`dmul`+`ddiv`+`depilogue`+`dfixul` = 1,018 B 由 `mc_w.l(printfa.o)` 的 `_printf_core → _fp_digits` 无条件引用,MicroLIB 层面删不掉。**数值等价用穷举证明**(宏内 42 个字面量 + `int32` 全域 ÷1024 往返 4.49×10⁶ 例零差异;×1024 方向 2×10⁵ 例零差异);回归 = `prot_set` 90/90、`prot_elm` 47/47、`iec104` 97/97 主机单测全过。**F-4 ❌ 判定不做**:五项字节数逐字节仍准(合计 10,060 B)但**无一项有开关**,根因是 `lv_draw_sw.c` 的 `execute_drawing()` 无条件 switch 引用全部 task 类型;唯一总开关 `LV_DRAW_SW_COMPLEX` 被 `ui_deco.c` 的"浅 V"3 px 粗斜腿锁死(**2026-09-03 已实测失败并两端固化 =1**);**原"mask/grad 是文字必经路径"的理由同时证伪**(字形走 blend 层 `mask_buf`,不经 `lv_draw_sw_mask_*`)。**F-5 🟡 降级观察项**:uvprojx 实测 326 个 `.c` / LVGL 201 个 / `.map` 零产出 **127 个**,但增量构建实测 4~5 s、远程 CI 刻意不跑 `@build`,原"−40%"无基线记录。同步更正 §0.1 Flash 行、§0.4 Flash 行、注册表 uvprojx 行、§1 口径行、§5.1 快照注与要点行、§6.4 LVGL 占比分母、「结构债」波次行;台账受管区与内存快照已 `--write` 回填(`mem-budget` / `mem-numbers` 转绿)。**`@test` 台架 PASS**(固件戳 `fw build: Oct 22 2026 10:36:15 suite=NONE dstr=off`;无 `[ERR]`/`ERROR`/`FAIL`/Fault,708 ms 到 `net init: OK`,`protect task start`、`i104: listening on 2404`、`[STACK]` 三面水位齐;`adc`/`phasor`/`freq` 心跳持续) | -| **2026-10-14** | **清理:删除已完成与过时内容** | ① **已修复项按销项删除**(去处见下表):N-02(FTP 鉴权)、N-03c(`Error_Handler` 降级)、**N-11(DMA 可达性三层防线 + 规则族 R1~R4)**、S-3(注册反向校验)、P2-5/P2-6(SD2506 负温度与 WRTC)、P2-8(`NET_RECV_TIMEOUT_MS` 已删)、P2-9(`mkdir` 幂等重试)、§5.5 前三条(内存治理三件套)、交付物清单已建项。② **删除过时层**:2026-09-16 / 2026-10-11 双列基线表与"复核期间未提交改动"口径说明、旧"组合结果预估"表、逐条"2026-10-11 复核"批注、历史变更记录行——内存数字改由 `../内存管理/RAM预算台账.md` 与 `scripts/ram_baseline.tsv` 持有。③ **按 2026-10-14 `.map` 与代码重测**全部保留结论的数字(含 `lftpd_log.c` 已删除并入 `lftpd_auth.c`,N-06 残余只剩 `rs485_task.c` 一条刻意缺口)。④ **修正三处错误**:R-5(`configMAX_PRIORITIES` 56→32)**判定不可行**(CMSIS-RTOS2 `#error`);原 §7 把报告 S-5(驱动统一错误码)与登记簿 S-5(卷锁覆盖面)混为一谈;原 §5.5 第 4 条建议的 `_Static_assert` 形态在 AC5 上取不到链接期地址,已被"窗口断言 + 启动自检 + 运行时守卫"三层取代。⑤ 报告自有编号**不回改、不重排**(`../编号规范.md`) | -| **2026-10-23** | **N-15 由"待评估"改判"判定不做":补上页缓冲可合并性论证** | 报告此前把 N-15(`nand_ftl.o` 6,216 B、三块 2 KB 页缓冲)写成"与 R-3 同批评估",但**评估本身从来没写过**——`nand_ftl.c:300` 的注释直接引用了这份不存在的"报告 R-3"。本次补齐(论证落 `../内存管理/存储栈RAM优化调研.md` §5):① `.map` 实证 6,216 = RW 16 + ZI 6,200,三块缓冲 6,144 B 占 98.8%;② **不可合并**——`dhara_map_write()` 先 `auto_gc()`(`map.c:327`)再落数据,回收里的 `dhara_nand_copy()` 与"待写的 `s_cache_buf`""攒了 16 页的 checkpoint 元数据 `s_page_buf`"三方同时存活,任两块合并都是**静默错数据而非报错**;`s_page_buf` 也不能缩(元数据跨 0..1,999 偏移,编程的是整页);③ 唯一可动的是 `s_copy_buf`:分块 512 B(−1,536 B,代价是 4 次 CPU 轮询)或内部搬页 copy-back(−2,048 B,须实证手册"奇偶属性相同"限制、并先给主机侧假芯片补 internal-data-move 语义);④ **省下来也没用**:三块都在 `RW_IRAM1`(余 55,808 B),红线是 `RW_CCM`(余 7,904 B),做满也不减红线,搬进 CCM 反而吃掉其 78% → 暂缓不变、重开仍按 §5.3 三条条件。顺带订正 `nand_ftl.c:405` 一句错注释(原写 `s_page_buf` "仅装 132 B 走轮询",实际按整页 2,048 B 编程、同样走 DMA,会误导 P1-5② 迁 CCM)。**仅注释 + 文档,镜像零变化**(`@build` 0 错 0 警告,Code/RO/RW/ZI 逐项不变) | - -### 已销项条目的记录去处 - -> 删除前已逐条核对:以下去处文档/代码均含完整记录,删了不丢信息。 - -| 已销项条目 | 去处 | -|-----------|------| -| N-01(配置引擎 C 堆必失败) | `../子系统设计/配置文件设计说明.md` §6.2 / §8 | -| N-02(FTP 无鉴权,登记簿 N-19) | `../子系统设计/网络配置说明.md` §3.4(`[ftp] user/pwd_hash/write`、恒定时间比较、5 败锁 60 s、出厂默认口令告警、明文嗅探边界)+ `../产品需求/产品需求设计文档.md` §FTP 鉴权 + `Drivers/BSP/NET/lftpd/lftpd_auth.c` + 主机侧 `test/host/sha256/`、`test/host/ftp_auth/` | -| N-03a/N-03b/N-07/N-08(IWDG、`configASSERT`、两个钩子、4 个 Fault 现场) | `../子系统设计/看门狗设计说明.md`(§4.4、§10.1/§10.2)+ AGENTS.md「平台约束」 | -| N-03c(`Error_Handler` 死循环,登记簿 **N-20**,2026-10-15 已销项) | `../子系统设计/看门狗设计说明.md` §4.4(统一降级:1 条自检 + `NVIC_SystemReset()`、三条实现约束含 `__builtin_return_address` 不可用的实证、内核前日志路径安全性、重生成存活三层)+ 实施代码 `Src/main.c` 的 `USER CODE Error_Handler_Debug` 区注释 + `scripts/check_cubemx_survival.py` 审计项 | -| N-06 主体(`crc.c`/`ringbuf.c`/`lftpd_log.c` 删除、`adc_task.c` 注册)+ S-3(注册反向校验,登记簿 N-23) | `scripts/check_registration.py`(`KNOWN_GAPS` 白名单 + `--strict`)+ `../代码规范/pre-commit使用说明.md`(`registration-check`);`lftpd_log.c` 并入 `Drivers/BSP/NET/lftpd/lftpd_auth.c` | -| **N-11**(NAND 直 DMA 调用方缓冲 / CCM 迁移硬边界,登记簿 **N-26**,2026-10-15 已销项) | `../内存管理/内存内容分配策略.md` §3(全板 DMA 使用方清点)+ §4 规则 R1~R4(**R3 堆/栈禁为 DMA 源/目的**,含"缓冲自身地址无法编译期断言"这条边界)+ §8 落点索引;代码三层 = `gd5f2gq5ue.h:96-107` 编译期窗口断言 → `nand_ftl.c:241-243` 启动期自检 → `gd5f_dma_buf_ok()` 运行时强制;负路径用例 TC-GD5F-704/705 | -| N-10(UI accept 门控) | `../UI设计/RemoDispBus协议与接收设计说明.md` §3 + 看门狗设计说明 §11.4 | -| N-17(栈/堆水位观测)+ R-8(观测常开) | `../内存管理/RAM使用分析与优化方案.md` + `../测试说明/实机测试实施指南.md`(`[STACK]` 水位 + `stack_report.py` + `ram_report.py`) | -| N-18(本报告口径:无 CI) | `../测试说明/测试开发标准流程.md` §9 + `../CI/README.md` | -| P2-5 / P2-6(SD2506 负温度解析、WRTC 解锁顺序) | `Drivers/BSP/SD2506/sd2506.c`(符号扩展 `val \| 0xF0`;WRTC1→WRTC2/3 顺序按手册,上电即写禁止态) | -| P2-8(`net_recv` 30 s 阻塞超时) | `Drivers/BSP/NET/net_config.h` 头注(2026-10-13 recv 语义主流化:删除 `NET_RECV_TIMEOUT_MS`,预算由调用方显式给)+ `../网络/Net层阻塞模型架构设计.md` | -| P2-9(`mkdir` 失败不再重试) | `App/log/sys_log_mcu.c`(`s_fs_ready` 幂等 + `mkdir /log fail (%d), will retry` + 上报自检) | -| P2-13 / P2-14 / P2-15 | AGENTS.md(`test-suite-switch`、`keil-build`、`stlink-flash`)+ `../测试说明/ST-LINK_CLI_复位使用说明.md` | -| D-2 / D-3 / D-4 / D-5 / D-6 / D-7 | `../文档规范.md` + `../代码规范/pre-commit使用说明.md`;断链由 `scripts/check_doc_links.py` 门禁接管 | -| U4 主体(golden 回归) | `simulator/tests/` 四脚本 + `../UI设计/UI_自动化测试流程.md`(残余 = 挂门禁,见 §6.3) | -| R-1 / R-7 | `../子系统设计/看门狗设计说明.md` + AGENTS.md 任务表(`scripts/gen_task_table.py` 生成区) | -| §5.5 前三条(92% 门禁 / 趋势基线 / 预算台账,登记簿 N-27 前半) | `../内存管理/RAM预算台账.md`(阈值与配额的**唯一权威**)+ `scripts/ram_baseline.py`(`--gate/--update/--trend/--write`)+ `../代码规范/pre-commit使用说明.md`(`mem-budget`) | -| **F-4 判定不做 / F-6 已落地(2026-10-22,登记簿 N-28)** | 实测复核与"为什么关不掉"记在本报告 §5.4;`LV_DRAW_SW_COMPLEX` 必须为 1 的约束本身在 `../UI设计/UI_设计架构.md` §1.4 第 7 条与 `../UI设计/UI_界面制作流程.md` 陷阱表;宏改动与等价性论证在 `App/algo/prot_set.h` 的 Q10 注释;MicroLIB `snprintf` 拖入 `_fp_digits` 的取证方法(在 `.map` 的 Section Cross References 区反查 `refers to mf_w.l(d*.o)`)见 §5.4 F-6 行 | -| F-1 / F-2 / F-3(LVGL 死代码裁剪) | `../内存管理/RAM使用分析与优化方案.md` §2.6.4;`../UI设计/UI_设计架构.md` §1.4 第 10 条(**两份 `lv_conf.h` 必须同一特性子集**);`../UI设计/UI_自动化测试流程.md` 变更记录(池水位基线) | -| **R-9(`LV_MEM_SIZE` 40→16 KB,登记簿 N-27 原「预算与内存」的第一步,2026-10-15 已执行;该簇其余部分同日整簇暂缓)** | 取值依据与再降 8 KB 的前置写在 `Lib/lv_conf.h` 与 `simulator/lv_conf.h` 的池注释;实测水位 → `../内存管理/RAM使用分析与优化方案.md` §2.6.2 与 §阶段 1.1(已执行);解锁链第 ① 步 ✅(后续步骤暂缓)→ `../内存管理/RAM预算台账.md` §3;池容量口径 → `../UI设计/UI_设计架构.md` §1.2、`../UI设计/UI_界面制作流程.md` C4 | -| **N-12 / N-13**(dhara 移植层 `is_free` 精度 + HAL 越界守卫,登记簿 **N-21**,2026-10-15 已销项) | `../架构设计/STM32F4-Base存储架构说明.md` §5.3(移植层两条硬约束:整页精确的原因链 + 错误码取舍与"为什么不会静默清卷")+ `Drivers/BSP/GD5F2GQ5UE/nand_ftl.c` 的 `ftl_page_in_range` / `ftl_block_in_range` / `dhara_nand_is_free` 注释 + 主机侧单测 `test/host/nand_port/`(含"旧算法只看页首 64 B"的对照用例,防止将来被改回去) | -| **N-16**(日志读写放大,登记簿 **N-24**,2026-10-15 已销项) | `../子系统设计/运行与自检记录设计说明.md` §4.4(写侧批量合并 + **掉电语义不变**的论证 + 失败回投不丢条目 + 容量轮转只在慢路径)与 §4.5(读侧 8 条窗口 + 写者代数失效 + API 不变)+ `App/log/sys_log_mcu.c` 的 `s_format_rec` / `s_append_rec` / `s_append_many` / `s_read_raw` 注释 | -| **§4.8 两处空白(①无覆盖率口径 ②无 `malloc(` 正则)+ §5.5 第 5 条整条(2026-10-23 全部销项)** | `../测试说明/主机单测覆盖率口径.md`(口径 / 工具链实测 / 统计面 / 门禁姿态 / **九条限制与盲区** / 未挂钩子的三条理由与待粘 YAML)+ `scripts/check_test_coverage.py`(`--list` / `--module` / `--update-baseline` / `--md` / `--json`)+ 基线台账 `scripts/test_coverage_baseline.json`(首登 2552/2893 行、未触及 125 文件)。 -空白 ② → `docs/门禁说明/coding-standard.md`(CODE-RULE-20 判据 / 唯一豁免 / 盲区 / 落地前普查数)+ -`scripts/check_coding_standard.py`;禁令本身的事实源仍是 AGENTS.md 平台约束与 -`../内存管理/RAM使用分析与优化方案.md` §4.2.1;另 `../代码规范/嵌入式C语言代码规范_V1.0.md` §6.1 的示例 - 自己写着 `malloc/free`(通用 C 模板遗留),已同日在示例下加"本仓禁止"批注 | diff --git a/scripts/check_doc_links.py b/scripts/check_doc_links.py index 8b82904b..6ab01ee4 100644 --- a/scripts/check_doc_links.py +++ b/scripts/check_doc_links.py @@ -14,7 +14,7 @@ 实测可把误报压到 0);昵称式引用如「内存方案 §2.1」不校验。 豁免(不算失效,不报错): - * 以 `[计划]` 前缀标记的路径(尚未创建的约定产物,见《项目审查与优化建议报告》D-3 建议) + * 以 `[计划]` 前缀标记的路径(尚未创建的约定产物,源于 D-3 建议) * 含 `[示例]` 标记的行——引用报错样例 / 日志片段等含路径的引文 * 引用附近(±40 字符)出现「未创建/尚未创建/已删除/待排期」等状态词 * 含通配符 `*`、尖括号 `<模块>` 等占位符 diff --git a/scripts/check_ids.py b/scripts/check_ids.py index 1eb51966..8ce18b38 100644 --- a/scripts/check_ids.py +++ b/scripts/check_ids.py @@ -141,6 +141,13 @@ class Checker(object): f["_re"] = re.compile(fam["pattern"]) f["_full"] = re.compile("^(?:%s)$" % fam["pattern"]) f["_owners"] = self._expand_owners(fam) + # 定义集属主 ≠ 登记处属主。冻结历史快照族(snapshot_only)的登记处只能挂在 + # 规范正文(docs/编号规范.md §4.5 那种存档表)时,那张表**是存档不是定义**: + # 规范里还混着大量写法示例(`N-99`、`S1`、`N-31`),若进定义集会同时打穿 + # 裸形判定(`S1` 被判成 `S-1` 的漏连字符,实测 238 条)与撞号判定(§4.5 的 + # `S-3` 与登记簿 S-3 被判重复定义)。因此只对快照族做这个剔除。 + f["_def_owners"] = ([o for o in f["_owners"] if o not in self.spec_docs] + if fam.get("snapshot_only") else f["_owners"]) f["_max"] = self._cursor_max(fam) self.families.append(f) # 长形态优先匹配:TC-UPPER 要先于 TC,避免大写后缀被当成合规 @@ -210,7 +217,7 @@ class Checker(object): for rel in rels: self.read(rel) for fam in self.families: - for owner in fam["_owners"]: + for owner in fam["_def_owners"]: self.owner_docs.add(owner) self.owner_tokens[fam["name"]].update( m.group(0) for m in fam["_re"].finditer(self.read(owner))) @@ -298,7 +305,7 @@ class Checker(object): self._check_frozen(rel, lineno, literal, fam) self._check_dangling(rel, lineno, literal, fam) self._check_adjacent(rel, lineno, literal, fam, line, start) - if rel not in fam["_owners"]: + if rel not in fam["_def_owners"]: self.refs.setdefault(literal, set()).add(rel) self._scan_malformed(rel, lineno, line) @@ -308,7 +315,7 @@ class Checker(object): if len(fams) == 1: return fams[0] for f in fams: - if rel in f["_owners"]: + if rel in f["_def_owners"]: return f for f in fams: if f.get("adjacent_required") and self._has_adjacent_cue(f, line, start): @@ -327,7 +334,7 @@ class Checker(object): if literal in self.owner_tokens[f["name"]]: return f for f in fams: - if f.get("check_dangling") and f["_owners"]: + if f.get("check_dangling") and f["_def_owners"]: return f for f in fams: if f["scope"] == "global": @@ -339,7 +346,7 @@ class Checker(object): for o in fam.get("owner_docs", []): stem = o.rsplit("/", 1)[-1] cues += [stem, stem.rsplit(".", 1)[0]] - for o in fam["_owners"][:6]: + for o in fam["_def_owners"][:6]: stem = o.rsplit("/", 1)[-1] cues += [stem, stem.rsplit(".", 1)[0]] out, seen = [], set() @@ -428,7 +435,7 @@ class Checker(object): def _check_frozen(self, rel, lineno, literal, fam): if not fam.get("frozen") or fam["_max"] is None: return - if fam.get("cursor_owner_only") and rel not in fam["_owners"]: + if fam.get("cursor_owner_only") and rel not in fam["_def_owners"]: # 裸形族(B5/C6/D7/M1/U3/R3/V5…)与位号、档位词、其它文档的同名清单大面积同形 # (§1.2 五义/四义)→ 越游标只在属主登记处文档内判,文档外不判(见 unmanaged_bare) return @@ -442,7 +449,7 @@ class Checker(object): "该族已封闭,新条目改语义标识(§3.3);确需新号先改 docs/编号规范.md §4") def _check_dangling(self, rel, lineno, literal, fam): - if not fam.get("check_dangling") or not fam["_owners"] or rel in fam["_owners"]: + if not fam.get("check_dangling") or not fam["_def_owners"] or rel in fam["_def_owners"]: return if rel in self.spec_docs: # 规范正文里的 `N-99`→`N-100`、`Trap 07` 这类是**写法示例**,不是引用 @@ -463,14 +470,14 @@ class Checker(object): if base != literal and base in self.defined_all: self.stats["subitem_hits"] += 1 return - sev = fam.get("dangling_outside_owner", "error") if rel not in fam["_owners"] else "error" + sev = fam.get("dangling_outside_owner", "error") if rel not in fam["_def_owners"] else "error" self.add(3, sev, rel, lineno, literal, "悬空引用:%s 在属主登记处(%s)查无定义,也不在别名表里(§8 校验 3)" - % (literal, " / ".join(fam["_owners"][:2])), + % (literal, " / ".join(fam["_def_owners"][:2])), "补定义行,或删引用(§5.5:销项 = 删行 + 清全库引用)") def _check_adjacent(self, rel, lineno, literal, fam, line, start): - if not fam.get("adjacent_required") or rel in fam["_owners"] or rel in self.spec_docs: + if not fam.get("adjacent_required") or rel in fam["_def_owners"] or rel in self.spec_docs: return if "-" not in literal: # 只约束连字符形态的文档内编号:裸形(A2/B5/U3/D7)与位号、档位词大面积同形 @@ -479,7 +486,7 @@ class Checker(object): if self._has_adjacent_cue(fam, line, start): return owner = fam["owner_docs"][0] if fam.get("owner_docs") else ( - fam["_owners"][0] if fam["_owners"] else "docs/<属主文档>.md") + fam["_def_owners"][0] if fam["_def_owners"] else "docs/<属主文档>.md") self.add(6, "error", rel, lineno, literal, "文档内编号未紧邻文档名:%s 属「%s」,跨文档引用必须写全属主(§5.2 / §8 校验 6)" % (literal, fam["title"]), @@ -520,7 +527,7 @@ class Checker(object): allowed.add(frozenset((fam["class"], cw))) defs = defaultdict(list) # literal -> [(class, family_title, owner_doc)] for fam in self.families: - for owner in fam["_owners"]: + for owner in fam["_def_owners"]: for line in self.read(owner).splitlines(): m = self.DEF_ANCHOR.match(line) if m and fam["_full"].match(m.group(1)): @@ -549,18 +556,18 @@ class Checker(object): def check_orphans(self): for fam in self.families: - if not fam.get("check_dangling") or not fam["_owners"]: + if not fam.get("check_dangling") or not fam["_def_owners"]: continue if fam.get("allow_orphans"): # 属主登记处 = 代码的族(TC-HOST-*):号定义在测试函数上、本来就只在 # 自己文件里出现,按"无人引用"报孤儿是纯噪音(118 条),显式声明不判 continue for lit in sorted(self.owner_tokens[fam["name"]]): - outside = {r for r in self.refs.get(lit, set()) if r not in fam["_owners"]} + outside = {r for r in self.refs.get(lit, set()) if r not in fam["_def_owners"]} if not outside: - self.add(7, "warn", fam["_owners"][0], 0, lit, + self.add(7, "warn", fam["_def_owners"][0], 0, lit, "孤儿条目:%s 定义在 %s,全库无引用(§8 校验 7)" - % (lit, fam["_owners"][0]), + % (lit, fam["_def_owners"][0]), "确认已闭环可销项(§5.5),或补上引用") # ---------- 报告 ---------- diff --git a/scripts/check_test_coverage.py b/scripts/check_test_coverage.py index a0493cb2..1b575b88 100644 --- a/scripts/check_test_coverage.py +++ b/scripts/check_test_coverage.py @@ -15,7 +15,7 @@ r""" 自研生产源文件里有多少从未被任何主机单测编译过(未触及面 = 覆盖率的 0 分母盲区)。 为什么要它(2026-10-23,W5 验证常态): - docs/问题记录/项目审查与优化建议报告.md §4.8 记的两处空白之一:无覆盖率口径—— + 原评审报告 §4.8 记的两处空白之一(该报告 2026-10-25 已删除):无覆盖率口径—— L0.5 只回答“跑过哪些 TC”,回答不了“生产源码里哪些行根本没进过”。用例数与 TC 追溯率 会随时间上升,但覆盖率照的是另一类真相:**新增分支一行没测**(N-12/N-13 那类“读代码 才发现”的缺陷,覆盖率是最便宜的机器照法)。 @@ -67,7 +67,7 @@ r""" - **PDB 里的源路径大小写会漂**(盘符、VS 根),比对前先按仓库实际拼写归一,否则同一文件 在基线里裂成两份。 -设计依据:docs/测试说明/主机单测覆盖率口径.md;docs/问题记录/项目审查与优化建议报告.md §4.8 §5.5 +设计依据:docs/测试说明/主机单测覆盖率口径.md 创建日期:2026-10-23 """ diff --git a/scripts/id_aliases.json b/scripts/id_aliases.json index 56593415..cc1f3420 100644 --- a/scripts/id_aliases.json +++ b/scripts/id_aliases.json @@ -1,7 +1,7 @@ { "schema": 1, "generated_from": "docs/编号规范.md §7 迁移映射 + §4.3 冻结前缀;本表只登记**仓库里已实际出现**的旧字面量 → 现行字面量,不做尚未落地的批量改写(§7.2 阶段 1 一律保留存量)", - "note": "旧号引用不因本表而改写:本表只让门禁把「旧号引用」判成可解析(校验 3 悬空引用 / 校验 4 重复定义)。批量改写属 §9 阶段 1,须逐批 dry-run + 三重复核(§7.3)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。", + "note": "旧号引用不因本表而改写:本表只让门禁把「旧号引用」判成可解析(校验 3 悬空引用 / 校验 4 重复定义)。批量改写属 §9 阶段 1,须逐批 dry-run + 三重复核(§7.3)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。", "aliases": { "N-31": { "to": null, @@ -2706,7 +2706,6 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/问题记录/项目审查与优化建议报告.md", "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", @@ -2721,7 +2720,6 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/问题记录/项目审查与优化建议报告.md", "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", @@ -2736,7 +2734,6 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/问题记录/项目审查与优化建议报告.md", "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", @@ -2751,7 +2748,6 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/问题记录/项目审查与优化建议报告.md", "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", @@ -2766,7 +2762,6 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/问题记录/项目审查与优化建议报告.md", "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", @@ -2781,7 +2776,6 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/问题记录/项目审查与优化建议报告.md", "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", @@ -2796,7 +2790,6 @@ "note": "GD5F 存储域:Trap 01~07 → TRAP-GD5F-01~07(属主文档 7 个标题行为定义位,其余为引用)(scripts/rename_ids.py 批:族 TRAP)|旧号仅在本批 scope 内指向新号;scope 外同字面量属其它族,不受本条影响", "scope": [ "docs/问题记录/GD5F2GQ5UE_Trap_Records.md", - "docs/问题记录/项目审查与优化建议报告.md", "docs/测试说明/GD5F2GQ5UE_Test_Guide.md", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c", "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h", @@ -3102,6 +3095,61 @@ "docs/硬件平台/V0.1_网表详细分析报告.md" ], "note": "批 7:硬件网表报告里的裸形 Trap05 统一成 TRAP-NET-05(属主条目 docs/问题记录/CH395F_Trap_Records.md,语义 = CH395F 与 RTL8305 自动协商不兼容)。该目录仍不在门禁扫描语料内(约 4200 处位号噪声,位号类型识别未做前不纳入)。" + }, + "N-03b": { + "to": null, + "status": "void", + "note": "报告 N-03b(IWDG / `configASSERT` / 两个钩子 / 4 个 Fault 现场)——属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除。现行去处:docs/子系统设计/看门狗设计说明.md §4.4、§10.1/§10.2 + AGENTS.md「平台约束」" + }, + "N-10": { + "to": null, + "status": "void", + "note": "报告 N-10(UI accept 门控)——属主文档 2026-10-25 已删除。现行去处:docs/UI设计/RemoDispBus协议与接收设计说明.md §3、docs/子系统设计/看门狗设计说明.md §11.4;实施代码 Drivers/BSP/UI/ui_net_sink.c" + }, + "N-11": { + "to": null, + "status": "void", + "note": "报告 N-11(NAND 直 DMA 调用方缓冲 / CCM 迁移硬边界,登记簿曾用 N-26)——属主文档 2026-10-25 已删除。现行去处:docs/内存管理/内存内容分配策略.md §3 + §4 规则 R1~R4 + §8;代码三层 = gd5f2gq5ue.h 编译期窗口断言 → nand_ftl.c 启动期自检 → gd5f_dma_buf_ok() 运行时强制" + }, + "N-12": { + "to": null, + "status": "void", + "note": "报告 N-12(dhara 移植层 `is_free` 整页精度,登记簿曾用 N-21)——属主文档 2026-10-25 已删除。现行去处:docs/架构设计/STM32F4-Base存储架构说明.md §5.3 + 主机侧单测 test/host/nand_port/(含「旧算法只看页首 64 B」的对照用例)" + }, + "N-13": { + "to": null, + "status": "void", + "note": "报告 N-13(移植层 HAL 越界守卫 + `DHARA_E_CORRUPT_MAP`,登记簿曾用 N-21)——属主文档 2026-10-25 已删除。现行去处:docs/架构设计/STM32F4-Base存储架构说明.md §5.3 + Drivers/BSP/GD5F2GQ5UE/nand_ftl.c 的 `ftl_page_in_range` / `ftl_block_in_range` 注释" + }, + "N-20": { + "to": null, + "status": "void", + "note": "登记簿 N-20 = 报告 N-03c(`Error_Handler` 死循环统一降级),2026-10-15 销项删行。结论去处:docs/子系统设计/看门狗设计说明.md §4.4(含 `__builtin_return_address` 不可用的实证)+ Src/main.c 的 `USER CODE Error_Handler_Debug` 区注释" + }, + "N-21": { + "to": null, + "status": "void", + "note": "本号两义,均已死:① 登记簿 N-21 = 报告 N-12/N-13(dhara 移植层两条硬约束),2026-10-15 销项删行 → docs/架构设计/STM32F4-Base存储架构说明.md §5.3;② 报告 N-21(时钟/对时,已闭环)→ docs/编号规范.md §4.5。存量引用几乎都是①" + }, + "N-24": { + "to": null, + "status": "void", + "note": "登记簿 N-24 = 报告 N-16(日志读写放大:写侧合并 open/write/close + 读侧 8 条滑动窗口),2026-10-15 销项删行。结论去处:docs/子系统设计/运行与自检记录设计说明.md §4.4/§4.5 + App/log/sys_log_mcu.c 的 `s_format_rec` / `s_append_rec` / `s_append_many` / `s_read_raw` 注释" + }, + "N-26": { + "to": null, + "status": "void", + "note": "登记簿 N-26 = 报告 N-11(DMA 可达性三层防线 + 规则族 R1~R4),2026-10-15 销项删行。结论去处:docs/内存管理/内存内容分配策略.md §3/§4/§8 + Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h 的窗口断言块;负路径用例 TC-GD5F-704/705" + }, + "S-1": { + "to": null, + "status": "void", + "note": "本号两义,均已死:① 登记簿 S-1(defaultTask 栈余量 3664B/4096 ≈10%,2026-10-04 登记),2026-10-10 削链销项 → 复测见 docs/内存管理/RAM使用分析与优化方案.md §4 阶段 0「不抬栈」小节;② 报告 S-1(分层反向依赖 BSP include App 的头)→ docs/门禁说明/layer-deps.md 与 docs/编号规范.md §4.5。存量引用几乎都是①" + }, + "S-2": { + "to": null, + "status": "void", + "note": "本号两义,均已死:① 登记簿 S-2(启动日志固化流程,2026-09-22 提出、2026-10-05 固化后销项)→ docs/测试说明/boot_log_data/README.md;② 报告 S-2(跨模块裸 `extern`,2026-10-22 已闭环)→ 契约见 App/task/task_handles.h、gd5f_spi1_notify_*、net_msg_queue_adopt" } }, "id_aliases": {} diff --git a/scripts/id_known_backlog.json b/scripts/id_known_backlog.json index 6296a8d9..8eecdcbf 100644 --- a/scripts/id_known_backlog.json +++ b/scripts/id_known_backlog.json @@ -1106,66 +1106,6 @@ "literal": "gen 45", "count": 1 }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 2, - "literal": "W1-0", - "count": 1 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P1-10", - "count": 3 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-10", - "count": 2 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-13", - "count": 1 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-14", - "count": 1 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-15", - "count": 1 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-5", - "count": 2 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-6", - "count": 1 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-8", - "count": 2 - }, - { - "file": "docs/问题记录/项目审查与优化建议报告.md", - "code": 6, - "literal": "P2-9", - "count": 2 - }, { "file": "scripts/README.md", "code": 6, diff --git a/scripts/id_registry.json b/scripts/id_registry.json index b65f5c36..d7b121ea 100644 --- a/scripts/id_registry.json +++ b/scripts/id_registry.json @@ -1,7 +1,7 @@ { "schema": 1, "generated_from": "docs/编号规范.md §4 编号空间总表(§4.1 在册 / §4.2 目标 / §4.3 冻结 / §4.4 划界)+ §6 模块码表 + §7 迁移映射。游标取「规范记载值」与「全库实测最大号」的较大者,实测偏差一律写进 cursor_note,不凭印象编。", - "decidable_ratio_baseline": 82.6, + "decidable_ratio_baseline": 84.0, "spec_docs": [ "docs/编号规范.md" ], @@ -351,7 +351,7 @@ "title": "里程碑目标形态 MS-(§4.2;存量 M1~M3)", "pattern": "\\bMS-[0-9]{1,2}\\b", "owner_docs": [ - "docs/任务规划/W1-采集保护收尾.md" + "docs/任务规划/采集保护收尾.md" ], "scope": "global", "frozen": false, @@ -688,7 +688,7 @@ "pattern": "\\bB[0-9]{1,2}\\b", "owner_docs": [ "docs/任务规划/README.md", - "docs/任务规划/W1-采集保护收尾.md", + "docs/任务规划/采集保护收尾.md", "docs/任务规划/排期详述.md" ], "scope": "global", @@ -757,7 +757,7 @@ "title": "里程碑 M1~M3(§4.2 目标 MS-;存量冻结)", "pattern": "\\bM[1-3]\\b", "owner_docs": [ - "docs/任务规划/W1-采集保护收尾.md", + "docs/任务规划/采集保护收尾.md", "docs/任务规划/README.md" ], "scope": "global", @@ -904,15 +904,15 @@ { "name": "N-RPT", "class": "N-RPT", - "title": "《项目审查与优化建议报告》自有编号 N-xx(§4.3 冻结历史快照)", + "title": "《项目审查与优化建议报告》自有编号 N-xx(原属主文档 2026-10-25 已删;登记处迁 §4.5,§4.3 冻结历史快照)", "pattern": "\\bN-[0-9]{1,3}[a-z]?\\b", "owner_docs": [ - "docs/问题记录/项目审查与优化建议报告.md" + "docs/编号规范.md" ], "scope": "doc-scoped", "frozen": true, "cursor": null, - "check_dangling": true, + "check_dangling": false, "dangling_outside_owner": "warn", "adjacent_required": true, "adjacent_cues": [ @@ -922,20 +922,21 @@ "collides_with": "N", "cursor_note": "⚠ 与登记簿 N-x 同名不同义(§4.3 / AGENTS.md 模块约定)→ 引用必须紧邻「报告」或报告文档名", "snapshot_only": true, - "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走" + "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走", + "owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇" }, { "name": "D-RPT", "class": "D-RPT", - "title": "报告自有编号 D-x(§4.3 冻结历史快照)", + "title": "报告自有编号 D-x(原属主文档 2026-10-25 已删;登记处迁 §4.5,§4.3 冻结历史快照)", "pattern": "\\bD-[0-9]\\b", "owner_docs": [ - "docs/问题记录/项目审查与优化建议报告.md" + "docs/编号规范.md" ], "scope": "doc-scoped", "frozen": true, "cursor": null, - "check_dangling": true, + "check_dangling": false, "dangling_outside_owner": "warn", "adjacent_required": true, "adjacent_cues": [ @@ -944,20 +945,21 @@ ], "collides_with": "D", "snapshot_only": true, - "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走" + "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走", + "owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇" }, { "name": "S-RPT", "class": "S-RPT", - "title": "报告自有编号 S-x(§4.3 冻结历史快照)", + "title": "报告自有编号 S-x(原属主文档 2026-10-25 已删;登记处迁 §4.5,§4.3 冻结历史快照)", "pattern": "\\bS-[0-9]\\b", "owner_docs": [ - "docs/问题记录/项目审查与优化建议报告.md" + "docs/编号规范.md" ], "scope": "doc-scoped", "frozen": true, "cursor": null, - "check_dangling": true, + "check_dangling": false, "adjacent_required": true, "adjacent_cues": [ "报告", @@ -965,20 +967,21 @@ ], "collides_with": "N", "snapshot_only": true, - "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走" + "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走", + "owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇" }, { "name": "R-RPT", "class": "R-RPT", - "title": "报告自有编号 R-x(§4.3 冻结;内存优化项)", + "title": "报告自有编号 R-x(原属主文档 2026-10-25 已删;登记处迁 §4.5,§4.3 冻结;内存优化项)", "pattern": "\\bR-[0-9]{1,2}\\b", "owner_docs": [ - "docs/问题记录/项目审查与优化建议报告.md" + "docs/编号规范.md" ], "scope": "global", "frozen": true, "cursor": "R-9", - "check_dangling": true, + "check_dangling": false, "adjacent_required": true, "adjacent_cues": [ "报告", @@ -986,27 +989,29 @@ ], "cursor_note": "实测现存至 R-9(2026-10-15 落地);§1.2 记「R1=风险、R-2=内存优化项」同字母歧义", "snapshot_only": true, - "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走" + "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走", + "owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇" }, { "name": "F-RPT", "class": "F-RPT", - "title": "报告自有编号 F-x(§4.3 冻结历史快照)", + "title": "报告自有编号 F-x(原属主文档 2026-10-25 已删;登记处迁 §4.5,§4.3 冻结历史快照)", "pattern": "\\bF-[0-9]{1,2}\\b", "owner_docs": [ - "docs/问题记录/项目审查与优化建议报告.md" + "docs/编号规范.md" ], "scope": "global", "frozen": true, "cursor": null, - "check_dangling": true, + "check_dangling": false, "adjacent_required": true, "adjacent_cues": [ "报告", "审查" ], "snapshot_only": true, - "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走" + "snapshot_note": "§4.3 冻结历史快照:只在引用写了文档名(紧邻线索)时参与定族,不参与「定义位优先」——避免同号把活登记处接管走", + "owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇" }, { "name": "A-AUDIT", @@ -1210,10 +1215,9 @@ { "name": "U-RPT", "class": "U", - "title": "报告 UI 标准化簇 U1~U5(§4.3 冻结历史快照)", + "title": "报告 UI 标准化簇 U1~U5(原属主文档 2026-10-25 已删;排期见 README §2.0 / 登记簿 U 簇,§4.3 冻结历史快照)", "pattern": "\\bU[1-5]\\b", "owner_docs": [ - "docs/问题记录/项目审查与优化建议报告.md", "docs/任务规划/README.md", "docs/任务规划/登记簿.md" ], @@ -1223,7 +1227,8 @@ "cursor_owner_only": true, "check_dangling": false, "dangling_note": "与 UI 状态机 U1~U15、位号 U17 三方同形(§4.4 位号目录已排除)→ 只拦越游标", - "cursor_note": "U1~U5 见报告 §6.5;W6 波次按此推进(docs/任务规划/README.md §2.0)" + "cursor_note": "U1~U5 原见《项目审查与优化建议报告》§6.5(该报告 2026-10-25 已删除);现行排期见 docs/任务规划/README.md §2.0「UI 扩展」与 登记簿 U 簇行", + "owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇" }, { "name": "U-STATE", diff --git a/test/host/iec104_master.py b/test/host/iec104_master.py index f985ab2b..81415364 100644 --- a/test/host/iec104_master.py +++ b/test/host/iec104_master.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """B6 bench leg: IEC 60870-5-104 master client (GI + COV round-trip). -Task card: docs/任务规划/W1-采集保护收尾.md (B6 DoD); protocol baseline: +Task card: docs/任务规划/采集保护收尾.md (B6 DoD); protocol baseline: docs/子系统设计/IEC104上行设计说明.md §3/§4. Constants mirror App/protocol/iec104/iec104_asdu.h / iec104_link.h. @@ -31,7 +31,7 @@ Usage: python iec104_master.py [--ip 192.168.1.100] [--port 2404] [--restore 10.0] B7 bench leg modes (setpoint persistence + global soft plate, task card -docs/任务规划/W1-采集保护收尾.md B7; firmware side App/cfg/prot_set_store.c): +docs/任务规划/采集保护收尾.md B7; firmware side App/cfg/prot_set_store.c): --b7-pre : before reset: mark setpoint 7.5 (C_SE+C_RD), YK12 OFF (two-step) -> low setpoint 0.05 must NOT trip YX16 (plate OUT disables protection); YK12 ON -> YX16 trips (linkage); restore 10.0; diff --git a/test/host/nand_port/run_unit_test.py b/test/host/nand_port/run_unit_test.py index c4a231cf..cefa25eb 100644 --- a/test/host/nand_port/run_unit_test.py +++ b/test/host/nand_port/run_unit_test.py @@ -27,7 +27,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:docs/问题记录/项目审查与优化建议报告.md N-12/N-13(报告 R-3 建议的 +设计依据:原评审报告 N-12/N-13(该报告 2026-10-25 已删除;报告 R-3 建议的 `test/host/dhara/` 移植层单测,落位为 test/host/nand_port/); 创建日期:2026-10-15 """