门禁扩容:新增 lv-conf-sync、simulator/ 纳入全部钩子;含 L3 定值/元件框架落地

本轮把"自研代码落在门禁之外"的口子收掉,同时落地 LVGL 特性裁剪与
L3 保护定值/元件框架。

门禁(.pre-commit-config.yaml,26 个钩子)
- 新增 scripts/check_lv_conf_sync.py + 钩子 lv-conf-sync:比对两份
  lv_conf.h 的**生效值**(未定义则取 lv_conf_internal.h 兜底默认),
  抓 MISMATCH / LVGL 不认的宏名 / 同文件重复定义
- 顶层 exclude 删掉 simulator/:其下 21 个 tracked 文件全是本项目自研
  代码,生成物(build/、SDL2/、tests/ref/、shot*)已在 .gitignore;
  doc-links 的 exclude 同步删除
- lv-conf-sync 的 files: 覆盖两端配置 → 只改 simulator/lv_conf.h 也触发
  (pre-commit 4.x 已移除 always: true,实测只告警并跳过,无兜底开关)
- 新增 prot-set-unit-test / prot-elm-unit-test 两个主机侧单测钩子
- S11(2.3.5) 判定细化:禁的是"用路径找文件",尖括号系统头带子目录
  (如 <sys/stat.h>)不再误报;全仓库复核仅 2 处项目代码判定变化

模拟器代码整改(纳入钩子后暴露,全部修代码而非豁免)
- cppcheck 4 处:sim_syslog.c 判空分支内解引用 p_epoch(真实 bug)、
  2 处 struct tm 未初始化、1 处指针可加 const
- coding-standard 61 处:44 处函数左大括号并到右括号同行、8 处补函数
  注释、3 处补文件头注释块、2 处 __ 前缀保护宏改 XXX_H、2 处 sprintf
  改 snprintf(写入字节数与原来完全一致)

LVGL 特性裁剪(F-1/F-2/F-3)
- 两端 lv_conf.h 对齐同一特性子集:删 26 个 LVGL 9.3 不存在的选项名、
  3 处重复定义,10 项靠默认值隐式生效的改为显式固化
- 实测对镜像体积中性;价值在防漂移,且模拟器 golden 回归跑的正是固件
  实际编译的配置

L3 软件侧
- App/algo/prot_set.* Q10 定值模型(范围校验 / 整表 all-or-nothing /
  校验和封存-自检-闭锁)+ prot_elm.* 通用"滞回+定时限"元件框架 7 实例
- test/host/prot_set、test/host/prot_elm 主机侧单测;uvprojx 挂载两处

文档同步
- pre-commit使用说明:§2.8 S11 口径、§2.15 lv-conf-sync 详解、新增 §5.5
  复盘(教训:exclude 只写真正不该进钩子的路径)
- AGENTS.md、UI_设计架构 §1.4 第 10 条、RAM 分析、审查报告刷新与销项

验证
- @build BUILD_OK 0/0(Code=194276 RO=15872 RW=876 ZI=139892)
- 模拟器重建:菜单 8 状态像素逐字节一致(池 5368 B)、11 内容页黄金参考
  全过(往返 5448 B)、remo sink 0/25600 位差异、--logtest/--cfgtest PASS
- 全仓库 cppcheck / coding-standard / no-mojibake --all-files 全过
- check_doc_links --all 129/0;check_mem_numbers --check 内存数字一致
- 端到端:往 simulator/lv_conf.h 注入一行漂移 → 钩子 FAIL(exit 1)
This commit is contained in:
2026-10-11 08:48:49 +08:00
parent 13a4e61c27
commit c936441c83
36 changed files with 2220 additions and 565 deletions
+228
View File
@@ -0,0 +1,228 @@
/*
* 模块名称:保护定值模型(P1,L5-1 载体)——实现
* 模块功能:见 prot_set.h。纯逻辑,零平台依赖(仅 stdint.h + 自身头)。
*
* ⚠ 默认值/范围为拟定值(参考 EEPROM 出厂默认表不在本仓库,规划 §10.3 待补);
* 通讯地址逐项对照参考 Comm/Pub/Const_CommSetPara.c g_tCommSetParaTab。
*
* 创建日期:2026-10-11
*/
#include "prot_set.h"
/* 元数据表:顺序必须与 prot_set_id_t 严格一致(逐行带地址注释,同 phasor
* k_inst 的朴素行式风格) */
const prot_set_meta_t g_prot_set_meta[PS_ID_COUNT] = {
/* addr ctl default min max 说明 */
{ 0x8856, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) }, /* OC1 投退 */
{ 0x8857, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) }, /* OC1 跳闸投退 */
{ 0x8858, 0u, PROT_SET_Q10(10.0), 0, PROT_SET_Q10(100.0) }, /* OC1 电流 A */
{ 0x8859, 0u, PROT_SET_Q10(0.0), 0, PROT_SET_Q10(60000) }, /* OC1 延时 ms */
{ 0x885A, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) },
{ 0x885B, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) },
{ 0x885C, 0u, PROT_SET_Q10(5.0), 0, PROT_SET_Q10(100.0) },
{ 0x885D, 0u, PROT_SET_Q10(500.0), 0, PROT_SET_Q10(60000) },
{ 0x885E, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) },
{ 0x885F, 1u, PROT_SET_Q10(0), 0, PROT_SET_Q10(1) }, /* OC3 默认告警 */
{ 0x8860, 0u, PROT_SET_Q10(2.0), 0, PROT_SET_Q10(100.0) },
{ 0x8861, 0u, PROT_SET_Q10(3000.0), 0, PROT_SET_Q10(60000) },
{ 0x8871, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) }, /* 过负荷投退 */
{ 0x8872, 1u, PROT_SET_Q10(0), 0, PROT_SET_Q10(1) }, /* 默认告警 */
{ 0x8873, 0u, PROT_SET_Q10(1.0), 0, PROT_SET_Q10(100.0) },
{ 0x8874, 0u, PROT_SET_Q10(10000.0),0, PROT_SET_Q10(60000) },
{ 0x0000, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) }, /* OV 投退(本地) */
{ 0x8029, 0u, PROT_SET_Q10(120.0), 0, PROT_SET_Q10(200.0) }, /* 过压 V */
{ 0x802A, 0u, PROT_SET_Q10(10000.0),0, PROT_SET_Q10(60000) },
{ 0x0000, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) }, /* UV 投退(本地) */
{ 0x8027, 0u, PROT_SET_Q10(20.0), 0, PROT_SET_Q10(200.0) }, /* 欠压 V */
{ 0x8028, 0u, PROT_SET_Q10(10000.0),0, PROT_SET_Q10(60000) },
{ 0x888E, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) }, /* 3U0 投退 */
{ 0x888F, 0u, PROT_SET_Q10(15.0), 0, PROT_SET_Q10(200.0) }, /* 3U0 V */
{ 0x8890, 0u, PROT_SET_Q10(5000.0), 0, PROT_SET_Q10(60000) },
{ 0x0000, 0u, PROT_SET_Q10(0.95), PROT_SET_Q10(0.5), PROT_SET_Q10(1.0) }, /* 过量返回系数 */
{ 0x0000, 0u, PROT_SET_Q10(1.05), PROT_SET_Q10(1.0), PROT_SET_Q10(1.5) }, /* 欠量返回系数 */
{ 0x8820, 0u, PROT_SET_Q10(10000.0),PROT_SET_Q10(100.0), PROT_SET_Q10(500000.0) },
{ 0x8821, 0u, PROT_SET_Q10(100.0), PROT_SET_Q10(1.0), PROT_SET_Q10(200.0) },
{ 0x8825, 0u, PROT_SET_Q10(100.0), PROT_SET_Q10(1.0), PROT_SET_Q10(10000.0) },
{ 0x8826, 0u, PROT_SET_Q10(5.0), PROT_SET_Q10(1.0), PROT_SET_Q10(10.0) },
};
static uint32_t s_val[PS_ID_COUNT]; /* RAM 值区(uint32 承载 int32,校验和按字覆盖) */
static uint32_t s_sum; /* 封存的正码 */
static uint32_t s_sumn; /* 封存的反码 */
static uint32_t s_bad_mask; /* load_raw 越界位图 */
static uint8_t s_locked; /* 定值非法 → 闭锁(L5-1) */
/*
* 函数功能:sum32 覆盖 RAM 值区(参考 Fun_CalSum32 同款:32 位字累加自然回绕)
* 入口参数:无
* 返 回 值:校验和正码
*/
static uint32_t prot_sum32(void) {
uint32_t sum = 0u;
uint32_t i;
for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) {
sum += s_val[i];
}
return sum;
}
/*
* 函数功能:把元数据表默认值刷进 RAM 值区
* 入口参数:无
* 返 回 值:无
*/
static void prot_load_defaults(void) {
uint32_t i;
for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) {
s_val[i] = (uint32_t)g_prot_set_meta[i].def;
}
}
/*
* 函数功能:装载出厂默认值并封存校验和(幂等)
* 入口参数:无
* 返 回 值:无
*/
void prot_set_init(void) {
prot_load_defaults();
s_bad_mask = 0u;
s_locked = 0u;
prot_set_seal();
}
/*
* 函数功能:取最近一次 load_raw 的越界位图
* 入口参数:无
* 返 回 值:bit i = 第 i 项越界(load_raw 失败后有效)
*/
uint32_t prot_set_bad_mask(void) {
return s_bad_mask;
}
/*
* 函数功能:整表装载外部值(P4 起由 cfg_file 定值段调用),逐项范围校验
* 入口参数:vals - PS_ID_COUNT 个 Q10 值
* 返 回 值:0 全部合法(已装载并封存)/ -1 存在越界项或空指针(整表不装载)
* 函数说明:all-or-nothing——宁可全旧不可半新(定值一致性优先);
* 越界项经 prot_set_bad_mask() 指认。
*/
int prot_set_load_raw(const int32_t *vals) {
uint32_t mask = 0u;
uint32_t i;
if (vals == 0) {
return -1;
}
for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) {
if ((vals[i] < g_prot_set_meta[i].min) || (vals[i] > g_prot_set_meta[i].max)) {
mask |= (1uL << i);
}
}
s_bad_mask = mask;
if (mask != 0u) {
return -1;
}
for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) {
s_val[i] = (uint32_t)vals[i];
}
prot_set_seal();
return 0;
}
/*
* 函数功能:单项写入(范围校验)
* 入口参数:id - 定值项编号;q10 - Q10 定点值
* 返 回 值:0 / -1 越界或非法编号拒写(原值不动)
* 函数说明:**不自动重封校验和**——批量改完必须显式 prot_set_seal(),
* 否则 selfcheck 判"定值被非法改写"(参考系统改定值走重写整表)。
*/
int prot_set_set(prot_set_id_t id, int32_t q10) {
if (id >= PS_ID_COUNT) {
return -1;
}
if ((q10 < g_prot_set_meta[id].min) || (q10 > g_prot_set_meta[id].max)) {
return -1;
}
s_val[(uint32_t)id] = (uint32_t)q10;
return 0;
}
/*
* 函数功能:读定值 Q10 原值
* 入口参数:id - 定值项编号
* 返 回 值:Q10 值;非法编号返回 0
*/
int32_t prot_set_get(prot_set_id_t id) {
if (id >= PS_ID_COUNT) {
return 0;
}
return (int32_t)s_val[(uint32_t)id];
}
/*
* 函数功能:读定值工程量浮点值
* 入口参数:id - 定值项编号
* 返 回 值:Q10 → float;非法编号返回 0.0
*/
float prot_set_get_f(prot_set_id_t id) {
return PROT_SET_FROM_Q10(prot_set_get(id));
}
/*
* 函数功能:读投退/枚举项
* 入口参数:id - 定值项编号
* 返 回 值:!=0 视为投入(1/0)
*/
uint8_t prot_set_get_ctl(prot_set_id_t id) {
return (prot_set_get(id) != 0) ? 1u : 0u;
}
/*
* 函数功能:实时计算校验和(不读封存值)
* 入口参数:无
* 返 回 值:sum32 正码
*/
uint32_t prot_set_checksum(void) {
return prot_sum32();
}
/*
* 函数功能:封存当前值区的正/反码对(合法改定值闭环的最后一步)
* 入口参数:无
* 返 回 值:无
* 函数说明:封存同时解除闭锁——selfcheck 失配后的唯一合法解锁路径。
*/
void prot_set_seal(void) {
s_sum = prot_sum32();
s_sumn = ~s_sum;
s_locked = 0u;
}
/*
* 函数功能:定值自检(L5-1)——重算 sum32 并与封存值比对
* 入口参数:无
* 返 回 值:0 通过 / -1 失配(已置闭锁)
* 函数说明:失配 → s_locked 置位并保持,直到下一次 seal;
* 元件层每拍读 prot_set_locked() 决定整体复位(联动闭锁)。
*/
int prot_set_selfcheck(void) {
if (prot_sum32() != s_sum) {
s_locked = 1u; /* 值区与封存不符:定值被非法改写 → 闭锁 */
}
if ((s_sum != (~s_sumn)) || (s_locked != 0u)) {
s_locked = 1u;
return -1;
}
return 0;
}
/*
* 函数功能:读闭锁状态
* 入口参数:无
* 返 回 值:1 = 定值非法(保护应整体闭锁)/ 0 = 正常
*/
uint8_t prot_set_locked(void) {
return s_locked;
}