94b0d79026
本笔含两组收尾工作(同一工作区内交错在 6 个共享文档/门禁配置里, 拆开会产生"文档声称的页数与树里黄金数不一致"的中间提交,故合为一笔): 一、UI 补齐(清单清空) - 新建 6 个内容页模块:ui_page_accident / oper / alarm / start / yk 复用 ui_w_records 共享组件(分页、空态"无记录"、按实例读盘缓存), 记录层与五个写入点已由道F task-10 / 道G task-12 落地,本批只补页面; ui_page_runreport 为 13 行 2 页只读统计,四个数逐个挂范围标签 (自电池周期 / 本次开机),boot_ready=0 显 "--" 不显 0。 - 数据面:ui_data_info_t 尾部追加 9 字段,ui_data_feed 用 boot_stats_get() + iec104_serv_get_stats() 纯搬运;模拟器填确定值假数据 (差异登记 docs/测试说明/模拟器差距清单.md §2.3 两行)。 - 接线:菜单树 6 叶绑 #page=,绑定叶 22→28、UI_PAGE_MAP_COUNT=28; 字库 185→218 字 / 280→313 字形;双端注册 uvprojx +30、CMakeLists +6。 - 回归:内容页黄金 53→60(含 runreport_p2 真拍第 2 页),文本断言 425 正向 / 36 反向;存量 53 张逐字节零漂移;记录 5 页各用独立空目录 (模拟器把操作留痕写进 cwd 的 sim_oper.log,共用 tmp 会让空态拍不到)。 二、数据可信销项 + 「数据可信」任务卡号整族清退 - 删除已闭环的"已知电压注入验证"行与闭环结论块(证据在 docs/硬件平台/ADC通道映射说明.md §8.1 与 docs/测试说明/ADC前端注入验证流程.md §5~§7),§5 标识列改语义短语。 - 卡 0/0b/1~12 共 14 个号全仓 288 站点 / 56 文件清退成语义短语, 代码注释、测试、门禁配置与文档一并改;换算表入 docs/编号规范.md §9.3。 这一族是中文前缀,不进 check_ids 语料,刻意不入 id_aliases.json。 验证(实测) - @build 0 错 0 警:Code=236456 RO=28124 RW=1876 ZI=137084; RAM +464 B(RW +304 / ZI +160),RW_IRAM1 62.2% / RW_CCM 87.9%, 体积同码凭证与 RAM 台账已回填。 - check_menu_rows 8 状态 rc=0(池 5368/5448 常量未动); check_content_pages 60 页 rc=0;check_font_charset / registration / coding-standard / bom-drift / mojibake / doc-links --all / layer-deps / nested-comment 全 rc=0;check_ids --strict 无错误;主机单测 ui_data 295 / boot_stats 21 / sys_log_mcu 141 / soe 32 / soe_store 27。 未做(不是遗漏) - 六页真机判据(真记录翻页、掉电保持、清除后归零、boot_count 自增、 拔 RTC 电池落 RESTARTED、IWDG 复位落 rst_cause、主站连一次 conn_up+1) 已登记 docs/任务规划/登记簿.md §7;模拟器结构上照不到。 - docs/产品需求/产品需求设计文档.md 属另一条在飞改动,本笔不含; 其中我已同步 6 处现状数字(28 叶 / 60 页 / 218 字),随该笔入库。
394 lines
16 KiB
C
394 lines
16 KiB
C
/*
|
||
* 模块名称:运行参数段(run_par)主机侧单元测试
|
||
* 模块功能:离线钉死「数据可信」运行参数段的三层契约——① [run_par] cfg 段:
|
||
* 注册/工厂默认/落盘往返/文件改值生效(真实 cfg 引擎 + 内存虚拟盘,
|
||
* 同 adc_cal 套件先例);② 104 地址映射:命中集/空隙/两段式/分档
|
||
* 量程守卫;③ k/b 覆盖直通 adc_cal_set(真实标定层):合法带拒绝、
|
||
* 单侧 RMW 保另一侧、回显 = 生效值视图。
|
||
* 被测对象:真实源文件(#include 纳入):run_par.c + cfg_file.c + adc_cal.c;
|
||
* dbg 计数桩(stub/dbg_log.h)+ cfg_store_* 内存虚拟盘 + adc_input_desc
|
||
* V0.1 权威映射桩。**路由顺序证据(run_par 表先 / prot_set 后)在
|
||
* test/host/iec104 TC-IEC104-029 钉(那边才有全协议栈)**。
|
||
*
|
||
* 覆盖点(TC-RUNPAR-xxx;属主登记处 = 本目录,族 TC-HOST-RUNPAR):
|
||
* TC-RUNPAR-001 init 工厂默认 = 工程量重定后的额定档 + idx 守卫
|
||
* 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-005 104 两段式:选择段不提交不置脏,执行段提交置脏
|
||
* TC-RUNPAR-006 k/b 直通:合法带接受与拒绝 / 非正 k 拒 / b 单侧 RMW 保 k /
|
||
* 非法带值经 load 注入后回显 = 生效值(哨兵视图)
|
||
* TC-RUNPAR-007 init 幂等:重复调用复位默认 + 清脏;重注册被引擎拒(留痕)
|
||
* TC-RUNPAR-008 引擎副本 = 生效值(无回调):load 原地改副本即时可见
|
||
*
|
||
* 通过:全部 TC PASS(main 返回 0)。
|
||
* 创建日期:2026-10-25(道D 运行参数段)
|
||
*/
|
||
|
||
#include <stdint.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
/* 先桩头后生产源码(顺序敏感,同 adc_cal 套件) */
|
||
#include "dbg_log.h"
|
||
|
||
/* ===================== 内存虚拟文件系统(cfg_store_* 强符号) ===================== */
|
||
#include "cfg_file_store.h"
|
||
|
||
#define VFS_CAP 8192u
|
||
|
||
static uint8_t s_vfs[VFS_CAP];
|
||
static size_t s_vfs_len = 0u;
|
||
static uint32_t s_vfs_mtime = 100u;
|
||
static int s_vfs_exists = 0;
|
||
static int s_vfs_writes = 0;
|
||
|
||
void *cfg_store_alloc(size_t size) { return malloc(size); }
|
||
void cfg_store_free(void *p_buf) { free(p_buf); }
|
||
uint32_t cfg_store_heap_free(void) { return 0u; }
|
||
|
||
int cfg_store_read(const char *p_path, uint8_t *p_buf, size_t cap, size_t *p_nread) {
|
||
size_t n;
|
||
|
||
(void)p_path;
|
||
if (!s_vfs_exists) {
|
||
return -1;
|
||
}
|
||
n = s_vfs_len;
|
||
if (n > cap) {
|
||
n = cap;
|
||
}
|
||
(void)memcpy(p_buf, s_vfs, n);
|
||
*p_nread = n;
|
||
return 0;
|
||
}
|
||
|
||
int cfg_store_write_atomic(const char *p_path, const uint8_t *p_buf, size_t len) {
|
||
(void)p_path;
|
||
if (len > VFS_CAP) {
|
||
return -1;
|
||
}
|
||
(void)memcpy(s_vfs, p_buf, len);
|
||
s_vfs_len = len;
|
||
s_vfs_exists = 1;
|
||
s_vfs_mtime++;
|
||
s_vfs_writes++;
|
||
return 0;
|
||
}
|
||
|
||
int cfg_store_stat(const char *p_path, cfg_file_stat_t *p_st) {
|
||
(void)p_path;
|
||
if (!s_vfs_exists) {
|
||
return -1;
|
||
}
|
||
p_st->size = (uint32_t)s_vfs_len;
|
||
p_st->mtime = s_vfs_mtime;
|
||
return 0;
|
||
}
|
||
|
||
int cfg_store_remove(const char *p_path) {
|
||
(void)p_path;
|
||
s_vfs_exists = 0;
|
||
s_vfs_len = 0u;
|
||
return 0;
|
||
}
|
||
|
||
const char *cfg_store_config_path(void) { return "/config.ini"; }
|
||
const char *cfg_store_tmp_path(void) { return "/config.tmp"; }
|
||
|
||
/* ---- sys_log 桩 ---- */
|
||
#include "sys_log.h"
|
||
|
||
static int s_syslog_count = 0;
|
||
|
||
void syslog_post(syslog_id_t id, const char *desc) {
|
||
(void)id;
|
||
(void)desc;
|
||
s_syslog_count++;
|
||
}
|
||
|
||
/* ---- adc_input_desc 桩:V0.1 权威映射(docs/硬件平台/ADC通道映射说明.md) ---- */
|
||
#include "adc_input.h"
|
||
|
||
static const adc_channel_desc_t s_desc_stub[ADC_SEM_COUNT] = {
|
||
{ ADC_SRC_TPAFE, 6u }, /* UA = buf[6] */
|
||
{ ADC_SRC_STM32, 14u }, /* UB = CH14(PC4) */
|
||
{ ADC_SRC_STM32, 3u }, /* UC = CH3 */
|
||
{ ADC_SRC_TPAFE, 5u }, /* UN = buf[5] */
|
||
{ ADC_SRC_TPAFE, 2u }, /* IA = buf[2] */
|
||
{ ADC_SRC_STM32, 6u }, /* IB = CH6 */
|
||
{ ADC_SRC_STM32, 1u }, /* IC = CH1 */
|
||
{ ADC_SRC_STM32, 2u }, /* IN = CH2 */
|
||
{ ADC_SRC_STM32, 5u }, /* TEMP = CH5 */
|
||
};
|
||
|
||
const adc_channel_desc_t *adc_input_desc(adc_semantic_t ch) {
|
||
if ((int)ch < 0 || (unsigned)ch >= (unsigned)ADC_SEM_COUNT) {
|
||
return NULL;
|
||
}
|
||
return &s_desc_stub[(unsigned)ch];
|
||
}
|
||
|
||
/* dbg 计数定义(stub/dbg_log.h extern 声明) */
|
||
int g_rptest_err_count = 0;
|
||
int g_rptest_info_count = 0;
|
||
int g_rptest_debug_count = 0;
|
||
|
||
/* ===================== 测试框架(极简,同 adc_cal 套件) ===================== */
|
||
static int s_total = 0, s_passed = 0, s_failed = 0;
|
||
|
||
#define CHECK(cond, name) do { \
|
||
s_total++; \
|
||
if (cond) { s_passed++; printf(" [PASS] %s\n", name); } \
|
||
else { s_failed++; printf(" [FAIL] %s (line %d)\n", name, __LINE__); } \
|
||
} while (0)
|
||
|
||
#define ASSERT_NEAR(a, b, eps, name) CHECK(fabsf((float)(a) - (float)(b)) <= (eps), name)
|
||
|
||
/* ===================== 被测代码 ===================== */
|
||
#include "cfg_file.c"
|
||
#include "adc_cal.c"
|
||
#include "run_par.c"
|
||
|
||
static void vfs_reset(void) {
|
||
s_vfs_len = 0u;
|
||
s_vfs_mtime = 100u;
|
||
s_vfs_exists = 0;
|
||
}
|
||
|
||
/* 全复位:引擎段复位 + run_par 复位 + 标定复位(重注册被拒 = 预期,清计数) */
|
||
static void reset_all_rp(void) {
|
||
run_par_init();
|
||
adc_cal_init();
|
||
g_rptest_err_count = 0;
|
||
}
|
||
/* ===================== 测试用例 ===================== */
|
||
|
||
static void tc_defaults(void)
|
||
{
|
||
uint8_t i;
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
for (i = 0u; i < 4u; i++) {
|
||
CHECK(fabsf(run_par_deadband(i) - 0.5f) <= 1e-6f, "TC-RUNPAR-001 voltage ch factory 0.5 V");
|
||
}
|
||
for (i = 4u; i < 8u; i++) {
|
||
CHECK(fabsf(run_par_deadband(i) - 0.005f) <= 1e-9f, "TC-RUNPAR-001 current ch factory 0.005 A");
|
||
}
|
||
CHECK(fabsf(run_par_deadband(8u) - 0.5f) <= 1e-6f, "TC-RUNPAR-001 freq factory 0.5 Hz");
|
||
CHECK(run_par_deadband(9u) == 0.0f, "TC-RUNPAR-001 idx guard returns zero");
|
||
CHECK(run_par_dirty_peek() == 0u, "TC-RUNPAR-001 init leaves clean");
|
||
}
|
||
|
||
static void tc_set_range(void)
|
||
{
|
||
volatile float fnan;
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
CHECK((run_par_deadband_set(0u, 0.7f) == 0)
|
||
&& (fabsf(run_par_deadband(0u) - 0.7f) <= 1e-6f),
|
||
"TC-RUNPAR-002 write round trip voltage domain");
|
||
CHECK((run_par_deadband_set(4u, 0.02f) == 0)
|
||
&& (fabsf(run_par_deadband(4u) - 0.02f) <= 1e-6f),
|
||
"TC-RUNPAR-002 write round trip current domain");
|
||
CHECK(run_par_deadband_set(0u, 50.0f) == 0, "TC-RUNPAR-002 voltage cap endpoint inclusive");
|
||
CHECK((run_par_deadband_set(0u, 50.001f) == -1)
|
||
&& (fabsf(run_par_deadband(0u) - 50.0f) <= 1e-6f),
|
||
"TC-RUNPAR-002 over voltage cap rejected");
|
||
CHECK(run_par_deadband_set(4u, 1.001f) == -1, "TC-RUNPAR-002 current cap 1 A enforced");
|
||
CHECK(run_par_deadband_set(8u, 5.001f) == -1, "TC-RUNPAR-002 freq cap 5 Hz enforced");
|
||
CHECK(run_par_deadband_set(0u, -0.001f) == -1, "TC-RUNPAR-002 negative rejected");
|
||
fnan = 0.0f;
|
||
fnan = fnan / fnan;
|
||
CHECK(run_par_deadband_set(0u, fnan) == -1, "TC-RUNPAR-002 NaN rejected");
|
||
CHECK(run_par_deadband_set(9u, 1.0f) == -1, "TC-RUNPAR-002 idx guard rejected");
|
||
CHECK((run_par_deadband_set(2u, 0.1234f) == 0)
|
||
&& (fabsf(run_par_deadband(2u) - 0.123f) <= 1e-6f),
|
||
"TC-RUNPAR-002 milli quantization rounds to nearest");
|
||
}
|
||
|
||
static void tc_persist(void)
|
||
{
|
||
char probe[24];
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
CHECK(run_par_store_save() == 0, "TC-RUNPAR-003 clean save is no-op ok");
|
||
CHECK(run_par_deadband_set(2u, 0.9f) == 0, "TC-RUNPAR-003 seed write ok");
|
||
CHECK(run_par_dirty_peek() == 1u, "TC-RUNPAR-003 write marks dirty");
|
||
CHECK((run_par_store_save() == 0) && (run_par_dirty_peek() == 0u),
|
||
"TC-RUNPAR-003 save clears dirty on success");
|
||
(void)memset(probe, 0, sizeof(probe));
|
||
(void)memcpy(probe, "db_uc=", 6u);
|
||
CHECK((s_vfs_exists == 1) && (strstr((const char *)s_vfs, "db_uc=900") != NULL),
|
||
"TC-RUNPAR-003 file carries milli value");
|
||
CHECK(strstr((const char *)s_vfs, "db_freq=500") != NULL,
|
||
"TC-RUNPAR-003 all nine keys present (freq spot check)");
|
||
/* 往返:改内存 → 落盘 → 引擎 load 回读 */
|
||
CHECK(run_par_deadband_set(4u, 0.02f) == 0, "TC-RUNPAR-003 second seed");
|
||
(void)run_par_store_save();
|
||
run_par_deadband_set(4u, 0.5f); /* 覆盖内存态 */
|
||
CHECK(cfg_file_load() == 0, "TC-RUNPAR-003 engine reload ok");
|
||
CHECK(fabsf(run_par_deadband(4u) - 0.02f) <= 1e-9f,
|
||
"TC-RUNPAR-003 reload restores last saved value");
|
||
/* set(4,0.5) 是一次未落盘的本地整定 → 脏必须活过 reload(reload 不是
|
||
* 清脏事件;只有 save 成功才清) */
|
||
CHECK(run_par_dirty_peek() == 1u, "TC-RUNPAR-003 unsaved local edit survives reload");
|
||
/* 外部改档(FTP 手改 config.ini 的现场形态):load 后副本即生效值 */
|
||
{
|
||
static const char s_edited[] =
|
||
"[run_par]\ndb_ua=250\ndb_ub=500\ndb_uc=500\ndb_un=500\n"
|
||
"db_ia=10\ndb_ib=5\ndb_ic=5\ndb_in=5\ndb_freq=800\n";
|
||
(void)memcpy(s_vfs, s_edited, sizeof(s_edited) - 1u);
|
||
s_vfs_len = sizeof(s_edited) - 1u;
|
||
s_vfs_exists = 1;
|
||
s_vfs_mtime++;
|
||
}
|
||
CHECK(cfg_file_load() == 0, "TC-RUNPAR-003 edited file accepted");
|
||
CHECK((fabsf(run_par_deadband(0u) - 0.25f) <= 1e-6f)
|
||
&& (fabsf(run_par_deadband(4u) - 0.01f) <= 1e-9f)
|
||
&& (fabsf(run_par_deadband(8u) - 0.8f) <= 1e-6f),
|
||
"TC-RUNPAR-003 edited values live in copy immediately");
|
||
/* 越界文件值:引擎照收(int32 域),104/COV 读到超程值 —— 守卫在**写路径**,
|
||
* 文件通路的防线是"人工编辑 + 沉降去抖 + 可再改回";与 adc_cal 合法带不同,
|
||
* 死区超程不毁量纲(只是上送变钝),此处钉住"引擎不吞值"即可 */
|
||
CHECK(fabsf(run_par_deadband(0u) - 0.25f) <= 1e-6f, "TC-RUNPAR-003 value stable re-read");
|
||
}
|
||
|
||
static void tc_104_read(void)
|
||
{
|
||
float v;
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
(void)run_par_deadband_set(0u, 0.6f);
|
||
CHECK((run_par_104_read(0x8030u, &v) == 0) && (fabsf(v - 0.6f) <= 1e-6f),
|
||
"TC-RUNPAR-004 db first slot hit");
|
||
CHECK((run_par_104_read(0x8038u, &v) == 0) && (fabsf(v - 0.5f) <= 1e-6f),
|
||
"TC-RUNPAR-004 db last slot (freq) hit");
|
||
CHECK(run_par_104_read(0x8039u, &v) == -1, "TC-RUNPAR-004 gap address not owned");
|
||
CHECK(run_par_104_read(0x8027u, &v) == -1, "TC-RUNPAR-004 prot_set alarm addr untouched");
|
||
CHECK(run_par_104_read(0x802Fu, &v) == -1, "TC-RUNPAR-004 below base not claimed");
|
||
CHECK((run_par_104_read(0x8040u, &v) == 0) && (fabsf(v - 152.587890625f) <= 1e-4f),
|
||
"TC-RUNPAR-004 k echo = adc_cal effective UA");
|
||
CHECK((run_par_104_read(0x8047u, &v) == 0) && (fabsf(v - 805.6640625f) <= 1e-4f),
|
||
"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");
|
||
}
|
||
|
||
static void tc_104_two_step(void)
|
||
{
|
||
float v;
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
CHECK((run_par_104_write(0x8031u, 0.8f, 1u) == 0)
|
||
&& (fabsf(run_par_deadband(1u) - 0.5f) <= 1e-6f)
|
||
&& (run_par_dirty_peek() == 0u),
|
||
"TC-RUNPAR-005 select validates without commit or dirty");
|
||
CHECK((run_par_104_write(0x8031u, 0.8f, 0u) == 0)
|
||
&& (fabsf(run_par_deadband(1u) - 0.8f) <= 1e-6f)
|
||
&& (run_par_dirty_peek() == 1u),
|
||
"TC-RUNPAR-005 execute commits and marks dirty");
|
||
CHECK(run_par_104_write(0x8031u, 60.0f, 1u) == -1, "TC-RUNPAR-005 range reject in select");
|
||
CHECK(run_par_104_write(0x8039u, 1.0f, 0u) == -2, "TC-RUNPAR-005 foreign addr passes through");
|
||
CHECK(run_par_104_write(0x8027u, 1.0f, 0u) == -2, "TC-RUNPAR-005 alarm addr passes through");
|
||
CHECK((run_par_104_read(0x8031u, &v) == 0) && (fabsf(v - 0.8f) <= 1e-6f),
|
||
"TC-RUNPAR-005 committed value readable at same addr");
|
||
}
|
||
|
||
static void tc_104_cal_proxy(void)
|
||
{
|
||
float v;
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
CHECK(run_par_104_write(0x8040u, 300.0f, 0u) == 0, "TC-RUNPAR-006 k in-band accepted");
|
||
CHECK((run_par_104_read(0x8040u, &v) == 0) && (fabsf(v - 300.0f) <= 0.01f),
|
||
"TC-RUNPAR-006 k echo follows adc_cal_set");
|
||
CHECK((run_par_104_write(0x8040u, 400.0f, 0u) == -1)
|
||
&& (fabsf(adc_cal_k_uv(ADC_SEM_UA) - 300.0f) <= 0.01f),
|
||
"TC-RUNPAR-006 k over band rejected by adc_cal, RAM intact");
|
||
CHECK((run_par_104_write(0x8040u, 70.0f, 0u) == -1),
|
||
"TC-RUNPAR-006 k under band rejected (0.5x ROM)");
|
||
CHECK(run_par_104_write(0x8040u, -1.0f, 0u) == -1, "TC-RUNPAR-006 non-positive k rejected");
|
||
CHECK((run_par_104_write(0x8048u, -5.0f, 0u) == 0)
|
||
&& (fabsf(adc_cal_b_codes(ADC_SEM_UA) + 5.0f) <= 1e-3f)
|
||
&& (fabsf(adc_cal_k_uv(ADC_SEM_UA) - 300.0f) <= 0.01f),
|
||
"TC-RUNPAR-006 b single-side RMW keeps k");
|
||
CHECK(run_par_104_write(0x8048u, -9000.0f, 0u) == -1, "TC-RUNPAR-006 b over +-8192 rejected");
|
||
CHECK((run_par_104_write(0x8040u, 200.0f, 1u) == 0)
|
||
&& (fabsf(adc_cal_k_uv(ADC_SEM_UA) - 300.0f) <= 0.01f),
|
||
"TC-RUNPAR-006 k select does not touch adc_cal");
|
||
/* 生效值视图回显:文件塞越带 k → 哨兵回退 ROM → 104 回显 ROM */
|
||
{
|
||
static const char s_badk[] =
|
||
"[adc_cal]\nk_ua=99011483\nvalid=1\n";
|
||
(void)memcpy(s_vfs, s_badk, sizeof(s_badk) - 1u);
|
||
s_vfs_len = sizeof(s_badk) - 1u;
|
||
s_vfs_exists = 1;
|
||
s_vfs_mtime++;
|
||
}
|
||
CHECK(cfg_file_load() == 0, "TC-RUNPAR-006 poisoned file loaded by engine");
|
||
CHECK((run_par_104_read(0x8040u, &v) == 0) && (fabsf(v - 152.587890625f) <= 1e-4f),
|
||
"TC-RUNPAR-006 echo = effective (ROM fallback), not raw file value");
|
||
reset_all_rp();
|
||
CHECK(cfg_file_save() == 0, "TC-RUNPAR-006 reset file rewritten");
|
||
}
|
||
|
||
static void tc_init_idempotent(void)
|
||
{
|
||
int err_before;
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
(void)run_par_deadband_set(1u, 0.9f);
|
||
(void)run_par_104_write(0x8040u, 200.0f, 0u);
|
||
err_before = g_rptest_err_count;
|
||
run_par_init();
|
||
CHECK(fabsf(run_par_deadband(1u) - 0.5f) <= 1e-6f, "TC-RUNPAR-007 re-init restores defaults");
|
||
CHECK(run_par_dirty_peek() == 0u, "TC-RUNPAR-007 re-init clears dirty");
|
||
CHECK(g_rptest_err_count > err_before, "TC-RUNPAR-007 dup register leaves trace");
|
||
CHECK(fabsf(run_par_deadband(0u) - 0.5f) <= 1e-6f, "TC-RUNPAR-007 values intact after dup reg");
|
||
}
|
||
|
||
static void tc_copy_is_effective(void)
|
||
{
|
||
static const char s_file[] =
|
||
"[run_par]\ndb_ua=650\ndb_ub=500\ndb_uc=500\ndb_un=500\n"
|
||
"db_ia=5\ndb_ib=5\ndb_ic=5\ndb_in=5\ndb_freq=500\n";
|
||
|
||
vfs_reset();
|
||
reset_all_rp();
|
||
(void)memcpy(s_vfs, s_file, sizeof(s_file) - 1u);
|
||
s_vfs_len = sizeof(s_file) - 1u;
|
||
s_vfs_exists = 1;
|
||
s_vfs_mtime++;
|
||
CHECK(cfg_file_load() == 0, "TC-RUNPAR-008 load ok");
|
||
CHECK(fabsf(run_par_deadband(0u) - 0.65f) <= 1e-6f,
|
||
"TC-RUNPAR-008 no cache layer: copy read is effective value");
|
||
CHECK(run_par_dirty_peek() == 0u, "TC-RUNPAR-008 load itself is not a local edit");
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
printf("=== RunPar Layer Host Tests ===\n");
|
||
tc_defaults();
|
||
tc_set_range();
|
||
tc_persist();
|
||
tc_104_read();
|
||
tc_104_two_step();
|
||
tc_104_cal_proxy();
|
||
tc_init_idempotent();
|
||
tc_copy_is_effective();
|
||
printf("=== RunPar Tests: %d/%d PASSED (failed=%d) ===\n",
|
||
s_passed, s_total, s_failed);
|
||
return (s_failed == 0) ? 0 : 1;
|
||
}
|