门禁扩容:新增 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
+5 -2
View File
@@ -30,7 +30,9 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v
## 提交门禁(pre-commit)
- 任一失败即拦截,共 **18 个钩子**(`.pre-commit-config.yaml`,2026-10-10 清点):通用 5 个(`trailing-whitespace` / `end-of-file-fixer` / `check-added-large-files` / `check-merge-conflict` / `check-yaml`)+ `gitlint`(提交信息)+ `cppcheck`(warning/performance/portability/style)+ `test-cppcheck`(`test/` 只开 warning)+ `no-mojibake`(U+FFFD)+ `coding-standard`(规范 V1.0)+ 文档一致性三件套 `doc-links` / `task-table` / `mem-numbers` + `cubemx-survival`(重生成存活审计)+ 主机侧单测 `watchdog-unit-test` / `sys-clock-unit-test` / `cfg-file-unit-test` + `test-suite-switch`(测试开关=产品构建)。范围仅项目代码(第三方 `Lib/`/`Middlewares/`/CMSIS/HAL/`lftpd`/`dhara`/`MDK-ARM` 排除;`cppcheck`/`coding-standard` 另排除 `test/`,规范检查再排除 CubeMX 生成的 `Src/`/`Inc/`)
- 任一失败即拦截,共 **26 个钩子**(`.pre-commit-config.yaml`,2026-10-11 清点):通用 5 个(`trailing-whitespace` / `end-of-file-fixer` / `check-added-large-files` / `check-merge-conflict` / `check-yaml`)+ `gitlint`(提交信息)+ `cppcheck`(warning/performance/portability/style)+ `test-cppcheck`(`test/` 只开 warning)+ `no-mojibake`(U+FFFD)+ `coding-standard`(规范 V1.0)+ 文档一致性三件套 `doc-links` / `task-table` / `mem-numbers` + `lv-conf-sync`(**两份 `lv_conf.h` 特性子集一致**,见 `docs/UI设计/UI_设计架构.md` §1.4 第 10 条)+ `cubemx-survival`(重生成存活审计)+ 主机侧单测 10 个 `watchdog` / `sys-clock` / `cfg-file` / `phasor` / `adc-input` / `vol-lock` / `time-sync` / `adc-health` / `prot-set` / `prot-elm`(均 `-unit-test` 后缀)+ `test-suite-switch`(测试开关=产品构建)。范围仅项目代码(第三方 `Lib/`/`Middlewares/`/CMSIS/HAL/`lftpd`/`dhara`/`MDK-ARM` 排除;`cppcheck`/`coding-standard` 另排除 `test/`,规范检查再排除 CubeMX 生成的 `Src/`/`Inc/`)
- **`simulator/` 已纳入全部钩子**(2026-10-11 修正):顶层 `exclude` 原先整目录挡 `simulator/`,实际效果是把 **21 个本项目自研文件**(模拟器入口 `main.c`、`sim/*` 平台后端、`tests/*.py` 回归脚本、`lv_conf.h`/`dbg_log.h`、3 个 README)挡在门禁外——而那些生成物(`build/`、`SDL2/`、`tests/ref/`、`shot*.{bin,png}`、`__pycache__/`)**已在 `.gitignore` 里**,pre-commit 只看 git 索引,根本不需要重复豁免。纳入当天 `cppcheck` 即揪出 `sim/sim_syslog.c` 一处**真实空指针解引用**(`if (p_epoch == NULL || …) { *p_epoch = 0u; … }`),`coding-standard` 报 61 处(44 处函数左大括号 Allman 风格 / 8 处缺函数注释 / 3 处缺文件头 / 2 处 `__` 前缀保护宏 / 2 处 `sprintf` / 2 处 S11 误报)已全部处理;顺带细化 **S11 只禁"用路径找文件"**——`<sys/stat.h>` 这类尖括号系统头带子目录不再误报(全仓库复核:仅这 2 处项目代码判定变化)。⚠ **写模拟器代码与固件代码同标准**
- ⚠ **pre-commit 4.x 已移除 `always: true`**(实测对 `local` 钩子只告警 `Unexpected key(s)` 并跳过)→ 想要"总是跑"的钩子**必须让 `files:` 覆盖到所有会触发它的文件**,没有兜底开关。例:`lv-conf-sync` 的 `files:` 同时匹配 `Lib/lv_conf.h`、`simulator/lv_conf.h` 与脚本自身,两端任一改动都会跑
- **改写型钩子(`trailing-whitespace` + `end-of-file-fixer`)豁免 CubeMX/Keil 生成文件**(2026-10-09 定;配置里 YAML 锚点 `&cubemx-generated` 两处共用):`Src/*.{c,h}`、`Inc/*.{c,h}`、`Drivers/CMSIS/`、`Drivers/STM32F4xx_HAL_Driver/`、`Middlewares/`、`MDK-ARM/*.{uvprojx,uvoptx,sct,map}`、`.mxproject`、`*.ioc`——这类文件每次重生成按工具自己的风格写回(实测每次 10+ 个文件各被补 1 行末尾空行),改写只会制造提交抖动。⚠ **只读检查不受影响**:`cppcheck` / 乱码 / `cubemx-survival` / `task-table` / `mem-numbers` 仍覆盖 `Src/`、`Inc/`;`App/`、`Drivers/BSP/` 自研代码仍受改写型钩子检查
- 提交信息:**单行中文标题 ≤100 字符**(gitlint `title-max-length=100`)+ **正文每行 ≤80 字符**(gitlint 默认 `body-max-line-length`,本项目未关)→ 长说明一律用**短标题 + `git commit -F -` 多行正文**(中文长标题极易超限);UTF-8 无 BOM + `git commit -F <文件>`(防终端转码破坏)
- 代码规范 V1.0:小写下划线命名(`g_`/`s_`/`p_`/`a_` 前缀)、头文件保护宏 `XXX_H`、常量在右、文件头模块注释块 → `docs/代码规范/`
@@ -83,7 +85,7 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v
- netTask:`net_stack_bring_up`(配置已由 defaultTask 在屏障前加载,本任务只读 RAM 副本 → `net_init` + PHY 强制 100M 全双工 → 递增网络代次号)→ 置 NET_READY → 循环 `net_poll` + `net_process_messages`;消费 `SYS_EVT_NET_RECONFIG` → 立即重建网络(新 IP 免重启生效,各 TCP 服务据代次号重建监听)
- defaultTask:`f_mount` forced(无卷自动 `f_mkfs` FAT32;挂载后卷健康探针:小写两击确认,FAT 区陈旧/擦除时自动重格式化自愈,`/config.ini` 回落工厂默认——2026-09-20 /log 写失败修复)→ 网络配置加载(`net_cfg_load`;旧档迁移已于 2026-10-10 删除,见「模块约定」网口配置条)→ STORAGE_READY → LED 闪烁;同时是 syslog(`/log/run.log`·`selftest.log`,定长 64B 记录)的**唯一写者**与**配置引擎属主**(`cfg_file` 静态态单任务收敛于此:UI 保存请求执行 `net_cfg_save_run` + 2s `cfg_file_poll`,经 `SYS_EVT_CFG_SAVE` 事件唤醒;netTask/uiTask 不得直接触碰配置引擎,见 P1-3)
- adcTask(**B1,2026-10-10;L1 层 v2.3;P1-5 事件驱动消费;v2.8 节拍源 TIM3 + STM32 侧 DMA,2026-10-10**):**纯消费者**——每拍调 `adc_input_poll()`(`App/algo/adc_input.c`)= TPAFE `tpafe5160_snapshot()` 临界区原子快照(8 通道)+ **消费一帧 STM32 ADC1 DMA 双缓冲**(L1-3)→ 帧统计 + 每 10 s 心跳日志;取数一律经 `adc_input_raw()` **按语义**(L1-4,不写死下标);只取数、不做保护运算(V0.1 仅 TPAFE 三路 `UA`/`UN`/`IA` 测量有效,见 N-18)。**采样节拍(1 kHz)由 TIM3 更新事件硬件提供**(`Src/main.c` 的 `HAL_TIM_PeriodElapsedCallback` 在 TIM3 分支内调 `tpafe5160_start_conv_irq()`;同一更新事件经 **TRGO** 触发 ADC1 一轮 9 通道转换 → 两片转换器同源对齐);**消费唤醒与该节拍同源**——同一分支再调 `adc_tick_irq_notify()` 置位 `ADC_WAKE_FLAG`,任务用 `osThreadFlagsWait(..., osWaitForever)` 等唤醒(不再 1 ms 轮询;实测 `idle` 由 1~649 降到 **0**)。⚠ ISR 侧**只能**走 `adc_tick_irq_notify()`——它内含"消费者就绪"门(TIM3 在 `app_main_init` 就启动,比调度器早 ≈100 ms)。手写于 `Src/freertos.c` 的 `USER CODE` 区(同 timeSyncTask,**640 words** / **AboveNormal**——2026-10-11 L2 相量 + L1-6 有效性校验上链后静态最坏链 1080 B,512 words 余量跌破 1024 B 底线故抬栈),纳入 IWDG `required_mask`(`TASK_WD_ADC`)。详见 `docs/子系统设计/ADC采样节拍设计说明.md` §10、`App/algo/README.md`
- **采集与算法层(L1/L2)落在 `App/algo/`**(2026-10-10 建):现有 `adc_input.c/h` = L1(语义通道映射 + STM32 ADC1 DMA 消费)、`adc_health.c/h` = L1-6(采样有效性判定:静默/丢帧/单调性/错误增量,纯逻辑免桩单测)、`sample_ring.c/h` + `phasor.c/h` = L2(40 点采样环 + 全周傅氏 5 实例 + 双区交换,2026-10-11 台架闭环)。新算法模块一律进这里,勿塞进 `App/task/`(任务只做消费/编排);见 `App/algo/README.md`
- **采集与算法层(L1/L2/L3)落在 `App/algo/`**(2026-10-10 建):现有 `adc_input.c/h` = L1(语义通道映射 + STM32 ADC1 DMA 消费)、`adc_health.c/h` = L1-6(采样有效性判定:静默/丢帧/单调性/错误增量,纯逻辑免桩单测)、`sample_ring.c/h` + `phasor.c/h` = L2(40 点采样环 + 全周傅氏 5 实例 + 双区交换,2026-10-11 台架闭环)、`prot_set.c/h` + `prot_elm.c/h` = L3 软件侧(Q10 定值模型 + 校验和自检闭锁 + 通用"滞回+定时限"元件框架 7 实例,2026-10-11;**尚无任务调用 `prot_elm_run()`**——链接器移除、零足迹,板端接线随 protectTask 立项走 E-59 同款门禁)。新算法模块一律进这里,勿塞进 `App/task/`(任务只做消费/编排);见 `App/algo/README.md`
- 全景 `docs/架构设计/项目架构总览.md`(六层分层 / 启动时序 / 存储·网络·UI 栈 / 目录组织)
## 硬件引脚
@@ -130,6 +132,7 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v
- `simulator/`(CMake + SDL2 预编译库)与 MCU 端共用 UI 源码(`ui_menu.c`、`ui_font_cn_12.c`),免烧录开发 UI:`& "simulator\build_sim.bat"`(按本机 VS 自动选生成器:16=2019 / 17=2022 / 18=2026,**勿把生成器版本写死**;`build/` 缓存生成器与本机 VS 不符时自动删除重建)→ 运行 `simulator\build\Debug\lvgl_sim.exe`
- 自检:`--cfgtest`(配置闭环)/ `--logtest`(日志引擎)/ `--standby shot.bin`(待机屏截图)/ `--idle <秒>`
- **模拟器代码与固件同标准受检**(2026-10-11):`simulator/` 下自研文件全部纳入 pre-commit(`cppcheck` / `coding-standard` / 乱码 / 改写型钩子 / `doc-links` / `lv-conf-sync`),生成物只靠 `.gitignore` 挡、**不在 `exclude` 里写目录名**(详见 `docs/代码规范/pre-commit使用说明.md` §5.5)。改 `simulator/lv_conf.h` 会触发 `lv-conf-sync`;改模拟器 C/H 会触发 cppcheck + 规范 V1.0
- UI 改动一律走 **`ui-verify` skill 五步门禁**;含新汉字的 UI 文案提交前先跑 **`font-regen` skill** 重生成中文字体
## 文档与图形