fix(cfg): 配置热重载吞段缺陷修复 + 两点标定工具链与台架实测落档

修复运行期改配置被打回出厂值的缺陷:cfg_file_poll() 按段循环复用同一
份读缓冲,而 s_parse() 通过 s_split_line()/s_key_value() 就地改写缓冲
(把换行与等号换成 NUL)。第一个段解析完,缓冲里已没有键值行,后续 7
个段静默保持出厂值;随后 run_par_store_save() 又把这份出厂值写回
config.ini,用户的标定值被永久覆盖。开机路径 cfg_file_load() 只解析一
轮,所以该缺陷长期不可见,只在运行中改配置时发作。

- s_parse() 改为非破坏性:入参 const char *,逐行 memcpy 到栈缓冲
  (CFG_LINE_TEST_MAX + 1)后再交给会破坏缓冲的解析子函数;超长行跳
  过(保存侧已拒绝落盘超长受管键行)。
- 新增 TC-CONFIG-063:同时改两段内容,断言第二个注册段也重载成功、
  含负值 INT 键存活,把「热重载吞段」钉成机器面。

新增两点标定台架工具链(test/host/):
- cal_two_point.py:整数算术镜像 adc_cal_two_point(),支持单路模式与
  从执行卡 CALDATA 表批量求解(--from-doc),带合法带与零点自检拦截。
- cal_write.py:复用 iec104_master 作库,经 104 定值段写 r 后写 b 并
  读回校验,是所有写入的唯一入口。

adc_task 的 meas: 心跳行精度提到 4 位小数,标定读数需要。

文档:新增《采样数据校正全流程》(端到端导航)与《ADC 两点标定执行
流程》(台架执行卡,含 CALDATA 可填表);ADC通道映射说明新增 §7.3 台
架实测结果(UA 554.687914、IA 29.634259,出厂默认值保持不变);配置
文件设计说明新增解析器契约 v1.19;采集与算法层设计说明 §13 系列与
README 索引同步。

台架实测:UA r=554.687914(出厂 1000.0 偏大 1.80 倍,根因是接线分压
使 PT 一次侧只拿到一半电压,实测与参数算定 606.06 只差 8.5%)、IA
r=29.634259(与出厂 29.4118 只差 0.76%,反证链路未算错)。UN 按用户
裁定本轮不标定,保护闭锁(vl=0x11)是预期行为,未伪造 VALID。

同时入库 .dsh/roles 角色定义(原被 .gitignore 挡住)。
This commit is contained in:
2026-11-13 01:35:58 +08:00
parent 18c087500a
commit 1355dbe1b1
29 changed files with 2470 additions and 201 deletions
+27 -1
View File
@@ -69,7 +69,9 @@
* TC-CONFIG-061 同尺寸全 0 旧映射块(长度/令牌双检全过)-> 内容判据拦下:
* HELD RAM 保旧、视图刷新后自愈应用 + 回调
* TC-CONFIG-062 保存链遇同尺寸全 0 旧视图 -> 拒存 -1,文件字节/写次数不动,
* 视图恢复后同一保存重试成功落盘
* 视图恢复后同一保存重试成功落盘
* TC-CONFIG-063 多段热重载:同一读缓冲按段各解析一轮,**每个段都必须生效**
* (s_parse 非破坏性;只断言首段会漏掉"后续段静默回默认"缺陷)
*
* 通过:全部 TC PASS(main 返回 0)。
* 入口:int main(void),返回 0=PASS / 1=FAIL(由 run 脚本判读)。
@@ -1281,6 +1283,30 @@ static void tc_view_content(void) {
CHECK(cfg_file_save() == 0, "save succeeds once view converges");
CHECK(strstr(vfs_get(), "u8=9") != NULL, "dirty value persisted on retry");
}
printf("[TC-CONFIG-063] multi-section reload: every section sees the same "
"non-destructive buffer\n");
{
/* 台架 2026-11-12 实证:热重载对同一份读缓冲**按段各解析一轮**,旧
* s_parse 原地把 '=' / '\n' 改写成 NUL —— 第一个段解析完,后面所有段
* 再拿到的文本里已无键值行 → 静默全体回出厂默认;随后落盘又把出厂值
* 写回文件,永久覆盖用户整定(现象:104 写入当场读得回、约 8 s 后被打
* 回,而开机 load 始终正确,因为 load 只解析一轮)。
* 本用例把**两个段同时改**并要求两段都生效——只断言第一个段是抓不到
* 这个缺陷的(既有 poll 用例都只断言 net 段,故长期绿)。 */
vfs_reset();
register_std();
vfs_put("[net]\r\nu8=5\r\n[sys]\r\nbaud=9600\r\nofs8=-7\r\nofs16=-9\r\n");
cfg_file_poll(); /* 建基线 */
vfs_put("[net]\r\nu8=88\r\n[sys]\r\nbaud=115200\r\nofs8=-7\r\nofs16=-9\r\n");
cfg_file_poll(); /* settle 1 */
cfg_file_poll(); /* settle 2 -> 重载 */
CHECK(s_net_data.u8 == 88u, "first registered section reloaded");
CHECK(s_sys_data.baud == 115200u,
"later registered section reloaded too (buffer not consumed)");
CHECK(s_sys_data.ofs8 == -7, "signed INT key in later section survived");
CHECK(s_sys_data.ofs16 == -9, "second signed INT key in later section survived");
}
}
int main(void) {