From f86cb8824b8e4a34dcc690bd45c4f2c3624b69c3 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 21 Sep 2026 11:23:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=98=E5=82=A8=E6=A0=88RAM=E4=BC=98?= =?UTF-8?q?=E5=8C=96P0-1=EF=BC=9ABBT=E7=BC=93=E5=86=B2=E6=8C=89=E5=AE=9E?= =?UTF-8?q?=E9=99=85=E8=BD=BD=E8=8D=B7272B=E6=94=B6=E7=B4=A7=EF=BC=8C?= =?UTF-8?q?=E7=BC=96=E7=A8=8B=E5=9B=9E=E8=AF=BB=E6=A0=A1=E9=AA=8C=E6=95=B4?= =?UTF-8?q?=E4=BD=93=E7=A7=BB=E9=99=A4=EF=BC=88=E5=90=91=E4=B8=9A=E7=95=8C?= =?UTF-8?q?=E9=9D=A0=E6=8B=A2=EF=BC=89=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=AD=98?= =?UTF-8?q?=E5=82=A8=E6=A0=88RAM=E4=BC=98=E5=8C=96=E8=B0=83=E7=A0=94?= =?UTF-8?q?=E6=8A=A5=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c | 4 +- Drivers/BSP/GD5F2GQ5UE/nand_ftl.c | 36 ++------------- docs/内存管理/存储栈RAM优化调研.md | 70 +++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 34 deletions(-) create mode 100644 docs/内存管理/存储栈RAM优化调研.md diff --git a/Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c b/Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c index 0d4b92c6..2c9d8f5e 100644 --- a/Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c +++ b/Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c @@ -35,7 +35,7 @@ static uint32_t s_usable_blocks = GD5F_TOTAL_BLOCKS; /* dhara 可见块数(= static uint32_t s_bbt_write_slot = 0; /* 下一写入槽(轮转指针) */ static uint32_t s_bbt_version = 0; /* 当前持久化 BBT 版本号 */ static uint8_t s_bbt_slot_dead = 0; /* 池块损坏位掩码 */ -static uint8_t s_bbt_page_buf[GD5F_PAGE_SIZE]; /* BBT 读写页缓冲(静态,避免占栈) */ +static uint8_t s_bbt_page_buf[GD5F_BBT_HDR_SIZE + GD5F_BBT_SIZE]; /* BBT 读写缓冲(静态,避免占栈):实际载荷仅 16B 头+256B 位图,按实际传输长度声明(2026-09-21 由整页 2048 收紧,省 1776B) */ static uint8_t s_bbt_best[GD5F_BBT_SIZE]; /* 最高版本位图缓存 */ static const uint8_t s_bbt_magic[4] = { 'G', 'B', 'B', 'T' }; /* BBT 存储魔数 "GBBT" */ @@ -230,7 +230,7 @@ static void gd5f_page_read_issue(uint32_t page_addr) { * 台架实证(2026-09-20,VDD 3.1V 欠压工况):① 就绪信号可早于 * array→buffer 整页装载完成 → 0Bh 读到"前段新、后段旧"混合页; * ② 13h 命令在编程/擦除风暴后可不被芯片锁存(空操作)→ 0Bh - * 读到上一操作残留 buffer(编程数据)→ in-boot 回读校验/文件 + * 读到上一操作残留 buffer(编程数据)→ 后续文件/BBT/journal * 读取全部"虚假成功",阵列实际未更新 → 复位后数据丢失。 * 二次发令覆盖②(重发必被锁存),固定沉降覆盖①(整页装载完成)。 */ diff --git a/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c b/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c index 49e6bd23..49286333 100644 --- a/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c +++ b/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c @@ -131,38 +131,10 @@ int dhara_nand_prog(const struct dhara_nand *n, dhara_page_t p, const uint8_t *d return -1; } - /* 编程回读校验(硬化措施,2026-09-20):拦截"状态寄存器报成功但 - * cell 未可靠 latch"的静默编程失败——此类页若流入 journal,复位后 - * resume 会因 ECC/魔数门整体拒收 checkpoint,造成新写入丢失。 - * 回读比对+ECC 检查,失败即标记坏块交由 dhara 迁移(宁可丢块)。 - * 注:本校验曾被认为是重格式化循环根因(低电压假设),后经验证 - * 该假设证伪——循环真根因是 FatFs 探针名非法(见 freertos.c 探针 - * 注释与 Trap Records);本校验作为数据完整性硬化长期保留。 */ - if (gd5f_page_read(phy_pg) != GD5F_OK) { - dhara_nand_mark_bad(n, p >> n->log2_ppb); - dhara_set_error(err, DHARA_E_ECC); - DBG_ERROR("program verify: readback fail, blk %lu", - (unsigned long)(p >> n->log2_ppb)); - return -1; - } - - if (gd5f_check_ecc() != GD5F_OK) { - dhara_nand_mark_bad(n, p >> n->log2_ppb); - dhara_set_error(err, DHARA_E_ECC); - DBG_ERROR("program verify: ecc uncorrectable, blk %lu", - (unsigned long)(p >> n->log2_ppb)); - return -1; - } - - gd5f_read_from_cache(0, s_copy_buf, FTL_PAGE_SIZE); - if (memcmp(s_copy_buf, data, FTL_PAGE_SIZE) != 0) { - dhara_nand_mark_bad(n, p >> n->log2_ppb); - dhara_set_error(err, DHARA_E_BAD_BLOCK); - DBG_ERROR("program verify: data mismatch, blk %lu", - (unsigned long)(p >> n->log2_ppb)); - return -1; - } - + /* 编程正确性以 P_FAIL 状态位(gd5f_program_exec 内检查)+ 读时 ECC + + * journal 读时门(magic/CRC)为准;数据路径不做整页回读比对—— + * 2026-09-20 曾加回读校验(GD5F_PROG_VERIFY),2026-09-21 经评估整体 + * 移除(依据见 docs/内存管理/存储栈RAM优化调研.md 与 GD5F Trap Records Trap 05) */ return 0; } diff --git a/docs/内存管理/存储栈RAM优化调研.md b/docs/内存管理/存储栈RAM优化调研.md new file mode 100644 index 00000000..db84009e --- /dev/null +++ b/docs/内存管理/存储栈RAM优化调研.md @@ -0,0 +1,70 @@ +# 存储栈 RAM 优化调研 + +> 版本 v1.0 日期 2026-09-21 作者 AI 辅助调研 +> 数据来源:`data/ram_report_20260921.md`(.map 静态占用)+ 逐行代码核验(`nand_ftl.c` / `gd5f2gq5ue.c` / `Lib/dhara` / `Lib/FatFs/ffconf.h` / `lftpd*`) +> 定位:`RAM使用分析与优化方案.md` 的存储专项补充;优化项编号 P0/P1/P2,与总方案 §6 的 S 序号在"规划"一节对齐 + +## 1. 现状盘点(2026-09-21 基线) + +存储栈静态 RAM 全部在 **RW_IRAM1(主 SRAM 128KB)**,合计 **≈15.5 KB(占已用 82,048B 的 18.9%)**。运行期堆占用(CCM)仅 lftpd 路径串/`DIR` 约 ≤100B 瞬态,FatFs/dhara 无大块堆分配。 + +| 模块 (.o) | RW+ZI | 主要构成 | 约束 | +|---|---:|---|---| +| nand_ftl.o | 6,216 | `s_page_buf` 2,048(dhara journal checkpoint,协议要求整页)+ `s_cache_buf` 2,048(512B 扇区 RMW 写回缓存)+ `s_copy_buf` 2,048(GC 拷贝暂存)+ dhara map/journal 结构 ~120 | 页缓冲走 SPI1 DMA(>阈值 1024B),DMA 不可达 CCM | +| gd5f2gq5ue.o | 2,596 | `s_bbt_page_buf` 2,048 + `s_bbt`/`s_bbt_best` 位图 2×256 + 保留池 16 + 状态 | 同上 | +| lftpd.o | 4,768 | 9 处函数级 static:2×1024(STOR/RETR 数据块)、512×3(response/read_buffer/arg_buf)、256×3(message/name×2)+ 256(log) | 纯 CPU 访问,无 DMA | +| lftpd_io.o | 556 | `s_ftp_file`(FIL,内含 512B 私有扇区窗) | 纯 CPU | +| freertos.o 内 `default_fatfs` | ~576 | FATFS 对象(`win[512]` 共享窗 + 卷状态) | 纯 CPU | +| cfg_file.o | 724 | 配置引擎静态态 | 纯 CPU | +| ff.o + ffsystem.o | 16 | 文件系统对象指针 + 同步原语 | `FF_FS_REENTRANT=1`(defaultTask/ftpTask 并发所需,保留) | + +FatFs 配置已是低 RAM 取向:`FF_MAX_SS=512`、`FF_USE_LFN=0`、`FF_VOLUMES=1`、`FF_FS_LOCK=0`。 + +## 2. 调研发现 + +- **F1 BBT 页缓冲超配 10 倍**:`s_bbt_page_buf[2048]`,但实际读写只有 `GD5F_BBT_HDR_SIZE(16)+GD5F_BBT_SIZE(256)=272B`(`gd5f2gq5ue.c:925` 读 272B、`:1010` program_load 272B)。缩到 272B 行为零变化。 +- **F2 ~~GC 搬迁路径 program verify 空转~~(已随校验整体移除而消失,留档备查)**:2026-09-21 前 `dhara_nand_copy()` 回读缓冲与源同址(`s_copy_buf`),memcmp 恒真自比对(空校验);2026-09-21 编程回读校验整体移除(选项 (b),向 Linux mtd 形态靠拢)后该缺陷不复存在。教训:任何比对式校验必须在**两份独立副本**间进行(U-Boot `sf test` 双缓冲形态)——若未来在测试构建恢复回读诊断,勿重蹈此坑。 +- **F3 3×2KB 页缓冲是结构成本,不可直缩**:dhara journal 要求整页 checkpoint(`journal.c:196` 整页 memset);512B 扇区落 2KB 页必须整页 RMW。可动的只有 `s_copy_buf`(改分段暂存)。 +- **F4 CCM 迁移功能上安全**:`gd5f_dma_buf_ok()` 运行时守卫会把 DMA 不可达缓冲自动回落 CPU 轮询(2026-09-21 加固),把 NAND 页缓冲挪进 CCM 不会静默失败,代价只是每页零点几 ms CPU(轮询 vs DMA 卸载)。CPU-only 缓冲(lftpd/cfg/FATFS win)迁 CCM 则零代价。 +- **F5 栈上 FIL 重复占深链**:syslog 两处、cfg 存储两处、开机探针各一个局部 `FIL`(每个含 512B buf,≈552B),全部压在 defaultTask 最坏链 2,776B 内——这是 `FF_FS_TINY` 的靶点(见 P1-4)。 + +## 3. 方案清单 + +| # | 方案 | 省 RAM | 区域 | 风险 | 验证 | +|---|---|---:|---|---|---| +| P0-1 | `s_bbt_page_buf` 2048→272(按实际读写字节数定义) | **−1,776B** | SRAM1 | 极低(一行宏+数组维) | `@build` + 开机 BBT 加载 + `@test` | +| P0-2 | `s_copy_buf` 2048→512:GC 拷贝改分段 read→program_load(`program_load`/`read_from_cache` 支持列地址)【性质变更 2026-09-21:回读校验整体移除后,此项变为**纯 RAM 优化**(GC 拷贝暂存减半),无校验语义风险,与原"分块+修 F2"解耦】 | **−1,536B(可选,不计入当前预期)** | SRAM1 | 低(仅动拷贝机制) | 待 RAM 余量需要时再议 | +| P0-3 | lftpd 缓冲收紧:response 512→256、read_buffer 512→256、arg_buf 512→256、name 256→128 ×2(本卷仅 8.3 短名,路径深度浅);数据块 2×1024 与 message 不动 | **−1,024B** | SRAM1 | 低(FTP 客户端实测行长远低于新值) | `@build` + FTP 上传/下载/LIST 闭环 + `@test` | +| P1-4 | `FF_FS_TINY=1`:删每 FIL 私有的 512B buf,文件数据走 `FatFs->win` 共享窗 | 静态 **−528B**;且栈上每处 FIL 峰值 **−528B**(defaultTask 最坏链 2,776→~2,250,实测峰 2,136→~1,600) | SRAM1 + CCM 栈 | 中(所有文件 I/O 经 512B 窗 bounce,FTP 吞吐 −20~40%;LIST 与文件读交错只影响速度) | 存储套件 + FTP 吞吐实测 + 日志/配置闭环;**与 S7 缩栈捆绑**(直接支撑 defaultTask 降档) | +| P1-5 | `APP_CCM_ENABLE` 门(与 S6 同宏):①CPU-only 缓冲迁 CCM——lftpd static 3.6K + cfg_file 0.7K + FATFS win 0.6K + lftpd_io ≈ **−4.9K** 零代价;②DMA 页缓冲(nand_ftl 4.6K + gd5f 位图/页 0.8K)迁 CCM 走轮询 ≈ **−5.4K**,需实测吞吐 | **−10.3K** | SRAM1→CCM | 低①/中② | 分段实施;每步跑 `ram_report.py` + `@test` + FTP 吞吐 | +| P2-6 | NAND copy-back 命令(0x15→0x10)替代主机搬页:省 `s_copy_buf` 的拷贝用途 + 减半 SPI 流量 | −512B(P0-2 后) | SRAM1 | 高(片上 ECC 在 copy-back 下的语义须台架实证) | 仅评估,暂缓 | +| P2-7 | lftpd 数据块 2×1024→512 | −1,024B | SRAM1 | 吞吐 −~30% | RAM 仍紧时才做 | +| P2-8 | syslog/cfg 共享一个静态 FIL(同任务串行) | 净≈0(静态+528/栈−528) | — | 不推荐:P1-4 已覆盖同一收益面 | — | + +**明确不做**:移除 dhara(丢掉电一致性与坏块重映射,代价不对称);journal checkpoint 分片(违反 dhara 协议);调 `gc_ratio`(无 RAM 收益);`FF_FS_REENTRANT=0`(defaultTask+ftpTask 并发访问 FatFs 必需)。 + +**实施记录**: + +| # | 状态 | 日期 | 验证 | +|---|---|---|---| +| P0-1 | ✅ 已落地 | 2026-09-21 | `@build` 0/0;`@test` PASS(BBT 开机加载闭环);.map RW_IRAM1 82,048→80,272(**−1,776B**,精确命中) | +| P0-2 | ⏸ 搁置(性质已变) | 2026-09-21 | 回读校验整体移除后,此项由"校验分块+修 F2"变为 **GC 拷贝纯 RAM 优化**(`s_copy_buf` 2048→512 分段 read→load);无紧急性,待 RAM 余量需要时再议 | +| 编程回读校验整体移除 | ✅ 已落地 | 2026-09-21 | 先改编译开关 `GD5F_PROG_VERIFY`,同日按选项 (b) **整体移除**(向 Linux mtd / U-Boot / dhara 上游形态靠拢:数据路径无回读比对,编程正确性以 P_FAIL 状态位+读时 ECC+journal 读时门为准);代码/宏/开关全部移除,"实证失效"误记录同步更正(幻影编程假设已被 Trap 05 证伪,本板无实测编程失效);F2 自比对缺陷随之消失;产品构建 `@build` 0/0 + `@test` PASS | +| P0-3 / P1-4 / P1-5 | 待实施 | — | — | + +## 4. 分阶段规划(与总方案 §6 S 序号对齐) + +| 阶段 | 内容 | 收益(SRAM1 已用 82,048B 基础上) | 前置 | +|---|---|---:|---| +| **第一步 P0**(独立小批) | P0-1(已落地)+ P0-3(P0-2 搁置,性质已变为纯拷贝优化) | **−2,800B**(P0-1 已省 1,776B) | 无 | +| **第二步**(并入 S7 缩栈批) | P1-4 `FF_FS_TINY=1` → 复跑 `stack_report.py` → defaultTask 降档(最坏链 ~2,250 支撑 3,584B 配置,余量 37%)+ 其余任务按 S7 目标 | −528B 静态 + 栈档下调释放 CCM 堆 | 第一步合入 | +| **第三步**(与 S6/S8 同批) | 先 S8 堆 48K→32K(CCM 释放 ~16K),再 P1-5 ①→② 分批迁 CCM | SRAM1 再 **−10.3K**;CCM 占用 +10.3K(由 S8 腾挪覆盖) | S8 或同批评估 CCM 水位 | + +**全部落地后存储栈预期**:SRAM1 常驻从 15.5KB 降至 **~1.9KB**(仅小状态量),页缓冲驻 CCM(轮询),静态合计挪入 CCM 换回 SRAM1 ≈ **−13.6KB**(P0-2 搁置(性质已变为纯拷贝优化),其 −1,536B 不计);叠加 S5(LVGL 40K→16K)后 SRAM1 余量 >65KB。 + +## 5. 风险与回归要求 + +- 回读校验移除(2026-09-21 落地):产品构建 `@build` 0/0 + `@test` 开机闭环(编程路径仅余 P_FAIL 状态检查);GD5F/STORAGE 测试构建各编译 0/0(套件 ECC 写读用例经读路径覆盖编程正确性);台架破坏性套件 + 掉电 resume 随下次存储改动照常执行。 +- P1-4 前后各跑一次 `stack_report.py` + `ram_report.py`(AGENTS.md 门禁),FTP 吞吐留实测数字(当前基线可先记一轮 RETR/STOR 速率)。 +- P1-5 的 ②(页缓冲入 CCM 走轮询)须以实测吞吐定去留:若 NAND 读吞吐降幅 >30%,则只迁 CPU-only 侧(①)。 +- 本文数字均可由 `data/ram_report_20260921.md` 与上表代码行号复核;实施后重生成基线报告并回填本文状态列。