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:
2026-10-25 09:23:20 +08:00
parent 13ef0715bb
commit 484d068250
17 changed files with 712 additions and 4 deletions
+9
View File
@@ -23,6 +23,9 @@
* 耗时(task_prof_report),并在**心跳位图出现 1→0 边沿**
* 的瞬间留一份现场快照(task_prof_report_raw,裸 UART);
* 另给控制台排空与 syslog 落盘各加一个耗时探针
* v1.3 2026-10-25 DTU 项目组 写回缓存空闲 flush 接线:主循环 syslog 排空
* 之后调 vol_idle_sync_poll()(卷空闲周期 CTRL_SYNC 兜底,
* 模块 = App/fs/vol_idle_sync.[ch],道F 批 2)
*/
#include "default_task.h"
@@ -46,6 +49,7 @@
#include "task_watchdog.h"
#include "task_prof.h" /* 各任务最坏耗时上报 */
#include "vol_lock.h"
#include "vol_idle_sync.h" /* 写回缓存空闲 flush 兜底(App/fs/vol_idle_sync.h) */
#include "task_handles.h" /* 任务句柄与属性块的引用契约(定义处仍是 Src/freertos.c) */
/* Private defines -----------------------------------------------------------*/
@@ -275,6 +279,11 @@ void default_task_func(void *argument) {
task_prof_enter(TASK_PROF_DEF_SYSLOG);
syslog_drain();
task_prof_exit(TASK_PROF_DEF_SYSLOG);
/* 写回缓存空闲 flush 兜底:卷空闲(try 锁)+ 周期节流 + 就绪门控全在
* 模块内(App/fs/vol_idle_sync.h);clean 态零 NAND 触点,脏态最坏 =
* 一次 f_close 同型的同步段。放在 drain 之后:本拍若写过日志,close
* 已同步过,这里随即 clean 短路——漏网脏页的驻留窗由周期封顶 */
vol_idle_sync_poll();
#endif
/* 栈水位观测:首次 5s 后报告,此后每 2s 采样、出现更深峰值才打印 */
task_wd_seg(TASK_WD_SEG_STACK);