通用配置文件 P1–P3:设计文档、FS 并发 A+ 定案、FatFs 墙钟接入、cfg_file 双端引擎与 net_cfg 集成(旧档 NCFG 首启迁移)

This commit is contained in:
2026-09-14 02:15:49 +08:00
parent cf2597f998
commit 97661415ca
29 changed files with 3076 additions and 359 deletions
+126
View File
@@ -0,0 +1,126 @@
/*
* 模块名称:cfg_file
* 模块功能:通用配置文件引擎(双端共享核心)公共接口——INI 段/键表解析校验、
* 外科手术式保存(保留注释/未知内容,缺失段/键写回)、出厂模板生成、
* 沉降去抖轮询与分段变更回调;平台文件操作经 cfg_file_store 后端
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:王建锋
* 创建日期:2026-09-14
* 修改记录:
* v1.0 2026-09-14 王建锋 创建初始版本(P3:段键表引擎 + net_cfg 集成)
*/
#ifndef CFG_FILE_H
#define CFG_FILE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
/* 配置文件长度上限(字节);超过 = 文件损坏,按出厂模板重建 */
#define CFG_FILE_MAX_LEN 4096u
/* 引擎可注册段数上限 */
#define CFG_FILE_MAX_SECTIONS 8u
/* 单段键数上限 */
#define CFG_FILE_MAX_KEYS 16u
/* 沉降去抖:变更基线连续 N 次轮询不变才重载(轮询周期 2s → 4s 沉降) */
#define CFG_FILE_SETTLE_CNT 2u
/*
* 键值类型
* UINT:无符号十进制;len = 目标字段字节数(1/2/4,小端)
* IP4 :点分 IPv4 "a.b.c.d";字段 uint8_t[4]
* MAC :十六进制 MAC "xx:xx:xx:xx:xx:xx"(分隔符兼容 - 与 .);字段 uint8_t[6]
* STR :ASCII 字符串;字段 char[len](len = 缓冲长度,自动补 NUL)
*/
typedef enum {
CFG_VAL_UINT = 0,
CFG_VAL_IP4,
CFG_VAL_MAC,
CFG_VAL_STR
} cfg_val_type_t;
/* 键定义(offset/len 均相对段 RAM 副本起始) */
typedef struct {
const char *name; /* 键名(小写) */
cfg_val_type_t type; /* 值类型 */
size_t offset; /* 字段偏移 */
size_t len; /* 字段长度 */
} cfg_key_def_t;
/* 段注册描述符 */
typedef struct {
const char *name; /* 段名(≤ 15 字符) */
void *p_data; /* 段 RAM 副本(模块自有静态区,引擎原地更新) */
const void *p_defaults; /* 工厂默认值(与 p_data 同布局;load 先复位再解析) */
size_t data_size; /* RAM 副本字节数 */
const cfg_key_def_t *p_keys; /* 键表 */
uint8_t key_count; /* 键数(1 ~ CFG_FILE_MAX_KEYS) */
void (*p_cb)(void); /* 变更回调(可空;poll 重载后该段有差异时调用;
注册段 data_size 须 ≤ 64 字节方可挂回调) */
} cfg_section_reg_t;
/*
* 函数功能:注册配置段(引擎建立"段 → RAM 副本 + 键表"映射)
* 入口参数:p_reg - 段注册描述符(不可为 NULL) const cfg_section_reg_t *
* 返回值:0 - 成功;-1 - 参数非法/段名重复/段数超限 int
* 限定条件:启动早期调用一次(重复注册同段名拒绝);
* 注册后 p_data/p_defaults/p_keys 生命周期须覆盖引擎使用期
*/
int cfg_file_register(const cfg_section_reg_t *p_reg);
/*
* 函数功能:从配置文件加载全部段(文件 = 配置唯一来源)
* 入口参数:无
* 返回值:0 - 正常(含回退工厂默认);-1 - 严重错误(RAM 已置工厂默认,仍安全) int
* 限定条件:至少注册一个段
* 函数说明: 1. 各段先复位工厂默认(文件缺失/损坏的键 = 工厂默认)
* 2. 文件缺失 → 按当前 RAM 副本生成出厂模板写盘(首启建文件)
* 3. 文件存在 → 解析:有效键写入 RAM 副本;无效键留工厂默认并留痕
* 4. 文件超长(> CFG_FILE_MAX_LEN)= 损坏 → 工厂默认 + 重建模板
*/
int cfg_file_load(void);
/*
* 函数功能:保存全部段到配置文件(外科手术式)
* 入口参数:无
* 返回值:0 - 成功;-1 - 写失败(原文件保持不动) int
* 限定条件:至少注册一个段
* 函数说明:文件存在 → 逐行保留注释/未知段/未知键,受管段/键按 RAM 副本
* 值原位改写,缺失段/键补写;文件缺失/损坏 → 按 RAM 副本重建
* 完整文档(含文件头注释);写盘 = 临时文件 + 原子改名
*/
int cfg_file_save(void);
/*
* 函数功能:配置文件变更轮询(沉降去抖 + 重载 + 分段变更回调)
* 入口参数:无
* 返回值:无
* 限定条件:由单一任务周期调用(建议 2s,收敛于 netTask)
* 函数说明:(size, mtime 变更令牌) 相对基线变化且连续 CFG_FILE_SETTLE_CNT
* 次轮询稳定 → 重载全部段(各段复位工厂默认后解析);挂回调段
* 有差异 → 调用其回调(如触发网络重建);重载后刷新基线
* (回调触发的写盘不引发二次重载)
*/
void cfg_file_poll(void);
/*
* 函数功能:取段 RAM 副本指针
* 入口参数:p_name - 段名 const char *
* 返回值:段 RAM 副本指针;未注册返回 NULL void *
* 限定条件:无
*/
void *cfg_file_section_data(const char *p_name);
#ifdef __cplusplus
}
#endif
#endif /* CFG_FILE_H */