docs: 裁定——内存优化簇整簇暂缓(R-2 后半 / R-3 / R-4 / R-6)

用户判定"把 LVGL 池与 UI 帧缓冲(现 ≈29.6 KB)搬进 CCM 作为后续
功能预算来源"这个决定不合适,内存优化的事先放一放。据此把这条
主线降级为暂缓,同时明确:不回退已落地的部分,不拆治理面。

报告(docs/问题记录/项目审查与优化建议报告.md):
- §0.2 Top 3 → Top 2:R-2 剩余移出,表下加一条 ⏸ 说明
- §0.3 主线一由"把内存从卡死变富裕"改写为"这条线到此为止"
- §0.4 两条内存条目 🟡/❌ → ⏸ 暂缓
- §5.1 结论段与 §5.2 诊断补"不代表现在要动"
- §5.3 加暂缓横幅:三条理由(没有功能等这块预算 / 搬迁有风险和
  工时 / 收益与代价不对称)+ 保留常开的治理面 + 三条重开条件
- §5.3 表内 R-2 / R-3 / R-4 / R-6 优先级一律 ~~P1/P2~~ → ⏸ 暂缓
- §7 路线图 W3 划掉标暂缓,映射行改为"暂缓期间无验收动作"
- 去处表 R-9 行注明"该簇其余部分已暂缓";变更记录加一条

任务规划:登记簿 N-27 波次 W3 → 暂缓,并写清代价——CCM 只剩
7,904 B、FreeRTOS 堆实测 min_ever 8,464 B,**加任务 / 抬栈 / 加堆
会先在这里撞墙**,届时 mem-budget 会先报警,那就是重开信号。
README §1 结构/健壮性 7 → 6、暂缓块 1 簇 → 2 簇、§2.0 第 3 条
订正(顺带修掉旧值 ≈8,160 B → 实测 7,904 B)、W3 行与 §2.1 链路
图标暂缓、§3 暂缓规则推广到"只在原处标注"的簇。**W3 槽位保留
不重编号**,避免全库改 W4~W7 引用。

内存管理三篇:RAM预算台账 §2 把 UI 超配额改判为"已知长期挂账"
(R-2 暂缓后这条 ⚠ 会一直挂着,别每轮当新问题追)、§3 解锁链标
暂缓并去掉"← 现在卡在这一步";RAM使用分析 §4 加实施状态横幅
(测量与长效机制常开 / 已落地不回退 / 1.2、1.3、2.2、2.3 与 8KB
试探暂缓)、§5 加"别拿目标列当现状"、§6 S5 补 ✅ 2026-10-15、
S6/S7/S8 改暂缓、S9 台账门禁补 ✅、1.5 里"缓冲已迁 CCM"订正为
"实际仍在 SRAM1";存储栈RAM优化调研加同款横幅(P0-2 / P1-5 /
第三步)。

校验:check_doc_links --all 通过(142 文档、无法判定 0);
check_mem_numbers 与 .map 一致;6 个文件无 BOM/CRLF/U+FFFD。
纯文档改动,不涉及代码与构建,故未跑 @build / @test。
This commit is contained in:
2026-10-15 10:27:02 +08:00
parent ff9fcbd43c
commit 8739faa7fe
6 changed files with 59 additions and 33 deletions
+6 -6
View File
@@ -67,12 +67,12 @@
| 网络 | 4 | N-2(49s 日志静默,**低风险观察项**)· N-3(L5 基线重验)· N-16(A2/A4 负向台架)· N-17(探针窗口心跳缺口) |
| 存储 / 日志 | 3 | **S-3(USART1 TX-only 根治)** · S-4(dhara 重试自旋)· S-5(可选全序列卷锁) |
| 数据正确性 | 1 | **N-21(dhara `is_free`/`copy`,全簿最高风险)** |
| 结构 / 健壮性 | 7 | N-22(写回 flush)· N-23(注册校验残余白名单)· N-24(日志逐条开关)· N-25(性能/语义簇)· N-27(内存优化簇,三件套 ✅ 前半落地)· N-28(Flash 死代码簇)· **N-33(栈余量收口,W1)** |
| 结构 / 健壮性 | 6 | N-22(写回 flush)· N-23(注册校验残余白名单)· N-24(日志逐条开关)· N-25(性能/语义簇)· N-28(Flash 死代码簇)· **N-33(栈余量收口,W1)** |
| 仓库 | 1 | N-29(`.git` **235 MB**,**已决策暂不处理、登记观察**) |
| 硬件 | 1 | N-18(V0.2 改版项) |
| 测试 / 基础设施 | 6 | T-7(CI runner + 推送闭环 + 第二机交叉验证)· S12(断言宏)· S1-c(可选单测)· A-4(采集链路测试约束,RS485 侧随 B2 暂缓)· A-5 残余(CI 体积门禁盲区)· D7(串口助手 A6/A7 待 CH340) |
| UI | 1 簇 | U 簇(27 页标准化,**本轮不排期**) |
| **暂缓** | 1 簇 | **B2 RS-485 整簇(2026-10-12 用户决定,`暂缓-RS485.md`)** |
| **暂缓** | 2 簇 | **B2 RS-485 整簇**(2026-10-12 用户决定,`暂缓-RS485.md`)· **N-27 内存优化簇剩余部分**(2026-10-15 用户裁定:R-2 后半 / R-3 / R-4 / R-6 不排期,理由与重开条件见 `../问题记录/项目审查与优化建议报告.md` §5.3;**已落地的 R-9 与 `mem-budget` 门禁、台账、趋势、观测不回退也不暂缓**) |
> **网络侧 E-xx 存量项**(历史编号族,属主文档已于 2026-10-15 删除,编号冻结见
> `docs/编号规范.md` §4.3):E-25 / E-27 / E-28 挂 C1(net 层跨上下文收口,见 `排期详述.md` §1);
@@ -84,7 +84,7 @@
1. **用户决定(2026-10-12):先把 ADC 采集、保护等相关功能完成**——"转发 + 保护"两环代码已落地(B4/B5,2026-10-12),但**尚未台架闭环、功能面不完整**(定值不落盘、无频率保护、无动作记录/SOE、栈安全线两处 FAIL)。新 W1 = 采集→相量→保护→上送链路的**收尾与闭环**(B6~B10 + N-33,见 `W1-采集保护收尾.md`),其余波次顺延。**RS-485 对下采集(B2)按用户决定暂缓(2026-10-12,`暂缓-RS485.md`),主线不再等它**。
2. **数据正确性最高风险 = N-21**(dhara `is_free` 只查页首 64 B / `copy` 不处理哨兵):低概率、后果重(数据丢失),且至今只能靠人工读代码发现——修复须配主机侧移植层测试(一并补报告"覆盖率"缺口)。
3. **内存预算红线已机械化(2026-10-12,W1-0)**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势基线 → `docs/内存管理/RAM预算台账.md`;实际优化 R-9→R-2 排 W3(**B5 堆扩容 48→56 KB 后 CCM 只剩 ≈8,160 B**,解锁链见 `docs/内存管理/RAM预算台账.md` §3)。
3. **内存预算红线已机械化(2026-10-12,W1-0)**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势基线 → `docs/内存管理/RAM预算台账.md`。实际优化只做了 **R-9(2026-10-15 落地,SRAM1 74.9% → 56.1%)**;**R-2 后半与 R-3 / R-4 / R-6 已按用户裁定 2026-10-15 整簇暂缓**(当前 CCM 只剩 **7,904 B**,重开条件见 `../问题记录/项目审查与优化建议报告.md` §5.3)——**门禁与台账继续常开,它们正是"何时该重开"的传感器**。
4. **验证债仅剩窗口性事项**(D2/D5/D6/D7 + P1-10 收尾),不单独排期、逢窗口顺手做。
---
@@ -102,7 +102,7 @@
|---|---|---|
| **W1 采集+保护收尾** | **里程碑制 + 并行道**:M1 台架闭环 ✅ 达成(B6 ✅→N-33 ✅)∥ M2 功能面(代码道 B7 ✅→{B8∥B9})→ M3 送检(B10,Fixed Date)——任务卡/判据/写范围见 `W1-采集保护收尾.md` | **用户决定(2026-10-12):先把 ADC 采集、保护等相关功能完成**。B4/B5 代码已落地但未台架闭环、功能面不完整(定值不落盘 / 无频率保护 / 无动作记录 / 栈两处 FAIL)——本波收口到"可用 + 可验收";真约束只有**台架**与**送检窗口**两个稀缺资源,其余任务按写范围切分并行 |
| **W2 数据正确性** | **N-21** dhara `is_free`/`copy`(报告 N-12/13) | 低概率、后果重(数据丢失);修复须配主机侧移植层测试,一并补报告"覆盖率"缺口 |
| **W3 预算与内存** | **N-27 后半**:~~R-9 池 40→16 KB~~ ✅(2026-10-15)→ **缩堆 56→32 KB** → R-2 后半(**29.5 KB→CCM**)→ R-3/R-4/R-6 逐项评估(**R-5 已判定不可行**,见 `登记簿.md`) | **R-9 已落地**:SRAM1 由 74.9% 降到 **56.1%**,待迁体量 54,146 → **29,570 B**;**瓶颈换到 CCM——只剩 7,904 B**(56 KB 堆),⚠ B5 是反向扩容,缩回 32 KB 前必须重跑 `stack_report.py` + 上板 `min_ever` 复测(解锁链见 `docs/内存管理/RAM预算台账.md` §3) |
| **W3 预算与内存** | ⏸ **整簇暂缓**(用户裁定 2026-10-15):~~缩堆 56→32 KB → R-2 后半(29.5 KB→CCM)→ R-3 / R-4 / R-6 逐项评估~~。本簇已落地的只有 **R-9 ✅(2026-10-15)**;R-5 已判定不可行 | **不再排期**:没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测。**W3 槽位保留、不重编号**(避免全库改 W4~W7 引用)。重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3 |
| **W4 结构债** | **C6(S-3)→ C3(N-2+N-24)→ C1 net 层跨上下文收口 → C5(含 N-23 残余)→ N-22/N-25/N-28**(详表 `排期详述.md` §1) | 无紧急,按性价比排:C6 灭 IWDG 误复位机制根源;C1 消化 E-25/E-27/E-28(原 ACCEPT+SEND pending 化已收口),体量大、验证重,放后(N-23 钩子已落地 2026-10-12,残余并入 C5) |
| **W5 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · D7 串口助手 · S12 · S1-c · A-5(详表 `排期详述.md` §2) | 窗口性,逢机顺带,不单独排期 |
| **W6 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5);**本轮不排期(2026-10-11 已确认)** |
@@ -118,7 +118,7 @@ W1 收尾 台架道: B6✅→N-33✅(M1 ✅ 2026-10-12) ∥ 代码道: B7✅
↓
W2 数据 N-21 dhara is_free/copy(配主机侧移植层测试)
↓
W3 预算 R-9 池瘦身 ✅ → 缩堆 56→32KB → R-2 后半(29.5KB→CCM)→ R-3/R-4/R-6 评估
W3 预算 ⏸ 整簇暂缓(2026-10-15 用户裁定);R-9 池瘦身 ✅ 已落地不回退
↓
W4 结构 C6(S-3) → C3(N-2/N-24) → C1 net 层跨上下文收口 → C5(含 N-23 残余) → N-22/25/28
↓
@@ -145,7 +145,7 @@ W7 仓库 N-29 .git 149MB(已决策暂不处理) 硬件:N-18 V0.2
- **引用审查报告编号一律带文档名**(报告 N-16 ≠ 登记簿 N-16、报告 S-3 ≠ 登记簿 S-3);
报告并轨项用本登记簿新编号(N-19~N-29 + U 簇),出处列保留报告编号。
- **§2 是全项目唯一的推进顺序权威**:`产品需求设计文档.md` 等文档中的路线图只留指针,顺序变更只改 §2.0(详表文件跟着挪,不改顺序)。
- **暂缓块(`暂缓-RS485.md`)不是销项**:条目仍在簿,只是不占波次;重启或关闭时更新该文件与 §1/§2.0。
- **暂缓不是销项**:条目仍在簿,只是不占波次。有独立清单文件的(`暂缓-RS485.md` = B2)重启或关闭时更新该文件与 §1/§2.0;**只在原处标注的**(N-27 内存优化簇,2026-10-15 用户裁定,理由与重开条件挂在 `../问题记录/项目审查与优化建议报告.md` §5.3)重启时改 `登记簿.md` 该行 + 本文件 §1/§2.0 三处。
- 新增发现按既有惯例分流:能立即修的进 §2 波次(W4 C5);需排期的进 `登记簿.md` / `测试与架构专项.md` 对应编号空间;跨版本观察的进 `登记簿.md`。
- 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、
`测试说明/实机测试实施指南.md`(执行流程)——两者均不在本文件夹合并范围。
+1 -1
View File
@@ -46,7 +46,7 @@
| N-23 残余 | **钩子已落地**(2026-10-12 `registration-check` 挂 pre-commit,存量缺口走 `KNOWN_GAPS` 白名单只 WARN);**残余** = 白名单只剩 `rs485_task.c` 一条**刻意**缺口(E-59 门禁下随 B2 暂缓,见 `暂缓-RS485.md`);`app_cfg.h` 未接线开关(C5)。⚠ `lftpd_log.c` 已随 N-19 删除并入 `lftpd_auth.c`(2026-10-11),不再是缺口 | 白名单不清 = "写了不编译"盲区仍在 | 随 B2 一并出白名单(`--strict` 供审计复跑);开关随 C5 处置 | W4(C5) | 报告 N-06 残余 + 报告 S-3 |
| N-24 | 日志每条 `f_open+f_write+f_close`(`sys_log_mcu.c:123-140`) | 每条日志 2–4 次 NAND 页读写;UI 翻记录逐条 open/seek/close | 与 C3 日志管线合并评估(现仅 `FIL` static 化省 528 B 栈) | W4 | 报告 N-16(**≠ 本登记簿 N-16**) |
| N-25 | 性能/资源建议簇:PASV 每次新建监听;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(**DE 项随 B2 暂缓,见 `暂缓-RS485.md`**)。⚠ 原列的 `NET_RECV_TIMEOUT_MS 30000` 已随 2026-10-13「recv 语义主流化」删除(挂起 recv 模型),不再是待办 | 次级性能/语义一致性 | 逐项见 `../问题记录/项目审查与优化建议报告.md` §4.2/§4.7,随窗口评估 | W4 | 报告 N-09/PHY/P3-x/rs485 |
| N-27 | **内存优化簇**:**R-9 ✅ 已落地(2026-10-15)**——`LV_MEM_SIZE` 40→16 KB → SRAM1 由 74.9% 降到 **56.1%(余 57,504 B)**;待迁 CCM 体量随之由 54,146 B 降到 **29,570 B**,而 CCM 只剩 **7,904 B**(`RW_CCM` 上限 65,280 − 57,376) | R-2 后半段(迁 CCM)**只差"缩堆"一步**:堆 56→32 KB 可腾 24 KB → CCM 余 ≈31.9 KB ≥ 29,570 B。⚠ 2026-10-12 B5 是**反向**扩容至 56 KB(9 任务栈 + 队列实测需要),缩回前必须重跑 `stack_report.py` + 上板 `min_ever` 复测 | **三件套 ✅ 2026-10-12 落地**(`ram_baseline.py` 四模式 + `ram_baseline.tsv` 趋势 + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子 92% 门禁)→ **R-9 ✅ 2026-10-15**(实测峰值 6,568 B = 池的 40%,水位表见 `../内存管理/RAM使用分析与优化方案.md` §2.6.2)→ **W3** 缩堆 → R-2 后半;R-3/R-4/R-6 逐项评估(R-6 前置已满足)。⚠ **R-5 已判定不可行、从本簇剔除**:CMSIS-RTOS2 `freertos_os2.h` 有 `#if (configMAX_PRIORITIES != 56) #error`,改小直接编译失败(为 480 B 改第三方包装层不划算) | **W3** | 报告 R-2 剩余/R-3/R-4/R-6/§5.5 |
| N-27 | **内存优化簇**:**R-9 ✅ 已落地(2026-10-15)**——`LV_MEM_SIZE` 40→16 KB → SRAM1 由 74.9% 降到 **56.1%(余 57,504 B)**;待迁 CCM 体量随之由 54,146 B 降到 **29,570 B**,而 CCM 只剩 **7,904 B**(`RW_CCM` 上限 65,280 − 57,376) | ⏸ **整簇暂缓(用户裁定 2026-10-15)**:R-2 后半(缩堆 56→32 KB → 迁 CCM)与 R-3 / R-4 / R-6 **不再排期**——没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测,收益不抵风险与工时。⚠ 代价落在"以后加任务 / 抬栈 / 加堆"那一刻:CCM 只剩 7,904 B、FreeRTOS 堆实测 `min_ever` 8,464 B,届时 `mem-budget` 会先报警 → 按报告 §5.3 重开条件评估 | **三件套 ✅ 2026-10-12 落地**(`ram_baseline.py` 四模式 + `ram_baseline.tsv` 趋势 + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子 92% 门禁)→ **R-9 ✅ 2026-10-15**(实测峰值 6,568 B = 池的 40%,水位表见 `../内存管理/RAM使用分析与优化方案.md` §2.6.2)→ **⏸ 其余整簇暂缓**(2026-10-15 裁定;理由与重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3)。⚠ **R-5 已判定不可行、从本簇剔除**:CMSIS-RTOS2 `freertos_os2.h` 有 `#if (configMAX_PRIORITIES != 56) #error`,改小直接编译失败(为 480 B 改第三方包装层不划算) | **暂缓** | 报告 R-2 剩余/R-3/R-4/R-6/§5.5 |
| N-28 | Flash 死代码评估簇:剩余 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个空 LVGL TU(F-1/F-2/F-3 已闭环,省的是编译时长) | 编译时长 + 文档噪音 | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制必经路径,**不可盲关** | W4 | 报告 F-4/F-5/F-6 |
| N-29 | **仓库膨胀**:`.git` **235.3 MB**(2026-10-14 实测;本行建档时记 149 MB)+ 手册图片 36.3 MB(受控文件合计仅 79.3 MB,`.git` 已是它的 3 倍) | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**(三项都不解决历史膨胀)。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(届时未推送提交更少、重写代价最低) | **W7** | 报告 D-1 |
| U 簇 | UI 标准化:无令牌层/组件库/页注册表(手写 `case` 仍在),**27 页**未落地;golden 未挂 pre-commit、字符集差集检查仍是约定 | 新增一页成本仍是 8 处手工改动 | 按 `../问题记录/项目审查与优化建议报告.md` §6.5:U4 残余(两脚本入门禁,可逢窗口顺带)→ U1 令牌层 → U2/U3 → 页面落地;U4 golden 可直接当 U1 验收工具。**已确认(2026-10-11):本轮不排期**,等功能主线出结果后按产品需求启动 | W6 | 报告 U1~U5 |
@@ -231,6 +231,14 @@
## 4. 方案
> ⏸ **实施状态(用户裁定 2026-10-15)**——本节的"阶段/天数"是当初的排期设想,现在按下面口径执行:
>
> - **保持常开**:阶段 0 的测量能力 + 阶段 3 的长效机制(`mem-budget` 92% 门禁、`RAM预算台账.md` 受管区、`ram_baseline.tsv` 趋势、`[STACK]` 水位与 `stack_report.py` / `ram_report.py`)。它们已落地、零维护成本,且正是"何时该重开优化"的传感器。
> - **已落地的优化不回退**:1.1 LVGL 池 40→16 KB(✅ 2026-10-15,SRAM1 74.9% → **56.1%**)、1.4 lftpd 大栈局部变量改静态(✅ 2026-09-21)。
> - **整簇暂缓、不再排期**:1.2 启用 CCM 承载 UI 侧缓冲、1.3 任务栈按实测缩减、2.2 缩减 `configTOTAL_HEAP_SIZE`、2.3 任务/队列全静态化,以及把池进一步试到 8 KB。
>
> **暂缓理由与重开条件** → `../问题记录/项目审查与优化建议报告.md` §5.3。一句话:**当前没有功能在等这块预算**,而搬迁要动 scatter、要逐条过 DMA 可达性清单(违例是静默传错不是报错)、缩堆还得上板复测 `min_ever`——收益不抵风险与工时。下面各节**保留作重开时的实施依据,不代表现在要做**。
### 阶段 0:建立测量能力(先做,1~2 天)
> 原则:没有数据不动刀。本阶段全部是"只增不减"的改动,零功能风险。
@@ -509,7 +517,7 @@ ISR 余量:该任务运行期间可能被中断打断的最深中断链(SPI/
#### 1.5 其他小项
- `Lib/FatFs/ffconf.h:32` `FF_FS_TINY` 0→1(每打开文件省 512B 扇区窗;FAT32 适用;`FF_FS_REENTRANT=0` 现状下安全)
- `ui_net_sink`(PC 远程显示,6.4KB):加 `APP_UI_NET_SINK` 编译开关,产品固件可关;保留时缓冲已迁 CCM(1.2)
- `ui_net_sink`(PC 远程显示,6.4KB):加 `APP_UI_NET_SINK` 编译开关,产品固件可关;保留时缓冲随 1.2 迁 CCM(⏸ **1.2 已暂缓,实际仍在 SRAM1**)
- `CH395F_TCP_MSS=1024` 已是压缩值,DMA 缓冲 `MSS×2+4` 为协议决定,不动
### 阶段 2:堆与动态分配治理(1~2 天)
@@ -549,6 +557,8 @@ ISR 余量:该任务运行期间可能被中断打断的最深中断链(SPI/
> 已落地项(不再计入预期):1.2 堆迁 CCM(2026-09-21)、1.4 lftpd 静态化、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` 受管区为准**,不要拿本表"目标"列当现状。
## 6. 实施顺序与验证
@@ -558,11 +568,11 @@ ISR 余量:该任务运行期间可能被中断打断的最深中断链(SPI/
| S2 | 0.3 `ram_report.py` + 基线 | 脚本输出与 map 人工核对一致 | ✅ 2026-09-21(`data/ram_report_20260921.md`) |
| S3 | 全功能回归跑数(菜单/FTP/网络/格式化/浸泡 1h) | 拿到各任务 `free_min` 与堆 free 底值 | ◐ boot + FTP 路径已实测(09-21);全菜单遍历 + 1h 浸泡待补 |
| S4 | 1.4 lftpd 静态化 + 2.1 malloc 修复 | FTP STOR/RETR 大文件 + 长路径回归 | ✅(2.1 于 2026-09-10、1.4 于 2026-09-21 完成) |
| S5 | 1.1 LVGL 池 40K→16K | UI 全量回归(模拟器 + 实机),无断言失败 | 待办 |
| S6 | 1.2 CCM(scatter + section + 门禁宏) | map 显示 `RW_CCM`;关 `APP_CCM_ENABLE` 也能编译通过 | ◐ `RW_CCM` + 堆迁入已完成(09-21);缓冲 section 迁移与门禁宏待办 |
| S7 | 1.3 栈缩减(按 S3 数据)+ 复测 | 每任务 `free_min ≥ 新栈×30%`,无溢出钩子触发 | 待办(目标值已按 09-21 实测修正) |
| S8 | 2.2 堆 48K→32K + 复测 | 全负载 `heap free ≥ 8KB` | 待办 |
| S9 | 1.5 小项 + 台账/门禁/AGENTS.md | `@build` + `@test` 全绿 | ◐ AGENTS.md 内存条目已增补(09-21);台账/门禁待办(§3) |
| S5 | 1.1 LVGL 池 40K→16K | UI 全量回归(模拟器 + 实机),无断言失败 | ✅ **2026-10-15**(11 页黄金参考 + 池水位 5,448 B + `@test` 真机 `used=3192`;实测峰值 6,568 B = 池的 40%,§2.6.2) |
| S6 | 1.2 CCM(scatter + section + 门禁宏) | map 显示 `RW_CCM`;关 `APP_CCM_ENABLE` 也能编译通过 | ⏸ **暂缓(2026-10-15 裁定)**;已完成部分仅 `RW_CCM` + 堆迁入(09-21),缓冲 section 迁移与门禁宏不再排期 |
| S7 | 1.3 栈缩减(按 S3 数据)+ 复测 | 每任务 `free_min ≥ 新栈×30%`,无溢出钩子触发 | ⏸ **暂缓(2026-10-15 裁定)**(目标值已按 09-21 实测修正,重开时可直接用) |
| S8 | 2.2 堆 48K→32K + 复测 | 全负载 `heap free ≥ 8KB` | ⏸ **暂缓(2026-10-15 裁定)**;⚠ 2026-10-12 B5 反向扩容至 56 KB,重开时须重跑 `stack_report.py` + 上板 `min_ever` |
| S9 | 1.5 小项 + 台账/门禁/AGENTS.md | `@build` + `@test` 全绿 | ◐ AGENTS.md 内存条目已增补(09-21);台账 / 趋势 / `mem-budget` 三件套 ✅ 2026-10-12(**常开,不受暂缓影响**) |
每步都必须 `@build` 通过(0 错误 0 警告)后再进入下一步;涉及 UI 的步骤用 `simulator` 先过一遍再上实机。
+6 -5
View File
@@ -56,9 +56,10 @@ UI 16 KB / RTOS 堆 56 KB / 应用 8 KB**。归集口径(按 `.map` 对象名
**现状判读(2026-10-12 建档)**:
- **UI ⚠ 超配额 = W3 的既有债务,不是新增违规**:LVGL 池 16 KB(R-9 已于 2026-10-15 落地,由 40 KB 收缩)+ 帧/远显缓冲
≈12.8 KB(R-2 目标迁 CCM)——配额 16 KB 描述的是 **R-9/R-2 落地后的目标态**(排期见
`docs/任务规划/README.md` §2 W3)。
- **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 W3 已标暂缓)→
**这条 ⚠ 会长期挂着**,判读时按已知挂账处理,别每轮当新问题追;重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3。
- **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
@@ -71,8 +72,8 @@ 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 后半解锁链 | ① **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` §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 → 迁入 | **顺序不可颠倒**;每步前后跑 `stack_report.py` / `ram_report.py`(铁律) |
| 现余量 | 受管区 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` §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`(铁律) |
| 迁入前置 | 目标缓冲必须过 DMA 可达性清单(`内存内容分配策略.md`) | 违例 = 静默传错(N-11 同类坑);克隆芯片 CCM 可靠性风险见 `docs/内存管理/RAM使用分析与优化方案.md` §7 |
## 4. 趋势基线(`scripts/ram_baseline.tsv`)
@@ -4,6 +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;本文保留作重开时的实施依据,**不代表现在要做**。
## 1. 现状约束(不变,是下述全部方案的依据)
@@ -26,25 +26,26 @@
| 项目结构 | **A−** | 六层分层真实可执行、命名一致、门禁到位;反向依赖控制在 4 处 | `NETCFG`/`UI` 语义层错位(S-1)、4 处裸 `extern`(S-2)、`rs485_task.c` 仍在注册白名单里等 B2 |
| 文档分布 | **A−** | 工程文档 **87 篇 / 30,781 行**(2026-10-15 随 `错误码传播审计.md` 删除而 −1 篇 / −635 行),`docs/README.md` 索引 + `docs/文档规范.md` + 三档一致性门禁全部落地,`check_doc_links --all` = 0 失效 | **D-1**:`docs/` 占仓库 **71.8%**、手册图片 **36.3 MB**、`.git` 已 **235 MB**(已决策暂不处理,登记观察) |
| 模块设计 | **A−** | 看门狗(IWDG + 心跳位图 + 4 个 Fault 现场 + `.noinit`)、就绪屏障、卷锁、FTP 鉴权、`Error_Handler` 自恢复、ADC 全链均已落地 | **N-12/N-13** dhara 移植两处缺陷(数据丢失风险)、**N-16** 日志逐条开关、驱动层无统一错误码约定(S-5)、RS485 无协议栈(随 B2 暂缓) |
| 内存使用 | **B+** | 堆迁 CCM + 栈/堆三面观测常开 + `mem-budget` 92% 门禁 + 预算台账与趋势基线;**R-9 已落地(2026-10-15)→ SRAM1 由 74.9% 降到 56.1%(余 57,504 B),不再是卡点** | **瓶颈收敛到 CCM 单点:87.9%、只剩 7,904 B**,而待迁的 LVGL 池 + UI 两份缓冲 = **29,570 B** → R-2 后半只差"缩堆 56→32 KB"这一步(§5.3);MicroLIB 512 B C 堆仍无机械检查(§5.5) |
| 内存使用 | **B+** | 堆迁 CCM + 栈/堆三面观测常开 + `mem-budget` 92% 门禁 + 预算台账与趋势基线;**R-9 已落地(2026-10-15)→ SRAM1 由 74.9% 降到 56.1%(余 57,504 B),不再是卡点** | **内存优化簇已整簇暂缓**(用户裁定 2026-10-15):R-2 后半(待迁 29,570 B → CCM,只差缩堆 56→32 KB)与 R-3 / R-4 / R-6 不再排期,理由与重开条件见 §5.3;**当前真正的约束是 CCM 只剩 7,904 B**——加任务 / 抬栈 / 加堆会先在这里撞墙,届时按 §5.3 重开;MicroLIB 512 B C 堆仍无机械检查(§5.5) |
| Flash 使用 | **A−** | F-1/F-2/F-3 落地省 64,576 B → 占用 **22.0%(231,084 B)** | F-4/F-5/F-6 ≈10 KB + 编译时长(§5.4) |
| UI 标准化 | **B** | golden 回归已建(`simulator/tests/` 四脚本,含池水位门禁) | 无令牌层 / 无组件库 / 无页注册表(手写 `case` 仍在)、**27 页**未落地、golden 与字符集差集未挂门禁(§6) |
### 0.2 未闭环问题(Top 3,2026-10-15)
### 0.2 未闭环问题(Top 2,2026-10-15)
| # | 编号 | 问题 | 影响 | 现状 |
|---|------|------|------|------|
| 1 | **N-12 / N-13**(登记簿 **N-21**,W2) | `dhara_nand_is_free()` 只查页首 64 B(`nand_ftl.c:152-179`);`dhara_nand_copy()` 不处理 `DHARA_NO_PAGE` 哨兵(`:204-216`) | 映射恢复误判 → **数据丢失风险**(低概率、后果重);哨兵页号被当真实页 → 未定义行为 | ❌ 两处原样;至今只能靠人工读代码发现(主机侧无 dhara 移植层测试) |
| 2 | **R-2 剩余**(登记簿 **N-27**,W3) | R-9 已落地(`LV_MEM_SIZE` 40→16 KB,2026-10-15)→ 待迁体量由 54,146 B 降到 **29,570 B**(池 16,384 + `ui_port.o` 6,420 + `ui_net_sink.o` 6,766),SRAM1 由 74.9% 降到 **56.1%** | **CCM 仍只剩 7,904 B**(堆 56 KB 占掉)→ 29.5 KB 还是装不下,R-2 后半段只差"缩堆"一步 | 🟡 下一步 = 堆 56→32 KB(⚠ B5 是反向扩容,缩回前须重跑 `stack_report.py` + 上板 `min_ever` 复测)→ 解锁链 `../内存管理/RAM预算台账.md` §3 |
| 3 | **N-16**(登记簿 **N-24**,W4) | 日志每条记录一次 `f_open + f_write + f_close`(`sys_log_mcu.c:124-141`) | 每条日志 2–4 次 NAND 页读写;UI 翻记录逐条 open/seek/close | ❌ 未办(仅 `FIL` static 化省 528 B 栈) |
| 2 | **N-16**(登记簿 **N-24**,W4) | 日志每条记录一次 `f_open + f_write + f_close`(`sys_log_mcu.c:124-141`) | 每条日志 2–4 次 NAND 页读写;UI 翻记录逐条 open/seek/close | ❌ 未办(仅 `FIL` static 化省 528 B 栈) |
⚠ 另有两条**不在上表但需知晓**:`.git` 已膨胀到 **235 MB**(D-1,§3.1,2026-10-11 决策"暂不处理、登记观察");`rs485_task.c` 仍不在两端构建清单里——**这是 E-59 门禁下的刻意缺口**(随 B2 暂缓),已登记在 `check_registration.py` 的 `KNOWN_GAPS`,不是漏注册。
⏸ **内存优化簇已整簇暂缓**(用户裁定 2026-10-15,原 Top 2 的 R-2 剩余已移出):R-2 后半(把 LVGL 池 + UI 两份缓冲 ≈29.6 KB 搬进 CCM)与 R-3 / R-4 / R-6 不再排期。**已落地的 R-9 与治理面保留常开**(`mem-budget` 92% 门禁、预算台账、趋势基线、栈/堆观测)。理由与重开条件 → §5.3;登记簿 N-27 已标暂缓。
### 0.3 两条主线建议
> **推进顺序的唯一权威是 [`../任务规划/README.md`](../任务规划/README.md) §2**;本节只是体系评审视角的两条结构性建议,不另立顺序。
1. **把内存从"卡死"变"富裕"**:R-9 已把 LVGL 池 40→16 KB(2026-10-15,SRAM1 由 74.9% 降到 56.1%);下一步缩堆腾出 CCM,把 LVGL 池与 UI 帧缓冲(现 **≈29.6 KB**)搬进 CCM,作为后续功能的预算来源(§5.3)。
1. **内存这条线到此为止**(用户裁定 2026-10-15,**覆盖本报告的原建议**):R-9 已把 LVGL 池 40→16 KB、SRAM1 降到 **56.1%(余 57,504 B)**,够用了。原建议的"缩堆腾 CCM → 把 LVGL 池与 UI 帧缓冲(现 ≈29.6 KB)搬进 CCM 作为后续功能预算来源"**整簇暂缓,不再作为主线**——没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还得上板复测,收益不抵风险与工时。**保留的是治理面**(92% 门禁 + 台账 + 趋势 + 栈/堆观测):它会在真正吃紧时自动报警,届时再按 §5.3 的重开条件评估,而不是现在预先腾预算。
2. **把 UI 从"每页手写"变"声明 + 原型库"**:令牌层 → 原型库 → 生成器补全注册 → golden 入门禁,使新增一页的成本从 8 处手工改动降到 1 处声明(§6)。
---
@@ -57,8 +58,8 @@
| 类别 | 编号 | 未闭环内容 | 下一步 |
|------|------|-----------|--------|
| **数据正确性** | **N-12 / N-13** ❌(N-21,W2) | `is_free` 只查页首 64 B;`copy` 不处理 `DHARA_NO_PAGE` | 整页(或首/中/尾)扫描 + 返回 `DHARA_E_UNSUPPORTED` + **必须配主机侧移植层单测** |
| **内存 RAM** | **R-2 剩余** 🟡(N-27,W3) | 待迁体量已由 54,146 B 降到 **29,570 B**(R-9 落地后);CCM 只剩 7,904 B | 只差**缩堆 56→32 KB** 腾 CCM,再迁(解锁链 → `../内存管理/RAM预算台账.md` §3) |
| 内存 RAM | R-3 / R-4 / R-6 ❌(N-27,W3) | 页缓冲未合并 / UI 帧 4 副本 / 栈仍动态 | **R-9 已落地销项**(2026-10-15,SRAM1 74.9%→56.1%,见 §5.3);R-6 前置条件已满足。**R-5 已判定不可行**(§5.3) |
| 内存 RAM | **R-2 剩余** ⏸ **暂缓**(N-27,原 W3) | 待迁体量已由 54,146 B 降到 **29,570 B**(R-9 落地后);CCM 只剩 7,904 B | **用户裁定 2026-10-15:暂不做**——没有功能在等这块预算;重开条件 → §5.3 |
| 内存 RAM | R-3 / R-4 / R-6 ⏸ **暂缓**(N-27,原 W3) | 页缓冲未合并 / UI 帧 4 副本 / 栈仍动态 | **同上裁定,暂不做**。本簇已落地的只有 R-9(2026-10-15,SRAM1 74.9%→56.1%,见 §5.3);**R-5 已判定不可行**(§5.3) |
| 内存 RAM | N-14 🟡(N-22,W4) | 写回缓存无空闲/掉电强制 flush(整页写与换页已 flush) | 空闲 N ms 由 defaultTask flush |
| **Flash** | **F-4 / F-5 / F-6** ❌(N-28,W4) | 剩余可评估 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个 LVGL `.c`(F-2 后均为空 TU,省的是编译时长) | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制的必经路径,**不可盲关** |
| **性能/资源** | N-09 / PHY / P3-x / rs485 DE ❌(N-25,W4) | PASV 每次新建监听;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(DE 项随 B2 暂缓) | 见 §4.2 / §4.7 各行建议 |
@@ -339,7 +340,7 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap
| **CCM(0x10000000,64 KB)** `RW_CCM` | **57,376 B** | 65,280 B | **87.9%(余 7,904 B)** |
| `UNINIT_CCM`(`.noinit` 崩溃现场) | 48 B | 256 B | 18.8% |
> **R-9 已落地(2026-10-15)**:`LV_MEM_SIZE` 40→16 KB → SRAM1 由 98,144 B / **74.9%** 降到 **73,568 B / 56.1%**(−24,576 B,与池缩减量逐字节吻合)。SRAM1 首次从"最紧的一块"变成**余 57.5 KB**;**当前瓶颈换到 CCM(87.9%,只剩 7,904 B)**。
> **R-9 已落地(2026-10-15)**:`LV_MEM_SIZE` 40→16 KB → SRAM1 由 98,144 B / **74.9%** 降到 **73,568 B / 56.1%**(−24,576 B,与池缩减量逐字节吻合)。SRAM1 首次从"最紧的一块"变成**余 57.5 KB**;**当前瓶颈换到 CCM(87.9%,只剩 7,904 B)**。⏸ 该簇后续动作(缩堆 → 迁 CCM)已按用户裁定 2026-10-15 **整簇暂缓**,见 §5.3。
> **权威源**:区域水位与子系统配额 → `../内存管理/RAM预算台账.md`(受管区);趋势 → `scripts/ram_baseline.tsv`(`ram_baseline.py --trend` 高亮 RW+ZI 增长 >1 KB 的对象)。本节只列支撑结论所需的数。
@@ -382,6 +383,7 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap
1. **瓶颈已从 SRAM1 换到 CCM**:R-9 落地后 SRAM1 只剩 56.1%(**余 57,504 B**),而 **CCM 被堆占掉 87.9%(只剩 7,904 B)**,待迁的 LVGL 池 + UI 两份缓冲 = **29,570 B**。
→ R-2 的剩余部分**只差"缩堆"这一步**(56→32 KB,`../内存管理/RAM使用分析与优化方案.md` §2.2;⚠ 2026-10-12 B5 是反向扩容,缩回前必须重跑 `stack_report.py` + 上板 `min_ever` 复测);顺序不可颠倒(`../内存管理/RAM预算台账.md` §3)。
⏸ **本簇已按用户裁定 2026-10-15 整簇暂缓**(§5.3)——这条诊断保留作将来重开时的现状基线,**不代表现在要动**。
2. **任务栈全部动态取自 FreeRTOS 堆**:`osThreadAttr_t` 只设 `stack_size` 不设 `stack_mem`(`Src/freertos.c`)→ 8 条产品任务栈合计 **9,792 words = 39,168 B**(另 testTask 2,048 words 仅测试构建)连同 idle/timer 栈、TCB、IPC 全部从堆里扣,**留给动态分配的实际余量很紧**(堆 56 KB 是 2026-10-12 B5 扩容后的值)。
→ **R-6(栈静态化)是把"池内碎片"变"可核算静态区"的正解,前置条件(观测常开 + `stack_report.py` 每任务最坏链)已满足。** 实时水位以串口 `[STACK]` / 自检打印为准,不在本文固化快照。
3. **MicroLIB 512 B C 堆是隐形地雷**:任何新代码写一个 `malloc` 都会中招。
@@ -389,12 +391,23 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap
### 5.3 RAM 优化路线(收益/风险/优先级)
> ⏸ **本表除已落地的 R-9 外整簇暂缓(用户裁定 2026-10-15)**,理由三条:
> ① **没有功能在等这块预算**——SRAM1 已降到 56.1%(余 57,504 B)、Flash 22.0%,离 `mem-budget` 的 92% 红线很远;
> ② **搬迁本身有风险和工时**——R-2 要动 scatter 并逐条过 DMA 可达性清单(规则 R2/R3,违例是**静默传错**不是报错),R-4 要重排 sink 与 LVGL 刷新的生命周期,R-6 静态化后栈溢出更难发现,缩堆还得上板复测 `min_ever`;
> ③ **收益与代价不对称**——腾出的 CCM 是给"以后可能有的功能",代价是现在动存储与显示两条主链。
>
> **保留常开的是治理面**(不是优化动作):`mem-budget` 92% 门禁、`../内存管理/RAM预算台账.md` 受管区、`scripts/ram_baseline.tsv` 趋势、`[STACK]` 水位与 `stack_report.py` / `ram_report.py`。它们是传感器,会在真正吃紧时报警。
>
> **重开条件(任一成立即重新评估,不必现在预防)**:
> ① `mem-budget` 逼近 92%,或某项**已定功能**的增量装不进现有余量——最可能先撞的是 **CCM**:只剩 **7,904 B**,而 FreeRTOS 堆实测 `min_ever` 仅 8,464 B(2026-10-15 台架),**加任务 / 抬栈 / 加堆都会先在这里撞墙**;
> ② 出现必须把 UI 帧缓冲搬离 SRAM1 才能做的显示功能;③ 送检或现场暴露 RAM 相关的稳定性问题。
| 编号 | 措施 | 收益 | 风险 | 优先级 | 状态 |
|------|------|------|------|--------|------|
| **R-2** | **启用 CCM 承载 LVGL 池与 UI 缓冲**:对 `work_mem_int` 与 UI 帧/绘制缓冲加段属性(`.sct` 已有 `RW_CCM`) | **−29,570 B**(R-9 后的待迁体量:16,384 + 6,420 + 6,766) | 中:必须确保这些缓冲**不被任何 DMA 直接寻址**。已核实 UI 发送路径 memcpy 进 CH395F 自有 SRAM1 DMA 缓冲,LVGL 为纯 CPU;**NAND 路径(规则 R2/R3)绝对不可迁入** | **P1(W3)** | 🟡 **只做一半**:`RW_CCM` 只收 `heap_4.o`(57,376 B)→ SRAM1 已减 49 KB+。⚠ 前置条件**只剩一步**:R-9 已落地(2026-10-15),但 **CCM 只剩 7,904 B,29.5 KB 仍装不下** → 需缩堆 56→32 KB |
| **R-3** | 存储页缓冲合并:`nand_ftl` 三块 2 KB 中 `s_page_buf`(dhara scratch) 与 `s_copy_buf` 不可并发,可复用 | **−2 KB** | 中:需严格审查 dhara 调用序列(copy 期间不会用 map scratch) | P2 | ❌ 未办(`s_bbt_page_buf` 已单独收紧为 272 B) |
| **R-4** | UI 帧副本去重:同一 3,200 B 帧当前存 **4 份**(`g_ui_draw_buf` → `g_ui_fbuf` → `g_lcdmem_data` → `g_tx`)。让 `ui_flush_cb` 直接把 `color_p` 交给 sink、sink 发送时才拼帧头 | **−6.4 ~ −9.6 KB** | 中:需要 sink 与 LVGL 刷新生命周期对齐(同任务,可控) | P1 | ❌ 未办(`ui_port.o` 6,420 + `ui_net_sink.o` 6,766 = 13,186 B,副本数未变) |
| **R-6** | 任务栈改**静态分配**(`stack_mem` 指向各自 `.bss` 数组),从堆里释放 ≈39 KB | 堆可用 +39 KB(**总量不变**,但把"池内碎片"变成"可核算静态区") | 低-中:静态后溢出检测更难发现;先测水位再定尺寸 | P2 | ❌ 未办。⚠ 前置已满足:观测三面常开 + `stack_report.py` 已给出每任务最坏链 → 可直接按实测值定尺寸 |
| **R-2** | **启用 CCM 承载 LVGL 池与 UI 缓冲**:对 `work_mem_int` 与 UI 帧/绘制缓冲加段属性(`.sct` 已有 `RW_CCM`) | **−29,570 B**(R-9 后的待迁体量:16,384 + 6,420 + 6,766) | 中:必须确保这些缓冲**不被任何 DMA 直接寻址**。已核实 UI 发送路径 memcpy 进 CH395F 自有 SRAM1 DMA 缓冲,LVGL 为纯 CPU;**NAND 路径(规则 R2/R3)绝对不可迁入** | ~~P1(W3)~~ → **⏸ 暂缓** | ⏸ **暂缓(2026-10-15 裁定)**。现状仍是**只做一半**:`RW_CCM` 只收 `heap_4.o`(57,376 B)→ SRAM1 已减 49 KB+;剩余一步是缩堆 56→32 KB(CCM 只剩 7,904 B,29.5 KB 装不下) |
| **R-3** | 存储页缓冲合并:`nand_ftl` 三块 2 KB 中 `s_page_buf`(dhara scratch) 与 `s_copy_buf` 不可并发,可复用 | **−2 KB** | 中:需严格审查 dhara 调用序列(copy 期间不会用 map scratch) | ~~P2~~ → **⏸ 暂缓** | ⏸ **暂缓(2026-10-15 裁定)**;未办(`s_bbt_page_buf` 已单独收紧为 272 B) |
| **R-4** | UI 帧副本去重:同一 3,200 B 帧当前存 **4 份**(`g_ui_draw_buf` → `g_ui_fbuf` → `g_lcdmem_data` → `g_tx`)。让 `ui_flush_cb` 直接把 `color_p` 交给 sink、sink 发送时才拼帧头 | **−6.4 ~ −9.6 KB** | 中:需要 sink 与 LVGL 刷新生命周期对齐(同任务,可控) | ~~P1~~ → **⏸ 暂缓** | ⏸ **暂缓(2026-10-15 裁定)**;未办(`ui_port.o` 6,420 + `ui_net_sink.o` 6,766 = 13,186 B,副本数未变) |
| **R-6** | 任务栈改**静态分配**(`stack_mem` 指向各自 `.bss` 数组),从堆里释放 ≈39 KB | 堆可用 +39 KB(**总量不变**,但把"池内碎片"变成"可核算静态区") | 低-中:静态后溢出检测更难发现;先测水位再定尺寸 | ~~P2~~ → **⏸ 暂缓** | ⏸ **暂缓(2026-10-15 裁定)**。若将来重开,前置已满足:观测三面常开 + `stack_report.py` 已给出每任务最坏链 → 可直接按实测值定尺寸 |
> ✅ **R-9 已落地并销项(2026-10-15)**:`LV_MEM_SIZE` 40→16 KB(两份 `lv_conf.h` 同步,`lv-conf-sync` 生效值比对 163 项 PASS)。依据 = 池水位门禁实测(菜单基线 5,368 B / 开页-关页往返 5,448 B / 最重页面峰值 6,568 B = 池的 40%),**≈2.5× 余量**;PC 侧 11 页黄金参考逐字节比对 10/11 一致(唯一差异是 `netcfg_save` 保存态文本,A/B 复测证明与本次改动无关——真因是 `--cfgtest` 留在工作目录的 4000 B 伪造配置档触发了引擎"拒写超长文档"这条**正确**行为,同日已修,见 `../UI设计/UI_自动化测试流程.md` §五)、往返池水位 5,448 B **分毫未变**;`@build` 0 错 0 警,ZI 精确 −24,576 B。**真机复跑 ✅(2026-10-15 `@test` PASS)**:`menu build done: total=15020 free=11828 used=3192`——菜单根框只占建池后 15,020 B 的 **21%**(TLSF 元数据 ≈1,364 B),全程无 `[ERR]`/Fault。再往下试 8 KB 需先跑全量 UI 回归(PC + 真机),**不在本条范围**。
@@ -557,12 +570,12 @@ const ui_page_desc_t ui_page_deadzone = UI_FORM_PAGE("遥测死区", s_items_dea
## 7. 统一改进路线图
> **顺序的唯一权威 = [`../任务规划/README.md`](../任务规划/README.md) §2**(W1 采集保护收尾 → W2 数据正确性 → W3 预算与内存 → W4 结构债 → W5 验证常态 → W6 UI 扩展 → W7 仓库决策;B2 RS-485 暂缓)。本节只保留"本报告条目 → 波次"的映射,不另立顺序。
> **顺序的唯一权威 = [`../任务规划/README.md`](../任务规划/README.md) §2**(W1 采集保护收尾 → W2 数据正确性 → ~~W3 预算与内存~~ **⏸ 已整簇暂缓** → W4 结构债 → W5 验证常态 → W6 UI 扩展 → W7 仓库决策;B2 RS-485 暂缓)。本节只保留"本报告条目 → 波次"的映射,不另立顺序。
| 波次 | 本报告条目 | 验收要点 |
|------|-----------|---------|
| **W2 数据正确性** | N-12 / N-13(登记簿 N-21) | 整页扫描 + `DHARA_E_UNSUPPORTED` + **主机侧 dhara 移植层单测**(一并补覆盖率缺口) |
| **W3 预算与内存** | R-9 → R-2 后半 → R-3/R-4/R-6 逐项评估 | 按 `../内存管理/RAM预算台账.md` §3 解锁链走,每步前后跑 `stack_report.py` / `ram_report.py` |
| ~~**W3 预算与内存**~~ ⏸ | **整簇暂缓(用户裁定 2026-10-15)**:R-9 ✅ 已落地不回退;R-2 后半 / R-3 / R-4 / R-6 不再排期 | 暂缓期间**无验收动作**;`mem-budget` 92% 门禁与台账、趋势、`stack_report.py` / `ram_report.py` 观测**照常跑**(它们是判断何时重开的输入)→ 重开条件见 §5.3 |
| **W4 结构债** | N-16、N-14、F-4/F-5/F-6、S-1/S-2/S-4/S-5;`rs485_task.c` 随 B2 出注册白名单 | `--strict` 默认化;`bsp_err_t` 进规范 |
| **W5 验证常态** | P1-10 收尾(构建实测链接 + `@test` 闭环) | 逢窗口顺手做 |
| **W6 UI 扩展** | U4 残余 → U1 → U2/U3 → U5(27 页) | 新增一页 ≤30 行;**本轮不排期** |
@@ -630,6 +643,7 @@ const ui_page_desc_t ui_page_deadzone = UI_FORM_PAGE("遥测死区", s_items_dea
| **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` W3、`../内存管理/RAM预算台账.md` §3、`../内存管理/RAM使用分析与优化方案.md` 阶段 1.2 / 2 |
| **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`) |
### 已销项条目的记录去处
@@ -656,4 +670,4 @@ const ui_page_desc_t ui_page_deadzone = UI_FORM_PAGE("遥测死区", s_items_dea
| 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-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 的 W3 第一步,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 |
| **R-9(`LV_MEM_SIZE` 40→16 KB,登记簿 N-27 原 W3 的第一步,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 |