Files
STM32F4-Base/App/algo/adc_cal.h
T
wandering1 d64bbdc57f feat(wave): 故障录波数据面、接线与单通道回放页(软件闭环交付)
数据面(App/algo,纯逻辑,双端编译)
- wave_ring:8 路 × 320 点列优先环(1 kHz,预触发 160 + 后触发 160),adcTask
  唯一写者;触发/冻结/封存/冷却四态,冻结持续到落盘回执才解冻,滞留 2 s 自弃
  兜底——下一次真故障无波可录比丢一段更贵
- wave_store:段头编解码 + 拉模式打包游标 + 自带无表位运算 CRC-16/MODBUS(带
  锚点自检)+ 段名与整段长度等式;格式不依赖平台类型宽度
- 段头只存原始码值与封存瞬间生效系数,工程量只当单位标签、不进任何算式
- 三套主机单测(环 113 / 编解码 170 / 触发状态机 110),全部无桩、生产源原样
  纳入;新文件补 stddef 是 ARMCC 与主机差异,主机侧照不出这条分叉
- test/host/wave_read.py 是按 §6.2 的独立第二实现(dump/fft/shape/plot),92 条
  自洽断言;三份合成段互读双校验全过、哈希钉死,格式面双向闭合
- 三套新单测不加专属钩子,由覆盖率总闸全量真跑(沿用既有裁定)

接线(任务层)
- adc_cal:新增生效系数的 32 位定点原值入口(与既有浮点入口共用生效视图),
  段头按最低有效位精确记账,不经浮点回算
- adcTask:每拍压 8 路语义原始码值并推进状态机,封存那一拍同拍交棒封存瞬间事实;
  台架定周期自抓走双层编译门,产品镜像里零存在;串口新增一条 wave: 周期行
- defaultTask:卷空闲后一次心跳整段搬完(try 锁 + 256 字节分片 + 一次完整开档到
  关档),成败都回执;失败先删半成品再计错,段号只在成功时推进;持锁超 50 ms
  补一条告警并记历史峰值(喂狗余量可核)
- Lead 复核补第四道并发陷阱:采集任务优先级高于落盘道,搬段中途它可能正好把滞留
  超时的本段自弃、甚至封出下一段——数据区校验和是对「实际读到的字节」算的,
  半新半旧的段照样自洽,故关档后复检环侧身份判废:删文件、不补账、段号不推进
- Lead 复核抓到触发挂号不是原子操作(旧实现分三个字节写,消费者可在窗口里读到
  上一段的触发源与元件号):已把载荷压进一个字节,越界当场拒且不记任何计数;
  段文件字节布局零改动,三份合成段哈希逐字节不变
- protectTask:保护启动上升沿同点请求录波,一拍一次、元件号取最低位;判据本体
  零改动

人机(160×160 单色屏)
- 菜单树节点 26「手动录波」绑页面 + 记录查询组末新增「录波回放」叶,重跑生成器
  得 43 节点 / 34 叶 / 30 已绑,页面映射 28 → 30
- 回放页一屏一路、触发点前后各一周波共 40 点、每点 3 像素阶梯线(只用水平与
  垂直两种线段——单色屏斜线会被阈值裁掉);零点虚线、触发光标、窗口峰值、
  单位徽标与形状受限徽标;空态与坏段各一句显式文案,绝不用半截波形冒充数据
- ui_data 新增录波注入通道(六件操作表、三态返回);执行侧胶水带段头缓存、
  手动请求后连缓存一起作废、逐点走全仓唯一的码值换算入口
- 模拟器接真实环与编解码合成两段(含坏段与空态旗标),6 张新黄金参考,既有
  60 张逐字节零漂移未用更新模式;字库 218 → 224 字 / 319 字形
- 两份图形配置里图表组件仍为关;零堆分配;页面池水位不变
- 回放读路径的 uiTask 阻塞上界按实码写清:一次渲染 = 段表刷新 + 未缓存段头最坏
  22 次小读;已验段只剩一次开窗读 + 40 点解码;无实测数不编,实测归台架、
  仪器用已在跑的单轮工作耗时探针,不新加埋点

台账与文档
- 内存台账:录波环与落盘/回放静态逐条入册,三档对照 81,536 → 88,296 → 89,936
  字节(62.2% → 68.6%),累计 +8,400;预估 5.9 KB 与实测 +6,760 的差额点名;
  散列文件头注释同步;任务栈表核对后无需抬栈;体积趋势行与同码凭证由权威构建
  重打(0 错误 0 警告,四项体积与上一轮相同——本轮改动只有注释与声明位置)
- 设计说明:§5 补第四条并发陷阱;§6.3 定字段口径(两份独立实现的共同依据);
  §7 回填实测;§9 周期行写实;§10 台架判据改两段式且不比绝对相位;§12 补读路径
  风险行;抬头状态改成「代码面已交付、未做完的只有板级那一轮」
- 卡片:软件闭环一栏列证据;台架三条按用户裁定保持未完成,不做虚假销项
- 口径同步:数据可信、UI 补齐、页面补齐规划、产品需求、采集短板评测、任务规划
  索引与两份 README;陈旧现状句清扫 16 处(带日期戳的历史取数行一律不动)
- 门禁说明:nested-comment 记仓库根探测必须兼容 linked worktree 的 gitdir 文件
  形态(修前该钩子在任务树里恒报环境错、静默不可用);coding-standard 记
  「函数头注释超过 24 行就把函数功能挤出回看窗口」这条机制与本次现场
- 覆盖率基线登记两个新覆盖模块(套件 41 → 44 套);环单测重打后该文件有效行
  227 → 226、覆盖行 226 → 225,比率仍 99.6%,是分母变小不是覆盖率回退

为什么是单一提交:文档链接、双端注册、生成器幂等(菜单与字库)、内存数字与
体积事实源、编号门禁这五道整仓门禁要求代码、页面、菜单树、字库、文档与台账
同处一个提交才自洽,按数据面/接线/人机/台账拆成四笔必然红其中至少四道

编号门禁新增行 14 处命中已按语义改写:魔数常量按字符命名、段名样例改由格式串
生成、频谱表头改 f / 2x / 5x 并加一行图例;改写后自洽断言 92 条仍全过
2026-10-29 19:23:15 +08:00

277 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:通道标定与量纲折算(标定折算,「数据可信」标定折算与落盘整定)
* 模块功能:把 adc_input 的原始码值折算成工程量——模型与系数口径的唯一落点:
* 工程量 = (code + b) × k_f,k_f = k[µV/码] × 1e-6
* k 以 int32 **Q16**(µV/码 × 65536)落盘、b 以 int32 码值落盘,
* RAM 副本注册进 cfg_file 引擎([adc_cal] / [adc_cal_ofs] 两段,
* 布局见 docs/任务规划/数据可信.md §4.4);**不挂回调**——RAM 副本
* 即生效值,逐点折算现取现用(1 kHz × 9 通道 = 9k 次/秒浮点乘,可忽略)。
* 三态可用性:ADC_CAL_F_VALID(已按变比标定 → 工程量为二次值)与
* ADC_CAL_F_CLIPPED(V0.1 硬件削顶)由 adc_cal_flags() 单点查询,
* 104 / UI / 保护闭锁(未标定即闭锁)共用(docs/任务规划/数据可信.md §4.2)。
* **未标定闭锁的判定本身也归本层**(`adc_cal_prot_blocked()`):它讲的是
* 「这几路标定齐了没」,属标定层事实,不是任务编排逻辑——保护任务与 UI
* 组装器都只是它的消费者(道F task-16 把此前的两份实现收成一份)。
* ⚠ 输出单位口径 = **ADC 引脚电压 V**(eng=0):ROM 默认系数按量程口径冻结
* 定死的引脚侧 LSB(TPAFE 152.59 µV/码、STM32 805.66 µV/码,见
* docs/硬件平台/ADC通道映射说明.md §7.1);端子/子板变比确认与两点
* 标定完成前不得把输出当二次值消费。TEMP 不参与线性标定
* (决策 5),adc_cal_apply() 原样透传码值。
* 本层**纯算法 + 纯数据**:不碰寄存器、不等事件;adc_cal_init() 内核前
* 可调(注册进引擎必须先于 cfg_file_load,FTP 鉴权确立的契约);apply/flags
* 任意上下文可读(cfg RAM 副本 4 字节对齐字读写在 Cortex-M4 上原子,
* 与 defaultTask 的 load/poll 复位存在 µs 级混窗——设计接受,见 .c 头)。
* 适用平台:STM32F407ZGTx(Cortex-M4F);主机侧纯逻辑单测 test/host/adc_cal/
* 作者:DTU 项目组
* 创建日期:2026-10-25(道A 标定折算与落盘整定)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:Q16 系数/零点 + 折算/flags/集
* v1.1 2026-10-25 DTU 项目组 运行参数段:+adc_cal_b_codes()(run_par 回显/RMW 用)
* v1.2 2026-10-26 DTU 项目组 道F task-16:+adc_cal_prot_blocked()——「UA/UN/IA
* 三路 VALID 是否齐」这份判据停走条件从
* protect_task.c 与 ui_data_feed.c 的两份重复实现收成本层
* 单点(DTU_BENCH 旁路同时收成一处)
* v1.3 2026-10-29 DTU 项目组 故障录波 task-2:新增 adc_cal_k_q16()——k 的 int32
* Q16 原值直读口(adc_cal_k_uv 的孪生)。录波段头 k 字段
* 是 LSB 精确记账,float 在 5.28e7 码字上掉尾数,
* 禁止经浮点反推(docs/子系统设计/故障录波设计说明.md §6.3)
*/
#ifndef ADC_CAL_H
#define ADC_CAL_H
#include <stdint.h>
#include "adc_input.h" /* adc_semantic_t(语义通道编号 = 系数表下标口径) */
#ifdef __cplusplus
extern "C" {
#endif
/* 通道可用性标志(adc_cal_flags() 返回值位) */
#define ADC_CAL_F_VALID (0x01u) /* k 已按变比标定 → 工程量为二次值(两点标定后置位) */
#define ADC_CAL_F_CLIPPED (0x02u) /* 硬件削顶(V0.1 STM32 侧单极性无偏置)→ 交流量不可信 */
/*
* ROM 默认系数(int32 Q16 = µV/码 × 65536,量程口径冻结定死的引脚侧口径):
* TPAFE ±5 V 档:10 V 跨度 / 65536 码 = 152.587890625 µV/码 → ×65536 = 10,000,000(整)
* STM32 0~3.3 V:3.3 V / 4096 码 = 805.6640625 µV/码 → ×65536 = 52,800,000(整)
* 两个默认值在 Q16 下**无舍入**(系数定点舍入项从误差预算里抹掉,
* 选型依据 → docs/任务规划/数据可信.md §4.1)
*/
#define ADC_CAL_K_Q16_TPAFE (10000000L)
#define ADC_CAL_K_Q16_STM32 (52800000L)
/* 系数合法带(「数据可信」§8 风险表):k 必须落在板级 ROM 系数的 ×[0.5, 2.0]
* 区间内;带宽用 ROM 值移位实现(>>1 / <<1),不设独立宏防两处真相 */
/* 零点偏移幅值上限(码值):超此即判文件损坏/异常标定,回退 ROM 并留痕 */
#define ADC_CAL_B_MAX (8192L)
/*
* 函数功能:标定层初始化——RAM 副本置 ROM 默认 + 注册两段进 cfg 引擎(幂等)
* 入口参数:无
* 返 回 值:无
* 限定条件:内核启动前调用(app_main_init);注册必须先于 cfg_file_load
* (「所有受管段先注册、后 load」契约,见 Drivers/BSP/NETCFG/net_cfg.c 的
* net_cfg_load 注释)
* 函数说明:段属主为 defaultTask(配置引擎),本模块只提供 RAM 副本与默认值;
* 文件值由引擎 load/poll 原地写入 RAM 副本,本层逐点折算现读
*/
void adc_cal_init(void);
/*
* 函数功能:码值 → 工程量折算(「数据可信」§4.1 模型)
* 入口参数:sem - 语义通道(TEMP 透传不折算) adc_semantic_t
* code - 原始码值(TPAFE 16 位补码 / STM32 0..4095) int32_t
* 返 回 值:工程量浮点(未标定时单位 = ADC 引脚电压 V;VALID 后置位 = 二次值) float
* 限定条件:无(任意上下文,纯读)
* 函数说明:eng = (code + b) × k[µV/码] × 1e-6,由 Q16 现值派生,无缓存副本
* (避免无回调下的陈旧系数);k/b 越合法带 → 该通道回退 ROM 默认 +
* 首见沿 [ERR] 留痕(adc_cal_init 重置留痕位),flags 同时不报 VALID
*/
float adc_cal_apply(adc_semantic_t sem, int32_t code);
/*
* 函数功能:读通道可用性标志(消费者判「能不能信」的唯一入口)
* 入口参数:sem - 语义通道 adc_semantic_t
* 返 回 值:ADC_CAL_F_VALID / ADC_CAL_F_CLIPPED 组合;TEMP 恒 0;sem 越界恒 0 uint32_t
* 限定条件:无
* 函数说明:VALID = 文件位图置位 **且** 该通道 k 在合法带内(哨兵不落状态,
* 天然跟随 load/poll 重载);CLIPPED = V0.1 静态表(UB/UC/IB/IC/IN)
*/
uint32_t adc_cal_flags(adc_semantic_t sem);
/*
* 函数功能:**未标定闭锁判定**——保护判据所需的三路标定是否齐(「数据可信」未标定即闭锁
* / §4.3;道F task-16 把它从两处重复实现收敛成这一份真源)
* 入口参数:无
* 返 回 值:1 - 闭锁(UA/UN/IA 中至少一路 `ADC_CAL_F_VALID` 未置位,判据链应停走);
* 0 - 三路全 VALID(标定侧允许判据跑) uint8_t
* 限定条件:任意上下文(纯读 `adc_cal_flags()`,与它同一条并发契约:int32 对齐
* 字读写原子、cfg poll 重载 µs 级混窗设计接受);**现查,本层不留任何状态**
* 函数说明:① **为什么恰好这三路**:V0.1 把 8 路电气量分给两片转换器(AGENTS
* 「双转换器无共同采样触发」),UA/UN/IA = TPAFE 侧这三路是**唯一有效**
* 的测量通道;UB/UC/IB/IC/IN 即使将来标定也另受 `CLIPPED` 品质约束
* (M5 快照层处理),不掺进本闭锁源。
* ② ⚠ **不得当「保护在跑」的总括用**:判据停走共四路来源,本函数只覆盖
* 第二路——(a) 自检失败闭锁 采样故障闭锁(`adc_health_flags()`);(b) 本函数
*(保护功能清单见 docs/算法/继电保护功能复现规划.md)
* (未标定);(c) 定值校验和失配闭锁(`prot_set_locked()`);(d) 全局软压板
* 退出(`PS_GLOBAL_EN` = 0)。要判「这拍到底评估了没有」必须四路一起看
* (编排顺序见 `App/task/protect_task.c`)。
* ③ ⚠ **两个同族谓词与它不是一件事,不要顺手合并**(三种口径各有用途):
* · 电气 **8** 路全 VALID 才升 eng=二次值(量纲标签,判据在
* `App/app/ui_data_feed.c` 的 `feed_eng()`)——并进来会让部分标定的整帧
* 被误标二次值;反过来把本三路口径当 8 路用,V0.1 下 UB/UC/IB/IC/IN
* 永不置位 → 徽标与停走**永不解除**;
* · 逐通道打印 VALID/CLIPPED 位图是诊断输出(`App/task/adc_task.c`),
* 不是判定。
* ④ 台架调试旁路 = 编译期 `-DDTU_BENCH`(「数据可信」§4.3 决策 1 的例外通道,
* 仅本地台架自行定义;本仓任何工程档都不定义 = 产品恒强制)。旁路**只在
* 本函数实现内部这一处**,调用方不再各自写 `#ifndef`:否则有人只给单个
* TU 加宏,屏上「未标定」徽标与判据停走当场分叉,且 0 错误 0 警告。
*/
uint8_t adc_cal_prot_blocked(void);
/*
* 函数功能:读通道当前生效系数(µV/码,浮点)
* 入口参数:sem - 语义通道 adc_semantic_t
* 返 回 值:k[µV/码](回退后口径);TEMP / 越界返 0 float
* 限定条件:无
* 函数说明:采样通道自检 门限换算、日志与整定界面回显用;勿据其反推二次值(看 flags)
*/
float adc_cal_k_uv(adc_semantic_t sem);
/*
* 函数功能:读通道当前生效零点偏移(码值,浮点)——adc_cal_k_uv 的孪生入口
* 入口参数:sem - 语义通道 adc_semantic_t
* 返 回 值:b[码值](越带时为 0,与折算同视图);TEMP/越界返 0 float
* 限定条件:无
* 函数说明:104 运行参数段(「数据可信」这一项)b 覆盖回显与 k 单侧改写的 RMW
* 读侧用(App/algo/run_par.c);勿据其反推二次值(看 flags)。
*/
float adc_cal_b_codes(adc_semantic_t sem);
/*
* 函数功能:读通道当前生效系数的 **int32 Q16 原值**(µV/码 × 65536)——
* adc_cal_k_uv() 的孪生入口,给「必须 LSB 精确」的消费者用
* 入口参数:sem - 语义通道 adc_semantic_t
* 返 回 值:k[Q16 原值](与折算同一生效视图:越带回退 ROM、b 不参与);TEMP/越界返 0 int32_t
* 限定条件:无(任意上下文,纯读)
* 函数说明:故障录波段头的 k 字段是 int32 LSB 精确记账(docs/子系统设计/故障录波设计说明.md
* §6.3 裁定)——float 还原后在 5.28e7 码字上掉尾数,**禁止**拿
* adc_cal_k_uv() 反乘 65536 回算落盘,故开本原值口。
*/
int32_t adc_cal_k_q16(adc_semantic_t sem);
/*
* 函数功能:整定入口——写通道系数与零点,并置位 VALID(「数据可信」标定落盘与整定入口)
* 入口参数:sem - 语义通道(电气 8 路) adc_semantic_t
* k_q16 - 系数,µV/码 × 65536 内 int32_t
* b_codes - 零点偏移,码值 内 int32_t
* 返 回 值:0 - 成功;-1 - 参数非法/越出合法带(RAM 不动,[ERR] 留痕) int
* 限定条件:**整定路径上下文**(defaultTask 标定流程/整定链;运行参数段落地起 iec104Task
* 经 App/algo/run_par.c 的 0x8040~/0x8048~ 直通写亦为授权写者——写的仍是
* 引擎对齐 int32 单字,µs 级混窗契约同「数据可信」§4.4)。勿在 adcTask 调用
* 函数说明:**只写 RAM 副本,不置脏、不落盘、不返回"稍后会存"的承诺**——落盘由属主经
* cfg_file_save 完成,而"要不要落盘"这件事只有一个真源:run_par 的脏标志。
* 因此授权写者是 run_par 的语义 setter(写值 + 置脏成对发生,lead 裁②);
* 绕过它直调本函数 = 值只活在 RAM 里,重启即丢且**没有错误返回**,
* 该形态现可被本层观测计数抓到(差分口径见下方 adc_cal_stats_t 那张表)
*/
int adc_cal_set(adc_semantic_t sem, int32_t k_q16, int32_t b_codes);
/*
* 函数功能:两点标定公式(「数据可信」标定项的算术核,纯函数无状态)
* 入口参数:c_lo/c_hi - 两点码值(c_hi > c_lo) int32_t
* v_lo_uv/v_hi_uv - 两点实测电压(µV,v_hi > v_lo,端子/引脚域均可) int32_t
* p_k_q16 / p_b - 输出:系数(Q16)与零点偏移(码值) int32_t *
* 返 回 值:0 - 成功;-1 - 参数/斜率非法;-2 - 零点越 ±ADC_CAL_B_MAX(先查前端,
* 不得用系数凑错斜率,「数据可信」§8 风险表) int
* 限定条件:无(纯整数运算,主机侧可直接单测)
* 函数说明:k = (v_hi−v_lo)×65536/(c_hi−c_lo)(四舍五入),b = v_lo×65536/k − c_lo;
* 实测注入未做(台架待跑),本函数即「公式齐备」的交付物
*/
int adc_cal_two_point(int32_t c_lo, int32_t c_hi, int32_t v_lo_uv, int32_t v_hi_uv,
int32_t *p_k_q16, int32_t *p_b);
/*
* 函数功能:通道码值域「贴轨带」门限(采样通道自检 越界检出的门限来源,按 FS 百分比)
* 入口参数:sem - 语义通道 adc_semantic_t
* p_lo_th - 下轨带上界(code ≤ 此值判触底) int32_t *
* p_hi_th - 上轨带下界(code ≥ 此值判触顶) int32_t *
* 返 回 值:0 - 已给出门限;-1 - TEMP/越界(不做贴轨监视) int
* 限定条件:无
* 函数说明:TPAFE 双极性 ±98% FS(±32112);STM32 上轨 98% FS(4013)、
* 下轨 2% FS(81);判定状态机在 adc_health_rail_watch()(采样通道自检)
*/
int adc_cal_rail_ths(adc_semantic_t sem, int32_t *p_lo_th, int32_t *p_hi_th);
/*
* 观测计数:把「改了没落盘」从意图式陈述变成可诊断事实(道G task-43 第②项;
* 先例 App/fs/vol_lock.h 的同族设计——只计数、不取锁、不在调用点打日志、不打 [ERR])
*
* 三态语义(**定义只在本头文件这一处**,消费者只描述取数与断言,不重定义):
* set_ok RAM 副本被本层 API 成功改写的累计次数
* set_reject 被本层拒掉的整定请求累计次数(参数非法 / 越出合法带)
* persisted_set_ok **水位**而不是计数:最近一次随整档保存落盘成功时的
* set_ok 快照(由 adc_cal_note_persisted() 盖写,永不越过 set_ok)
*
* 未落盘差额 = set_ok − persisted_set_ok,即"自上次成功落盘之后被改写的次数"。
* 单看差额不够定性,必须与 run_par_dirty_peek() 成对读(两列一起才只有一种解释):
*
* 差额 run_par_dirty_peek() 说的是什么事
* ------ ---------------------- ----------------------------------------------
* 0 0 盘与 RAM 齐(或压根没改过)——健康
* >0 1 改了、还没到落盘时机——正常在途
* >0 0 **改了且永远不会落盘**:写者绕过 run_par 的语义
* setter 直调 adc_cal_set()(运行参数段起的事)
*
* 消费者告诫(与 vol_lock_get_stats() 同一套,别重犯):
* ① 本组接口不取锁、不取时刻,任意上下文可读;三个数各自是 uint32 单字读写,
* Cortex-M4 上原子,但三个数之间**没有共同时刻**——别把它们拼成"一个瞬间的快照"
* 下结论,定性只按上面那张两列表成对读。
* ② 需要"被观测到的时刻"请在消费者侧自盖并冠 obs_ 前缀命名(先例:喂狗点单写者 latch),
* 本层不存时刻——存了就得连带管溢出与单位。
* ③ 这些计数**不参与任何判定**:能不能信只看 adc_cal_flags() /
* adc_cal_prot_blocked(),要不要落盘只看 run_par 的脏标志。别拿差额去改控制流,
* 那等于把观测升级成第二真源(标定写入口已由 run_par 语义 setter 收口,不再加口)。
* ④ 写清盲区:本层刻意**不挂** cfg_file 回调,因此"盘 → RAM 的覆盖"(cfg_file_load
* 与外部变更重载)不产生任何计数;未落盘的改值被一次重载无声吞掉,正是这三个
* 数照不到的那一条。要照它得先给本层挂回调 = 行为改动,另行立项处置。
*/
typedef struct {
uint32_t set_ok; /* 成功改写 RAM 副本次数(见上方唯一落点) */
uint32_t set_reject; /* 被拒次数(见上方唯一落点) */
uint32_t persisted_set_ok; /* 落盘水位,不是计数(见上方唯一落点) */
} adc_cal_stats_t;
/*
* 函数功能:读标定层观测计数(只读,不改任何状态)
* 入口参数:p_out - 输出:三个观测计数 adc_cal_stats_t *
* 返 回 值:无 void
* 限定条件:任意上下文可读(含 ISR 与内核启动前);adc_cal_init() 之前可读,得全 0
* 函数说明:p_out 为 NULL 时静默返回——观测件不得反过来制造故障
*/
void adc_cal_get_stats(adc_cal_stats_t *p_out);
/*
* 函数功能:落盘成功回执——把水位 persisted_set_ok 盖写为当前的 set_ok(**不是自增**)
* 入口参数:无 void
* 返 回 值:无 void
* 限定条件:只允许配置引擎属主侧"整档保存已成功"那一条路径调用;当前唯一调用点 =
* App/algo/run_par.c 的 run_par_store_save() 中 cfg_file_save() 返 0 之后
* 函数说明:为什么盖写不自增——一次 save 覆盖整档,可能对应多次整定改写(逐通道
* 标定 3 路 = 3 次 adc_cal_set + 1 次 save);自增会留下 2 次"假未落盘"。
* 水位语义让差额只反映"上次落盘之后的改写",回归锁见
* test/host/adc_cal/adc_cal_test.c 的 TC-ADCCAL-021
*/
void adc_cal_note_persisted(void);
#ifdef __cplusplus
}
#endif
#endif /* ADC_CAL_H */