docs(cfg): 配置设计档补示例文件一章,写作规范补单篇自洽原则
配置文件设计.md 增加第 2 章「一份完整示例文件」:给出首启模板全文 (8 段 46 键,值全部对照工厂默认宏核对),再按段拆成 2.1~2.6 六张 键表(键 / 类型 / 出厂值 / 含义 + 生效时机),读者不必再翻别的文档 才能知道每个段的键是什么意思。 为保持文档自洽顺带收敛: - 删掉文件格式章里重复的文件头代码块,改为指向第 2 章 - 删掉段表下「默认值见网络配置说明」的跳转,默认值现就在本篇 - 相关文档里把网络配置说明降级为对外使用手册 - 后续章号整体后移一位,交叉引用同步校准 doc-writer 角色补写作原则:原「同一事实只写一次」只覆盖跨篇去重, 照字面执行会逼出一篇到处跳转的文档。改为明确两条的分工——同一篇内 求完整、篇与篇之间求唯一,并给出判断标准(读者会不会被逼着另开一篇 才能读懂)与常见取舍。反模式表同步加一行。 验证:48 个提交期钩子全通过;check_doc_links / check_mermaid 通过。
This commit is contained in:
+179
-42
@@ -2,7 +2,7 @@
|
||||
|
||||
> **读者**:要改配置引擎、接入新配置段、或排查"配置没生效"的人。
|
||||
> **读这一篇能得到什么**:当前 `/config.ini` 这套配置体系的**现状设计**——文件长什么样、引擎怎么解析与落盘、谁在什么时候写、异常时退到哪儿。
|
||||
> **相关文档**:`网络配置说明.md`(各段键表与使用手册)· `项目架构总览.md`(分层位置)· `docs/内存管理/RAM预算台账.md`(内存数字台账)
|
||||
> **相关文档**:`docs/硬件平台/ADC通道映射说明.md`(采集通道语义)· `项目架构总览.md`(分层位置)· `docs/内存管理/RAM预算台账.md`(内存数字台账)
|
||||
|
||||
本文只描述**现在**的系统。演进过程不在此展开,需要时查 `git log` 与代码文件头注释。
|
||||
|
||||
@@ -19,9 +19,156 @@
|
||||
|
||||
引擎本身**不认识任何具体配置项**:配置项由各模块以"段"为单位注册(段名 + 段 RAM 副本 + 键表 + 可选变更回调),引擎只按注册表解析与回写。新增配置项 = 新模块注册一个段,不动引擎。
|
||||
|
||||
## 2. 文件格式
|
||||
## 2. 一份完整示例文件
|
||||
|
||||
### 2.1 位置与容量
|
||||
设备开箱首启时,引擎按已注册段的工厂默认值生成的文件如下(8 段、46 个键,每段后面的表逐键说明含义):
|
||||
|
||||
```ini
|
||||
; ============================================================
|
||||
; STM32F4-Base 通用配置文件
|
||||
; 格式: INI (UTF-8 / CRLF),本文件为配置唯一来源
|
||||
; - 以 ';' 或 '#' 开头的行为注释,保存时保留
|
||||
; - 未知段/键保存时保留;缺失段/键保存时写回
|
||||
; - 编辑后经 FTP 上传或设备端保存,设备 4s 沉降后自动重载
|
||||
; ============================================================
|
||||
|
||||
[network]
|
||||
ip=192.168.31.100
|
||||
mask=255.255.255.0
|
||||
gw=192.168.31.1
|
||||
mac=00:00:00:00:00:00
|
||||
|
||||
[ftp]
|
||||
user=admin
|
||||
pwd_hash=d82494f05d6917ba02f7aaa29689ccb444bb73f20380876cb05d1f37537b7892
|
||||
write=1
|
||||
|
||||
[sntp]
|
||||
enable=0
|
||||
server1=0.0.0.0
|
||||
server2=0.0.0.0
|
||||
poll_min=60
|
||||
|
||||
[comm]
|
||||
ca=1
|
||||
port=2404
|
||||
|
||||
[adc_cal]
|
||||
k_ua=10000000
|
||||
k_un=10000000
|
||||
k_ia=10000000
|
||||
k_ub=52800000
|
||||
k_uc=52800000
|
||||
k_ib=52800000
|
||||
k_ic=52800000
|
||||
k_in=52800000
|
||||
valid=0
|
||||
|
||||
[adc_cal_ofs]
|
||||
b_ua=0
|
||||
b_un=0
|
||||
b_ia=0
|
||||
b_ub=0
|
||||
b_uc=0
|
||||
b_ib=0
|
||||
b_ic=0
|
||||
b_in=0
|
||||
|
||||
[adc_cal_sec]
|
||||
r_ua=36381980
|
||||
r_un=36381980
|
||||
r_ia=1940570
|
||||
r_ub=36381980
|
||||
r_uc=36381980
|
||||
r_ib=1940570
|
||||
r_ic=1940570
|
||||
r_in=1940570
|
||||
|
||||
[run_par]
|
||||
db_ua=500
|
||||
db_ub=500
|
||||
db_uc=500
|
||||
db_un=500
|
||||
db_ia=5
|
||||
db_ib=5
|
||||
db_ic=5
|
||||
db_in=5
|
||||
db_freq=500
|
||||
```
|
||||
|
||||
读这份文件只要记住三件事:`[段名]` 分隔配置领域、`键=值` 是明文(没有十六进制、没有二进制、没有 CRC)、**段的先后与键的先后就是注册顺序与键表顺序**(引擎写文件时按这个顺序排)。
|
||||
|
||||
### 2.1 `[network]`:网口
|
||||
|
||||
| 键 | 类型 | 出厂值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `ip` | IP | `192.168.31.100` | 本机静态 IP(无 DHCP) |
|
||||
| `mask` | IP | `255.255.255.0` | 子网掩码 |
|
||||
| `gw` | IP | `192.168.31.1` | 网关 |
|
||||
| `mac` | MAC | `00:00:00:00:00:00` | 全 0 = 用 CH395F 芯片内置 MAC;填非 0 则覆盖 |
|
||||
|
||||
改这一段会**立即重建网络**(该段挂了变更回调),约 1~3 s 生效。键表与默认值在 `Drivers/BSP/NETCFG/net_cfg.c`。
|
||||
|
||||
### 2.2 `[ftp]`:FTP 登录
|
||||
|
||||
| 键 | 类型 | 出厂值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `user` | 字符串 | `admin` | 登录用户名 |
|
||||
| `pwd_hash` | 字符串 | `d82494f0…`(全串见上) | **SHA-256(用户名 拼接 口令)** 的十六进制;出厂值是 `sha256("adminadmin")`,即用户名 `admin` + 口令 `admin`。明文不落盘,改口令要自己算好摘要再填 |
|
||||
| `write` | 无符号 | `1` | `1` = 允许 STOR / DELE 等写操作,`0` = 只读 |
|
||||
|
||||
下次 FTP 登录生效。来源 `Drivers/BSP/NETCFG/ftp_cfg.c`。
|
||||
|
||||
### 2.3 `[sntp]`:SNTP 对时
|
||||
|
||||
| 键 | 类型 | 出厂值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `enable` | 无符号 | `0` | `1` = 开启对时客户端 |
|
||||
| `server1` | IP | `0.0.0.0` | 主服务器;全 0 表示未配置 |
|
||||
| `server2` | IP | `0.0.0.0` | 备用服务器 |
|
||||
| `poll_min` | 无符号 | `60` | 对时周期(分钟) |
|
||||
|
||||
客户端每轮直读 RAM 副本,改完保存即进入下一轮。来源 `Drivers/BSP/NETCFG/sntp_cfg.c`。
|
||||
|
||||
### 2.4 `[comm]`:IEC 60870-5-104 通讯参数
|
||||
|
||||
| 键 | 类型 | 出厂值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `ca` | 无符号 | `1` | 公共地址 CA(1~65535) |
|
||||
| `port` | 无符号 | `2404` | 104 服务端口(1024~65535) |
|
||||
|
||||
**改后需重启生效**(该链路在任务启动时建立连接参数)。来源 `App/protocol/iec104/iec104_comm.c`。
|
||||
|
||||
### 2.5 `[adc_cal]`、`[adc_cal_ofs]`、`[adc_cal_sec]`:采集标定
|
||||
|
||||
三段描述同一批 8 个采集通道(UA / UB / UC / UN / IA / IB / IC / IN),分别管**增益 k**、**零点 b**、**变比 r**:
|
||||
|
||||
| 段 | 键 | 类型 | 出厂值 | 含义 |
|
||||
|---|---|---|---|---|
|
||||
| `[adc_cal]` | `k_ua`…`k_in` | 有符号 | 电压族 `10000000` / 电流族 `52800000` | 增益,Q16 定点(值 / 65536 = 倍率);出厂值 = 按芯片量程算出的理论系数,只区分 TPAFE 与 STM32 两种来源 |
|
||||
| | `valid` | 无符号 | `0` | 已标定位图,bit0~bit7 对应上表通道顺序;`0` = 全部未标定 |
|
||||
| `[adc_cal_ofs]` | `b_ua`…`b_in` | 有符号 | `0` | 零点偏置(同一 Q16 口径) |
|
||||
| `[adc_cal_sec]` | `r_ua`…`r_in` | 有符号 | 电压族 `36381980` / 电流族 `1940570` | 一次侧变比,Q16;`0` 表示本路不折算 |
|
||||
|
||||
- 键顺序(`k_ua, k_un, k_ia, k_ub, k_uc, k_ib, k_ic, k_in`)**不是**通道顺序,看 `valid` 的位定义时按上表含义,别按下标猜。
|
||||
- 标定系数由标定流程写入并置对应 `valid` 位;手工改这三个段会让采集口径与标定记录脱节,只建议在厂商指导下做。
|
||||
- 来源 `App/algo/adc_cal.c`;通道语义与硬件对应 → `docs/硬件平台/ADC通道映射说明.md`。
|
||||
|
||||
### 2.6 `[run_par]`:运行参数死区
|
||||
|
||||
| 键 | 类型 | 出厂值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `db_ua`…`db_un` | 有符号 | `500` | 四路电压死区,毫伏 |
|
||||
| `db_ia`…`db_in` | 有符号 | `5` | 四路电流死区,毫安 |
|
||||
| `db_freq` | 有符号 | `500` | 频率死区,毫赫兹 |
|
||||
|
||||
用于 104 上送的越死区判断(COV 上送门槛)。值域由模块守卫(电压 ≤ 50000、电流 ≤ 1000、频率 ≤ 5000 毫单位,下限 0),越界写被拒。来源 `App/algo/run_par.c`。
|
||||
|
||||
> 这张示例文件是**首启模板**,8 段 46 键全部在场。真实设备上标定落盘后 `[adc_cal]` 三段会变成实测值,其余段则视现场是否改过而定。
|
||||
|
||||
## 3. 文件格式
|
||||
|
||||
### 3.1 位置与容量
|
||||
|
||||
| 端 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
@@ -34,14 +181,14 @@
|
||||
| 常量 | 值 | 含义 |
|
||||
|---|---|---|
|
||||
| `CFG_FILE_MAX_LEN` | 4096 B | 文件字节上限;超过即判损坏 |
|
||||
| `CFG_FILE_MAX_SECTIONS` | 8 | 可注册段数上限(**当前已用满**,见 §4.1) |
|
||||
| `CFG_FILE_MAX_SECTIONS` | 8 | 可注册段数上限(**当前已用满**,见 §5.1) |
|
||||
| `CFG_FILE_MAX_NAME_LEN` | 15 | 段名/键名最长字符数 |
|
||||
| `CFG_FILE_MAX_KEYS` | 16 | 单段键数上限 |
|
||||
| `CFG_FILE_SETTLE_CNT` | 2 | 沉降去抖轮数(2 轮 × 2 s 轮询 = 4 s) |
|
||||
|
||||
文件名 `config.ini` 满足 8.3 短名约束(`FF_USE_LFN=0`);段名与键名是**文件内容**,不受 8.3 限制,但受上表 15 字符限制。
|
||||
|
||||
### 2.2 语法
|
||||
### 3.2 语法
|
||||
|
||||
| 元素 | 规则 |
|
||||
|---|---|
|
||||
@@ -54,25 +201,13 @@
|
||||
| 行尾 | 设备写出 CRLF;解析同时接受 LF 与 CRLF |
|
||||
| 编码 | UTF-8(内容实际为 ASCII);解析为字节定向,不依赖代码页 |
|
||||
|
||||
### 2.3 出厂模板
|
||||
### 3.3 出厂模板
|
||||
|
||||
文件缺失(首启、或 FTP `DELE` 后重建)时,引擎按当前已注册段的 RAM 副本渲染一份新文件:固定 7 行文件头注释 + 每段 `[段名]` 与 `key=value` 行。
|
||||
文件缺失(首启、或 FTP `DELE` 后重建)时,引擎按当前已注册段的 RAM 副本渲染一份新文件:固定 7 行文件头注释 + 每段 `[段名]` 与 `key=value` 行。完整样子见第 2 章。
|
||||
|
||||
文件头原文(`s_doc_header`,cfg_file.c):
|
||||
模板**不含逐段逐键的中文注释**——段落顺序与键序就是注册顺序与键表顺序;渲染时按 `s_sections[]` 的注册顺序逐段输出,段内按键表顺序逐键输出。
|
||||
|
||||
```ini
|
||||
; ============================================================
|
||||
; STM32F4-Base 通用配置文件
|
||||
; 格式: INI (UTF-8 / CRLF),本文件为配置唯一来源
|
||||
; - 以 ';' 或 '#' 开头的行为注释,保存时保留
|
||||
; - 未知段/键保存时保留;缺失段/键保存时写回
|
||||
; - 编辑后经 FTP 上传或设备端保存,设备 4s 沉降后自动重载
|
||||
; ============================================================
|
||||
```
|
||||
|
||||
模板**不含逐段逐键的中文注释**——段落顺序与键序就是注册顺序与键表顺序。
|
||||
|
||||
### 2.4 值类型
|
||||
### 3.4 值类型
|
||||
|
||||
键表里每个键声明一种类型,解码/编码由引擎统一完成(`cfg_val_type_t`):
|
||||
|
||||
@@ -86,9 +221,9 @@
|
||||
|
||||
**逐键容错**:某个键写错不牵连别的键——非法值只让该键回落到工厂默认并打一条 `DBG_ERROR`,下次保存时该行会被改写成合法当前值(自愈)。
|
||||
|
||||
## 3. 运行时机制
|
||||
## 4. 运行时机制
|
||||
|
||||
### 3.1 上电加载
|
||||
### 4.1 上电加载
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
@@ -110,7 +245,7 @@ sequenceDiagram
|
||||
- 加载前各段 RAM 副本先整体复位为工厂默认,再逐行解析覆盖——因此"文件里缺键"天然等价于"取工厂默认"。
|
||||
- `net_cfg_load()` 在置 `SYS_EVT_STORAGE_READY` **之前**调用(`App/task/default_task.c`),使"存储就绪"这一屏障本身蕴含"配置已就绪"。
|
||||
|
||||
### 3.2 保存:外科手术式行替换
|
||||
### 4.2 保存:外科手术式行替换
|
||||
|
||||
`cfg_file_save()` 不改写整份文件,而是**只替换受管键所在的行**,其余内容(注释、空行、未知段、未知键、段落顺序)逐字节保留。
|
||||
|
||||
@@ -137,21 +272,21 @@ flowchart TD
|
||||
2. **引擎永不产出超长文件**:`s_write_doc()` 是唯一落盘闸口(模板与外科保存共用),超过 `CFG_FILE_MAX_LEN` 直接拒写。否则下一次开机 `load` 会把整份文件判损坏并销毁用户注释。
|
||||
3. **失败即原文件不动**:任何一步失败返回 -1,由调用方保留脏标志重试。
|
||||
|
||||
### 3.3 变更检测:2 s 轮询 + 沉降去抖
|
||||
### 4.3 变更检测:2 s 轮询 + 沉降去抖
|
||||
|
||||
`cfg_file_poll()` 由**配置引擎属主任务**周期调用(MCU = defaultTask,2 s;模拟器主循环 2 s),检测"文件被别人改了"(典型是 FTP 上传或编辑器直接改模拟器文件):
|
||||
|
||||
1. `f_stat` 取 `(size, mtime)`,与基线比对;
|
||||
2. 连续 `CFG_FILE_SETTLE_CNT`(2)轮稳定才认为改动结束(4 s);
|
||||
3. 沉降后先判 `size > 4096`:是则各段复位工厂默认 + 重建模板 + 自检留痕,**不触发段回调**(保留在线修复通道);
|
||||
4. 否则读全文并过**视图一致性守卫**(§3.4);
|
||||
4. 否则读全文并过**视图一致性守卫**(§4.4);
|
||||
5. 通过后逐段"复位默认 + 解析",挂回调的段若内容有变则调用其回调;最后刷新基线。
|
||||
|
||||
外部编辑到生效的总延迟约 2~5 s(4 s 沉降 + 网络重建时间)。
|
||||
|
||||
> 文件在位但内容被判无效时,poll 会保持 RAM 与基线不动并每 2 s 重试;持续被拒会在串口打 `[CFG] poll ... HELD` 与限速 WARN。
|
||||
|
||||
### 3.4 视图一致性守卫
|
||||
### 4.4 视图一致性守卫
|
||||
|
||||
存储层(dhara FTL + FatFS)在某些情形会给回**与 stat 不符的旧视图**:读长不足、读到同尺寸的全 0 旧映射块、或读取过程中文件被改写。若照单应用,后果是全段静默回到工厂默认(且随后落盘把工厂值写回文件,永久覆盖用户整定);若按短视图外科保存,则会吞掉后面的段。
|
||||
|
||||
@@ -166,7 +301,7 @@ flowchart TD
|
||||
- save 侧:拒绝落盘 → 返回 -1,原文件不动,调用方保留脏标志重试。
|
||||
- **已知边界**:内容合法但整体陈旧的视图(size/mtime/内容三者一致地滞后)引擎层无法检出——那属于卷层课题,重启是最后防线。
|
||||
|
||||
### 3.5 写者归属
|
||||
### 4.5 写者归属
|
||||
|
||||
`/config.ini` 的直接写者**收敛为 defaultTask**(配置引擎属主):
|
||||
|
||||
@@ -179,9 +314,9 @@ flowchart TD
|
||||
|
||||
**唯一例外是 FTP 上传(lftpd 的 `STOR`)**:它在 ftpTask 里直接原地覆写 `/config.ini`,不经引擎,也没有"临时文件 + rename"。它的后果由 poll 的沉降去抖与视图一致性守卫兜住(看到完整的新文件才重载);上传中途断开时 lftpd 会删除截断文件并回 `450`。因此"4 s 沉降 + 一致性守卫"不只是体感优化,它是 FTP 这条非原子写入路径的安全网。
|
||||
|
||||
## 4. 段与键表
|
||||
## 5. 段与键表
|
||||
|
||||
### 4.1 已注册段总览
|
||||
### 5.1 已注册段总览
|
||||
|
||||
当前注册 **8 段 = 段上限 8,已满**。新增配置领域必须先扩 `CFG_FILE_MAX_SECTIONS`(并复核 RAM)。
|
||||
|
||||
@@ -196,16 +331,18 @@ flowchart TD
|
||||
| `[adc_cal_sec]` | 8 | `App/algo/adc_cal.c` | 无 | 同上 |
|
||||
| `[run_par]` | 9 | `App/algo/run_par.c` | 无 | 104 COV 每拍直读 |
|
||||
|
||||
各段键名、工厂默认值、合法域与语义 → `docs/子系统设计/网络配置说明.md` §1 与 §3.3~§3.6,以及被引用的算法文档。本表只给"有哪几段、归谁、怎么生效"。
|
||||
**注意本表的顺序就是注册顺序**(`net_cfg_load()` 先注册 network / ftp / sntp,其余模块初始化时依次跟上),也是引擎写文件时的段落顺序。
|
||||
|
||||
### 4.2 注册顺序
|
||||
各键的类型、出厂值、含义与生效时机 → 本文第 2 章逐段表。对外使用手册(改法、FTP 操作流程、现场排查)→ `docs/子系统设计/网络配置说明.md`。
|
||||
|
||||
### 5.2 注册顺序
|
||||
|
||||
注册由各模块自己的初始化函数完成,引擎按注册顺序建立段表:
|
||||
|
||||
- `net_cfg_load()` 内统一注册 `[network]` / `[ftp]` / `[sntp]`(`s_net_register()` / `ftp_cfg_register()` / `s_sntp_register()`);
|
||||
- 其余段由各模块在 `cfg_file_load()` 之前的初始化路径里注册(`adc_cal` 三段、`run_par`、`iec104_comm`)。
|
||||
|
||||
### 4.3 接入一个新段
|
||||
### 5.3 接入一个新段
|
||||
|
||||
```c
|
||||
/* 1) 段 RAM 副本 + 工厂默认(两份同布局,默认值建议共用宏避免漂移) */
|
||||
@@ -233,7 +370,7 @@ static void demo_cfg_init(void)
|
||||
.data_size = sizeof(demo_cfg_t),
|
||||
.p_keys = s_demo_keys,
|
||||
.key_count = 2u,
|
||||
.p_cb = NULL, /* 需要"改了就提醒"时挂回调,见 §4.4 */
|
||||
.p_cb = NULL, /* 需要"改了就提醒"时挂回调,见 §5.4 */
|
||||
};
|
||||
(void)cfg_file_register(&s_sec);
|
||||
}
|
||||
@@ -246,7 +383,7 @@ static void demo_cfg_init(void)
|
||||
- `p_data` / `p_defaults` / `p_keys` 的生命周期必须覆盖引擎全部使用期(放静态区);
|
||||
- 新 `.c` 双端注册(uvprojx + `simulator/CMakeLists.txt`),见 `new-source-file` skill。
|
||||
|
||||
### 4.4 段变更回调
|
||||
### 5.4 段变更回调
|
||||
|
||||
```c
|
||||
void cfg_file_register_cb(const char *p_name, cfg_section_cb_t p_cb);
|
||||
@@ -256,9 +393,9 @@ void cfg_file_register_cb(const char *p_name, cfg_section_cb_t p_cb);
|
||||
|
||||
没有回调的段,消费方自己按拍从 RAM 副本读——这是多数段的做法,也更省事。
|
||||
|
||||
## 5. 接口
|
||||
## 6. 接口
|
||||
|
||||
### 5.1 引擎 API(`App/cfg/cfg_file.h`)
|
||||
### 6.1 引擎 API(`App/cfg/cfg_file.h`)
|
||||
|
||||
```c
|
||||
int cfg_file_register(const cfg_section_reg_t *p_reg); /* 注册段:0 成功 / -1 参数非法·段名重复·超上限 */
|
||||
@@ -269,7 +406,7 @@ void *cfg_file_section_data(const char *p_name); /* 取段 RAM 副本;
|
||||
void cfg_file_register_cb(const char *p_name, cfg_section_cb_t p_cb);
|
||||
```
|
||||
|
||||
### 5.2 平台后端(`App/cfg/cfg_file_store.h`,每端一份实现)
|
||||
### 6.2 平台后端(`App/cfg/cfg_file_store.h`,每端一份实现)
|
||||
|
||||
| API | 语义 |
|
||||
|---|---|
|
||||
@@ -286,7 +423,7 @@ void cfg_file_register_cb(const char *p_name, cfg_section_cb_t p_cb);
|
||||
|
||||
**为什么所有 KB 级缓冲都走 `cfg_store_alloc`**:ARMCC 默认 MicroLIB,C 库堆只有 512 B,直接 `malloc` 必失败且症状是"配置静默回落到工厂默认"。引擎自身(`cfg_file.c`)不出现 `malloc`。
|
||||
|
||||
## 6. 内存占用
|
||||
## 7. 内存占用
|
||||
|
||||
当前构建实测(`scripts/ram_baseline.tsv` 与 Keil map):
|
||||
|
||||
@@ -306,7 +443,7 @@ void cfg_file_register_cb(const char *p_name, cfg_section_cb_t p_cb);
|
||||
|
||||
平台总量台账(SRAM1 / CCM / Flash 的当前百分比与余量)→ `docs/内存管理/RAM预算台账.md`。
|
||||
|
||||
## 7. 异常与恢复
|
||||
## 8. 异常与恢复
|
||||
|
||||
| 场景 | 行为 |
|
||||
|---|---|
|
||||
@@ -323,7 +460,7 @@ void cfg_file_register_cb(const char *p_name, cfg_section_cb_t p_cb);
|
||||
|
||||
自检留痕标签(`syslog_post(SYSLOG_SELFTEST, ...)`):`cfg load oversized`、`cfg template write fail`、`cfg heap alloc fail`、`cfg save read fail`、`cfg save view stale`、`cfg poll view stale`、`cfg save line too long`、`cfg save overflow`、`cfg save write fail`。
|
||||
|
||||
## 8. 双端差异
|
||||
## 9. 双端差异
|
||||
|
||||
| 项 | MCU | 模拟器 |
|
||||
|---|---|---|
|
||||
@@ -337,7 +474,7 @@ void cfg_file_register_cb(const char *p_name, cfg_section_cb_t p_cb);
|
||||
|
||||
`get_fattime()` 在 `Lib/FatFs/ffsystem.c` 里直引用 `sys_clock` 墙钟(与调试日志时间戳同源),因此设备写出的文件时间与日志时间一致、FTP `LIST` 也显示真实时间;墙钟无效时回退固定值,此时变更检测退化为仅比 size。
|
||||
|
||||
## 9. 已知限制
|
||||
## 10. 已知限制
|
||||
|
||||
- **段落上限已满**:8/8,新增领域必须先扩宏并复核 RAM。
|
||||
- **FTP 上传非原子**:`STOR` 原地覆写,可靠性依赖沉降去抖与视图一致性守卫;上传中掉电会留下截断文件(下次上电按 4096 B 界限判损坏或按逐行容错解析)。
|
||||
|
||||
Reference in New Issue
Block a user