refactor(adc): 最小二乘拟合移出固件,只留 PC 侧唯一实现

用户裁定(2026-11-13):设备本体只需要校正后的参数,不需要自己拟合
标定曲线,故固件侧最小二乘拟合整体移出,拟合的唯一实现留在 PC 侧
test/host/cal_fit.py。

删除的死代码(生产零调用、上一轮 map 里已被 linker 标 Removing):
- adc_cal.h:adc_cal_fit() 声明、8 个拒绝码、5 个常量
- adc_cal.c:s_div_round() / s_fit_accum() / adc_cal_fit() 共 224 行
- adc_cal_test.c:tc_00b_fit 226 行(184 -> 150 条)

原样保留的设备侧安全闸:
- adc_cal_apply() 折算、adc_cal_set() / adc_cal_set_ratio() 参数合法
  带拦截(防工具写坏参数)、adc_cal_flags() / adc_cal_prot_blocked() /
  adc_cal_rail_ths()。设备不「算」,但必须「用」和「验」。

测试面:
- cal_fit.py 转为唯一实现,新增 --selftest:承接原 C 侧金标向量
  (r_q16=39322000 / b=12)与 4 条拒绝路径,共 11 条断言;已做变异
  测试证明它会红(改坏圆整口径 -> 2 条 FAIL)
- cal_two_point.py 删除,两点工具由多点拟合取代

文档口径统一为「求参在 PC、设备只做折算与合法带校验」,6 篇 docs 同步;
执行卡改名 ADC多点标定执行流程.md(正文同步 5 点最小二乘口径)。

cfg 热重载吞段缺陷的解析器契约与 TC-CONFIG-063 机器钉一并入库。
Program Size 不变(Code=256196):删掉的是从未链接进镜像的死代码。

验证:Keil 0 errors 0 warnings;adc_cal 150/150;selftest 11/11;
ci_local.py RC=0(static 48/48、manual 三根、size-gate、host-unit
4341/4341);doc-links / mermaid / mojibake 全 0。
This commit is contained in:
2026-11-13 08:09:09 +08:00
parent 1355dbe1b1
commit 7c505b2457
27 changed files with 945 additions and 608 deletions
+3 -61
View File
@@ -22,9 +22,9 @@
* TC-ADCCAL-009 合法带哨兵回退:坏 k/坏 b → ROM 值 + 每通道一次 [ERR] +
* flags 不报 VALID(即便位图置位)+ init 重置观测窗
* TC-ADCCAL-014 零点 b 生效(set 路径):(code+b)×k×r 逐项可算
* TC-ADCCAL-015 两点标定公式:合成 r/b 回算(独立推导、相对误差 1e-6)+
* 写回往返(set k/b + set_ratio 后两点复现端子值)+ 参数/斜率/
* k 合法域/v 越 ±1e9/r < 1.0(-1)/零点越界(-2)守卫
* TC-ADCCAL-015 (已移除)N 点最小二乘拟合:v2.2 起拟合移出固件,算术核唯一实现
* 在主机侧 test/host/cal_fit.py,其 --selftest 承接原金标向量
* (r_q16=39322000 / b=12)与拒绝路径断言。本文件不再覆盖。
* TC-ADCCAL-016 rail_ths 门限:TPAFE ±32112 / STM32 4013·81 / TEMP 不监视
* TC-ADCCAL-017 init 幂等:重复调用 RAM 复位默认 + 重新注册
* —— 以下走真实 cfg_file 引擎(标定落盘与整定入口 DoD)——
@@ -430,63 +430,6 @@ static void tc_00a_b_effect(void) {
"IA apply = (code-77)*ROMk*r_curr");
}
/* TC-ADCCAL-015:两点标定公式 + 写回往返 */
static void tc_00b_two_point(void) {
int32_t rq = 0, bb = 0;
const int32_t k0 = 10000000L; /* 该路生效 k(TPAFE 152.587890625 uV/code) */
const double r0 = 1000.0; /* 待标定的端子 vs 引脚变比(电压族量级) */
const int32_t b0 = -30L; /* 真零点,码值 */
const int32_t c1 = 300, c2 = 800; /* 两点码值(合端子 41 V / 117 V 量级) */
int32_t v1, v2;
int rc;
printf("[TC-ADCCAL-015] two-point formula recovers synthetic r/b\n");
/* 合成测量:v = (c + b0) * k0/65536 µV(lround 模拟量化读数) */
/* 合成测量:端子 uV = (c + b0) x (k0/65536) uV/code x r0(lround 模拟量化读数) */
v1 = (int32_t)my_lround(((double)c1 + (double)b0) * ((double)k0 / 65536.0) * r0);
v2 = (int32_t)my_lround(((double)c2 + (double)b0) * ((double)k0 / 65536.0) * r0);
rc = adc_cal_two_point(c1, c2, v1, v2, k0, &rq, &bb);
CHECK(rc == 0, "two_point ok");
CHECK(((double)rq > (r0 * 65536.0 * (1.0 - 1.0e-6))) &&
((double)rq < (r0 * 65536.0 * (1.0 + 1.0e-6))),
"r recovered within 1e-6 relative");
CHECK(bb > (b0 - 3) && bb < (b0 + 3), "b recovered within +-3 codes");
/* 写回往返:set(k,b) 置位 + set_ratio 定量纲,两点都应复现端子值 */
reset_all();
adc_cal_init();
CHECK(adc_cal_set(ADC_SEM_UA, k0, bb) == 0, "set recovered k/b");
CHECK(adc_cal_set_ratio(ADC_SEM_UA, rq) == 0, "set recovered ratio");
CHECK((adc_cal_flags(ADC_SEM_UA) & ADC_CAL_F_VALID) != 0u,
"VALID needs both writes (k/b band + ratio configured)");
CHECK(near_d(adc_cal_apply(ADC_SEM_UA, c1), (double)v1 / 1.0e6),
"roundtrip v(c_lo) = measured");
CHECK(near_d(adc_cal_apply(ADC_SEM_UA, c2), (double)v2 / 1.0e6),
"roundtrip v(c_hi) = measured");
printf("[TC-ADCCAL-015] two_point guards\n");
CHECK(adc_cal_two_point(100, 100, 0L, 100000L, k0, &rq, &bb) == -1, "dc=0 rejected");
CHECK(adc_cal_two_point(100, 200, 50000L, 50000L, k0, &rq, &bb) == -1, "dv=0 rejected");
CHECK(adc_cal_two_point(100, 200, 100000L, 50000L, k0, &rq, &bb) == -1, "inverted slope rejected");
CHECK(adc_cal_two_point(100, 200, 0L, 1000L, 0L, &rq, &bb) == -1, "k_q16 = 0 rejected");
CHECK(adc_cal_two_point(100, 200, 0L, 1000L, 100000001L, &rq, &bb) == -1, "k_q16 > 1e8 rejected");
CHECK(adc_cal_two_point(100, 200, 0L, 1000L, k0, NULL, &bb) == -1, "NULL r rejected");
CHECK(adc_cal_two_point(100, 200, 0L, 1000L, k0, &rq, NULL) == -1, "NULL b rejected");
/* v 超 +-1e9 uV(= +-1000 V):几乎必然把 mV/码值当 uV 填了 */
CHECK(adc_cal_two_point(100, 200, 1000000000L, 1000100000L, k0, &rq, &bb) == -1,
"v beyond +1e9 rejected");
CHECK(adc_cal_two_point(100, 200, -1000100000L, -1000000000L, k0, &rq, &bb) == -1,
"v beyond -1e9 rejected");
/* 算出的变比 < 1.0(dc=100、k=1e7 时 dv 仅 1000 uV -> r 约 0.065)-> -1 */
CHECK(adc_cal_two_point(100, 200, 0L, 1000L, k0, &rq, &bb) == -1, "computed r < 1.0 -> -1");
/* 真零点 +9000 码 > B_MAX:斜率对(r = 1.5)但 b 越界 -> -2(先查前端,不用系数凑) */
v1 = (int32_t)my_lround((100.0 + 9000.0) * ((double)k0 / 65536.0) * 1.5);
v2 = (int32_t)my_lround((2000.0 + 9000.0) * ((double)k0 / 65536.0) * 1.5);
CHECK(adc_cal_two_point(100, 2000, v1, v2, k0, &rq, &bb) == -2, "b beyond +-8192 -> -2");
/* 真零点 +9000 码 > B_MAX:斜率对(r = 1.5)但 b 越界 -> -2(先查前端,不用系数凑) */
v1 = (int32_t)my_lround((100.0 + 9000.0) * ((double)k0 / 65536.0) * 1.5);
v2 = (int32_t)my_lround((2000.0 + 9000.0) * ((double)k0 / 65536.0) * 1.5);
CHECK(adc_cal_two_point(100, 2000, v1, v2, k0, &rq, &bb) == -2, "b beyond +-8192 -> -2");
}
/* TC-ADCCAL-016:贴轨门限表 */
static void tc_00c_rail_ths(void) {
@@ -791,7 +734,6 @@ int main(void) {
tc_008_set();
tc_009_sanitize();
tc_00a_b_effect();
tc_00b_two_point();
tc_00c_rail_ths();
tc_00d_idempotent();
tc_010_file_apply();