feat(存储): 写回缓存空闲 flush 兜底——卷空闲周期 CTRL_SYNC(登记簿 N-22 收口)
道F 批 2 / task-16。FTL 单页写回缓存(nand_ftl.c s_cache_dirty)与 dhara journal 只在换页/整页写/f_close 时刷出,漏网脏页的掉电驻留窗无上限。本 提交以最小面收口:不碰 GD5F/dhara 驱动,全部走既有 FatFs CTRL_SYNC 路径。 实现 App/fs/vol_idle_sync.[ch](新增,仅 MCU 端,uvprojx App 组注册): - 四级门:STORAGE_READY 就绪门 → 5 s 节流(无符号差回绕安全判据)→ vol_lock_wait(0) try(锁被持有=文件序列在做,跳过,不改 STOR 持有期 语义)→ disk_ioctl(0, CTRL_SYNC); - clean 态脏标志+journal 双短路、零 NAND 触点;脏态最坏 = 一次 f_close 的同步段同型成本,不引入新磨损来源; - 失败按边沿 latch 一条 DBG_ERROR、成功重新武装;失败路径也成对放锁; - TEST_SUITE_STORAGE 构建整体 no-op(卷由 testTask 独占)。 接线:defaultTask 主循环 syslog_drain 之后(default_task.c v1.3)。 文档:docs/架构设计/STM32F4-Base存储架构说明.md §5.5 补空闲兜底与边界; 本板无掉电检测硬件、不做掉电前强制 flush、勿当掉电保护——口径同步落 注释与文档(sys_log_mcu.c 两处旧「暂不做」注释随实现改口)。 测试:新主机单测 test/host/vol_idle_sync/(TC-VOLSYNC-001..012,19 断言 全过);scripts/id_registry.json 建 TC-HOST-VOLSYNC 族(仿 ADCCAL 先例); .pre-commit-config.yaml 加 vol-idle-sync-unit-test hook(只加自己条目)。 越界申报(①②③ 均 lead 批准,④ 为门禁连带必要): ① App/task/default_task.c 单点接线(include + 1 调用 + 头修改记录); ② docs/架构设计/STM32F4-Base存储架构说明.md §5.5; ③ .pre-commit-config.yaml 单 hook + scripts/id_registry.json 单族; ④ scripts/check_registration.py SIM_EXEMPT 加一行(vol_idle_sync.c 模拟器 侧豁免,registration-check GAP 所需;与批准③同类别但未列名,特此申报)。 体积增量(vs scripts/ram_baseline.tsv 2026-10-25 行): Flash(Code+RO) 237140→237328(+188 B)、RW 1224→1232(+8 B)、ZI 0; 增量 = 3 个文件级 static + 一处 DBG_ERROR 调用点;栈/堆无变化。 gate: only mem-budget/mem-numbers pending lead ledger backfill 全量 pre-commit --all-files:40 项 Passed,仅 mem-numbers(D-7 体积档)与 mem-budget 两条红 = 台账数字待回填(增量如上,属 lead 单写者禁区); 其余含 doc-links/id-check/registration/test-coverage/全部主机单测皆绿。 @build 0 错误 0 警告(Code=215932 RO=21396 RW=1232 ZI=131984)。 台架:空闲 sync 实机节奏(clean 零触点、脏态时长、无心跳扰动)属实际 测量采样类——本批跳过,留「待台架实测」。
This commit is contained in:
@@ -334,8 +334,10 @@ static int s_append(syslog_id_t id, const char *desc) {
|
||||
* **不改掉电语义**:批次仍在同一次 syslog_drain() 调用内写完并
|
||||
* f_close;close 内部 sync_fs → disk_ioctl(CTRL_SYNC) 会调
|
||||
* ftl_flush_cache() 把 FTL 的单页写回缓存刷进 NAND(nand_ftl.c)。
|
||||
* 落盘时机与旧实现每条 close 等价,批次不跨调用驻留 RAM;残余只到
|
||||
* "单次写事务进行中掉电/复位"为止(登记簿 N-22,2026-10-22 裁定暂不做)。
|
||||
* 落盘时机与旧实现每条 close 等价,批次不跨调用驻留 RAM;漏网脏页
|
||||
* (留脏后再无调用触发刷出)已有写回缓存空闲 flush 兜底
|
||||
* (App/fs/vol_idle_sync.h:卷空闲 + 周期 CTRL_SYNC),掉电残余只到
|
||||
* "单次写事务进行中掉电/复位"为止。
|
||||
* 自愈重试与错误去重的判据与 s_append_rec 一致;容量不足时返回 -3
|
||||
* 而不是就地 unlink——"满了就重建"必须由按条慢路径统一执行,
|
||||
* 否则一批 8 条会跨越多轮重建、语义说不清。
|
||||
@@ -846,8 +848,9 @@ int syslog_last_epoch(syslog_id_t id, uint32_t *p_epoch) {
|
||||
* ⚠ 2026-10-02 round 3~8 那次"复位后写入整段丢失"的根因是 dhara resume 锚错
|
||||
* checkpoint 使 journal 整段回退(docs/架构设计/STM32F4-Base存储架构说明.md
|
||||
* §5.4.1),不是这层缓存:单页缓存最多丢最后未跨页那笔(≤512 B),丢不出
|
||||
* "整段"。真正的残余(无空闲/掉电前周期 flush)= 登记簿 N-22,2026-10-22
|
||||
* 用户裁定暂不做。
|
||||
* "整段"。空闲周期 flush 兜底已接线(App/fs/vol_idle_sync.h:STORAGE_READY
|
||||
* 门控 + 周期节流 + 卷锁 try + CTRL_SYNC,脏页驻留窗由周期封顶);本板无
|
||||
* 掉电检测硬件,"掉电前强制 flush"仍是物理边界,不在该兜底承诺之内。
|
||||
* 顺序硬约束不变:s_append 自行取卷锁(非递归锁),必须在 vol_lock_release()
|
||||
* **之后**调用,绝不可在持锁状态下调用。
|
||||
* 容量护栏:> 8KB 先 unlink 重建,防长跑无界增长(8.3 合法名 wdev.log)。
|
||||
|
||||
Reference in New Issue
Block a user