d9303e05a4
真机 #73:运行中改配置触发热重载,卷层(dhara)偶发返回旧/短 视图时,引擎把该视图当成文件全文:逐段按缺省解析后整盘打回 出厂默认且不自愈;此后任何一次保存又按缩小的视图做手术式 重写,文件越写越小(台架 1066B→986B,[sntp] 段整体丢失), 即真机对时静默 10.5 小时的元凶。 处置(引擎侧根因无关防御;卷层回滚归 #79/#81 已合并的 FTL 修复域): - poll:读完加三点校验(读长==stat.size、读前后 re-stat 的 size/mtime 一致),判为旧/短视图则 RAM 不动、基线不刷新、 每 2 拍自动重试自愈;首次拒绝留 1 条 DBG_ERROR+syslog, 之后每 30 拍一条 WARN 提示重启收敛。 - save:同型三点校验,视图与 stat 不符返回 -1 且文件不动, 调用方保留 dirty 下拍重试,吞段链在第一次保存即被掐断。 - 边界:「一致但陈旧」的整卷回滚引擎层无法区分,靠重启 收敛,已写入设计说明风险表与文档口径。 测试:新增 TC-CONFIG-058/059/060(旧视图保持 RAM、保存短 视图拒写、读中改写拒绝+日志限速)。cfg_file 239/239; iec104 179、run_par 67、adc_cal 117、sntp 98、 cfg_file_store_mcu 34、net_cfg 48、ftp_cfg 16、prot_set 90、 prot_dim 38 全绿;/keil-build 0 Error 0 Warning。 文档:配置文件设计说明 §(3)/§5.3/风险表/变更记录 v1.17; 单元测试说明 058–060 行;网络配置说明与产品需求 FR-CFG-3 同步口径;台账随新鲜 .map 由 ram_baseline --update 回填。
App/cfg/ — 配置引擎
/config.ini配置引擎:分层解析、持久化(原子写)。 属主 = defaultTask(单任务收敛,静态态);其它任务不得直接触碰。
文件一览
| 文件 | 作用 |
|---|---|
cfg_file.c/h |
配置引擎核心:解析 / 查询 / 保存 / 2s 周期 cfg_file_poll |
cfg_file_store.h |
存储后端抽象接口(MCU=FreeRTOS 堆 / 模拟器=宿主堆,共享核心零分配符号) |
cfg_file_store_mcu.c |
MCU 端后端实现:/config.ini(临时名由目标路径同目录推导 + f_rename 原子写) |
prot_set_store.c/h |
保护定值持久化胶水:/prot_set.bin blob 读写(blob 格式/校验/原子装载在 App/algo/prot_set.c 纯逻辑层);装载 = storage bring-up(屏障前),落盘 = defaultTask 消费 SYS_EVT_PROT_SET_SAVE |
设计要点
- 单任务收敛:
cfg_file为静态态,只有 defaultTask 操作;UI 保存请求经SYS_EVT_CFG_SAVE事件唤醒 defaultTask 执行(netTask/uiTask 不得直接调用); 定值落盘同构——iec104Task 只置事件位(SYS_EVT_PROT_SET_SAVE),不碰文件系统 - 零分配共享核心:核心逻辑不含任何分配符号,动态内存收进平台后端
(
cfg_store_alloc/free:MCU→pvPortMalloc,模拟器→宿主堆) - 原子写:写
/config.TMP后f_rename替换,避免掉电损坏 - 旧档迁移已删除(2026-10-10):旧格式
/cfg/netcfg.bin不再读取——存在则被忽略(不读、 不删、不迁移),配置回落工厂默认;net_cfg_legacy.c/h与cfg_store_legacy_path()已移除 - 自研代码禁用 C 库堆分配:MicroLIB 堆仅 512B(
malloc必返回 NULL)
相关文档
docs/子系统设计/配置文件设计说明.md— 完整设计(分层/解析/持久化)docs/子系统设计/网络配置说明.md— 网络段