feat(adc): 新增变比维 r 三维折算,录波段格式升 v2

采样板注入 Ua=5V/Ia=0.5A 读数偏小,根因是固件只输出引脚电压、
缺「端子→引脚」变比。折算改三维:

工程量 = (code + b) × k[µV/码] × 1e-6 × r

k 保持 ROM 引脚 LSB,b 为零点,r 为端子变比(int32 Q16)。
变比不能并进 k:UA 端子域 k 达 1.5e5 µV/码、Q16 溢出 int32;
r 单独存 Q16 不溢出。两点标定改标 r,k 仍是板级事实。

- 新开单段 [adc_cal_sec](8 键 r_ua..r_in),cfg 段数达 8/8 上限
- 一次变比复用 prot_set 四项,不新开段;r=0 表示本路不折算
- ROM 默认带台架实测变比(电压族 1000、电流族 29.4118),
  烧进固件即显二次值;VALID 仍须两点标定,两者互不派生
- eng 判据改「每路要么已配变比、要么削顶不显示」,不再看 VALID
- 104 地址 0x8050~0x8057 写 r,run_par_cal_r_set 写值与置脏同函数
- 录波 v2:通道表加 int32 r_q16,头 128→160、整段 5250→5282;
  code_to_milli 用余数分解换等价单次圆整,20 万组大整数对拍 0 不符
- 文档同步:采集与算法层/通道映射/故障录波/网络配置/配置文件/
  产品需求/内存台账,历史带日期实测数字按冻结口径不改
- 单测 13 套全绿,/keil-build 0 错误 0 警告(256024/31760/
  2080/152368),RAM 实测回填内存内容分配策略 §6.1
This commit is contained in:
2026-11-11 11:31:34 +08:00
parent 8115fb9a87
commit 3675b89e8e
35 changed files with 1653 additions and 505 deletions
+84 -2
View File
@@ -15,12 +15,15 @@
* TC-RUNPAR-002 死区写往返 + 分档上限(V/A/Hz)+ NaN/负值拒 + 定点量化
* TC-RUNPAR-003 落盘链:set→脏→store_save 成功清脏 + 文件含 9 键 +
* load 回读往返 + 外部改文件值生效 + 无脏 save 空操作
* TC-RUNPAR-004 104 读映射:0x8030~0x8038 命中 / 空隙与邻段 -1 / k·b 回显
* TC-RUNPAR-004 104 读映射:0x8030~0x8038 命中 / 空隙与邻段 -1 / k·b·r 回显
* TC-RUNPAR-005 104 两段式:选择段不提交不置脏,执行段提交置脏
* TC-RUNPAR-006 k/b 直通:合法带接受与拒绝 / 非正 k 拒 / b 单侧 RMW 保 k /
* 非法带值经 load 注入后回显 = 生效值(哨兵视图)
* TC-RUNPAR-007 init 幂等:重复调用复位默认 + 清脏;重注册被引擎拒(留痕)
* TC-RUNPAR-008 引擎副本 = 生效值(无回调):load 原地改副本即时可见
* TC-RUNPAR-009 变比 r 的 104 读写:0x8050~0x8057 写 2000.0 回读一致 / 写 0
* 接受且回读 0 / 0.5 与 -1 与 40000 拒 / 0x8058 非本段 / 选择段
* 粗守只挡 NaN·Inf(0.5 在选择段返 0,执行段才拒——两段可不同)
*
* 通过:全部 TC PASS(main 返回 0)。
* 创建日期:2026-10-25(道D 运行参数段)
@@ -279,7 +282,11 @@ static void tc_104_read(void)
"TC-RUNPAR-004 k echo last channel (IN, STM32 ROM)");
CHECK((run_par_104_read(0x8048u, &v) == 0) && (v == 0.0f),
"TC-RUNPAR-004 b echo factory zero");
CHECK(run_par_104_read(0x8050u, &v) == -1, "TC-RUNPAR-004 above b block not owned");
CHECK((run_par_104_read(0x8050u, &v) == 0) && (fabsf(v - 1000.0f) <= 1e-3f),
"TC-RUNPAR-004 r echo first slot = ROM voltage family 1000.0");
CHECK((run_par_104_read(0x8054u, &v) == 0) && (fabsf(v - 29.4118f) <= 1e-3f),
"TC-RUNPAR-004 r echo current family = 29.4118");
CHECK(run_par_104_read(0x8058u, &v) == -1, "TC-RUNPAR-004 above r block not owned");
}
static void tc_104_two_step(void)
@@ -376,6 +383,80 @@ static void tc_copy_is_effective(void)
CHECK(run_par_dirty_peek() == 0u, "TC-RUNPAR-008 load itself is not a local edit");
}
/* TC-RUNPAR-009:变比 r 的 104 读写(0x8050~0x8057)与两段式粗守面 */
static void tc_104_ratio(void)
{
float v;
vfs_reset();
reset_all_rp();
/* 写 2000.0:电压族量级(2 倍于 ROM 默认 1000),回读 = 生效值 */
CHECK(run_par_104_write(0x8050u, 2000.0f, 0u) == 0, "TC-RUNPAR-009 r 2000.0 accepted");
CHECK((run_par_104_read(0x8050u, &v) == 0) && (fabsf(v - 2000.0f) <= 0.01f),
"TC-RUNPAR-009 r readback = 2000.0");
CHECK((adc_cal_ratio(ADC_SEM_UA) > 1999.99f) && (adc_cal_ratio(ADC_SEM_UA) < 2000.01f),
"TC-RUNPAR-009 r reached adc_cal (write-through)");
CHECK(run_par_dirty_peek() == 1u, "TC-RUNPAR-009 r execute marks dirty");
/* 写 0 = 显式关掉本路折算(成功路径,不是拒绝) */
CHECK(run_par_104_write(0x8050u, 0.0f, 0u) == 0, "TC-RUNPAR-009 r 0 accepted (explicit off)");
CHECK((run_par_104_read(0x8050u, &v) == 0) && (v == 0.0f), "TC-RUNPAR-009 r readback = 0");
CHECK(adc_cal_ratio_configured(ADC_SEM_UA) == 0u,
"TC-RUNPAR-009 r 0 -> channel reports not configured");
/* 拒绝面:0 与 >=1.0 之外、以及非有限值 */
CHECK(run_par_104_write(0x8050u, 0.5f, 0u) == -1, "TC-RUNPAR-009 r 0.5 rejected");
CHECK(run_par_104_write(0x8050u, -1.0f, 0u) == -1, "TC-RUNPAR-009 r -1 rejected");
CHECK(run_par_104_write(0x8050u, 40000.0f, 0u) == -1, "TC-RUNPAR-009 r 40000 rejected");
{
volatile float fnan = 0.0f;
fnan = fnan / fnan;
CHECK(run_par_104_write(0x8050u, fnan, 0u) == -1, "TC-RUNPAR-009 r NaN rejected");
CHECK(run_par_104_write(0x8050u, fnan, 1u) == -1, "TC-RUNPAR-009 r NaN rejected in select too");
}
/* 上限端点(32767.99)在带内,接受 */
CHECK(run_par_104_write(0x8050u, 32767.99f, 0u) == 0, "TC-RUNPAR-009 r upper band endpoint accepted");
/* 选择段:只粗守(NaN/Inf),0.5 这类"执行段会拒"的值在选择段返 0 */
CHECK(run_par_104_write(0x8051u, 0.5f, 1u) == 0,
"TC-RUNPAR-009 select only guards finiteness (0.5 passes)");
CHECK((run_par_104_read(0x8051u, &v) == 0) && (fabsf(v - 1000.0f) <= 1e-3f),
"TC-RUNPAR-009 select did not touch the ratio");
CHECK(run_par_104_write(0x8051u, 0.5f, 0u) == -1, "TC-RUNPAR-009 execute rejects the same 0.5");
CHECK((run_par_104_read(0x8051u, &v) == 0) && (fabsf(v - 1000.0f) <= 1e-3f),
"TC-RUNPAR-009 rejected execute left the ratio intact");
/* 段边界:0x8057 是 r 块末地址,0x8058 起非本段 */
CHECK(run_par_104_write(0x8057u, 29.4118f, 0u) == 0, "TC-RUNPAR-009 last r slot writable");
CHECK(run_par_104_write(0x8058u, 2.0f, 0u) == -2, "TC-RUNPAR-009 0x8058 passes through to prot_set");
CHECK(run_par_104_read(0x8058u, &v) == -1, "TC-RUNPAR-009 0x8058 not owned on read");
/* 落盘往返:脏 → save → 文件带 r_ua 键 → load 回读生效 */
CHECK(run_par_104_write(0x8050u, 2000.0f, 0u) == 0, "TC-RUNPAR-009 seed 2000.0 before save");
CHECK(run_par_store_save() == 0, "TC-RUNPAR-009 save ok");
CHECK((run_par_dirty_peek() == 0u) && (s_vfs_exists == 1),
"TC-RUNPAR-009 save cleared dirty and wrote file");
CHECK(strstr((const char *)s_vfs, "r_ua=131072000") != NULL,
"TC-RUNPAR-009 file carries r_ua=131072000 (= 2000 x 65536)");
(void)run_par_104_write(0x8050u, 1000.0f, 0u); /* 覆盖内存态 */
CHECK(cfg_file_load() == 0, "TC-RUNPAR-009 engine reload ok");
CHECK((run_par_104_read(0x8050u, &v) == 0) && (fabsf(v - 2000.0f) <= 0.01f),
"TC-RUNPAR-009 reload restores saved ratio");
/* 回显 = 生效值视图:文件塞越带 r(< 1.0)→ 哨兵按 0 报,不回显原始坏值 */
{
static const char s_badr[] =
"[adc_cal_sec]\r\nr_ua=1\r\n";
(void)memcpy(s_vfs, s_badr, sizeof(s_badr) - 1u);
s_vfs_len = sizeof(s_badr) - 1u;
s_vfs_exists = 1;
s_vfs_mtime++;
}
CHECK(cfg_file_load() == 0, "TC-RUNPAR-009 poisoned ratio file loaded");
CHECK((run_par_104_read(0x8050u, &v) == 0) && (v == 0.0f),
"TC-RUNPAR-009 echo = effective (out-of-band reported as 0)");
}
int main(void)
{
printf("=== RunPar Layer Host Tests ===\n");
@@ -387,6 +468,7 @@ int main(void)
tc_104_cal_proxy();
tc_init_idempotent();
tc_copy_is_effective();
tc_104_ratio();
printf("=== RunPar Tests: %d/%d PASSED (failed=%d) ===\n",
s_passed, s_total, s_failed);
return (s_failed == 0) ? 0 : 1;