feat(ui)+chore(docs): UI 补齐清单清空;数据可信销项与「卡」号清退

本笔含两组收尾工作(同一工作区内交错在 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 字),随该笔入库。
This commit is contained in:
2026-10-28 07:23:16 +08:00
parent 8f7c141a0b
commit 94b0d79026
113 changed files with 1934 additions and 615 deletions
+1 -1
View File
@@ -34,5 +34,5 @@ python tools/font_gen/extract_cn.py # 扫描 UI 源码字符串 →
- `requirements.txt` 必须**纯 ASCII**(Windows 下 pip 按 GBK 解码,中文注释 → UnicodeDecodeError)
- 生僻字(宋体可能无字形)→ **写码前先手动验证字形**,避免"代码写完才发现是空白"
- 生成成功后跑 `ui-verify` skill 全回归;黄金参考因字形变化而 FAIL 属预期 → `check_content_pages.py --update` 刷新
- 字数变化时同步更新文档中的字符集计数(当前 179 汉字/符号 + ASCII 0x20-0x7E,共 274 字形):`UI_中文字体生成与配置.md`、`UI_界面制作流程.md` C3、`UI_设计架构.md`、`simulator/README.md` 已知坑 #4
- 字数变化时同步更新文档中的字符集计数(当前 218 汉字/符号 + ASCII 0x20-0x7E,共 313 字形;2026-10-28 实测。历史上 119/214 → 179/274 → 185/280 均为当时快照):`UI_中文字体生成与配置.md`、`UI_界面制作流程.md` C3、`UI_设计架构.md`、`simulator/README.md` 已知坑 #4
- **新增字低于既有最小码位**(如 Ⅰ U+2160)会下探稀疏 cmap 起点并吞掉单码位补回条目(实测 ▶ 箭头全变方框而旧版 coverage 全绿)——`make_font.py`(2026-10-25 起)按 LVGL 首命中语义插入/守卫/校验,扩字后模拟器像素回归**必跑**
+9 -9
View File
@@ -358,7 +358,7 @@ repos:
files: ^(App/algo/adc_health\.(c|h)|App/task/adc_task\.c|test/host/adc_health/.*|test/host/common/unit_test_harness\.py)$
pass_filenames: false
# 7h2) 通道标定层(L1.5,「数据可信」卡 2/卡 4)主机侧单元测试(2026-10-25 加,道A)
# 7h2) 通道标定层(L1.5,「数据可信」标定折算与落盘整定)主机侧单元测试(2026-10-25 加,道A)
# 背景:标定折算是"码值→工程量"的唯一插入点,Q16 系数/零点两段落盘 +
# 合法带哨兵回退 + 两点标定公式——板端无标准源、坏文件注入路径在真机
# 上难以复现,只有离线端能逐系数钉死。钩子用 MSVC 编译真实源文件
@@ -371,7 +371,7 @@ repos:
language: system
files: ^(App/algo/adc_cal\.(c|h)|App/algo/adc_health\.(c|h)|App/cfg/cfg_file\.(c|h)|App/task/adc_task\.c|test/host/adc_cal/.*|test/host/common/unit_test_harness\.py)$
pass_filenames: false
# 7h3) 量纲回归(「数据可信」卡 7,道A)主机侧单元测试(2026-10-25 加)
# 7h3) 量纲回归(「数据可信」"不该动作时不动作"用例,道A)主机侧单元测试(2026-10-25 加)
# 背景:台架曾长期缺"不该动作时不动作"的判据,码值/工程量错配曾以
# 恒假动作的形态混过验收。本钩子用真实链(adc_cal→ring→phasor→
# prot_elm)+ 显式换算的合成波把七类元件的量纲钉死:折算点被旁路
@@ -383,11 +383,11 @@ repos:
files: ^(App/algo/(adc_cal|prot_elm|prot_set|phasor|sample_ring|freq)\.(c|h)|App/task/(adc_task|protect_task)\.c|test/host/prot_dim/.*|test/host/common/unit_test_harness\.py)$
pass_filenames: false
# 7h4) 遥测快照层(L2 发布侧,「数据可信」卡 8,道D)主机侧单元测试(2026-10-25 加)
# 背景:卡 8 的 DoD 一半是并发与结构类判据——双区切换无撕裂(撕裂窗
# 7h4) 遥测快照层(L2 发布侧,「数据可信」遥测快照发布,道D)主机侧单元测试(2026-10-25 加)
# 背景:遥测快照发布项的 DoD 一半是并发与结构类判据——双区切换无撕裂(撕裂窗
# 200 ms 量级,台架人工比对观测不到)、seq 只增、§4.5 布局与字段偏移
# (卡 9/UI 直接按整体拷贝消费,破布局 = 破协议)、CLIPPED 品质汇总
# (削顶位图要等卡 12 标定才真实出现)。主机侧以 #include 原样纳入
# (104 与 UI 直接按整体拷贝消费,破布局 = 破协议)、CLIPPED 品质汇总
# (削顶位图要等两点标定才真实出现)。主机侧以 #include 原样纳入
# meas/phasor/sample_ring 生产源,合成 9 通道帧序列一次性钉死;
# 读数与注入源比对类判据仍归台架(实测采样类)。files 覆盖被测源、
# 同链核(phasor/sample_ring)、编排方 adc_task 与 harness 本身。
@@ -398,7 +398,7 @@ repos:
files: ^(App/algo/meas\.(c|h)|App/algo/(phasor|sample_ring)\.(c|h)|App/task/adc_task\.c|test/host/meas/.*|test/host/common/unit_test_harness\.py)$
pass_filenames: false
# 7h5) 运行参数段(「数据可信」卡 10,道D)主机侧单元测试(2026-10-25 加)
# 7h5) 运行参数段(「数据可信」道D 交付项)主机侧单元测试(2026-10-25 加)
# 死区把守突发上报的量、104 整定段是现场唯一远程写入口:注册契约、
# 分档量程守卫、两段式、系数直通的合法带与生效值回显必须离线钉死。
- id: run-par-unit-test
@@ -475,7 +475,7 @@ repos:
name: IEC104 协议栈单测(主机侧)
entry: python test/host/iec104/run_unit_test.py
language: system
# 卡 10 起本 TU 链入真实 cfg_file/adc_cal/run_par(板端真源链),触发面同步扩
# 运行参数段落地起本 TU 链入真实 cfg_file/adc_cal/run_par(板端真源链),触发面同步扩
files: ^(App/protocol/iec104/iec104_(asdu|pts|link)\.(c|h)|App/algo/(prot_set|prot_elm|phasor|sample_ring|adc_input|freq|meas|adc_cal|run_par)\.(c|h)|App/cfg/cfg_file(_store)?\.(c|h)|test/host/iec104/.*|test/host/common/unit_test_harness\.py)$
pass_filenames: false
@@ -641,7 +641,7 @@ repos:
# 疑似 MSBuild 节点争用;此后 3 次干净树连跑均绿。判据:单次失败先复跑一次再看,
# 连续两次失败才当真(不许直接 --no-verify 绕过)。
- id: ui-golden
name: UI 像素回归(菜单 8 状态 + 内容页 53 页 黄金参考)
name: UI 像素回归(菜单 8 状态 + 内容页 60 页 黄金参考)
entry: python scripts/check_ui_golden.py
language: system
files: ^(Drivers/BSP/UI/|App/task/ui_task\.(c|h)$|simulator/(tests|sim|src)/|simulator/main\.c$|simulator/CMakeLists\.txt$|simulator/lv_conf\.h$|scripts/check_ui_golden\.py$|\.pre-commit-config\.yaml$)
+3 -3
View File
@@ -10,7 +10,7 @@
## 项目概况
**现状一句话**:平台能力(网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置)**已实现并台架验收**;采集主线已闭环到业务消费者(L1→L2 相量→L2.5 遥测快照→L3 保护判据 protectTask→104 遥信/遥测+UI,B5/批 2);⚠ **保护判据现处于「未标定闭锁」态**——产品构建下 `adc_cal_flags()` 的 `ADC_CAL_F_VALID` 未置位,`protect_task.c:98` 直接停走判据,等卡 12 两点标定写入 `[adc_cal] valid` 后自动解卡(用户裁定 2026-10-25:保持闭锁,不用万用表走捷径);**RS-485 采集尚未接线**(B2 按用户决策冻结,见 `docs/任务规划/暂缓-RS485.md`)——当前最大功能缺口,接线节奏受 **RS-485 接线门禁**约束(见「平台约束」)。
**现状一句话**:平台能力(网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置)**已实现并台架验收**;采集主线已闭环到业务消费者(L1→L2 相量→L2.5 遥测快照→L3 保护判据 protectTask→104 遥信/遥测+UI,B5/批 2);⚠ **保护判据现处于「未标定闭锁」态**——产品构建下 `adc_cal_flags()` 的 `ADC_CAL_F_VALID` 未置位,`protect_task.c:98` 直接停走判据,等两点标定写入 `[adc_cal] valid` 后自动解卡(用户裁定 2026-10-25:保持闭锁,不用万用表走捷径);**RS-485 采集尚未接线**(B2 按用户决策冻结,见 `docs/任务规划/暂缓-RS485.md`)——当前最大功能缺口,接线节奏受 **RS-485 接线门禁**约束(见「平台约束」)。
**数据主线**(能力视角;分层图与跨层依赖表 → `docs/架构设计/项目架构总览.md`):
@@ -92,7 +92,7 @@
## 提交门禁(pre-commit)
- 任一失败即拦截,共 **51 个钩子**(**口径 = YAML 解析后的 hook 条目数**:自查命令与「声明 / 文档 / 实跑」三数同源核对见 `docs/门禁说明/README.md` §2 首条——⚠ 直接 grep 配置里的声明行会多算一条**注释掉的**候选钩子(= 52),不是口径;**配置注释里也别复述那个 grep 字面量**,它会让文本计数再虚高 1(2026-10-27 实测踩过);加一条钩子就同批改 AGENTS 与门禁索引两处计数。2026-10-25 道E 连加 `bom-guard` / `setview-check` / `uinav-selftest` 三条,2026-10-26 加 `generated-fresh` 一条,2026-10-27 加 `nested-comment` 一条;**每种门禁一篇详解(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径)→ `docs/门禁说明/README.md` 索引**;通用机制与整体口径 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `id-check`(**编号门禁**,`docs/编号规范.md` §8 八项校验;**已关闸为【增量拦截】**:只拦 `scripts/id_known_backlog.json` 台账之外的新错误级问题,存量按指纹豁免、台账只减不增;另有一根恒生效的线——可判定比例跌破 `id_registry.json` 基线即失败;**2026-10-26 方案 B 同批加了第二根**:不可判定引用**绝对数**超过 `undecidable_total_ceiling` 即失败,因为比值会被"把可判定的引用改成散文"稀释(详见 `docs/门禁说明/id-check.md` §7.6))+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 **22 根专属钩子**(`-unit-test` 后缀 = 有独立 `files:` 触发面、需要秒级归因的那个子集;2026-10-25 增补 adc-cal / prot-dim / vol-idle-sync / ui-data / meas / run-par 六根)——**这是口径不是缺口**:`test/host/` 实测 40 套带 `run_unit_test.py`,其余 **18 套**(含 `test/host/ui_sink`)没有专属钩子,但每次提交都被 `test-coverage` 总闸全量真跑并守基线回退,**失败照样拦**,只是归因落在总闸输出上;**没有专属钩子 ≠ 没被跑**,18 套台账与补钩子的判据 → `docs/门禁说明/host-unit-tests.md` §6 第 4 条。**Lead 裁定 2026-10-27:不补第 23 根**——读「这套跑没跑」去看总闸输出,别数钩子(原写「23 个 / 含 ui-sink 七个」是双重错:既把 22 说成 23,又宣称 ui-sink 有钩子——配置历史里 `ui-sink-unit-test` 从未存在)+ `test-coverage`(**覆盖率总闸**:跑全部 40 套并守基线回退;缺 mscoverage 组件时按用户裁定 **FAIL**、不 skip,2026-10-24)+ `test-suite-switch` + `registration-check`(双端注册反向校验 + UI 页面描述符表接线,登记簿条目「rs485_task 白名单缺口」)+ `generated-fresh`(**生成器幂等性**:把 `tools/menu_gen/gen_menu.py`、中文字库链、`tools/arch_diagram/gen_*.py` 拷进**系统临时目录**重跑,与工作区**逐字节**必须一致——钩子只读、不写仓库也不 stash 别人在飞的改动;实证 `0f7b5a87` 改了模板文字没重跑生成物,接线前实测另有 5 张 `docs/images/` 配图已漂 → 钉成只减不增基线,**业务生成物零豁免面** → `docs/门禁说明/generated-fresh.md`)+ `nested-comment`(**块注释嵌套**:注释体内再出现 /* 会被 ARMCC 报 9-D,且**按包含者数量刷屏**、只在重编译该 TU 时才暴露;本仓诱因就是「在注释里写作用域/通配路径」,改法是写全目录或用尖括号 <Drivers/BSP/UI/ui_x.c>;接线当日实扫 403 个 .c/.h,新发 0、存量 2 处(`test/host/common/` 两份假件头)钉只减不增基线 → `docs/门禁说明/nested-comment.md`)+ `mem-budget`(RAM 92% 预算门禁,登记簿条目「缩堆迁 CCM 后半(暂缓)」)+ `font-charset`(UI 字符集差集检查,防缺字白框)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 53 页黄金参考)+ `layer-deps`(**分层方向**:`Drivers/BSP/**` 不得 include `App/**` 的头;存量 3 条基线只减不增(2026-10-25 记录 reader 注入削掉 UI 记录 3 条边,6→3))+ `bsp-err`(**BSP 错误码与超时命名约定**:公开 API 不得拿 `HAL_StatusTypeDef`/`bool` 当错误通道、`*_TIMEOUT` 宏不得取负值、非 void 须写「返回值:」、**返回错误码的函数不得裸丢弃返回值**(须接住或显式 `(void)`;实测编译器与 cppcheck 都不报这类,只有这条会响);约定正文 `Drivers/BSP/bsp_err.h`,存量基线只减不增(2026-10-23 首清点 19 条 → 已还 18;`consume-result` 上线又暴露 37 条存量丢弃 → **现 38 条**))
- 任一失败即拦截,共 **51 个钩子**(**口径 = YAML 解析后的 hook 条目数**:自查命令与「声明 / 文档 / 实跑」三数同源核对见 `docs/门禁说明/README.md` §2 首条——⚠ 直接 grep 配置里的声明行会多算一条**注释掉的**候选钩子(= 52),不是口径;**配置注释里也别复述那个 grep 字面量**,它会让文本计数再虚高 1(2026-10-27 实测踩过);加一条钩子就同批改 AGENTS 与门禁索引两处计数。2026-10-25 道E 连加 `bom-guard` / `setview-check` / `uinav-selftest` 三条,2026-10-26 加 `generated-fresh` 一条,2026-10-27 加 `nested-comment` 一条;**每种门禁一篇详解(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径)→ `docs/门禁说明/README.md` 索引**;通用机制与整体口径 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `id-check`(**编号门禁**,`docs/编号规范.md` §8 八项校验;**已关闸为【增量拦截】**:只拦 `scripts/id_known_backlog.json` 台账之外的新错误级问题,存量按指纹豁免、台账只减不增;另有一根恒生效的线——可判定比例跌破 `id_registry.json` 基线即失败;**2026-10-26 方案 B 同批加了第二根**:不可判定引用**绝对数**超过 `undecidable_total_ceiling` 即失败,因为比值会被"把可判定的引用改成散文"稀释(详见 `docs/门禁说明/id-check.md` §7.6))+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 **22 根专属钩子**(`-unit-test` 后缀 = 有独立 `files:` 触发面、需要秒级归因的那个子集;2026-10-25 增补 adc-cal / prot-dim / vol-idle-sync / ui-data / meas / run-par 六根)——**这是口径不是缺口**:`test/host/` 实测 40 套带 `run_unit_test.py`,其余 **18 套**(含 `test/host/ui_sink`)没有专属钩子,但每次提交都被 `test-coverage` 总闸全量真跑并守基线回退,**失败照样拦**,只是归因落在总闸输出上;**没有专属钩子 ≠ 没被跑**,18 套台账与补钩子的判据 → `docs/门禁说明/host-unit-tests.md` §6 第 4 条。**Lead 裁定 2026-10-27:不补第 23 根**——读「这套跑没跑」去看总闸输出,别数钩子(原写「23 个 / 含 ui-sink 七个」是双重错:既把 22 说成 23,又宣称 ui-sink 有钩子——配置历史里 `ui-sink-unit-test` 从未存在)+ `test-coverage`(**覆盖率总闸**:跑全部 40 套并守基线回退;缺 mscoverage 组件时按用户裁定 **FAIL**、不 skip,2026-10-24)+ `test-suite-switch` + `registration-check`(双端注册反向校验 + UI 页面描述符表接线,登记簿条目「rs485_task 白名单缺口」)+ `generated-fresh`(**生成器幂等性**:把 `tools/menu_gen/gen_menu.py`、中文字库链、`tools/arch_diagram/gen_*.py` 拷进**系统临时目录**重跑,与工作区**逐字节**必须一致——钩子只读、不写仓库也不 stash 别人在飞的改动;实证 `0f7b5a87` 改了模板文字没重跑生成物,接线前实测另有 5 张 `docs/images/` 配图已漂 → 钉成只减不增基线,**业务生成物零豁免面** → `docs/门禁说明/generated-fresh.md`)+ `nested-comment`(**块注释嵌套**:注释体内再出现 /* 会被 ARMCC 报 9-D,且**按包含者数量刷屏**、只在重编译该 TU 时才暴露;本仓诱因就是「在注释里写作用域/通配路径」,改法是写全目录或用尖括号 <Drivers/BSP/UI/ui_x.c>;接线当日实扫 403 个 .c/.h,新发 0、存量 2 处(`test/host/common/` 两份假件头)钉只减不增基线 → `docs/门禁说明/nested-comment.md`)+ `mem-budget`(RAM 92% 预算门禁,登记簿条目「缩堆迁 CCM 后半(暂缓)」)+ `font-charset`(UI 字符集差集检查,防缺字白框)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 60 页黄金参考)+ `layer-deps`(**分层方向**:`Drivers/BSP/**` 不得 include `App/**` 的头;存量 3 条基线只减不增(2026-10-25 记录 reader 注入削掉 UI 记录 3 条边,6→3))+ `bsp-err`(**BSP 错误码与超时命名约定**:公开 API 不得拿 `HAL_StatusTypeDef`/`bool` 当错误通道、`*_TIMEOUT` 宏不得取负值、非 void 须写「返回值:」、**返回错误码的函数不得裸丢弃返回值**(须接住或显式 `(void)`;实测编译器与 cppcheck 都不报这类,只有这条会响);约定正文 `Drivers/BSP/bsp_err.h`,存量基线只减不增(2026-10-23 首清点 19 条 → 已还 18;`consume-result` 上线又暴露 37 条存量丢弃 → **现 38 条**))
- **范围 = 项目代码**:第三方(`Lib/`、`Middlewares/`、CMSIS、HAL、`lftpd`、`dhara`、`MDK-ARM`)排除;`cppcheck`/`coding-standard` 另排除 `test/`,规范检查再排除 CubeMX 生成的 `Src/`/`Inc/`。**`simulator/` 已纳入全部钩子**(2026-10-11)——生成物只靠 `.gitignore` 挡,**不在 `exclude` 里写目录名**(教训见 `docs/代码规范/pre-commit使用说明.md` §5.5)
- ⚠ **pre-commit 4.x 已移除 `always: true`**(实测对 `local` 钩子只告警 `Unexpected key(s)` 并跳过)→ 想"总是跑"的钩子**必须让 `files:` 覆盖到所有会触发它的文件**,没有兜底开关
- **改写型钩子(`trailing-whitespace` + `end-of-file-fixer`)豁免 CubeMX/Keil 生成文件**(配置里 YAML 锚点 `&cubemx-generated`);⚠ **只读检查不受影响**:`cppcheck` / 乱码 / `cubemx-survival` / `task-table` / `mem-numbers` 仍覆盖 `Src/`、`Inc/`
@@ -153,7 +153,7 @@
## 文档与图形
- **登记簿类文档「完成即销项」**:`docs/任务规划/README.md` 这类待办登记簿,事项修复/关闭后**直接从表中删除该行**(不保留"已消化"行)——结论与证据应已沉淀进对应模块文档/问题记录。销项时必须:① 先核对目标文档确已含完整记录 ② 同步清理其他文档对该编号的引用 ③ 改完跑 `check_doc_links.py --all` + pre-commit。**新条目标识(用户裁定 2026-10-14)**:`#` 列填**语义短语**(如 `沉降窗 800ms 上限只留痕`),**不再新增字母+数字编号**——"编号不回收"只写规则却不留痕迹就不可执行(销项删行后仓库里毫无痕迹,2026-10-14 实测就发生过「销项号被重新取走」的撞号事故),语义标识自带唯一性;**存量编号(登记簿 N-x / S-x / T-x 与专项 A-x)已于 2026-10-26 全部转成语义短语**——旧号进 `scripts/id_aliases.json` 标 `retired-to-phrase`,不得再指;**已随销项消失的号永久作废**、不得复用 → `docs/任务规划/README.md` §0
- **登记簿类文档「完成即销项」**:`docs/任务规划/README.md` 这类待办登记簿,事项修复/关闭后**直接从表中删除该行**(不保留"已消化"行)——结论与证据应已沉淀进对应模块文档/问题记录。销项时必须:① 先核对目标文档确已含完整记录 ② 同步清理其他文档对该编号的引用 ③ 改完跑 `check_doc_links.py --all` + pre-commit。**新条目标识(用户裁定 2026-10-14)**:`#` 列填**语义短语**(如 `沉降窗 800ms 上限只留痕`),**不再新增字母+数字编号**——"编号不回收"只写规则却不留痕迹就不可执行(销项删行后仓库里毫无痕迹,2026-10-14 实测就发生过「销项号被重新取走」的撞号事故),语义标识自带唯一性;**存量编号(登记簿 N-x / S-x / T-x 与专项 A-x)已于 2026-10-26 全部转成语义短语**,旧号进 `scripts/id_aliases.json` 标 `retired-to-phrase`、不得再指;**「数据可信」任务卡号(中文前缀「卡」+ 数字,14 个)已于 2026-10-27 随卡销项整族清退**,换算表 `docs/编号规范.md` §9.3——这一族**刻意不进 `id_aliases.json`**:中文前缀不进 check_ids 语料,登记了机器也看不见,**没有机器识别面**,停发只靠规范与评审;**已随销项消失的号永久作废**、不得复用 → `docs/任务规划/README.md` §0
- 图形走 **`draw-diagram` skill**:精确布局图用 `tools/arch_diagram/gen_*.py` 生成器(产物放 `docs/images/`,**脚本与产物同一笔提交**:改生成器没重跑,下一个碰巧重跑的人会看到一段「不是我改的」diff——已机械化 `generated-fresh`,重跑到临时目录逐字节比对 → `docs/文档规范.md` §4.4);拓扑图用 Mermaid;**勿手绘 ASCII 框图**。文件引用关系图走 `tools/refgraph`(`& 'tools\refgraph\gen_refgraph.bat'`)
- **改名 / 挪目录一律走 `scripts/rename_ref.py`(先 dry-run,确认后 `--apply`)**:`git mv` + 自动改写全库引用(反引号引用 / Markdown 链接 / 图片 `../` 层级换算 / `#include` / `uvprojx` `<FilePath>` / `CMakeLists.txt`),落盘后自动跑 `check_doc_links --all` 复核——手工扫引用既慢又漏(一次改名历史上波及 10~30 文件)。引用章节用「`路径.md` §N.M」**紧邻写法**(`doc-links` 校验编号是否还在:紧邻/裸名/前缀/别名/自引用**全部拦提交**(钩子带 `--sections-strict`);每次跑打印「可判定比例」,`--section-todo` 出待改清单,昵称歧义就登记 `scripts/section_aliases.json` 或写清楚)→ `docs/文档规范.md` §3.5 / §3.6。**编号改名走 `scripts/rename_ids.py`**(映射表驱动、**显式 scope**、干跑默认、自动写 `scripts/id_aliases.json` 的 scoped 旧号→新号条目;`[示例]`/`[计划]` 行与变更记录表不改写;**绝不全局查找替换**——同一裸形字面量可能同时属多个族,全局替换等于造新撞号,实测 `S3` 三义)
- 文档写作规范(编码/BOM/链接/表格/一致性钩子)→ `docs/文档规范.md`;全量索引与推荐阅读顺序 → `docs/README.md`
+11 -11
View File
@@ -11,8 +11,8 @@
|---|---|---|---|---|
| `adc_input.h` / `.c` | L1 | 统一语义取数:两片转换器的码值按语义(`UA…IN` / 温度)暴露,并消费 STM32 ADC1 的 DMA 乒乓缓冲 | `adc_input_init()` `adc_input_poll()` `adc_input_raw()` | TPAFE 快照消费 / STM32 ADC1 启动与扫描 / 通道语义映射 |
| `adc_health.h` / `.c` | L1 | 采样有效性判定:吃计数快照,产出静默 / 丢帧 / 单调性 / 错误增量故障位(判定与告警编排分离);「采样通道自检」残余的码值贴轨观察器同层 | `adc_health_check()` `adc_health_flags()` `adc_health_rail_watch()` | 「采样有效性校验」/「采样通道自检」(残余) |
| `adc_cal.h` / `.c` | L1.5 | 通道标定折算(「数据可信」卡 2/卡 4):工程量 =(code+b)×k,Q16 系数/零点两段落盘 + 三态 flags + 合法带哨兵 + 两点公式 | `adc_cal_apply()` `adc_cal_flags()` `adc_cal_set()` | 「通道标定(一次系数 + 零漂)」(M4 半边) |
| `meas.h` / `.c` | L2 发布 | 遥测快照(「数据可信」卡 8,M5 地基):200 ms 基波有效值 + 品质快照,双区无锁读,全仓唯一发布者 = adcTask | `meas_tick()` `meas_get()` `meas_seq()` | M5(卡 9/11 与 UI 是读者) |
| `adc_cal.h` / `.c` | L1.5 | 通道标定折算(「数据可信」标定折算与落盘整定):工程量 =(code+b)×k,Q16 系数/零点两段落盘 + 三态 flags + 合法带哨兵 + 两点公式 | `adc_cal_apply()` `adc_cal_flags()` `adc_cal_set()` | 「通道标定(一次系数 + 零漂)」(M4 半边) |
| `meas.h` / `.c` | L2 发布 | 遥测快照(「数据可信」遥测快照发布,M5 地基):200 ms 基波有效值 + 品质快照,双区无锁读,全仓唯一发布者 = adcTask | `meas_tick()` `meas_get()` `meas_seq()` | M5(104 改读快照与频率点绑定、UI 是读者) |
| `sample_ring.h` / `.c` | L2 输入 | 按语义通道存最近 2 周波(40 点),供相量层"以当前时刻为终止"取窗 | `sample_ring_push_frame()` `sample_ring_window()` | L2 输入(为「每 1 ms 滑动窗刷新」供数) |
| `phasor.h` / `.c` | L2 | 全周傅氏:一周波 20 点 DFT → 基波 / 谐波相量(有效值口径),双区原子切换供无锁读 | `phasor_run()` `phasor_get()` `phasor_calc()` | 全周傅氏系数表 / 基波相量实例 / 相量有效值输出 / 每 1 ms 滑动窗刷新 / 双区指针原子交换 |
| `freq.h` / `.c` | L2 派生量 | 频率测量:相邻两拍基波相量共轭乘积取角 + 自适应窗滑动平均 + 假值钳制 + 幅值门(UA→IA 源回退) | `freq_run()` `freq_get()` `freq_valid()` | 「过频 / 低频」测量侧(测频范围 → `docs/算法/继电保护功能复现规划.md` §4.2) |
@@ -35,7 +35,7 @@
`adc_input_poll()` → `adc_input_raw()` ×9 → `adc_cal_apply()` ×9(L1.5 折算,现口径 =
ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」,码值域)→ `sample_ring_push_frame()`
→ `phasor_run()` → `freq_run()` → 消费者(`adcTask` 心跳与 L1 健康判定;`protectTask` 每 20 ms 取相量 / 频率跑
`prot_elm_run()`;**每 200 ms** `meas_tick()` 发布遥测快照供 iec104Task / uiTask 读,卡 8)。节拍 = TIM3 1 kHz 更新事件,两片转换器同源触发。
`prot_elm_run()`;**每 200 ms** `meas_tick()` 发布遥测快照供 iec104Task / uiTask 读,即「数据可信」遥测快照发布)。节拍 = TIM3 1 kHz 更新事件,两片转换器同源触发。
完整数据流图与初始化落点 → `docs/算法/采集与算法层设计说明.md` §2。
## 3. 逐文件要点(只留"改代码时必须知道"的;机制与理由见设计文档)
@@ -90,29 +90,29 @@ ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」
- 源切换即废相位基准重建(UA / IA 无共同相位基准,即双转换器无共同采样触发)。
- 判据 **J1~J6** 与实测口径 → `docs/算法/采集与算法层设计说明.md` §7.2(与 `test/host/freq/freq_test.c` 文件头同源)。
### 3.8 `adc_cal.c` / `.h` — L1.5 通道标定折算(「数据可信」卡 2 / 卡 4)
### 3.8 `adc_cal.c` / `.h` — L1.5 通道标定折算(「数据可信」标定折算与落盘整定)
- 折算模型:工程量 = (code + b) × k;**k 落盘用 int32 Q16(µV/码 × 65536)**、b 用
int32 码值(负零点靠 `CFG_VAL_INT`)——单位与定点格式的选型依据见
`docs/任务规划/数据可信.md` §4.1,勿改回 V/码 直存(Q16 只剩 20 个刻度)。
- **ROM 默认 = 卡 1 定死的引脚侧 LSB**(TPAFE 152.59 / STM32 805.66 µV/码,
- **ROM 默认 = 量程口径冻结定死的引脚侧 LSB**(TPAFE 152.59 / STM32 805.66 µV/码,
`docs/硬件平台/ADC通道映射说明.md` §7.1);表下标 = 语义枚举(UA0…IN7),
V0.2 改版与本目录 `adc_input` 映射表同步改。
- 三态可用性 `adc_cal_flags()`:VALID(已按变比标定,二次值成立——卡 0b/12 前恒 0)
- 三态可用性 `adc_cal_flags()`:VALID(已按变比标定,二次值成立——端子变比确认与两点标定前恒 0)
/ CLIPPED(运行期按来源派生,V0.2 后自动清零)。**消费者判「能不能信」只许查它**,
`adc_cal_apply()` 不返回可用性(「数据可信」§8 风险表)。
- 合法带哨兵:k ∉ ROM×[0.5,2.0] 或 |b| > 8192 → 折算回退 ROM + 每通道每开机一条
`[ERR]` + VALID 被压制(**即便文件位图说已标定**);这层兜底同时挡坏文件与坏标定。
- `adc_cal_set()` / `adc_cal_two_point()`:整定与两点公式的算术核已齐备(单测还原合成
k/b);**台架两点标定(卡 12)待实测**,本层不含注入。
k/b);**台架两点标定待实测**,本层不含注入。
- cfg 两段 `[adc_cal]` / `[adc_cal_ofs]` **不挂回调**(RAM 副本即生效值,引擎 load/poll
原地改写,逐点现读);注册在 `app_main_init()` 内核前完成,必须先于 `cfg_file_load`。
### 3.9 `meas.c` / `.h` — 遥测快照发布(L2 发布侧,「数据可信」卡 8)
### 3.9 `meas.c` / `.h` — 遥测快照发布(L2 发布侧,「数据可信」波次)
- **唯一发布者 = adcTask**:`phasor_run()`/`freq_run()` 同拍、200 ms **tick 经过**分频
调 `meas_tick()`(非拍计数——idle/skip 拍拉长名义节拍)。docs/任务规划/数据可信.md §8
风险表"快照双写"行 = 评审判据:全仓 `meas_tick` 调用点数须为 1;iec104Task /
uiTask 只读。
- 值口径(批 2 卡 8 A-lite 裁决):**基波有效值瞬时透传**,与 phasor 使用区
- 值口径(批 2「遥测快照发布」的 A-lite 裁决):**基波有效值瞬时透传**,与 phasor 使用区
**同拍同核逐位相等**(单测钉死);**不做** 4 点平均 / 谐波方和根——按
docs/任务规划/数据可信.md §4.5"上送节拍非平均窗,再平均引入滞后";谐波 k-bin 轨
(docs/算法/继电保护功能复现规划.md 「遥测谐波轨(可选)」)扩展只许结构尾部追加,
@@ -122,7 +122,7 @@ ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」
三态表;由 adc_task 编排注入,本层不链 `adc_cal`);TEMP = 最新一拍原始值透传 +
`NT`(「数据可信」决策 5);`MEAS_QDS_*` 低字节与 104 QDS 线上字节同值
(本层**不** include 协议层头——分层方向)。
- 104 死区迁移 / 频率点绑定 = 卡 9/卡 11(道D 后续分支);读数与注入源比对 = **待台架实测**。
- 104 死区迁移 / 频率点绑定 = 104 改读快照那一波(道D 后续分支);读数与注入源比对 = **待台架实测**。
## 4. 构建与测试
@@ -151,7 +151,7 @@ ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」
`@build` 0 错误 0 警告 → `@test` 看 `[ADC_TASK]` 首拍 / 心跳(`phasor(...)`、`freq(...)`、
`cal: ua_mv=… vl=0x00 cl=0xE6 rail=…`、`ring` / `skip` / `adc1_*` / `tgap`);
健康判据 = **零 `[ERR]`**(健康告警与标定哨兵全以 `[ERR]` 开头,误报会被闭环直接抓住;
`vl` 在未标定默认构建必须为 0x00,卡 5 闭锁落地后 `cal:` 行就是台架期望的直接证据)。
`vl` 在未标定默认构建必须为 0x00,未标定即闭锁落地后 `cal:` 行就是台架期望的直接证据)。
→ `docs/算法/采集与算法层设计说明.md` §12。
## 5. 新增一个算法模块的固定动作
+10 -10
View File
@@ -3,7 +3,7 @@
* 模块功能:见 adc_cal.h。折算模型(工程量 = (code + b) × k × 1e-6,k 为 Q16
* µV/码)与两段 cfg 布局([adc_cal]:k_* + valid 位图;[adc_cal_ofs]:
* b_*)照 docs/任务规划/数据可信.md §4.1 / §4.4 落地;系数口径
* (ROM 默认 = 卡 1 定死的引脚侧 LSB)见 docs/硬件平台/ADC通道映射说明.md
* (ROM 默认 = 量程口径冻结定死的引脚侧 LSB)见 docs/硬件平台/ADC通道映射说明.md
* §7.1。
* 并发契约:cfg RAM 副本属主 = 配置引擎(defaultTask 的 load/poll 原地
* 改写),本层逐点折算现读——int32 对齐字在 Cortex-M4 上读写原子,
@@ -15,10 +15,10 @@
* VALID,每通道每次开机首见沿打一条 [ERR](adc_cal_init 重置留痕)。
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
* 作者:DTU 项目组
* 创建日期:2026-10-25(道A 卡 2/卡 4)
* 创建日期:2026-10-25(道A 标定折算与落盘整定)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:Q16 系数/零点两段落盘 + 折算 + 三态 flags
* v1.1 2026-10-25 DTU 项目组 卡 10(道D):新增 adc_cal_b_codes() 生效零点
* v1.1 2026-10-25 DTU 项目组 运行参数段(道D):新增 adc_cal_b_codes() 生效零点
* 读取口;set() 授权写者扩至 iec104Task 直通路径
* (run_par 0x8040~/0x8048~,契约同 §4.4)
* + 合法带哨兵回退 + 两点标定公式(台架注入待跑)
@@ -61,7 +61,7 @@ typedef struct {
uint8_t valid;
} adc_cal_kcfg_t;
/* [adc_cal_ofs] 段 RAM 副本:b 按语义下标 0..7(int32 有符号,卡 3 的
/* [adc_cal_ofs] 段 RAM 副本:b 按语义下标 0..7(int32 有符号,有符号零点类型
* CFG_VAL_INT 是负零点偏移能干净落盘的前提) */
typedef struct {
int32_t b[8];
@@ -70,12 +70,12 @@ typedef struct {
static adc_cal_kcfg_t s_kcfg; /* 生效系数副本(引擎原地更新) */
static adc_cal_bcfg_t s_bcfg; /* 生效零点副本 */
/* 工厂默认(ROM 理论系数,卡 1 定死,「数据可信」§4.4):**下标 = 语义枚举**
/* 工厂默认(ROM 理论系数,量程口径冻结定死,「数据可信」§4.4):**下标 = 语义枚举**
* (UA0 / UB1 / UC2 / UN3 / IA4 / IB5 / IC6 / IN7)——UA/UN/IA 走 TPAFE
* (16 位 ±5 V 档),UB/UC/IB/IC/IN 走 STM32 ADC1;逐路对过
* docs/硬件平台/ADC通道映射说明.md §3(IN=ADC11/STM32,勿再按分组顺序误写)。
* ROM 表按**当前 V0.1 来源排布**显式书写(不查 desc 运行期派生),因为它是
* 卡 1 定稿的存档事实;V0.2 改版(消除双转换器无共同采样触发)时本表与 adc_input 映射表同步改,
* 量程口径冻结定稿的存档事实;V0.2 改版(消除双转换器无共同采样触发)时本表与 adc_input 映射表同步改,
* 上层语义与 API 不动。CLIPPED 位则**运行期按来源派生**(见 adc_cal_flags) */
static const adc_cal_kcfg_t s_kcfg_rom = {
/* idx0 UA / idx1 UB / idx2 UC / idx3 UN */
@@ -341,7 +341,7 @@ float adc_cal_k_uv(adc_semantic_t sem) {
* 入口参数:sem - 语义通道 adc_semantic_t
* 返 回 值:b[码值](越带时 s_eff_kb 已回 0);TEMP/越界返 0 float
* 限定条件:无(任意上下文,纯读)
* 函数说明:卡 10 的 104 b 覆盖回显 + k 单侧改写 RMW 读侧(App/algo/run_par.c)
* 函数说明:运行参数段的 104 b 覆盖回显 + k 单侧改写 RMW 读侧(App/algo/run_par.c)
*/
float adc_cal_b_codes(adc_semantic_t sem) {
int32_t k;
@@ -355,11 +355,11 @@ float adc_cal_b_codes(adc_semantic_t sem) {
}
/*
* 函数功能:整定入口——写通道系数与零点,并置位 VALID(「数据可信」卡 4)
* 函数功能:整定入口——写通道系数与零点,并置位 VALID(「数据可信」标定落盘与整定入口)
* 入口参数:sem - 语义通道;k_q16 - 系数(µV/码×65536);b_codes - 零点(码值)
* 返 回 值:0 - 成功;-1 - 参数非法/越出合法带(RAM 不动,[ERR] 留痕) int
* 限定条件:整定路径上下文(defaultTask 整定/标定链;iec104Task 经 run_par
* 直通为卡 10 授权写者,单字原子契约同 §4.4);落盘由属主经 cfg_file_save
* 直通为运行参数段授权写者,单字原子契约同 §4.4);落盘由属主经 cfg_file_save
* 函数说明:见 adc_cal.h 同名声明
*/
int adc_cal_set(adc_semantic_t sem, int32_t k_q16, int32_t b_codes) {
@@ -408,7 +408,7 @@ void adc_cal_note_persisted(void) {
}
/*
* 函数功能:两点标定公式(卡 12 的算术核,纯函数无状态)
* 函数功能:两点标定公式(标定项的算术核,纯函数无状态)
* 入口参数:c_lo/c_hi、v_lo_uv/v_hi_uv、p_k_q16/p_b 见 adc_cal.h 同名声明
* 返 回 值:0 成功 / -1 参数或斜率非法 / -2 零点越 ±B_MAX int
* 限定条件:无(int64 中间量,主机可测;台架注入待跑)
+17 -17
View File
@@ -1,5 +1,5 @@
/*
* 模块名称:通道标定与量纲折算(L1.5,「数据可信」卡 2/卡 4)
* 模块名称:通道标定与量纲折算(L1.5,「数据可信」标定折算与落盘整定)
* 模块功能:把 adc_input 的原始码值折算成工程量——模型与系数口径的唯一落点:
* 工程量 = (code + b) × k_f,k_f = k[µV/码] × 1e-6
* k 以 int32 **Q16**(µV/码 × 65536)落盘、b 以 int32 码值落盘,
@@ -8,14 +8,14 @@
* 即生效值,逐点折算现取现用(1 kHz × 9 通道 = 9k 次/秒浮点乘,可忽略)。
* 三态可用性:ADC_CAL_F_VALID(已按变比标定 → 工程量为二次值)与
* ADC_CAL_F_CLIPPED(V0.1 硬件削顶)由 adc_cal_flags() 单点查询,
* 104 / UI / 保护闭锁(卡 5)共用(docs/任务规划/数据可信.md §4.2)。
* 104 / UI / 保护闭锁(未标定即闭锁)共用(docs/任务规划/数据可信.md §4.2)。
* **未标定闭锁的判定本身也归本层**(`adc_cal_prot_blocked()`):它讲的是
* 「这几路标定齐了没」,属标定层事实,不是任务编排逻辑——保护任务与 UI
* 组装器都只是它的消费者(道F task-16 把此前的两份实现收成一份)。
* ⚠ 输出单位口径 = **ADC 引脚电压 V**(eng=0):ROM 默认系数按卡 1
* ⚠ 输出单位口径 = **ADC 引脚电压 V**(eng=0):ROM 默认系数按量程口径冻结
* 定死的引脚侧 LSB(TPAFE 152.59 µV/码、STM32 805.66 µV/码,见
* docs/硬件平台/ADC通道映射说明.md §7.1);端子变比(卡 0b)与两点
* 标定(卡 12)完成前不得把输出当二次值消费。TEMP 不参与线性标定
* docs/硬件平台/ADC通道映射说明.md §7.1);端子/子板变比确认与两点
* 标定完成前不得把输出当二次值消费。TEMP 不参与线性标定
* (决策 5),adc_cal_apply() 原样透传码值。
* 本层**纯算法 + 纯数据**:不碰寄存器、不等事件;adc_cal_init() 内核前
* 可调(注册进引擎必须先于 cfg_file_load,FTP 鉴权确立的契约);apply/flags
@@ -23,10 +23,10 @@
* 与 defaultTask 的 load/poll 复位存在 µs 级混窗——设计接受,见 .c 头)。
* 适用平台:STM32F407ZGTx(Cortex-M4F);主机侧 L0.5 单测 test/host/adc_cal/
* 作者:DTU 项目组
* 创建日期:2026-10-25(道A 卡 2/卡 4)
* 创建日期:2026-10-25(道A 标定折算与落盘整定)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:Q16 系数/零点 + 折算/flags/集
* v1.1 2026-10-25 DTU 项目组 卡 10:+adc_cal_b_codes()(run_par 回显/RMW 用)
* v1.1 2026-10-25 DTU 项目组 运行参数段:+adc_cal_b_codes()(run_par 回显/RMW 用)
* v1.2 2026-10-26 DTU 项目组 道F task-16:+adc_cal_prot_blocked()——「UA/UN/IA
* 三路 VALID 是否齐」这份判据停走条件从
* protect_task.c 与 ui_data_feed.c 的两份重复实现收成本层
@@ -45,11 +45,11 @@ extern "C" {
#endif
/* 通道可用性标志(adc_cal_flags() 返回值位) */
#define ADC_CAL_F_VALID (0x01u) /* k 已按变比标定 → 工程量为二次值(卡 12 后置位) */
#define ADC_CAL_F_VALID (0x01u) /* k 已按变比标定 → 工程量为二次值(两点标定后置位) */
#define ADC_CAL_F_CLIPPED (0x02u) /* 硬件削顶(V0.1 STM32 侧单极性无偏置)→ 交流量不可信 */
/*
* ROM 默认系数(int32 Q16 = µV/码 × 65536,卡 1 定死的引脚侧口径):
* ROM 默认系数(int32 Q16 = µV/码 × 65536,量程口径冻结定死的引脚侧口径):
* TPAFE ±5 V 档:10 V 跨度 / 65536 码 = 152.587890625 µV/码 → ×65536 = 10,000,000(整)
* STM32 0~3.3 V:3.3 V / 4096 码 = 805.6640625 µV/码 → ×65536 = 52,800,000(整)
* 两个默认值在 Q16 下**无舍入**(系数定点舍入项从误差预算里抹掉,
@@ -99,7 +99,7 @@ float adc_cal_apply(adc_semantic_t sem, int32_t code);
uint32_t adc_cal_flags(adc_semantic_t sem);
/*
* 函数功能:**未标定闭锁判定**——保护判据所需的三路标定是否齐(「数据可信」卡 5
* 函数功能:**未标定闭锁判定**——保护判据所需的三路标定是否齐(「数据可信」未标定即闭锁
* / §4.3;道F task-16 把它从两处重复实现收敛成这一份真源)
* 入口参数:无
* 返 回 值:1 - 闭锁(UA/UN/IA 中至少一路 `ADC_CAL_F_VALID` 未置位,判据链应停走);
@@ -144,18 +144,18 @@ float adc_cal_k_uv(adc_semantic_t sem);
* 入口参数:sem - 语义通道 adc_semantic_t
* 返 回 值:b[码值](越带时为 0,与折算同视图);TEMP/越界返 0 float
* 限定条件:无
* 函数说明:104 运行参数段(「数据可信」卡 10)b 覆盖回显与 k 单侧改写的 RMW
* 函数说明:104 运行参数段(「数据可信」这一项)b 覆盖回显与 k 单侧改写的 RMW
* 读侧用(App/algo/run_par.c);勿据其反推二次值(看 flags)。
*/
float adc_cal_b_codes(adc_semantic_t sem);
/*
* 函数功能:整定入口——写通道系数与零点,并置位 VALID(「数据可信」卡 4)
* 函数功能:整定入口——写通道系数与零点,并置位 VALID(「数据可信」标定落盘与整定入口)
* 入口参数:sem - 语义通道(电气 8 路) adc_semantic_t
* k_q16 - 系数,µV/码 × 65536 内 int32_t
* b_codes - 零点偏移,码值 内 int32_t
* 返 回 值:0 - 成功;-1 - 参数非法/越出合法带(RAM 不动,[ERR] 留痕) int
* 限定条件:**整定路径上下文**(defaultTask 标定流程/整定链;卡 10 起 iec104Task
* 限定条件:**整定路径上下文**(defaultTask 标定流程/整定链;运行参数段落地起 iec104Task
* 经 App/algo/run_par.c 的 0x8040~/0x8048~ 直通写亦为授权写者——写的仍是
* 引擎对齐 int32 单字,µs 级混窗契约同「数据可信」§4.4)。勿在 adcTask 调用
* 函数说明:**只写 RAM 副本,不置脏、不落盘、不返回"稍后会存"的承诺**——落盘由属主经
@@ -167,7 +167,7 @@ float adc_cal_b_codes(adc_semantic_t sem);
int adc_cal_set(adc_semantic_t sem, int32_t k_q16, int32_t b_codes);
/*
* 函数功能:两点标定公式(「数据可信」卡 12 的算术核,纯函数无状态)
* 函数功能:两点标定公式(「数据可信」标定项的算术核,纯函数无状态)
* 入口参数:c_lo/c_hi - 两点码值(c_hi > c_lo) int32_t
* v_lo_uv/v_hi_uv - 两点实测电压(µV,v_hi > v_lo,端子/引脚域均可) int32_t
* p_k_q16 / p_b - 输出:系数(Q16)与零点偏移(码值) int32_t *
@@ -210,7 +210,7 @@ int adc_cal_rail_ths(adc_semantic_t sem, int32_t *p_lo_th, int32_t *p_hi_th);
* 0 0 盘与 RAM 齐(或压根没改过)——健康
* >0 1 改了、还没到落盘时机——正常在途
* >0 0 **改了且永远不会落盘**:写者绕过 run_par 的语义
* setter 直调 adc_cal_set()(本卡起的事)
* setter 直调 adc_cal_set()(运行参数段起的事)
*
* 消费者告诫(与 vol_lock_get_stats() 同一套,别重犯):
* ① 本组接口不取锁、不取时刻,任意上下文可读;三个数各自是 uint32 单字读写,
@@ -220,10 +220,10 @@ int adc_cal_rail_ths(adc_semantic_t sem, int32_t *p_lo_th, int32_t *p_hi_th);
* 本层不存时刻——存了就得连带管溢出与单位。
* ③ 这些计数**不参与任何判定**:能不能信只看 adc_cal_flags() /
* adc_cal_prot_blocked(),要不要落盘只看 run_par 的脏标志。别拿差额去改控制流,
* 那等于把观测升级成第二真源(本卡第①项已由 run_par 语义 setter 收口,不再加口)。
* 那等于把观测升级成第二真源(标定写入口已由 run_par 语义 setter 收口,不再加口)。
* ④ 写清盲区:本层刻意**不挂** cfg_file 回调,因此"盘 → RAM 的覆盖"(cfg_file_load
* 与外部变更重载)不产生任何计数;未落盘的改值被一次重载无声吞掉,正是这三个
* 数照不到的那一条。要照它得先给本层挂回调 = 行为改动,另卡处置。
* 数照不到的那一条。要照它得先给本层挂回调 = 行为改动,另行立项处置。
*/
typedef struct {
uint32_t set_ok; /* 成功改写 RAM 副本次数(见上方唯一落点) */
+1 -1
View File
@@ -206,7 +206,7 @@ uint32_t adc_health_rail_watch(uint8_t ch, int32_t code, int32_t lo_th, int32_t
* 入口参数:无
* 返 回 值:bit ch = 该通道曾检出贴轨(1 kHz × 9 路 → 低 9 位有效) uint32_t
* 限定条件:无
* 函数说明:供心跳日志 / 后续品质位映射(卡 8/9 的 qds 消费者)只读。
* 函数说明:供心跳日志 / 后续品质位映射(遥测快照发布与 104 消费的 qds 消费者)只读。
*/
uint32_t adc_health_rail_sticky(void);
+4 -4
View File
@@ -50,14 +50,14 @@
#define FREQ_INST_MIN_HZ 35.0f
#define FREQ_INST_MAX_HZ 65.0f
/* 幅值门限(有效值,**二次值 V 口径**,「数据可信」卡 6 重定,依据其 §2.3 表第 1 行):
/* 幅值门限(有效值,**二次值 V 口径**,「数据可信」下游常数按工程量重定的结果,依据其 §2.3 表第 1 行):
* 低于该值判"无有效波形"。取值 50 V = 0.5×Un(相电压标称 100 V,与
* App/algo/prot_set.c 头部量纲基准同源):正常带载 UA 在 0.9~1.1×Un,
* 50 V 之下只可能是断保险/PT 空载/浮空噪声(浮空实测 ~1.7 V 引脚域、
* 二次域更小),不会吃掉正常纹波(纹波谷值远大于 0.5×Un)。
* ⚠ 过渡期行为(eng=0,卡 12 标定前):帧值还是引脚电压(≤5 V < 50 V),
* 本门**恒失效** → freq_valid()=0 → OF/UF 按"必不启动"填充复位——与卡 5
* 未标定闭锁同向(判据链本就停走),不构成额外风险;标定后自动恢复本意。
* ⚠ 过渡期行为(eng=0,两点标定完成前):帧值还是引脚电压(≤5 V < 50 V),
* 本门**恒失效** → freq_valid()=0 → OF/UF 按"必不启动"填充复位——与未标定即闭锁
* 同向(判据链本就停走),不构成额外风险;标定后自动恢复本意。
* 数值沿用原 50.0f 属巧合(原为"远小于千级码值"的拟定值),不是漏改。 */
#define FREQ_AMP_MIN 50.0f
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* 模块名称:遥测快照发布层(L2 派生·发布侧,「数据可信」卡 8)
* 模块名称:遥测快照发布层(L2 派生·发布侧,「数据可信」§4.5)
* 模块功能:实现见 meas.h——200 ms 基波有效值 + 品质快照,双区无锁读。
* 本文件纯算法:输入 = sample_ring 取窗 + 调用方注入(频率/削顶位图),
* 无 RTOS / 无寄存器 / 无日志(「数据可信」层内禁令:本目录不写日志)。
@@ -11,7 +11,7 @@
* 单核顺序执行,无需内存屏障;volatile 阻编译器把字段写入挪到翻转后。
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
* 作者:DTU 项目组
* 创建日期:2026-10-25(道D 卡 8)
* 创建日期:2026-10-25(道D 遥测快照发布)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:200 ms 遥测快照 + 双区无锁读
*/
+9 -9
View File
@@ -1,11 +1,11 @@
/*
* 模块名称:遥测快照发布层(L2 派生·发布侧,「数据可信」卡 8)
* 模块名称:遥测快照发布层(L2 派生·发布侧,「数据可信」§4.5)
* 模块功能:每 **200 ms** 从 L2 层取一次基波有效值 + 品质,产出一份全仓唯一的
* 遥测快照(meas_snap_t,布局权威 = docs/任务规划/数据可信.md §4.5),
* 让 104 与 UI **共用同一份上游**——"什么时候算新值、品质怎么判"只此
* 一处决定(M5 遥测链的地基;104 改读快照属卡 9,UI 侧 ui_data_feed 属
* 一处决定(M5 遥测链的地基;104 侧消费见「数据可信」104 改读快照,UI 侧 ui_data_feed 属
* 「UI 扩展」波次,两者都只是本快照的读者)。
* 值口径(批 2 卡 8 的 A-lite 裁决,2026-10-25):**基波有效值瞬时透传**
* 值口径(批 2「遥测快照发布」的 A-lite 裁决,2026-10-25):**基波有效值瞬时透传**
* (同拍 phasor 使用区口径,系数已在 L1.5 折算进帧值——现单位 = ADC
* 引脚电压 V,二次值语义等 adc_cal_flags() 出 VALID,见
* docs/算法/采集与算法层设计说明.md §10 红线③);**不做** 4 点平均 /
@@ -28,7 +28,7 @@
* §8 风险表"快照双写"行);其余任务/模块**只读**。
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
* 作者:DTU 项目组
* 创建日期:2026-10-25(道D 卡 8)
* 创建日期:2026-10-25(道D 遥测快照发布)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:200 ms 遥测快照 + 双区无锁读
*/
@@ -51,19 +51,19 @@ extern "C" {
/* 每点品质位(uint16)。**低字节与线上 104 QDS 字节同值**(OV/NT/IV,数值
* 口径同 App/protocol/iec104/iec104_asdu.h 的 IEC104_QDS_*)——但本层**不得**
* include 协议层头(分层方向:算法层在协议层之下,反向依赖禁止),故在此自
* 定义同值常量;卡 9 的 104 侧消费直接截低字节上送,一致性由本目录单测与
* 定义同值常量;104 侧消费(104 改读快照)直接截低字节上送,一致性由本目录单测与
* test/host/iec104/ 既有断言双向钉住。高字节为 meas 域扩展位(线上不直接
* 出现,由消费者映射): */
#define MEAS_QDS_OV (0x0001u) /* 溢出(留位,卡 8 不产出——判据待运行参数化) */
#define MEAS_QDS_OV (0x0001u) /* 溢出(留位,本项不产出——判据待运行参数化) */
#define MEAS_QDS_NT (0x0020u) /* 非当前值:未就绪 / 语义未处理(TEMP) */
#define MEAS_QDS_IV (0x0080u) /* 无效:该路取窗失败,无有效读数 */
#define MEAS_QDS_CLIPPED (0x0100u) /* 硬件削顶(adc_cal_flags 位图直通,
* 「数据可信」§4.2 三态表;AC 量不可信,
* 消费者应映射为品质无效,如卡 9 的 104 IV) */
* 消费者应映射为品质无效,如 104 改读快照侧的 IV) */
/* 遥测快照(docs/任务规划/数据可信.md §4.5 权威布局;实测 72 B,2×72 ≈ 144 B
* 双区 = 卡 8 DoD 预算口径,由 test/host/meas/ 的布局钉死用例锁字段偏移——
* 改字段 = 破协议,须同步卡 9 / UI) */
* 双区 = 本项 DoD 预算口径,由 test/host/meas/ 的布局钉死用例锁字段偏移——
* 改字段 = 破协议,须同步 104 改读快照 / UI) */
typedef struct {
uint32_t seq; /* 只增;消费者据此判断是否换帧 */
uint32_t tick_ms; /* 发布拍时基(osKernelGetTickCount 原值) */
+1 -1
View File
@@ -205,7 +205,7 @@ void prot_elm_eval(uint32_t now_ms, const float meas[PE_COUNT]) {
* 入口参数:now_ms - 单调时基(tick ms)
* 返 回 值:无
* 限定条件:仅保护消费者任务上下文;测量已是 L1.5 工程量(未标定域由
* protectTask 卡 5 闭锁挡在门外,本函数不感知标定态)
* protectTask 未标定即闭锁挡在门外,本函数不感知标定态)
* 函数说明:src=PHASOR 行任一相量未就绪(未满一周波)→ **整拍跳过**,
* 不引入陈旧/半新测量(B5 口径)。src=FREQ 行:freq 有有效读数
* (started 且幅值门 OK)→ 填测得频率;否则按方向填"必不启动"值
+2 -2
View File
@@ -23,9 +23,9 @@
* - 返回**即时**(参考 GRly_TimeRelay 带 10 ms 返回延时——V0.1 无出口硬件,
* 抖动只影响日志,P4 接出口时再补返回延时);
* - 复压/方向/无压无流闭锁(dwSetFyCtrl 类)随 P2/P3 元件扩展;
* - 测量输入 = adc_task 经 adc_cal_apply() 折算后的工程量(L1.5,卡 2 已落地):
* - 测量输入 = adc_task 经 adc_cal_apply() 折算后的工程量(L1.5,标定折算已落地):
* 未标定(VALID=0)时单位只是 ADC 引脚电压——该域下判据必然错配,由
* protectTask 的未标定闭锁(卡 5)停走整条判据链,元件核本身不掺和
* protectTask 的「数据可信」未标定即闭锁停走整条判据链,元件核本身不掺和
* 标定语义(保持纯逻辑);标定后单位 = 二次值,定值口径才名副其实。
*
* 线程约定:init 内核启动前或保护消费者任务上下文;eval/run 仅保护消费者任务
+3 -3
View File
@@ -6,12 +6,12 @@
* ⚠ 默认值/范围为拟定值(参考 EEPROM 出厂默认表不在本仓库,规划 §10.3 待补);
* 通讯地址逐项对照参考 Comm/Pub/Const_CommSetPara.c g_tCommSetParaTab。
*
* 量纲口径(「数据可信」卡 6 复核,2026-10-25):A/V 项 = **二次值**工程量,
* 量纲口径(「数据可信」下游常数按工程量重定一项复核,2026-10-25):A/V 项 = **二次值**工程量,
* 标称基准 100 V / 1 A(UA/UB/UC 相电压、3U0、OV/UV 同域——OV 120 = 1.2×Un、
* UV 20 = 0.2×Un、3U0 15 = 0.15×Un;OC1/2/3 = 10/5/2 ×Ir、OL = 1.0×Ir,
* 三段递升与过负荷低于速断均自洽)。ADC 帧仅在 adc_cal VALID 置位后才处
* 于此域(未标定 = 引脚电压域,由卡 5 闭锁停走判据,见 protect_task.c);
* min/max 范围覆盖 0~4×标称,无需随本卡改动数值——换算依据与三处下游
* 于此域(未标定 = 引脚电压域,由未标定即闭锁停走判据,见 protect_task.c);
* min/max 范围覆盖 0~4×标称,无需随这一项改动数值——换算依据与三处下游
* 常数同源,见 docs/任务规划/数据可信.md §2.3。
*
* 创建日期:2026-10-11
+4 -4
View File
@@ -1,13 +1,13 @@
/*
* 模块名称:运行参数段(L2/L3 整定层,「数据可信」卡 10)——实现
* 模块功能:见 run_par.h。工厂默认 = 「数据可信」卡 6 额定 0.5 % 档(电压 500
* 模块名称:运行参数段(L2/L3 整定层,「数据可信」这一项)——实现
* 模块功能:见 run_par.h。工厂默认 = 「数据可信」下游常数按工程量重定后的额定 0.5 % 档(电压 500
* mV / 电流 5 mA / 频率 500 mHz,毫单位 int32 定点落盘);[run_par]
* 段 9 键(db_ua…db_freq,均 ≤15 字符)≤ CFG_FILE_MAX_KEYS 不拆段
* (通道系数覆盖**不落本段**——直通 adc_cal 的 [adc_cal]/[adc_cal_ofs],
* 系数唯一真源在那两段,lead 裁②a)。
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
* 作者:DTU 项目组
* 创建日期:2026-10-25(道D 卡 10)
* 创建日期:2026-10-25(道D 运行参数段)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:[run_par] 段 + 104 映射 + 直通 adc_cal
* + B7 式脏标志落盘请求
@@ -52,7 +52,7 @@ typedef struct {
} run_par_db_t;
static const run_par_db_t s_db_rom = {
{ 500L, 500L, 500L, 500L, /* UA/UB/UC/UN:0.5 V(卡 6 额定档) */
{ 500L, 500L, 500L, 500L, /* UA/UB/UC/UN:0.5 V(工程量重定后的额定档) */
5L, 5L, 5L, 5L, /* IA/IB/IC/IN:0.005 A */
500L } /* 频率:0.5 Hz(绝对档,非额定百分比) */
};
+6 -6
View File
@@ -1,17 +1,17 @@
/*
* 模块名称:运行参数段(L2/L3 整定层,「数据可信」卡 10)
* 模块名称:运行参数段(L2/L3 整定层,「数据可信」这一项)
* 模块功能:遥测死区(9 点)与通道标定系数覆盖(k/b 各 8 路)的**单一真源**:
* - 死区 = 本模块 int32 毫单位 RAM 副本(注册进 cfg 引擎 [run_par] 段,
* 工厂默认 = 「数据可信」卡 6 额定 0.5 % 档),104 消费侧
* 工厂默认 = 「数据可信」下游常数按工程量重定后的额定 0.5 % 档),104 消费侧
* (App/protocol/iec104/iec104_pts.c)每拍实时读取——无投递、无缓存
* 副本(卡 9 曾在 pts 侧留运行时副本 s_yc_db,卡 10 落地后收编于此,
* 副本(104 改读快照曾在 pts 侧留运行时副本 s_yc_db,运行参数段落地后收编于此,
* 双源必打架);
* - 系数覆盖 = **直通 adc_cal_set()**([adc_cal]/[adc_cal_ofs] 是系数
* 唯一真源,卡 4 已定;本模块只加 104 地址映射 + 落盘请求,不另存
* 唯一真源,标定落盘与整定入口已定;本模块只加 104 地址映射 + 落盘请求,不另存
* 一份系数——同 D1 裁"两处判断必打架"逻辑)。
* 104 地址映射(docs/算法/继电保护功能复现规划.md §5.1 运行参数类
* 0x8020H~0x8058H;逐项表原文"待补"(参考项目 CommPara_ConfigTable
* 不在仓),本表即卡 10 的落实,送检点表若另给权威地址只改常量段:
* 不在仓),本表即运行参数段的落实,送检点表若另给权威地址只改常量段:
* 0x8030~0x8038 = 死区 UA/UB/UC/UN/IA/IB/IC/IN/FREQ(工程量 V/A/Hz);
* 0x8040~0x8047 = k 覆盖(µV/码);0x8048~0x804F = b 覆盖(码值,可负);
* 其余留白(未启用类别),**0x8027~0x802A 属 prot_set 告警段**,本表
@@ -41,7 +41,7 @@
* 接口级)→ 主机侧可单测(test/host/run_par,链真 cfg 引擎 + 真 adc_cal)。
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
* 作者:DTU 项目组
* 创建日期:2026-10-25(道D 卡 10)
* 创建日期:2026-10-25(道D 运行参数段)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:[run_par] 段 + 104 地址映射 + 直通
* adc_cal + B7 式脏标志落盘请求
+5 -5
View File
@@ -25,8 +25,8 @@
#include "gd5f2gq5ue.h"
#include "tpafe5160.h"
#include "adc_input.h" /* L1 采集层:adc_input_init()(语义映射 + STM32 ADC1 扫描) */
#include "adc_cal.h" /* L1.5 标定层:adc_cal_init()(ROM 系数 + cfg 两段注册,道A 卡2/4) */
#include "run_par.h" /* 运行参数段:run_par_init()([run_par] 注册 + 104 地址映射真源,道D 卡10) */
#include "adc_cal.h" /* L1.5 标定层:adc_cal_init()(ROM 系数 + cfg 两段注册,道A 标定折算与落盘整定) */
#include "run_par.h" /* 运行参数段:run_par_init()([run_par] 注册 + 104 地址映射真源,道D 这一项) */
#include "iec104_comm.h" /* [comm] 段:iec104_comm_init()(ca/端口注册,道G task-8) */
#include "phasor.h" /* L2 相量层:phasor_init()(系数表 + 实例 + 双区交换) */
#include "freq.h" /* L2 派生量:freq_init()(相位解缠绕测频,B8) */
@@ -272,8 +272,8 @@ int app_main_init(void) {
(void)freq_init();
DBG_INFO("freq layer init: OK");
/* 4c-3) 通道标定层(L1.5,「数据可信」卡 2/卡 4)初始化:RAM 系数副本置
* ROM 默认(卡 1 定死的引脚侧 LSB,docs/硬件平台/ADC通道映射说明.md §7.1)
/* 4c-3) 通道标定层(L1.5,「数据可信」标定折算与落盘整定)初始化:RAM 系数副本置
* ROM 默认(量程口径冻结定死的引脚侧 LSB,docs/硬件平台/ADC通道映射说明.md §7.1)
* + 向配置引擎注册 [adc_cal] / [adc_cal_ofs] 两段。注册必须先于
* defaultTask 的 cfg_file_load(「先注册后 load」契约)→ 只能落内核前;
* 折算消费在 adcTask 每拍(adc_cal_apply),标定文件值随 load/poll 原地
@@ -282,7 +282,7 @@ int app_main_init(void) {
DBG_INFO("adc cal init: OK (k_q16 tpafe=%ld stm32=%ld)",
(long)ADC_CAL_K_Q16_TPAFE, (long)ADC_CAL_K_Q16_STM32);
/* 4c2) 运行参数段初始化(「数据可信」卡 10):死区 9 点工厂默认 + 注册
/* 4c2) 运行参数段初始化(「数据可信」这一项):死区 9 点工厂默认 + 注册
* [run_par] 段。同 adc_cal 的「先注册后 load」契约 → 必须内核前;
* 104 消费(COV 实时读 / 0x8020 段读写映射)在 iec104Task 启动后进行。 */
run_par_init();
+1 -1
View File
@@ -34,7 +34,7 @@ extern osEventFlagsId_t sys_evtHandle;
#define SYS_EVT_PROT_SET_SAVE (1u << 7) /* 保护定值落盘请求(B7):iec104Task 检测到定值脏置位,
* defaultTask(配置引擎属主)消费并写 /prot_set.bin
* (消费型命令位;写盘失败脏标志保留 → 下轮再通知重试) */
#define SYS_EVT_RUN_PAR_SAVE (1u << 8) /* 运行参数段落盘请求(「数据可信」卡 10):iec104Task
#define SYS_EVT_RUN_PAR_SAVE (1u << 8) /* 运行参数段落盘请求(「数据可信」这一项):iec104Task
* 检测到 run_par 脏(死区 9 键 / 系数覆盖联动 [adc_cal])
* 置位,defaultTask 消费并 cfg_file_save 整档外科保存
* (消费型命令位;失败脏保留 → 下轮重试,B7 同款) */
+19 -2
View File
@@ -45,6 +45,8 @@
#include <string.h>
#include "cmsis_os.h" /* osKernelGetTickCount:与 adc_task 同一 ms 时基 */
#include "boot_stats.h" /* 运行报告:上电次数 + 本次复位原因快照(道G task-12 数据面) */
#include "iec104_serv.h" /* 运行报告:四个 104 只读观测计数(本次开机以来,跨重连不清零) */
#include "ui_data_feed.h"
@@ -145,7 +147,7 @@ static uint8_t s_map_done;
* par 帧有**三个各自独立**的变化源,任一变了就要重发一帧(详见 tick 里的门控注释):
* s_par_sum 定值改动(校验和)
* s_par_locked 定值闭锁(定值校验和自检失配,校验和不动)
* s_par_cal_block 未标定闭锁(卡 12 标定完成,校验和也不动)
* s_par_cal_block 未标定闭锁(两点标定完成,校验和也不动)
* 后两个各占一字节——省下来就是"屏上状态与真值脱拍"这笔债 */
static uint32_t s_last_rt_ms;
static uint32_t s_par_sum;
@@ -732,6 +734,8 @@ static void feed_fill_par(ui_data_par_t *p_snap, uint32_t sum) {
*/
static void feed_fill_info(ui_data_info_t *p_snap, uint32_t tick_ms) {
const ftp_cfg_t *p_ftp = ftp_cfg_get();
boot_stats_t boot;
iec104_serv_stats_t st104;
p_snap->valid = 1u;
p_snap->uptime_s = tick_ms / 1000u;
@@ -747,6 +751,19 @@ static void feed_fill_info(ui_data_info_t *p_snap, uint32_t tick_ms) {
} else {
p_snap->ftp_user[0] = '\0';
}
/* 运行报告四数(2026-10-28 UI 补齐):纯搬运,页面不得自己去 include 这两个头。
* uptime_s 仍由本函数用 tick 差算——boot_stats 不提供时长,别在那里再算一份。 */
boot_stats_get(&boot);
iec104_serv_get_stats(&st104);
p_snap->boot_count = boot.boot_count;
p_snap->boot_seq_state = boot.seq_state;
p_snap->boot_write_failed = boot.write_failed;
p_snap->rst_cause = boot.rst_cause;
p_snap->boot_ready = boot.ready;
p_snap->iec104_conn_up = st104.conn_up;
p_snap->iec104_apdu_tx = st104.apdu_tx;
p_snap->iec104_tx_fail = st104.tx_fail;
p_snap->iec104_rx_bytes = st104.rx_bytes;
}
/*
@@ -817,7 +834,7 @@ void ui_data_feed_tick(void) {
* 但"校验和没变"不等于"页面该看的没变"——本帧里还有两个与校验和无关的事实:
* · locked(定值闭锁):自检失配时置位,校验和一字不变,
* 而整定页保存行要显示 LOCK 并禁编辑;
* · cal_block(未标定闭锁):卡 12 两点标定写完 [adc_cal] 的 valid 就翻转,
* · cal_block(未标定闭锁):两点标定写完 [adc_cal] 的 valid 就翻转,
* 校验和同样不动,而标题上的"未标定"徽标要当场消失。
* 只盯校验和,这两件事都到不了屏上(真机现象:标定做完了屏上徽标永远挂着,
* 直到某次定值改动才被顺带刷掉——那是把两件不相干的事当同步点)。
+3 -3
View File
@@ -25,7 +25,7 @@
* s_gen_document 两处 `off += snprintf(...)` 改检查式(截断即
* 返回 -1,不再跳过缓冲末尾);注册拒超长键名(≤ 15 字符),
* 使每行 112 字节余量成为可编译期验证的前提
* v1.5 2026-10-25 DTU 项目组 数据可信卡 3:新增值类型 CFG_VAL_INT(有符号十进制,
* v1.5 2026-10-25 DTU 项目组 「数据可信」有符号零点类型:新增值类型 CFG_VAL_INT(有符号十进制,
* len 1/2/4 小端补码)——s_decode_int() 用 strtol + ERANGE +
* 宽度上下界校验,s_encode() 带负号输出;负零点偏移从此可
* 干净落盘(动因见 docs/任务规划/数据可信.md §4.4 与 §7 决策 3)
@@ -43,7 +43,7 @@
#include <ctype.h>
#include <errno.h> /* ERANGE:strtol 饱和判别(INT 键解码需要,数据可信卡 3) */
#include <errno.h> /* ERANGE:strtol 饱和判别(INT 键解码需要,「数据可信」有符号零点类型) */
#include "cfg_file.h"
@@ -358,7 +358,7 @@ static int s_decode_uint(uint8_t *p_dst, size_t len, const char *p_val) {
}
/*
* 函数功能:解析有符号十进制值(小端补码写入,数据可信卡 3)
* 函数功能:解析有符号十进制值(小端补码写入,「数据可信」有符号零点类型)
* 入口参数:p_dst - 目标字段 uint8_t *
* len - 字段字节数(1/2/4) size_t
* p_val - 值文本(可带 +/- 号) const char *
+1 -1
View File
@@ -15,7 +15,7 @@
* 超长;超长处置补自检留痕
* v1.3 2026-10-15 王建锋 新增公开常量
* CFG_FILE_MAX_NAME_LEN(段名/键名上限 15 字符)
* v1.4 2026-10-25 DTU 项目组 数据可信卡 3:新增 CFG_VAL_INT 有符号十进制值类型
* v1.4 2026-10-25 DTU 项目组 「数据可信」有符号零点类型:新增 CFG_VAL_INT 有符号十进制值类型
* (len = 1/2/4,小端补码)——标定零点偏移等负值需有符号
* 落盘,动因与取舍见 docs/任务规划/数据可信.md §4.4
*/
+2 -2
View File
@@ -42,7 +42,7 @@
`syslog_request_clear()` 调用内就删完了,因此 `WAIT` 态在模拟器上永不出现
(同 `syslog_post` 在两端"有队列 / 直写无队列"的差异)
### 五类记录与「记录类型 = 日志 ID」(道F task-10,2026-10-26;task-11 记录 5 页按此做)
### 五类记录与「记录类型 = 日志 ID」(道F task-10,2026-10-26;task-11 记录 5 页按此做,2026-10-28 五页已落地)
**决策一:记录类型就是 `syslog_id_t` 本身,一类记录 = `/log` 下一个严格 8.3 短名的文件。**
64B 定长记录体里**没有类型字段位**:`[0..18]` 时标 / `[19]` 空格 / `[20..29]` epoch /
@@ -78,7 +78,7 @@
任务用(**protectTask、iec104Task 必须用它**),丢弃只累加 `syslog_post_dropped()`、
由唯一写者 defaultTask 在 `syslog_drain()` 里按差值补一条留痕——同 `soe_store_post`
当年那条 `872 → 1192 B FAIL` 的实证纪律。收/丢判据两个口完全一致。
- **读侧契约(给 task-11)**:`syslog_count(id)` + `syslog_get_record(id, idx, ts, ts_len,
- **读侧契约(给 task-11;2026-10-28 五页已按此接上)**:`syslog_count(id)` + `syslog_get_record(id, idx, ts, ts_len,
desc, desc_len)` 与运行/自检记录**同一枚 reader**,"最近 20 条"= 从 `count-20` 起读;
`count()==0` 就是空态,页面显示"无记录"。**不要**在共享代码里调 MCU 专属的
`syslog_clear_apply()`(模拟器不实现 → 链接期报错是故意的);清除一律走
+2 -2
View File
@@ -61,7 +61,7 @@ extern "C" {
* 4 软压板投入 value = 1
* 5 采样闭锁 value = adc_health 闭锁位图(触发时的 hf & mask)
* 6 采样恢复 value = 0
* 7 标定闭锁 value = UA/UN/IA VALID 未齐的通道位图(卡 5,2026-10-25)
* 7 标定闭锁 value = UA/UN/IA VALID 未齐的通道位图(未标定即闭锁,2026-10-25)
* 8 标定复归 value = 0
*/
typedef enum {
@@ -71,7 +71,7 @@ typedef enum {
SOE_T_PLATE_IN,
SOE_T_SAMPLE_BLOCK,
SOE_T_SAMPLE_RESUME,
/* 未标定闭锁(「数据可信」卡 5,2026-10-25 道A 追加):UA/UN/IA 的 VALID
/* 未标定闭锁(「数据可信」未标定即闭锁一项,2026-10-25 道A 追加):UA/UN/IA 的 VALID
* 未全置位 → 判据停走;与采样闭锁分型,边沿各留一条记录 */
SOE_T_CAL_BLOCK,
SOE_T_CAL_RESUME,
+2 -1
View File
@@ -44,7 +44,8 @@ extern "C" {
* 同理二进制 SOE 通道的 soe_type_t 本轮**不动**:改它必须同步 UI 侧的类型名表
* (类型名表在 UI 侧 <Drivers/BSP/UI/ui_w_soe.c>,不在本道写域),而且 SOE
* 页与这五页是两套读者。
* 口径与五个写入点已登记进 App/log/README.md(task-11「记录 5 页」按此做)。
* 口径与五个写入点已登记进 App/log/README.md(task-11「记录 5 页」按此做——五个页面已于
* 2026-10-28 落地:ui_page_accident / oper / alarm / start / yk,各页只读一个文件)。
*/
typedef enum {
SYSLOG_RUN = 0u, /* 运行记录 /log/run.log:上电/重启事件 */
+28 -28
View File
@@ -1,24 +1,24 @@
/*
* 模块名称:IEC 60870-5-104 点表与数据源适配(实现)
* 模块功能:实现 iec104_pts.h——YC/YX/YK/定值点表(ROM)、板端默认源
* (**L2 遥测快照**(卡 9)/ prot_elm / prot_set)、COV 比对(遥信变位 +
* (**L2 遥测快照**(104 改读快照)/ prot_elm / prot_set)、COV 比对(遥信变位 +
* 遥测死区 2 点确认 + 品质变化)。点表口径见 iec104_pts.h 文件头与
* 设计文档 §3。
* 线程约定:init/bind 建服务前;其余仅 104 服务任务上下文(快照非原子)。
* 创建日期:2026-10-12(B4)
* 修改记录:
* 2026-10-25 DTU 项目组 卡 6(「数据可信」):YC 死区由拟定码值域重定为
* 2026-10-25 DTU 项目组 下游常数按工程量重定(「数据可信」):YC 死区由拟定码值域重定为
* 二次值工程量域(额定 0.5 % 规则),判据依据见
* k_yc 表头注释;数值随卡 9 迁运行参数,本表将退化为
* k_yc 表头注释;数值随 104 改读快照迁运行参数,本表将退化为
* ROM 默认载体。
* 2026-10-25 DTU 项目组 卡 9/卡 11(「数据可信」,道D):YC 板端源改读
* 2026-10-25 DTU 项目组 104 改读快照与频率点绑定(「数据可信」,道D):YC 板端源改读
* L2 遥测快照(App/algo/meas.h,meas_get 无锁双区);
* 削顶五路由快照品质 CLIPPED 驱动线上 IV(不再绑死 -1,
* V0.2 消除双转换器无共同采样触发后零改动自动启用);0x401d 绑频率源(卡 11);
* V0.2 消除双转换器无共同采样触发后零改动自动启用);0x401d 绑频率源(频率点绑定);
* 死区改运行时副本 + set/get 入口;COV 遥测腿 = 死区
* 连续 2 点确认(板端按快照 seq 去重)+ 品质翻转即报。
* 单测 = test/host/iec104 TC-IEC104-025~028。
* 卡 10 2026-10-25 DTU 项目组 死区真源收编 App/algo/run_par.c(本层 s_yc_db
* 运行参数段 2026-10-25 DTU 项目组 死区真源收编 App/algo/run_par.c(本层 s_yc_db
* 副本删除,set/get 转转发壳,壳保留清确认计数语义);
* 定值读写路由 = run_par 表先、prot_set 后(0x8020~
* 0x8058 运行参数段 C_RD/C_SE,系数覆盖直通 adc_cal)。
@@ -36,36 +36,36 @@
#include <string.h>
#include "iec104_asdu.h" /* QDS/DIQ 品质位常量 */
#include "meas.h" /* 板端源:遥测 = L2 遥测快照(卡 9;品质域位同源) */
#include "run_par.h" /* 卡 10:死区真源 + 运行参数段 104 读写路由 */
#include "meas.h" /* 板端源:遥测 = L2 遥测快照(104 改读快照;品质域位同源) */
#include "run_par.h" /* 运行参数段:死区真源 + 104 读写路由 */
#include "prot_elm.h" /* 板端源:遥信 = 元件状态 */
#include "prot_set.h" /* 板端源:定值 + 闭锁 */
#include "sys_log.h" /* task-10:遥控记录(SYSLOG_YK)/ 操作记录(SYSLOG_OPER) */
#include "adc_input.h" /* adc_semantic_t(phasor 实例按语义绑定) */
/* ---------------- YC 表(§1.5 点号 4011+;死区列 = ROM 默认值) ------------ */
/* 源类型(「数据可信」卡 11:YC 表加 src 类型区分相量/频率) */
/* 源类型(「数据可信」频率点绑定:YC 表加 src 类型区分相量/频率) */
#define PTS_SRC_MEAS 0u /* L2 快照槽 sem(电气量,yc/qds 直读) */
#define PTS_SRC_FREQ 1u /* 快照频率(freq_valid 门 → IV) */
typedef struct {
uint32_t ioa;
int8_t sem; /* 快照 yc 槽 = 语义通道(-1 = 非测量量点,当前仅频率) */
float db_default; /* 死区工厂默认(生效真源 = run_par [run_par] 段,卡 10) */
float db_default; /* 死区工厂默认(生效真源 = run_par [run_par] 段 = 运行参数段真源) */
uint8_t src; /* PTS_SRC_* 源类型 */
} pts_yc_def_t;
/* 死区规则 = 额定二次值的 0.5 %(「数据可信」§2.3 表第 2 行建议规则,卡 6 采纳;
/* 死区规则 = 额定二次值的 0.5 %(「数据可信」§2.3 表第 2 行建议规则,随下游常数按工程量重定采纳;
* 额定基准 100 V / 1 A 与 App/algo/prot_set.c 头部同源,勿在此另立口径):
* 电压类 0.5 % × 100 V = 0.5 V 电流类 0.5 % × 1 A = 0.005 A
* 频率点不适用"额定百分比"(额定附近 0.5 Hz 与旧值同量级,维持 0.5 并随
* 卡 10 运行参数段可调)。自卡 9 起本表**只作工厂默认载体**:生效死区 =
* App/algo/run_par.c 的 [run_par] 引擎副本(卡 10 真源收编,本层不再存副本);削顶五路不再 sem=-1 绑死,而是绑快照槽、由品质 CLIPPED
* 运行参数段可调)。自 104 改读快照起本表**只作工厂默认载体**:生效死区 =
* App/algo/run_par.c 的 [run_par] 引擎副本(运行参数段真源收编,本层不再存副本);削顶五路不再 sem=-1 绑死,而是绑快照槽、由品质 CLIPPED
* 驱动线上 IV——V0.2 削顶消失后点位零改动自动启用(docs/任务规划/
* 数据可信.md §10 的「双转换器无共同采样触发」行)。
* ⚠ 过渡期(eng=0 引脚电压域,卡 12 标定前):上送值本身非二次值,死区
* ⚠ 过渡期(eng=0 引脚电压域,两点标定完成前):上送值本身非二次值,死区
* 数字按本域偏保守(迟报不漏报);标定落地后复核(「数据可信」§2.3 表
* 第 2 行)。判定 = 死区连续 2 点确认(卡 9),见 iec104_pts.h COV 说明。 */
* 第 2 行)。判定 = 死区连续 2 点确认(104 改读快照),见 iec104_pts.h COV 说明。 */
static const pts_yc_def_t k_yc[] = {
{ 0x4011u, (int8_t)ADC_SEM_UA, 0.5f, PTS_SRC_MEAS }, /* 1Ua:0.5 % × 100 V */
{ 0x4012u, (int8_t)ADC_SEM_UB, 0.5f, PTS_SRC_MEAS }, /* 1Ub:削顶 → 品质驱动 IV */
@@ -75,12 +75,12 @@ static const pts_yc_def_t k_yc[] = {
{ 0x4016u, (int8_t)ADC_SEM_IB, 0.005f, PTS_SRC_MEAS }, /* 1Ib:削顶 → 品质驱动 IV */
{ 0x4017u, (int8_t)ADC_SEM_IC, 0.005f, PTS_SRC_MEAS }, /* 1Ic:同上 */
{ 0x4018u, (int8_t)ADC_SEM_IN, 0.005f, PTS_SRC_MEAS }, /* 1I0:同上 */
{ 0x401Du, -1, 0.5f, PTS_SRC_FREQ }, /* 1f:卡 11 绑频率源,
{ 0x401Du, -1, 0.5f, PTS_SRC_FREQ }, /* 1f:频率点绑定——绑频率源,
* freq_valid=0 → IV */
};
#define YC_N ((uint8_t)(sizeof(k_yc) / sizeof(k_yc[0])))
/* ===== 遥测 COV 运行时状态(卡 9;仅 iec104Task 上下文访问,无并发) =====
/* ===== 遥测 COV 运行时状态(104 改读快照;仅 iec104Task 上下文访问,无并发) =====
* 判据链:新测量点 → |v − 上次上送值| > 死区?→ 连续 2 点确认 → 置变化位。
* 基准 = **上次上送值**(非上次读值——否则慢漂移永不出死区,参考系统同款);
* 品质(线上 qds)翻转 = 事件:不参与 2 点计数、当拍直报。 */
@@ -124,7 +124,7 @@ static uint8_t s_yx_snap_ok;
/*
* 函数功能:初始化点表模块(死区装 ROM 默认、清 COV/快照状态、恢复默认源)
* 限定条件:内核启动前或 104 服务启动前,调一次
* 函数说明:卡 9 起不再扫 phasor 实例(数据源 = 快照,槽位 = 语义通道,编译期
* 函数说明:104 改读快照起不再扫 phasor 实例(数据源 = 快照,槽位 = 语义通道,编译期
* 直接可定);重复调用 = 全状态复位(单测 reset 依赖此语义)。
*/
void iec104_pts_init(void) {
@@ -172,7 +172,7 @@ uint32_t iec104_pts_yc_ioa(uint8_t idx) {
}
/*
* 函数功能:品质域位映射(uint16 meas 域 → uint8 线上 QDS,卡 9)
* 函数功能:品质域位映射(uint16 meas 域 → uint8 线上 QDS,104 改读快照)
* 入口参数:q16 - 源侧品质(低字节与线上同值;高字节为 MEAS_QDS_CLIPPED 域内位)
* 返 回 值:线上 QDS 字节 uint8_t
* 函数说明:CLIPPED(硬件削顶,104 无对应位)映射为 IV——「削顶通道 104 恒
@@ -195,7 +195,7 @@ static uint8_t s_q_map(uint16_t q16) {
* 返 回 值:0 有效;-1 IV(含 CLIPPED 映射);-2 NT(未就绪) int
* 函数说明:ex 源在场 → 品质由源给(板端 = 快照槽位透传);否则退 legacy
* yc_read,品质从返回值推导(-1→IV / -2→NT / 0→无位)——旧注入源
* 行为与卡 9 前**完全一致**(单测假源零改动)。判定顺序 IV > NT:
* 行为与 104 改读快照前**完全一致**(单测假源零改动)。判定顺序 IV > NT:
* 开机首帧 qds=IV|NT 按无效处理(NT 只留给纯暂态)。任何无效 →
* 信息体清零(线上口径:主站只信品质)。
*/
@@ -245,14 +245,14 @@ int iec104_pts_yc_read(uint8_t idx, float *v, uint8_t *qds) {
}
/*
* 函数功能:写死区(卡 9 API 壳,转发 run_par 真源 + 清本层确认计数)
* 函数功能:写死区(104 改读快照的 API 壳,转发 run_par 真源 + 清本层确认计数)
* 入口参数:idx - YC 表下标 db - 工程量绝对死区(≥0,分档上限见 run_par)
* 返 回 值:0 成功;-1 越界/负值/NaN/越程(run_par 副本不动) int
* 限定条件:**iec104Task 上下文**(run_par 副本写 = 引擎对齐 int32 单字,
* 104 执行段之外调用需自行避免与 104 写并发)
* 函数说明:成功时清零该点待确认计数——跨死区档位不保留半截确认序列;
* 不隐式重建基线(上送基准延续,新死区即刻生效)。落盘由 run_par
* 脏标志 + SYS_EVT_RUN_PAR_SAVE 走 defaultTask(卡 10 持久化链)。
* 脏标志 + SYS_EVT_RUN_PAR_SAVE 走 defaultTask(运行参数段持久化链)。
*/
int iec104_pts_yc_set_deadband(uint8_t idx, float db) {
if (idx >= YC_N) {
@@ -348,7 +348,7 @@ void iec104_pts_cov_check(iec104_pts_cov_t *cov) {
s_yx_snap_ok = 1u;
}
/* YC(卡 9):测点推进 = 板端源按快照换帧(100 ms poll vs 200 ms 快照,
/* YC(104 改读快照):测点推进 = 板端源按快照换帧(100 ms poll vs 200 ms 快照,
* 不去重则同一帧计两次 → "连续 2 点确认"退化成"连续 2 次轮询",单帧
* 噪声即可被确认,抗噪语义失效);注入源 = 每次调用一测点。
* 判定 = 死区连续 2 点确认 + 品质翻转直报(口径全文 → iec104_pts.h)。 */
@@ -383,7 +383,7 @@ void iec104_pts_cov_check(iec104_pts_cov_t *cov) {
continue;
}
if (q != s_yc_repq[i]) {
/* 品质翻转 = 事件直报(含 0x401d 的 IV 进出,卡 11) */
/* 品质翻转 = 事件直报(含 0x401d 的 IV 进出,频率点绑定) */
local.yc_changed |= (uint16_t)(1u << i);
s_yc_repq[i] = q;
s_yc_cnf[i] = 0u;
@@ -458,15 +458,15 @@ int iec104_pts_set_write(uint32_t addr, float v, uint8_t select) {
/* ============================ 板端默认源 ================================= */
/*
* 函数功能:板端默认源 - 遥测 = L2 遥测快照直读(「数据可信」卡 9/卡 11)
* 函数功能:板端默认源 - 遥测 = L2 遥测快照直读(「数据可信」104 改读快照与频率点绑定)
* 入口参数:idx - YC 表下标 out/qds - 值 + uint16 域品质(MEAS_QDS_*)
* 返 回 值:0 / -1 越界或频率未新鲜(IV)/ -2 快照从未发布(NT) int
* 限定条件:iec104Task 上下文(meas_get 为双区无锁读,App/algo/meas.h)
* 函数说明:**不做任何本地判断**——电气路值/品质整体透传快照槽(削顶路快照
* 已置 CLIPPED,s_q_map 映上线 IV;开机首帧 IV|NT 由 s_yc_point 按
* IV 处理),"新不新、能不能信"全在发布侧一处决定(卡 8 设计意图,
* IV 处理),"新不新、能不能信"全在发布侧一处决定(遥测快照发布的设计意图,
* 两处判断必打架)。频率路(PTS_SRC_FREQ):snap.freq_valid==0 →
* IV(卡 11 DoD 原句);有效时值 = snap.freq_hz,与 freq_get() 同源。
* IV(频率点绑定 DoD 原句);有效时值 = snap.freq_hz,与 freq_get() 同源。
*/
static int s_src_yc_read_ex(uint8_t idx, float *out, uint16_t *qds) {
meas_snap_t snap;
@@ -633,7 +633,7 @@ static int s_src_set_read(uint32_t addr, float *out) {
return -1;
}
if (run_par_104_read(addr, out) == 0) {
return 0; /* 运行参数段命中(卡 10) */
return 0; /* 运行参数段命中 */
}
for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) {
if ((g_prot_set_meta[i].comm_addr != 0u)
+8 -8
View File
@@ -6,7 +6,7 @@
* (asdu+pts+link)可离线跑(分层约束:协议解析与硬件 I/O 分离)。
* 点表口径(docs/算法/继电保护功能复现规划.md §1.5,验收 = 省电科院点表):
* - YC:IOA 0x4011~0x4018 + 0x401d(频率),短浮点、系数 1;数据源 =
* L2 遥测快照(App/algo/meas.h,「数据可信」卡 9/11):电气 8 路绑快照槽,
* L2 遥测快照(App/algo/meas.h,「数据可信」104 改读快照与频率点绑定):电气 8 路绑快照槽,
* 有效性由快照品质驱动——V0.1 削顶路(docs/算法/继电保护功能复现规划.md
* §1.6)快照置 CLIPPED → 本层映射为线上 IV(V0.2 后自动启用,绑定零
* 改动,见 docs/任务规划/数据可信.md §10「双转换器无共同采样触发」行);0x401d 绑频率源,
@@ -25,11 +25,11 @@
* 线程约定:init/bind 内核启动前或建服务前;cov_check/read 仅 104 服务任务上下文。
* 创建日期:2026-10-12(B4)
* 修改记录:
* 2026-10-25 DTU 项目组 卡 9/卡 11(「数据可信」,道D):YC 数据源 = L2 遥测
* 2026-10-25 DTU 项目组 104 改读快照与频率点绑定(「数据可信」,道D):YC 数据源 = L2 遥测
* 快照(削顶路由品质驱动 IV);死区改运行时副本 +
* set/get 入口;COV 遥测腿 = 死区 2 点确认(seq 去重)
* + 品质变化即报;0x401d 绑频率源(freq_valid → IV)。
* 2026-10-25 DTU 项目组 卡 10:死区真源迁 run_par([run_par] cfg 段 +
* 2026-10-25 DTU 项目组 运行参数段:死区真源迁 run_par([run_par] cfg 段 +
* 0x8020~0x8058 读写映射;本层 set/get 为转发壳)。
*/
#ifndef IEC104_PTS_H
@@ -52,7 +52,7 @@ typedef struct {
int (*set_read)(uint32_t addr, float *out);
/* 定值写:select=1 预置校验(范围)/ 0 执行写入。返回 0 / -1 越界或未知 */
int (*set_write)(uint32_t addr, float v, uint8_t select);
/* 遥测读(带品质,卡 9 追加于表尾——旧源 NULL = 走 yc_read 退路,品质由
/* 遥测读(带品质,104 改读快照时追加于表尾——旧源 NULL = 走 yc_read 退路,品质由
* 返回值推导:-1 → IV、-2 → NT、0 → 无位,行为与旧源完全一致)。
* qds = uint16 域位(App/algo/meas.h MEAS_QDS_*:低字节 = 线上 QDS 同值,
* 高字节 CLIPPED 由本层映射线上 IV);返回 0 / -1 IV / -2 NT */
@@ -83,11 +83,11 @@ uint32_t iec104_pts_yc_ioa(uint8_t idx);
/* 读 YC:v 有效值(无效时为 0);qds 输出线上品质位(IV/NT/OV,CLIPPED 已映射
* 为 IV)。返回 0/无效-1(NT 亦无效,品质位区分) */
int iec104_pts_yc_read(uint8_t idx, float *v, uint8_t *qds);
/* 死区写(卡 9 API;卡 10 起 = 转发 App/algo/run_par.c 真源 + 清本层确认计数):
/* 死区写(104 改读快照 API;运行参数段起 = 转发 App/algo/run_par.c 真源 + 清本层确认计数):
* db = 工程量绝对值 ≥0(电压 50 V / 电流 1 A / 频率 5 Hz 分档上限);越界/负值/
* NaN → -1 且真源不动;成功时清零该点待确认计数(跨档位不残留半截确认——此壳
* 行为有单测钉住)。仅 104 服务任务上下文调用。落盘 = run_par 脏 → 事件 →
* defaultTask(卡 10 持久化链,docs/子系统设计/IEC104上行设计说明.md §3.4)。 */
* defaultTask(运行参数段持久化链,docs/子系统设计/IEC104上行设计说明.md §3.4)。 */
int iec104_pts_yc_set_deadband(uint8_t idx, float db);
/* 读当前生效死区(越界 idx 返 0) */
float iec104_pts_yc_deadband(uint8_t idx);
@@ -104,12 +104,12 @@ void iec104_pts_yx_read(uint8_t idx, uint8_t *out);
* 函数功能:读全表并与上次比对(遥信变位 + 遥测死区 2 点确认 + 品质变化),
* 输出变化集
* 入口参数:cov - 输出(可为 NULL = 只刷快照不取变化)
* 函数说明:遥测判据(「数据可信」卡 9,对标参考系统 CalfYcMea 死区 2 点确认,
* 函数说明:遥测判据(「数据可信」104 改读快照,对标参考系统 CalfYcMea 死区 2 点确认,
* 短板评测口径):**连续 2 个新测量点** |v - 上次上送值| > 死区才置变化位
* (单点尖峰不确认——噪声回摆即撤销候选);品质位(线上 qds)相对上次
* 上送值翻转 → 当拍直接置位(不等 2 点,有效性变化必须即时可见,
* 含 0x401d 的 IV 进出)。死区 = 运行时副本(ROM 默认 = 点表列,
* iec104_pts_yc_set_deadband() 覆盖——卡 10 运行参数段的接线点)。
* iec104_pts_yc_set_deadband() 覆盖——运行参数段的接线点)。
* 测量点定义:板端默认源 = **快照换帧**(meas seq 前进;100 ms poll 对
* 200 ms 快照,同一帧重复比对会计数两次 → seq 去重是确认语义成立的
* 前提);注入源(单测假源)= 每次调用一测点。首次读到有效值只建基线
+14 -14
View File
@@ -85,21 +85,21 @@
* 者;该入口同时不再打日志——它落在本任务静态最坏链上,
* 每条 DBG_* 约 216 B 栈,而这一行毫无诊断价值(本任务
* 存活由首帧日志与 TASK_WD_ADC 心跳证明)
* v3.1 2026-10-25 DTU 项目组 L1.5 折算 + 采样通道自检 贴轨观测(「数据可信」卡 2,道A):
* v3.1 2026-10-25 DTU 项目组 L1.5 折算 + 采样通道自检 贴轨观测(「数据可信」标定折算落地,道A):
* frame[s] 由 (float)code 改 adc_cal_apply()——工程量 =
* (code+b)×k,现口径 = ADC 引脚电压 V(eng=0,卡 1 冻结的
* (code+b)×k,现口径 = ADC 引脚电压 V(eng=0,量程口径冻结的
* ROM 系数,docs/硬件平台/ADC通道映射说明.md §7.1);同拍
* 经 adc_health_rail_watch() 逐通道贴轨观察(采样通道自检 残余,
* 门限 adc_cal_rail_ths,码值域与标定正交),锁存边沿 →
* DBG_ERROR + 每开机一次 SYSLOG;心跳增 cal: 行(mV 定点
* + valid/clipped 位图 + rail 锁存),台架注入口径见该行判读
* v3.2 2026-10-25 DTU 项目组 L2 遥测快照发布(「数据可信」卡 8,道D,M5):新模块
* v3.2 2026-10-25 DTU 项目组 L2 遥测快照发布(「数据可信」这一项,道D,M5):新模块
* App/algo/meas.c——本任务为唯一发布者,新帧拍内
* freq_run() 之后按 200 ms **tick 经过**分频调
* meas_tick()(全仓调用点 = 1,评审判据);品质注入源 =
* adc_cal_flags() 削顶位图,频率 = 同拍 freq 读数;心跳新增
* meas: 行(seq/v/ua·un·ia_mv/f/fv),读数比对类判据待台架实测
* v3.3 2026-10-27 DTU 项目组 卡 0 台架读出口:心跳新增 adc: 行——连续输出 9 路
* v3.3 2026-10-27 DTU 项目组 已知电压注入验证台架读出口:心跳新增 adc: 行——连续输出 9 路
* **原始码值**(与 first: 行同序同格式)。动因 = 注入验证
* 原本只能靠"改电压 + 复位 + 抓一次 first:",8 个通道 × 3 个
* 注入点要复位二十余次;改为每 10 s 一行后可全程免复位。
@@ -116,8 +116,8 @@
#include "phasor.h" /* L2 相量层:phasor_run()/phasor_get()(全周傅氏) */
#include "freq.h" /* L2 派生量:freq_run()/freq_get()(测频,B8) */
#include "adc_health.h" /* 采样有效性校验(静默/丢帧/单调性/错误增量/贴轨) */
#include "adc_cal.h" /* L1.5:通道标定折算(「数据可信」卡 2;flags 供 cal 心跳行) */
#include "meas.h" /* L2 发布侧:遥测快照 meas_tick()(「数据可信」卡 8,道D) */
#include "adc_cal.h" /* L1.5:通道标定折算(「数据可信」标定折算落地;flags 供 cal 心跳行) */
#include "meas.h" /* L2 发布侧:遥测快照 meas_tick()(「数据可信」遥测快照发布,道D) */
#include "tpafe5160.h"
#include "task_watchdog.h"
#include "console_log.h"
@@ -152,7 +152,7 @@ static uint32_t s_health_logged;
static uint32_t s_rail_edge_latched;
static uint8_t s_rail_syslogged;
/* 遥测快照发布闸门(「数据可信」卡 8):上次发布拍时基。分频用 **tick 经过**
/* 遥测快照发布闸门(「数据可信」这一项):上次发布拍时基。分频用 **tick 经过**
* 对比 MEAS_PERIOD_MS,非拍计数——idle/skip 拍会把拍计数口径拉得超过名义
* 200 ms(与 v2.6 修"重复采样污染 DFT 窗"同族误差,勿"优化"成拍计数) */
static uint32_t s_meas_ms;
@@ -374,9 +374,9 @@ void adc_task_func(void *arg) {
all_ok = 0u;
break;
}
/* L1.5 折算(「数据可信」卡 2,§4.1 模型):工程量 = (code + b) × k。
* 现口径 = **ADC 引脚电压 V**(eng=0,卡 1 冻结的 ROM 系数,见
* docs/硬件平台/ADC通道映射说明.md §7.1);卡 0b/卡 12 写入标定
/* L1.5 折算(「数据可信」标定折算落地,§4.1 模型):工程量 = (code + b) × k。
* 现口径 = **ADC 引脚电压 V**(eng=0,量程口径冻结的 ROM 系数,见
* docs/硬件平台/ADC通道映射说明.md §7.1);端子变比确认与两点标定写入标定
* 系数(adc_cal_flags() 出 VALID)后才按二次值消费。TEMP 透传码值
* 不折算(决策 5)。*/
frame[s] = adc_cal_apply((adc_semantic_t)s, code);
@@ -398,7 +398,7 @@ void adc_task_func(void *arg) {
* 切换,freq 读的就是本拍相量(1 ms 同上下文,无竞态) */
freq_run();
/* L2 遥测快照发布(「数据可信」卡 8,道D,M5):200 ms tick 经过分频。
/* L2 遥测快照发布(「数据可信」这一项,道D,M5):200 ms tick 经过分频。
* 唯一发布者 = 本任务(全仓 meas_tick 调用点数 = 1 为评审判据,
* 「数据可信」§8 风险表"快照双写"行);只在**压环成功的真新帧拍**发布
* ——idle/skip 拍压环未推进,发布 = 重复旧窗。品质注入唯一源 =
@@ -527,7 +527,7 @@ void adc_task_func(void *arg) {
log_phasors("hb");
/* 全 9 路**原始码值**(「数据可信」卡 0 注入验证的唯一连续读出口):
/* 全 9 路**原始码值**(「数据可信」已知电压注入验证的唯一连续读出口):
* 与 first: 行同序同格式(UA/UB/UC/UN/IA/IB/IC/IN/T),台架
* "改电压 → 读一行"即可对表,不必为每个注入点反复复位去抓只在开机
* 出现一次的 first: 行。两处的通道顺序是同一份约定,改一处必须同步另一处。
@@ -554,9 +554,9 @@ void adc_task_func(void *arg) {
/* L1.5/采样通道自检 台架观测面(×1000 mV 定点,MicroLIB 无 %f):
* ua/un/ia_mv = 三路 TPAFE 引脚电压毫伏(未标定域,**不是**
* 二次值;卡 12 注入验证的读数落点,偏差判据 ≤2 %)
* 二次值;两点标定注入验证的读数落点,偏差判据 ≤2 %)
* vl = VALID 位图(默认构建应恒 0x00——未标定即未标定,
* 卡 5 的闭锁判据在 protect 侧同源消费这个位)
* 未标定即闭锁的判据在 protect 侧同源消费这个位)
* cl = CLIPPED 位图(V0.1 应恒 0xE6 = UB/UC/IB/IC/IN)
* rail/edge = 贴轨锁存/历史边沿位图(注入饱和电平后应起)*/
{
+2 -2
View File
@@ -38,7 +38,7 @@
#include "nand_ftl.h"
#include "net_cfg.h"
#include "cfg_file.h"
#include "run_par.h" /* 运行参数段落盘(卡 10,配置引擎属主 = 本任务) */
#include "run_par.h" /* 运行参数段落盘(「数据可信」这一项,配置引擎属主 = 本任务) */
#include "prot_set_store.h"
#include "prot_set.h" /* task-10:prot_set_dirty_peek(区分"无待写"与"真落盘") */
#include "iec104_comm.h" /* 道G task-9:[comm] 段落盘(脏位轮询同款,通讯设置页) */
@@ -242,7 +242,7 @@ void default_task_func(void *argument) {
if ((prot_set_dirty_peek() != 0u) && (prot_set_store_save() == 0)) {
syslog_post(SYSLOG_OPER, "settings saved");
}
/* 运行参数段落盘(卡 10):同款脏语义;save = 引擎整档外科写
/* 运行参数段落盘(「数据可信」这一项):同款脏语义;save = 引擎整档外科写
* ([run_par] 9 键 + 被 adc_cal_set 联动改写的 [adc_cal] 两段一趟落) */
(void)run_par_store_save();
/* [comm] 段落盘(道G task-9 通讯设置页):同款脏位、每轮无条件,
+2 -2
View File
@@ -23,7 +23,7 @@
#include "iec104_pts.h"
#include "net_socket.h"
#include "prot_set.h" /* 定值脏标志 peek(B7 落盘通知) */
#include "run_par.h" /* 运行参数脏 peek(卡 10 落盘通知,同款语义) */
#include "run_par.h" /* 运行参数脏 peek(运行参数段落盘通知,同款语义) */
#include "sys_clock.h"
#include "sys_log.h" /* task-19:对时成功落一条操作记录(SYSLOG_OPER) */
#include "sys_events.h"
@@ -432,7 +432,7 @@ void iec104_serv_task(void *argument) {
(void)osEventFlagsSet(sys_evtHandle, SYS_EVT_PROT_SET_SAVE);
}
/* 运行参数整定(C_SE 0x8020~0x8058 段)→ 通知属主落盘 config.ini
* (卡 10;peek 非消费 = 写盘失败天然重试,与上块 B7 语义完全同款) */
* (运行参数段;peek 非消费 = 写盘失败天然重试,与上块 B7 语义完全同款) */
if ((run_par_dirty_peek() != 0u) && (sys_evtHandle != NULL)) {
(void)osEventFlagsSet(sys_evtHandle, SYS_EVT_RUN_PAR_SAVE);
}
+5 -5
View File
@@ -10,7 +10,7 @@
* ③ prot_elm_run()(phasor rms → 判据步进)+ 动作位图边沿日志;
* ④ 全局软压板 PS_GLOBAL_EN(104 YK12 两段式投退,B7):退出 =
* 复位元件 + 停判据(与采样闭锁同构,独立边沿日志);
* ⑤ 未标定闭锁(「数据可信」卡 5,M4 唯一新增行为变更):UA/UN/IA
* ⑤ 未标定即闭锁(「数据可信」,M4 唯一新增行为变更):UA/UN/IA
* 的 adc_cal VALID 位未全置位 → 工程量还只是 ADC 引脚电压
* (eng=0),拿去比二次值定值必然错判 → 复位元件 + 本拍不 eval。
* 默认构建(未标定)恒闭锁是**期望行为**:边沿用 DBG_INFO 而非
@@ -33,7 +33,7 @@
* adc_health 的 stall 位依赖 adcTask 每拍跑 check(),
* 节拍源一停本任务就再没有任何人判"数据新不新",
* 而相量冻在最后一帧上还会被本任务继续用于判据
* v1.2 2026-10-25 DTU 项目组 卡 5:新增第⑤路「未标定闭锁」(adc_cal_flags
* v1.2 2026-10-25 DTU 项目组 未标定即闭锁:新增第⑤路「未标定闭锁」(adc_cal_flags
* VALID 口径,docs/任务规划/数据可信.md §4.3):
* 采样恢复分支内、巡检/压板之前判;边沿 INFO 对
* + SOE_T_CAL_BLOCK/RESUME(不用 [ERR]:未标定是
@@ -56,7 +56,7 @@
#include "adc_input.h" /* adc_input_stm32_seq():DMA 完成计数(中断侧写) */
#include "adc_health.h"
#include "adc_cal.h" /* 卡 5:adc_cal_prot_blocked() = 未标定闭锁判定单点(道F task-16) */
#include "adc_cal.h" /* 未标定即闭锁:adc_cal_prot_blocked() = 未标定闭锁判定单点(道F task-16) */
#include "console_log.h" /* dbg_console_writer_ready():启动锚点行门控(B6) */
#include "prot_elm.h"
#include "prot_set.h"
@@ -88,7 +88,7 @@ static uint32_t s_prev_active; /* 上拍动作位图(边沿日志用) */
static uint32_t s_prev_pick; /* 上拍启动位图(「保护启动」记录边沿用,task-10) */
static uint8_t s_prev_hf_lock; /* 上拍采样闭锁态(边沿日志用) */
static uint8_t s_prev_plate_out; /* 上拍全局软压板退出态(边沿日志用,B7) */
static uint8_t s_prev_cal_lock; /* 上拍未标定闭锁态(边沿日志用,卡 5) */
static uint8_t s_prev_cal_lock; /* 上拍未标定闭锁态(边沿日志用,未标定即闭锁) */
/*
* 函数功能:动作位图变化沿日志 + SOE 投递(逐变化元件)
@@ -237,7 +237,7 @@ void protect_task(void *argument) {
SOE_ELM_NONE, 0u);
s_prev_hf_lock = 0u;
}
/* 卡 5:未标定闭锁——夹在「采样可信」与「巡检/压板」之间:
/* 未标定即闭锁——夹在「采样可信」与「巡检/压板」之间:
* eng=0 域(引脚电压)拿去比二次值定值必然错判(UV 尤甚),
* 标定 VALID 未全置位前整条判据链停走(「数据可信」§4.3 决策 1) */
/* 判定本体在 adc_cal_prot_blocked()(标定层单点,道F task-16):本任务
+1 -1
View File
@@ -9,7 +9,7 @@
* 作者:道G log-maint-writer
* 创建日期:2026-10-27
* 修改记录:
* v1.0 2026-10-27 道G 创建(task-12「运行报告计数器」的数据面;UI 页面归 task-13)
* v1.0 2026-10-27 道G 创建(task-12「运行报告计数器」的数据面;UI 页面归 task-13 → 2026-10-28 已落地 ui_page_runreport.c)
*
* ┌── 四个数的分类台账(页面文案必须逐项挂类别,"不得含糊"是 UI 补齐清单的原文判据)──┐
* │ 上电次数 = **掉电保持**:本模块,落 RTC 用户 SRAM;口径见下面 BOOT_STATS_SEQ_* 一段 │
+15 -1
View File
@@ -88,7 +88,7 @@ extern "C" {
* 真值语义(现场口径 = docs/任务规划/数据可信.md §2.6 的承诺边界 + §4.2 三态
* 可用性;契约文档原先写的"0 = 原始码值(未标定)"是标定落地前的旧口径,
* 已按本表更正,勿再照抄旧表述):
* ENG_PIN 引脚电压 V —— 现状:adc_cal 的 ROM 默认系数是「数据可信」卡 1 定死
* ENG_PIN 引脚电压 V —— 现状:adc_cal 的 ROM 默认系数是「数据可信」量程口径冻结定死
* 的引脚侧 LSB(TPAFE 152.59 uV/码、STM32 805.66 uV/码),采样环
* 折算出来的就是 ADC 引脚电压,不是端子二次值
* ENG_SEC 二次值 —— 电气 8 路 adc_cal_flags() 的 VALID 全置位(拿到端子变比
@@ -210,6 +210,20 @@ typedef struct {
char build_date[UI_DATA_DATE_LEN]; /* 程序日期(编译期) */
char sw_sum[UI_DATA_SUM_LEN]; /* 软件校验;无构建期 CRC 步骤 = "--" */
char ftp_user[UI_DATA_FUSER_LEN]; /* FTP 登录用户名(只显名,不显口令) */
/* ── 运行报告四数(2026-10-28 UI 补齐「运行报告」;BSP 侧只搬运、不算第二份,
* 口径唯一出处 = App/util/boot_stats.h 的四数台账与 App/task/iec104_serv.h
* 的观测计数注;屏上文案(含"禁写终身次数"这类口径)归 UI 页面侧
* <Drivers/BSP/UI/ui_page_runreport.c>,分层方向由 layer-deps 门禁守护 ── */
uint32_t boot_count; /* 上电次数(掉电保持,自 RTC 电池周期起);
boot_seq_state == 0(UNKNOWN)时不可信 */
uint8_t boot_seq_state; /* 0 未知 / 1 首次启用 / 2 延续 / 3 电池域掉过重开 */
uint8_t boot_write_failed; /* 1 = 本次自增没写回 RTC SRAM(账本只会少不会重) */
uint8_t rst_cause; /* 本次开机复位原因编码(BOOT_STATS_CAUSE_*) */
uint8_t boot_ready; /* 0 = 开机账本未初始化 → 整组按占位显示,不得读成 0 */
uint32_t iec104_conn_up; /* 主站接入次数(本次开机以来,跨重连不清零) */
uint32_t iec104_apdu_tx; /* 成功发出的 APDU 帧数(短写不算,落在 tx_fail) */
uint32_t iec104_tx_fail; /* 发送短写/失败次数 */
uint32_t iec104_rx_bytes; /* 收到的**字节**数(帧边界在 link 层,serv 看不见帧) */
} ui_data_info_t;
/* ── 初始化 ───────────────────────────────────────────────────────────────── */
+370 -173
View File
@@ -324,6 +324,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80,
/* U+4E0A "上" */
0x8, 0x1, 0x0, 0x20, 0x4, 0x0, 0xfc, 0x10,
0x2, 0x0, 0x40, 0x8, 0x1, 0x0, 0x20, 0x7f,
0xf0,
/* U+4E3B "主" */
0x8, 0x0, 0x80, 0x0, 0x3f, 0xe0, 0x40, 0x8,
0x1, 0x3, 0xfe, 0x4, 0x0, 0x80, 0x10, 0x7f,
@@ -398,6 +403,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x3f, 0xf8, 0x20, 0xa, 0x2, 0x20, 0x82, 0x60,
0x30,
/* U+5199 "写" */
0xff, 0xf4, 0x4, 0x80, 0x1f, 0xe2, 0x0, 0x80,
0x1f, 0xf0, 0x2, 0x0, 0x5f, 0xe8, 0x1, 0x1,
0xc0,
/* U+51FA "出" */
0x4, 0x8, 0x89, 0x11, 0x22, 0x27, 0xfc, 0x8,
0x1, 0x4, 0x21, 0x84, 0x30, 0x87, 0xff, 0x80,
@@ -436,6 +446,10 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x7f, 0xe8, 0x1, 0x8, 0x21, 0x4, 0x20, 0xbf,
0x90, 0x82, 0x14, 0x42, 0x48, 0x42, 0xff, 0x80,
/* U+539F "原" */
0x7f, 0xe8, 0x81, 0x7f, 0x28, 0x25, 0xfc, 0xa0,
0x97, 0xf2, 0x10, 0x4a, 0x8a, 0x4a, 0x98, 0x80,
/* U+53C2 "参" */
0x10, 0x4, 0x11, 0xff, 0x4, 0xf, 0xfe, 0x45,
0x13, 0x15, 0x89, 0x6, 0xf, 0x8, 0xe, 0x3e,
@@ -445,6 +459,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xfb, 0xe1, 0x44, 0x28, 0xc5, 0x15, 0x14, 0xa2,
0x88, 0x21, 0x4, 0x51, 0x4a, 0x4a, 0x10, 0x80,
/* U+53D1 "发" */
0x9, 0x11, 0x12, 0x20, 0x7f, 0xf1, 0x0, 0x20,
0x7, 0xe1, 0x44, 0x25, 0x8, 0x42, 0x36, 0x18,
0x30,
/* U+53D6 "取" */
0xfc, 0x9, 0x79, 0x25, 0x3c, 0xa4, 0x94, 0xf2,
0x92, 0x52, 0x64, 0xf8, 0x81, 0x28, 0x28, 0x80,
@@ -453,6 +472,10 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xff, 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3,
0x1, 0xff, 0xc0, 0x40,
/* U+53EF "可" */
0xff, 0xe0, 0x8, 0x1, 0x3f, 0x24, 0x24, 0x84,
0x90, 0x93, 0xf2, 0x40, 0x40, 0x8, 0x7, 0x0,
/* U+53F7 "号" */
0x3f, 0x84, 0x10, 0x82, 0x1f, 0xc0, 0x1, 0xff,
0xc4, 0x1, 0x0, 0x3f, 0xc0, 0x8, 0x1, 0x0,
@@ -478,10 +501,25 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xc0, 0x3, 0xfe, 0x40, 0x48, 0x9, 0xff, 0x20,
0x20,
/* U+5468 "周" */
0x3f, 0xe4, 0x4, 0x88, 0x97, 0xd2, 0x22, 0x7f,
0xc8, 0x9, 0x7d, 0x28, 0xa5, 0xf5, 0x0, 0xc0,
0x70,
/* U+56DE "回" */
0xff, 0xe0, 0x18, 0x6, 0x79, 0x92, 0x64, 0x99,
0xe6, 0x1, 0x80, 0x7f, 0xf8, 0x4,
/* U+56E0 "因" */
0xff, 0xf0, 0x6, 0x10, 0xc2, 0x1b, 0xfb, 0x8,
0x62, 0x8c, 0x89, 0xa0, 0xb0, 0x7, 0xff, 0xc0,
0x10,
/* U+56F4 "围" */
0xff, 0xf0, 0x6, 0x10, 0xdf, 0xd8, 0x43, 0x3e,
0x61, 0xd, 0xfd, 0x84, 0xb0, 0xb6, 0x10, 0xff,
0xf0,
/* U+5730 "地" */
0x21, 0x4, 0x20, 0x95, 0x92, 0xdf, 0x72, 0x5a,
0x49, 0x49, 0x2b, 0x25, 0x6, 0x87, 0x10, 0x81,
@@ -507,6 +545,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xaa, 0x48, 0x89, 0x11, 0x4, 0x21, 0x4, 0x40,
0x80,
/* U+5931 "失" */
0x4, 0x4, 0x80, 0x90, 0x1f, 0xc4, 0x41, 0x8,
0x1, 0x7, 0xff, 0xa, 0x2, 0x20, 0x82, 0x60,
0x30,
/* U+5B50 "子" */
0x3f, 0x80, 0x20, 0x8, 0x2, 0x0, 0x41, 0xff,
0xc1, 0x0, 0x20, 0x4, 0x0, 0x80, 0x70, 0x0,
@@ -540,6 +583,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xff, 0x80, 0x20, 0xa, 0x2, 0x80, 0xbf, 0xe8,
0x2, 0x0, 0x80, 0x60, 0x17, 0xfc,
/* U+5E27 "帧" */
0x20, 0x84, 0x13, 0xe3, 0xd4, 0x4a, 0xbf, 0x54,
0x6a, 0xad, 0x55, 0xba, 0xa4, 0x54, 0x85, 0x11,
0x10,
/* U+5E38 "常" */
0x24, 0x82, 0xa3, 0xff, 0xc0, 0x13, 0xf8, 0x41,
0xf, 0xe0, 0x20, 0x7f, 0xc8, 0x89, 0x13, 0x2,
@@ -565,6 +613,10 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xc5, 0x20, 0xa4, 0x54, 0x84, 0xfd, 0x40, 0x47,
0xf0,
/* U+5F00 "开" */
0x7f, 0xc2, 0x20, 0x44, 0x8, 0x81, 0x11, 0xff,
0xc4, 0x40, 0x88, 0x21, 0x4, 0x21, 0x4, 0x0,
/* U+5F02 "异" */
0x7f, 0xc8, 0x9, 0xff, 0x20, 0x4, 0x2, 0x7f,
0xc4, 0x20, 0x84, 0xff, 0xe2, 0x10, 0x82, 0x20,
@@ -575,6 +627,10 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x1f, 0x40, 0x88, 0x10, 0x82, 0x14, 0x79, 0xf0,
0x10,
/* U+5F15 "引" */
0x0, 0xfc, 0x42, 0x21, 0x1f, 0x8c, 0x6, 0x3,
0xf1, 0x8, 0x84, 0x42, 0x2e, 0x10,
/* U+5F3A "强" */
0x7, 0xdc, 0x88, 0x91, 0x13, 0xee, 0x11, 0x1f,
0xe2, 0x4f, 0x49, 0x2f, 0xe4, 0x20, 0x85, 0x67,
@@ -649,6 +705,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xcd, 0x27, 0x3f, 0x26, 0x25, 0x44, 0xaf, 0xb9,
0x10,
/* U+6389 "掉" */
0x21, 0x4, 0x3f, 0xc4, 0x17, 0xf2, 0x82, 0x5f,
0xce, 0xf, 0x7f, 0x21, 0x5, 0xfc, 0x84, 0x30,
0x80,
/* U+63A5 "接" */
0x22, 0x4, 0x20, 0xbf, 0xfa, 0x22, 0x28, 0x5f,
0xcc, 0x47, 0x7f, 0x22, 0x44, 0xc8, 0x86, 0x37,
@@ -669,6 +730,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x4f, 0xbf, 0x8, 0x2f, 0xe4, 0x70, 0x95, 0x34,
0x90,
/* U+6536 "收" */
0x12, 0x12, 0x42, 0x48, 0x49, 0xf9, 0x45, 0x34,
0xa4, 0x95, 0x94, 0xd1, 0x12, 0x50, 0x51, 0xc,
0x10,
/* U+6545 "故" */
0x22, 0x4, 0x40, 0x88, 0x7d, 0xf2, 0x44, 0x44,
0xbe, 0x94, 0x52, 0x8a, 0x91, 0x23, 0xea, 0x46,
@@ -730,6 +796,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x5, 0x41, 0x24, 0x44, 0x57, 0xf4, 0x10, 0x2,
0x0,
/* U+673A "机" */
0x20, 0x4, 0xf0, 0x92, 0x7a, 0x42, 0x48, 0xe9,
0x1b, 0x25, 0x24, 0x24, 0x84, 0x94, 0xa2, 0x98,
0x30,
/* U+677F "板" */
0x20, 0x64, 0xf0, 0x90, 0x7a, 0x2, 0x7e, 0xea,
0x5b, 0x4d, 0x2a, 0x25, 0x44, 0x90, 0xa5, 0x19,
@@ -775,6 +846,10 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x0, 0x81, 0x28, 0x45, 0x11, 0x10, 0x41, 0x10,
0x10,
/* U+6B63 "正" */
0x7f, 0xc0, 0x80, 0x10, 0x2, 0x2, 0x40, 0x4f,
0x89, 0x1, 0x20, 0x24, 0x4, 0x83, 0xff, 0x80,
/* U+6B7B "死" */
0xff, 0xe4, 0x40, 0x88, 0x1d, 0x14, 0xa5, 0x55,
0x4, 0xc0, 0x90, 0x22, 0x28, 0x46, 0x7, 0x80,
@@ -789,6 +864,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x3, 0x40, 0xa8, 0x24, 0x98, 0x88, 0x10, 0x86,
0x0,
/* U+6C60 "池" */
0x2, 0x10, 0x41, 0x4b, 0x9, 0xa1, 0x65, 0x34,
0x9c, 0x90, 0x92, 0x12, 0xca, 0x42, 0x40, 0x87,
0xf0,
/* U+6CE2 "波" */
0x1, 0x10, 0x21, 0x7f, 0x88, 0x91, 0x11, 0x3f,
0x95, 0x10, 0xa2, 0x12, 0x8a, 0x22, 0x4a, 0x16,
@@ -839,6 +919,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x8, 0xa3, 0x14, 0xa2, 0x84, 0x88, 0x91, 0x14,
0x10,
/* U+72D7 "狗" */
0x12, 0xa, 0x40, 0x8f, 0xaa, 0x19, 0x82, 0x2f,
0x4d, 0x2a, 0xa5, 0x97, 0xa2, 0x84, 0x40, 0xb0,
0x60,
/* U+72EC "独" */
0x21, 0x14, 0x21, 0x4, 0x57, 0xf2, 0x92, 0x52,
0x5a, 0x4d, 0x7f, 0x21, 0x4, 0x24, 0x87, 0xe7,
0x90,
/* U+7528 "用" */
0x7f, 0xd1, 0x14, 0x45, 0xff, 0x44, 0x51, 0x17,
0xfd, 0x11, 0x44, 0x51, 0x18, 0x1c,
@@ -867,6 +957,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xc8, 0x13, 0xfe, 0xa0, 0x47, 0xf8, 0x81, 0x1f,
0xe0,
/* U+77E5 "知" */
0x20, 0x4, 0x0, 0xf7, 0xa8, 0x99, 0x12, 0x22,
0x7f, 0xc8, 0x89, 0x29, 0x24, 0xbd, 0x14, 0xc0,
0x0,
/* U+7801 "码" */
0xf, 0xde, 0x8, 0x91, 0x12, 0x24, 0x44, 0xef,
0xf4, 0xa, 0x81, 0x5f, 0xae, 0x5, 0x40, 0x80,
@@ -895,6 +990,21 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x9c, 0x43, 0x48, 0xa7, 0xc4, 0x20, 0x84, 0x17,
0xf0,
/* U+7A97 "窗" */
0x4, 0x1f, 0xfe, 0x44, 0x92, 0x40, 0x80, 0xff,
0x92, 0x12, 0xfa, 0x72, 0x49, 0x89, 0x49, 0x3f,
0xe0,
/* U+7ACB "立" */
0x8, 0x0, 0x80, 0x0, 0x3f, 0xe0, 0x0, 0x1,
0x8, 0x20, 0x84, 0x11, 0x2, 0x20, 0x8, 0x7f,
0xf0,
/* U+7AD9 "站" */
0x41, 0x4, 0x20, 0x4, 0x7c, 0xf0, 0x11, 0x22,
0x15, 0xfa, 0xa1, 0x24, 0x26, 0x87, 0x1f, 0x82,
0x10,
/* U+7AEF "端" */
0x81, 0x9, 0x24, 0x24, 0xf7, 0xf0, 0x1, 0x5f,
0xe8, 0x45, 0x7f, 0x4a, 0xa5, 0x57, 0x2a, 0x84,
@@ -925,6 +1035,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x13, 0x1f, 0x18, 0x0, 0x86, 0xc3, 0x6, 0x0,
0x20,
/* U+7EDF "统" */
0x21, 0x4, 0x11, 0x1f, 0xc8, 0x8e, 0x24, 0x48,
0x51, 0xff, 0x95, 0x2, 0x86, 0x53, 0x12, 0x84,
0x30,
/* U+7EED "续" */
0x21, 0x4, 0xf9, 0x4, 0x4b, 0xfe, 0x2, 0x45,
0x11, 0x67, 0x94, 0xf, 0xe6, 0x23, 0x9, 0x6,
0x10,
/* U+7EF4 "维" */
0x22, 0x84, 0x49, 0x1f, 0xca, 0x4e, 0xc8, 0x4f,
0xd1, 0x27, 0xa4, 0x7, 0xe6, 0x93, 0x12, 0x3,
@@ -940,15 +1060,30 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xf, 0xe1, 0x4, 0x20, 0x84, 0x90, 0x92, 0x7f,
0xf0,
/* U+811A "脚" */
0x4, 0x1c, 0x9e, 0xba, 0xd2, 0x5e, 0x4b, 0x5d,
0x69, 0x2f, 0x45, 0xaa, 0xb5, 0xde, 0x82, 0x30,
0x40,
/* U+81EA "自" */
0x8, 0x8, 0x3f, 0xf0, 0x18, 0xf, 0xfe, 0x3,
0x1, 0xff, 0xc0, 0x60, 0x3f, 0xf0,
/* U+8282 "节" */
0x11, 0x2, 0x23, 0xff, 0x88, 0x80, 0x1, 0xff,
0x82, 0x10, 0x42, 0x8, 0x41, 0x18, 0x20, 0x4,
0x0,
/* U+82AF "芯" */
0x11, 0x2, 0x23, 0xff, 0x88, 0x80, 0x0, 0x8,
0x4, 0x82, 0x92, 0x50, 0x2a, 0x16, 0x42, 0x87,
0xc0,
/* U+8303 "范" */
0x11, 0x1f, 0xfc, 0x44, 0x20, 0x2, 0xfc, 0x10,
0xa2, 0x12, 0x42, 0x9, 0x85, 0x5, 0x20, 0xc3,
0xf0,
/* U+8377 "荷" */
0x11, 0x1f, 0xfc, 0x44, 0x17, 0xf2, 0x4, 0x9e,
0xb2, 0x52, 0x4a, 0x4f, 0x49, 0x9, 0x1, 0x20,
@@ -969,6 +1104,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x82, 0x8f, 0xff, 0x0, 0xf, 0xf8, 0x82, 0x1f,
0xc0,
/* U+8BA1 "计" */
0x41, 0x4, 0x20, 0x4, 0x0, 0x8e, 0x10, 0x5f,
0xc8, 0x41, 0x8, 0x29, 0x6, 0x20, 0x84, 0x0,
0x80,
/* U+8BA4 "认" */
0x41, 0x4, 0x20, 0x4, 0x0, 0x8e, 0x10, 0x42,
0x8, 0xa1, 0x14, 0x2a, 0x86, 0x88, 0x91, 0x4,
@@ -1009,6 +1149,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x91, 0x12, 0x22, 0x44, 0x41, 0x60, 0xc3, 0x60,
0x10,
/* U+8D25 "败" */
0x1, 0x1f, 0x22, 0x28, 0x55, 0xfa, 0xc5, 0x54,
0xaa, 0x95, 0x52, 0xaa, 0x84, 0x21, 0x4a, 0x46,
0x30,
/* U+8D8A "越" */
0x20, 0xa4, 0x13, 0xdf, 0x92, 0x42, 0x4b, 0xeb,
0x49, 0xb5, 0x25, 0xb1, 0x74, 0x47, 0x80, 0x5f,
@@ -1059,6 +1204,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0x4a, 0x51, 0x54, 0x2c, 0x45, 0x9, 0x40, 0x47,
0xf0,
/* U+9001 "送" */
0x88, 0x88, 0xa0, 0x0, 0xf, 0xec, 0x20, 0x84,
0x1f, 0xfa, 0x10, 0x45, 0x9, 0x11, 0x41, 0x5f,
0xf0,
/* U+901A "通" */
0x9f, 0x88, 0x90, 0xc, 0xf, 0xed, 0x24, 0xbf,
0x94, 0x92, 0xfe, 0x52, 0x4a, 0x59, 0x0, 0x5f,
@@ -1123,6 +1273,10 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xc4, 0x80, 0x90, 0x11, 0x2, 0x90, 0x61, 0x88,
0x0,
/* U+95E8 "门" */
0x9f, 0xd0, 0x10, 0x6, 0x1, 0x80, 0x60, 0x18,
0x6, 0x1, 0x80, 0x60, 0x18, 0x6, 0x7,
/* U+95ED "闭" */
0x80, 0x13, 0xf0, 0x6, 0x11, 0x84, 0x6f, 0xd8,
0x46, 0x31, 0x94, 0x69, 0x18, 0xc6, 0x7,
@@ -1175,6 +1329,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
0xd0, 0x2, 0x7f, 0x49, 0x29, 0x25, 0x8b, 0x26,
0x10,
/* U+9996 "首" */
0x20, 0x82, 0x23, 0xff, 0x82, 0x7, 0xfc, 0x80,
0x9f, 0xf2, 0x2, 0x7f, 0xc8, 0x9, 0xff, 0x20,
0x20,
/* U+9A8C "验" */
0x1, 0x1c, 0x20, 0x8a, 0x52, 0x2a, 0x83, 0x4f,
0xbc, 0x0, 0x92, 0x39, 0x5a, 0xa8, 0x52, 0x37,
@@ -1304,8 +1463,8 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 513, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 529, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 546, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 563, .adv_w = 192, .box_w = 11, .box_h = 9, .ofs_x = 0, .ofs_y = -1},
{.bitmap_index = 576, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 563, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 580, .adv_w = 192, .box_w = 11, .box_h = 9, .ofs_x = 0, .ofs_y = -1},
{.bitmap_index = 593, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 610, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 627, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
@@ -1323,101 +1482,101 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 831, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 848, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 865, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 882, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 896, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 912, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 929, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 945, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 961, .adv_w = 192, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = -1},
{.bitmap_index = 973, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 990, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1007, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1024, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1041, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1058, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1072, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1089, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1106, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1123, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1140, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1157, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1173, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1190, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1207, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1224, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1241, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1258, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1272, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1289, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1306, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1323, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1340, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1357, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1374, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1391, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1408, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1425, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1439, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1456, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1473, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1490, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1507, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1524, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 882, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 899, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 916, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 930, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 946, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 962, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 979, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 995, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1012, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1028, .adv_w = 192, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = -1},
{.bitmap_index = 1040, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1056, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1073, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1090, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1107, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1124, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1141, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1158, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1172, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1189, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1206, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1223, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1240, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1257, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1274, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1291, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1308, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1324, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1341, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1358, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1375, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1392, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1409, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1423, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1440, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1457, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1474, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1491, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1508, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1525, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1541, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1558, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1575, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1592, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1609, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1626, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1643, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1660, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1677, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1694, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1711, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1728, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1745, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1762, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1779, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1795, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1808, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1825, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1575, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1589, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1606, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1623, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1637, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1654, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1671, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1688, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1705, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1722, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1739, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1756, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1773, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1790, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1807, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1824, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1841, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1858, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1872, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1889, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1906, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1923, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1940, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1957, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1974, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1991, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2008, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2025, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2042, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2059, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2076, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2092, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2109, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2126, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2143, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2160, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2177, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2194, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2211, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2228, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2245, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2262, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2279, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2296, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2310, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2327, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2344, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2361, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 2376, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2393, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2410, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2426, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2443, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1858, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1875, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1892, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1909, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1926, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1943, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1960, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1977, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1994, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2011, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2027, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 2040, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2057, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2073, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2090, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2104, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2121, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2138, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2155, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2172, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2189, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2206, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2223, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2240, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2257, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2274, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2291, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2308, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2325, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2341, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2357, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2374, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2391, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2408, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2425, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2442, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2459, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2476, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2493, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
@@ -1427,61 +1586,94 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 2561, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2578, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2595, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2612, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2629, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2646, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 2612, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2626, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2643, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2660, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2677, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2694, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2711, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2728, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2745, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2762, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2779, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2796, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2813, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2830, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2847, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2864, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2881, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2898, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2915, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2932, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2949, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2966, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2983, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3000, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3017, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3034, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3051, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3068, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3085, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3102, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3119, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3135, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3152, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3169, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3186, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3203, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3220, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3237, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3254, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3271, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3286, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3301, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3318, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3335, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3352, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3369, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3386, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3402, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3419, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3436, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3453, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3470, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3487, .adv_w = 192, .box_w = 2, .box_h = 4, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 3488, .adv_w = 192, .box_w = 2, .box_h = 6, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 3490, .adv_w = 165, .box_w = 8, .box_h = 10, .ofs_x = 1, .ofs_y = -1} /* U+25B6 */
{.bitmap_index = 2677, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 2692, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2709, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2726, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2743, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2759, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2776, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2792, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2809, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2826, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2843, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2860, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2877, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2894, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2911, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2928, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2945, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2962, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2979, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2996, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3013, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3030, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3047, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3064, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3081, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3095, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3112, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3129, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3146, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3163, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3180, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3197, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3214, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3231, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3248, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3265, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3282, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3299, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3316, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3333, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3350, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3367, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3384, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3401, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3418, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3435, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3452, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3469, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3486, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3503, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3520, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3537, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3554, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3571, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3588, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3605, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3622, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3639, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3655, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3672, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3689, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3706, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3723, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3740, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3757, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3774, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3791, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3806, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3821, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3836, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3853, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3870, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3887, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3904, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3921, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3937, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3954, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3971, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3988, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 4005, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 4022, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 4039, .adv_w = 192, .box_w = 2, .box_h = 4, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 4040, .adv_w = 192, .box_w = 2, .box_h = 6, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 4042, .adv_w = 165, .box_w = 8, .box_h = 10, .ofs_x = 1, .ofs_y = -1} /* U+25B6 */
};
/*---------------------
@@ -1489,29 +1681,34 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
*--------------------*/
static const uint16_t unicode_list_1[] = {
0x0, 0x1, 0x2, 0x2ca0, 0x2ca9, 0x2cdb, 0x2d2b, 0x2d2c,
0x2d44, 0x2d96, 0x2ded, 0x2dee, 0x2dfc, 0x2e7d, 0x2e81, 0x2edc,
0x3005, 0x300c, 0x3011, 0x3013, 0x309a, 0x30a6, 0x30d6, 0x30ed,
0x3148, 0x31b6, 0x31da, 0x322b, 0x3262, 0x326c, 0x3276, 0x3283,
0x3297, 0x32a8, 0x32cc, 0x32cf, 0x32ea, 0x357e, 0x35d0, 0x35e0,
0x362b, 0x37ad, 0x37b6, 0x39f0, 0x39f7, 0x39f8, 0x3a3a, 0x3a3e,
0x3a66, 0x3c92, 0x3cd8, 0x3d14, 0x3d2f, 0x3d46, 0x3d96, 0x3da2,
0x3daf, 0x3dda, 0x3df2, 0x3df3, 0x3df5, 0x3ea1, 0x3edb, 0x3f02,
0x3f0f, 0x40d7, 0x40eb, 0x4135, 0x4136, 0x4144, 0x4145, 0x420e,
0x4245, 0x4247, 0x4249, 0x436d, 0x43e5, 0x43e8, 0x4410, 0x4414,
0x4480, 0x4485, 0x4496, 0x44de, 0x45a0, 0x45a8, 0x45bf, 0x45ca,
0x45cc, 0x461f, 0x4685, 0x46a7, 0x46c1, 0x46d7, 0x4760, 0x48c1,
0x49c0, 0x49c1, 0x4a1b, 0x4a55, 0x4ae2, 0x4b82, 0x4be1, 0x4beb,
0x4c28, 0x4ca5, 0x4cc9, 0x4f59, 0x50e7, 0x50e8, 0x5156, 0x53c8,
0x53d5, 0x53ec, 0x5571, 0x5594, 0x55ab, 0x56a1, 0x570c, 0x570e,
0x57da, 0x5872, 0x58ab, 0x598f, 0x59cc, 0x5b1b, 0x5b9b, 0x5d5f,
0x5d68, 0x5d94, 0x5df1, 0x5e0e, 0x608a, 0x614f, 0x6217, 0x66ec,
0x6765, 0x6a06, 0x6a44, 0x6a4f, 0x6a50, 0x6a5e, 0x6a82, 0x6a8f,
0x6a97, 0x6bbf, 0x6c2a, 0x6c93, 0x6e0f, 0x6e1d, 0x6e33, 0x6e67,
0x6e70, 0x6e71, 0x6e74, 0x6ea0, 0x6eba, 0x6ef3, 0x6f05, 0x6f88,
0x6fed, 0x7067, 0x706d, 0x706f, 0x733f, 0x7345, 0x73a1, 0x73b9,
0x741f, 0x748d, 0x7494, 0x7498, 0x74d2, 0x7504, 0x753c, 0x7596,
0x7602, 0x7715, 0x7731, 0x7828, 0x792c, 0x7d78, 0xddac, 0xddba
0x0, 0x1, 0x2, 0x2ca0, 0x2ca9, 0x2caa, 0x2cdb, 0x2d2b,
0x2d2c, 0x2d44, 0x2d96, 0x2ded, 0x2dee, 0x2dfc, 0x2e7d, 0x2e81,
0x2edc, 0x3005, 0x300c, 0x3011, 0x3013, 0x3039, 0x309a, 0x30a6,
0x30d6, 0x30ed, 0x3148, 0x31b6, 0x31da, 0x322b, 0x323f, 0x3262,
0x326c, 0x3271, 0x3276, 0x3283, 0x328f, 0x3297, 0x32a8, 0x32cc,
0x32cf, 0x32ea, 0x3308, 0x357e, 0x3580, 0x3594, 0x35d0, 0x35e0,
0x362b, 0x37ad, 0x37b6, 0x37d1, 0x39f0, 0x39f7, 0x39f8, 0x3a3a,
0x3a3e, 0x3a66, 0x3c92, 0x3cc7, 0x3cd8, 0x3d14, 0x3d2f, 0x3d46,
0x3d96, 0x3da0, 0x3da2, 0x3daf, 0x3db5, 0x3dda, 0x3df2, 0x3df3,
0x3df5, 0x3ea1, 0x3edb, 0x3f02, 0x3f0f, 0x40d7, 0x40eb, 0x4135,
0x4136, 0x4144, 0x4145, 0x420e, 0x4229, 0x4245, 0x4247, 0x4249,
0x436d, 0x43d6, 0x43e5, 0x43e8, 0x4410, 0x4414, 0x4480, 0x4485,
0x4496, 0x44de, 0x45a0, 0x45a8, 0x45bf, 0x45ca, 0x45cc, 0x45da,
0x461f, 0x4685, 0x46a7, 0x46c1, 0x46d7, 0x4760, 0x48c1, 0x49c0,
0x49c1, 0x4a03, 0x4a1b, 0x4a55, 0x4ae2, 0x4b00, 0x4b82, 0x4be1,
0x4beb, 0x4c28, 0x4ca5, 0x4cc9, 0x4f59, 0x50e7, 0x50e8, 0x5156,
0x5177, 0x518c, 0x53c8, 0x53d5, 0x53ec, 0x5571, 0x5594, 0x55ab,
0x5685, 0x56a1, 0x570c, 0x570e, 0x57da, 0x5872, 0x58ab, 0x5937,
0x596b, 0x5979, 0x598f, 0x59cc, 0x5b1b, 0x5b9b, 0x5d5f, 0x5d68,
0x5d7f, 0x5d8d, 0x5d94, 0x5df1, 0x5e0e, 0x5fba, 0x608a, 0x6122,
0x614f, 0x61a3, 0x6217, 0x66ec, 0x6765, 0x6a06, 0x6a41, 0x6a44,
0x6a4f, 0x6a50, 0x6a5e, 0x6a82, 0x6a8f, 0x6a97, 0x6bbf, 0x6bc5,
0x6c2a, 0x6c93, 0x6e0f, 0x6e1d, 0x6e33, 0x6e67, 0x6e70, 0x6e71,
0x6e74, 0x6ea0, 0x6ea1, 0x6eba, 0x6ef3, 0x6f05, 0x6f88, 0x6fed,
0x7067, 0x706d, 0x706f, 0x733f, 0x7345, 0x73a1, 0x73b9, 0x741f,
0x7488, 0x748d, 0x7494, 0x7498, 0x74d2, 0x7504, 0x753c, 0x7596,
0x7602, 0x7715, 0x7731, 0x7828, 0x7836, 0x792c, 0x7d78, 0xddac,
0xddba
};
/*Collect the unicode lists and glyph_id offsets*/
@@ -1522,12 +1719,12 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
},
{
.range_start = 9654, .range_length = 1, .glyph_id_start = 280,
.range_start = 9654, .range_length = 1, .glyph_id_start = 313,
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
},
{
.range_start = 8544, .range_length = 56763, .glyph_id_start = 96,
.unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 184, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
.unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 217, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
}
};
+79
View File
@@ -0,0 +1,79 @@
/*
* 模块名称:UI Page 事故记录(事故记录内容页)
* 模块功能:事故记录叶子节点(node 34,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经 ui_w_records
* 注入 reader 取自 sys_log(/log/accid.log,容量上限 512 条,满时删除重建);
* 空日志显示单条伪行"无记录";向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 记录口径(本文件只读显示、不实现写入方;权威表 App/log/README.md §五类记录):
* 触发判据 = 元件 asserted 上升沿**且**该元件跳闸投退项 = 1(跳闸型动作);
* 写入点 = App/task/protect_task.c 的 s_log_active_edge();
* "记录类型 = 日志 ID 本身"(一类记录一个文件,记录体内没有类型字段位,
* Lead 裁定 2026-10-26)——本页只读 accid.log 一个文件,不做跨文件混排。
* 台架待补(不在本批,已登记 docs/任务规划/登记簿.md):真 NAND 上真实记录的翻页读取、
* 掉电后记录保持、清除记录后本页归零这三件事都要上板复核;模拟器侧该文件
* 没有写入方,像素黄金只能验空态"无记录"。
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」:照 ui_page_runlog.c 同构,
* 分页 / 空态 / 按实例读盘缓存全部复用 ui_w_records,
* 本文件不重复实现,也不改共享组件)
*/
/* 头文件包含区 */
#include "ui_page_accident.h"
#include "ui_w_records.h"
#include "ui_tokens.h"
/* 静态变量定义区 */
/*
* 记录页薄跳板:内容全部走 ui_w_records 共享组件(W6 合并先例)。
* 实例 s_rec 携带记录源编号与**本实例自己的**读盘缓存——多页共用组件代码,
* 但缓存不得共享,否则切页会命中上一记录号而显示另一页的陈旧行(静默错数据)。
*/
static ui_w_records_t s_rec = { UI_W_REC_LOG_ACCIDENT };
/*
* 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录")
* 入口参数:无
* 返 回 值:总行数 uint16_t
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static uint16_t pg_count(void) {
return ui_w_records_count(&s_rec);
}
/*
* 函数功能:逐行取数(转调共享组件;偶数行 = 时间戳、奇数行 = 描述)
* 入口参数:row - 全局行下标 uint16_t
* name - 名输出缓冲 char *
* value - 值输出缓冲(本组件恒写空串) char *
* 返 回 值:无 void
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static void pg_refresh(uint16_t row, char *name, char *value) {
ui_w_records_refresh(&s_rec, row, name, value);
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=accident 绑定引用):
* 动态列表页——每记录 2 行、UI_LIST_ROWS 行/页;band_h=UI_ROW_BAND_H(同 AC/DC 约定:
* selectable 页选中行黑字必须配白带,band_h=0 会致选中行不可见)
*/
const content_page_def_t ui_page_accident_desc = {
.id = "accident",
.title = "事故记录",
.selectable = 1u,
.top_y = UI_LIST_TOP,
.pitch = UI_ROW_PITCH,
.band_h = UI_ROW_BAND_H,
.text_dy = 0,
.left_x = UI_LIST_LEFT_X,
.right_x = UI_LIST_RIGHT_X,
.rows_per_page = UI_LIST_ROWS,
.count_cb = pg_count,
.refresh = pg_refresh,
};
+26
View File
@@ -0,0 +1,26 @@
/*
* 模块名称:UI Page 事故记录(事故记录内容页)
* 模块功能:事故记录叶子节点(node 34,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经
* ui_w_records 注入 reader 取自 sys_log(/log/accid.log;本文件不 include
* sys_log.h——task-6 分层收紧);空日志显示单条伪行"无记录";
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」;记录层与写入点已由
* 道F task-10 / 道G task-12 落地,本批只补页面)
*/
#ifndef UI_PAGE_ACCIDENT_H
#define UI_PAGE_ACCIDENT_H
#include "ui_content_page.h"
/*
* 页面描述符(Flash const):事故记录页(描述符 .id = "accident");
* 由生成物 ui_page_registry.c 按菜单树 #page=accident 注记绑定引用(定义于 ui_page_accident.c)
*/
extern const content_page_def_t ui_page_accident_desc;
#endif /* UI_PAGE_ACCIDENT_H */
+79
View File
@@ -0,0 +1,79 @@
/*
* 模块名称:UI Page 保护告警(保护告警内容页)
* 模块功能:保护告警叶子节点(node 36,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经 ui_w_records
* 注入 reader 取自 sys_log(/log/alarm.log,容量上限 1024 条,满时删除重建);
* 空日志显示单条伪行"无记录";向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 记录口径(本文件只读显示、不实现写入方;权威表 App/log/README.md §五类记录):
* 触发判据 = 元件 asserted 上升沿**且**跳闸投退项 = 0 或该元件无此项(告警型动作);
* 写入点 = App/task/protect_task.c 的 s_log_active_edge();
* "记录类型 = 日志 ID 本身"(一类记录一个文件,记录体内没有类型字段位,
* Lead 裁定 2026-10-26)——本页只读 alarm.log 一个文件,不做跨文件混排。
* 台架待补(不在本批,已登记 docs/任务规划/登记簿.md):真 NAND 上真实记录的翻页读取、
* 掉电后记录保持、清除记录后本页归零这三件事都要上板复核;模拟器侧该文件
* 没有写入方,像素黄金只能验空态"无记录"。
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」:照 ui_page_runlog.c 同构,
* 分页 / 空态 / 按实例读盘缓存全部复用 ui_w_records,
* 本文件不重复实现,也不改共享组件)
*/
/* 头文件包含区 */
#include "ui_page_alarm.h"
#include "ui_w_records.h"
#include "ui_tokens.h"
/* 静态变量定义区 */
/*
* 记录页薄跳板:内容全部走 ui_w_records 共享组件(W6 合并先例)。
* 实例 s_rec 携带记录源编号与**本实例自己的**读盘缓存——多页共用组件代码,
* 但缓存不得共享,否则切页会命中上一记录号而显示另一页的陈旧行(静默错数据)。
*/
static ui_w_records_t s_rec = { UI_W_REC_LOG_ALARM };
/*
* 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录")
* 入口参数:无
* 返 回 值:总行数 uint16_t
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static uint16_t pg_count(void) {
return ui_w_records_count(&s_rec);
}
/*
* 函数功能:逐行取数(转调共享组件;偶数行 = 时间戳、奇数行 = 描述)
* 入口参数:row - 全局行下标 uint16_t
* name - 名输出缓冲 char *
* value - 值输出缓冲(本组件恒写空串) char *
* 返 回 值:无 void
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static void pg_refresh(uint16_t row, char *name, char *value) {
ui_w_records_refresh(&s_rec, row, name, value);
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=alarm 绑定引用):
* 动态列表页——每记录 2 行、UI_LIST_ROWS 行/页;band_h=UI_ROW_BAND_H(同 AC/DC 约定:
* selectable 页选中行黑字必须配白带,band_h=0 会致选中行不可见)
*/
const content_page_def_t ui_page_alarm_desc = {
.id = "alarm",
.title = "保护告警",
.selectable = 1u,
.top_y = UI_LIST_TOP,
.pitch = UI_ROW_PITCH,
.band_h = UI_ROW_BAND_H,
.text_dy = 0,
.left_x = UI_LIST_LEFT_X,
.right_x = UI_LIST_RIGHT_X,
.rows_per_page = UI_LIST_ROWS,
.count_cb = pg_count,
.refresh = pg_refresh,
};
+26
View File
@@ -0,0 +1,26 @@
/*
* 模块名称:UI Page 保护告警(保护告警内容页)
* 模块功能:保护告警叶子节点(node 36,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经
* ui_w_records 注入 reader 取自 sys_log(/log/alarm.log;本文件不 include
* sys_log.h——task-6 分层收紧);空日志显示单条伪行"无记录";
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」;记录层与写入点已由
* 道F task-10 / 道G task-12 落地,本批只补页面)
*/
#ifndef UI_PAGE_ALARM_H
#define UI_PAGE_ALARM_H
#include "ui_content_page.h"
/*
* 页面描述符(Flash const):保护告警页(描述符 .id = "alarm");
* 由生成物 ui_page_registry.c 按菜单树 #page=alarm 注记绑定引用(定义于 ui_page_alarm.c)
*/
extern const content_page_def_t ui_page_alarm_desc;
#endif /* UI_PAGE_ALARM_H */
+79
View File
@@ -0,0 +1,79 @@
/*
* 模块名称:UI Page 操作记录(操作记录内容页)
* 模块功能:操作记录叶子节点(node 35,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经 ui_w_records
* 注入 reader 取自 sys_log(/log/oper.log,容量上限 512 条,满时删除重建);
* 空日志显示单条伪行"无记录";向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 记录口径(本文件只读显示、不实现写入方;权威表 App/log/README.md §五类记录):
* 触发判据 = 人工/远端操作留痕:定值保存、强制复归、对时(8888 与 104)、清除记录;
* 写入点 = App/task/default_task.c(定值保存)、App/protocol/iec104/iec104_pts.c(复归与整定写入)、App/task/iec104_serv.c 与 App/sync/time_sync.c(对时)、App/log/sys_log_mcu.c(清除记录留痕,OPER 自身除外);
* "记录类型 = 日志 ID 本身"(一类记录一个文件,记录体内没有类型字段位,
* Lead 裁定 2026-10-26)——本页只读 oper.log 一个文件,不做跨文件混排。
* 台架待补(不在本批,已登记 docs/任务规划/登记簿.md):真 NAND 上真实记录的翻页读取、
* 掉电后记录保持、清除记录后本页归零这三件事都要上板复核;模拟器侧该文件
* 没有写入方,像素黄金只能验空态"无记录"。
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」:照 ui_page_runlog.c 同构,
* 分页 / 空态 / 按实例读盘缓存全部复用 ui_w_records,
* 本文件不重复实现,也不改共享组件)
*/
/* 头文件包含区 */
#include "ui_page_oper.h"
#include "ui_w_records.h"
#include "ui_tokens.h"
/* 静态变量定义区 */
/*
* 记录页薄跳板:内容全部走 ui_w_records 共享组件(W6 合并先例)。
* 实例 s_rec 携带记录源编号与**本实例自己的**读盘缓存——多页共用组件代码,
* 但缓存不得共享,否则切页会命中上一记录号而显示另一页的陈旧行(静默错数据)。
*/
static ui_w_records_t s_rec = { UI_W_REC_LOG_OPER };
/*
* 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录")
* 入口参数:无
* 返 回 值:总行数 uint16_t
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static uint16_t pg_count(void) {
return ui_w_records_count(&s_rec);
}
/*
* 函数功能:逐行取数(转调共享组件;偶数行 = 时间戳、奇数行 = 描述)
* 入口参数:row - 全局行下标 uint16_t
* name - 名输出缓冲 char *
* value - 值输出缓冲(本组件恒写空串) char *
* 返 回 值:无 void
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static void pg_refresh(uint16_t row, char *name, char *value) {
ui_w_records_refresh(&s_rec, row, name, value);
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=oper 绑定引用):
* 动态列表页——每记录 2 行、UI_LIST_ROWS 行/页;band_h=UI_ROW_BAND_H(同 AC/DC 约定:
* selectable 页选中行黑字必须配白带,band_h=0 会致选中行不可见)
*/
const content_page_def_t ui_page_oper_desc = {
.id = "oper",
.title = "操作记录",
.selectable = 1u,
.top_y = UI_LIST_TOP,
.pitch = UI_ROW_PITCH,
.band_h = UI_ROW_BAND_H,
.text_dy = 0,
.left_x = UI_LIST_LEFT_X,
.right_x = UI_LIST_RIGHT_X,
.rows_per_page = UI_LIST_ROWS,
.count_cb = pg_count,
.refresh = pg_refresh,
};
+26
View File
@@ -0,0 +1,26 @@
/*
* 模块名称:UI Page 操作记录(操作记录内容页)
* 模块功能:操作记录叶子节点(node 35,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经
* ui_w_records 注入 reader 取自 sys_log(/log/oper.log;本文件不 include
* sys_log.h——task-6 分层收紧);空日志显示单条伪行"无记录";
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」;记录层与写入点已由
* 道F task-10 / 道G task-12 落地,本批只补页面)
*/
#ifndef UI_PAGE_OPER_H
#define UI_PAGE_OPER_H
#include "ui_content_page.h"
/*
* 页面描述符(Flash const):操作记录页(描述符 .id = "oper");
* 由生成物 ui_page_registry.c 按菜单树 #page=oper 注记绑定引用(定义于 ui_page_oper.c)
*/
extern const content_page_def_t ui_page_oper_desc;
#endif /* UI_PAGE_OPER_H */
+12
View File
@@ -10,6 +10,8 @@
#include "ui_page_registry.h"
#include "ui_page_ac.h"
#include "ui_page_accident.h"
#include "ui_page_alarm.h"
#include "ui_page_calib.h"
#include "ui_page_clear.h"
#include "ui_page_clock.h"
@@ -18,15 +20,19 @@
#include "ui_page_deadband.h"
#include "ui_page_device_info.h"
#include "ui_page_net_cfg.h"
#include "ui_page_oper.h"
#include "ui_page_password.h"
#include "ui_page_reset.h"
#include "ui_page_runlog.h"
#include "ui_page_runreport.h"
#include "ui_page_selftest.h"
#include "ui_page_soe.h"
#include "ui_page_start.h"
#include "ui_page_view_param.h"
#include "ui_page_view_plate.h"
#include "ui_page_view_set.h"
#include "ui_page_view_word.h"
#include "ui_page_yk.h"
#include "ui_page_yx.h"
const ui_page_entry_t g_ui_page_map[UI_PAGE_MAP_COUNT] = {
@@ -50,8 +56,14 @@ const ui_page_entry_t g_ui_page_map[UI_PAGE_MAP_COUNT] = {
{ 29u, &ui_page_comm_desc }, /* node 29 通讯设置 */
{ 30u, &ui_page_net_cfg_desc }, /* node 30 网口设置 */
{ 33u, &ui_page_soe_desc }, /* node 33 SOE记录 */
{ 34u, &ui_page_accident_desc }, /* node 34 事故记录 */
{ 35u, &ui_page_oper_desc }, /* node 35 操作记录 */
{ 36u, &ui_page_alarm_desc }, /* node 36 保护告警 */
{ 37u, &ui_page_start_desc }, /* node 37 保护启动 */
{ 38u, &ui_page_yk_desc }, /* node 38 遥控记录 */
{ 39u, &ui_page_selftest_desc }, /* node 39 自检记录 */
{ 40u, &ui_page_runlog_desc }, /* node 40 运行记录 */
{ 41u, &ui_page_runreport_desc }, /* node 41 运行报告 */
};
/*
+1 -1
View File
@@ -25,7 +25,7 @@ typedef struct {
const content_page_def_t *desc; /* 页面描述符(Flash const) */
} ui_page_entry_t;
#define UI_PAGE_MAP_COUNT 22u /* 绑定了内容页的叶子数 */
#define UI_PAGE_MAP_COUNT 28u /* 绑定了内容页的叶子数 */
extern const ui_page_entry_t g_ui_page_map[UI_PAGE_MAP_COUNT];
+276
View File
@@ -0,0 +1,276 @@
/*
* 模块名称:UI Page RunReport(运行报告内容页)
* 模块功能:运行报告叶子节点(node 41,父节点「记录查询」)的内容页数据——13 行只读统计,
* 分 2 页(UI_LIST_ROWS=8 行/页 → 8 + 5);数据全部经 ui_data 装置信息帧下发
* (写侧 App/app/ui_data_feed.c 搬 boot_stats_get() 与 iec104_serv_get_stats(),
* 本文件零 App include,分层方向由 layer-deps 门禁守护)
* 口径纪律(判据 docs/任务规划/UI补齐.md §2「运行报告」行 + App/util/boot_stats.h 四数台账):
* ① **四个数逐个挂范围标签**,不许含糊——上电次数=自 RTC 电池周期(换电池即清零,
* **禁写终身次数**,固件里压根没有跨开机计数器)、复位原因/运行时长/104 统计
* =本次开机以来(104 四枚跨重连不清零,但**断电即归零**);
* ② boot_ready==0(账本未初始化)或 seq_state==0(UNKNOWN)时上电次数显示 "--"
* 而不是 0——把"没有数"洗成"0 次"是最坏的一种误导;
* ③ write_failed==1 单独占一行("未写回"):后果是账本**少计**,绝不会重复计数
* (掉电保持数 +1 后先写 SRAM 再发布,写失败仍按内存值显示);
* ④ 运行时长是 tick 回绕口径(32 位 ms ≈ 49.7 天、uptime_s ≈ 136 年),
* 显示按"天 + 时时:分分"退化(与装置信息页同一 ASCII 记法,见 di_fmt_uptime),
* **不做跨开机累计**(用户裁定 2026-10-27)
* 几何余量(2026-10-28 黄金目检):「自电池周期」5 字 x12px 从 x=101 起、右缘 161,**余量 0**——
* 值列再加字或换字号必切边;要扩文案必须先减字或改标签列宽度,别直接加字。
* 台架待补(不在本批,已登记 docs/任务规划/登记簿.md):真机上电一次看 boot_count +1、
* 拔电换电池后 seq_state 落 RESTARTED、IWDG 复位后 rst_cause 落 IWDG、
* 主站连一次看 conn_up +1 —— 模拟器无 boot_stats(依赖 SD2506 I2C 与 RCC_CSR)
* 与 104 协议栈,黄金参考拍的是固定假数据
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(形态照 ui_page_device_info.c 的行表 + 值格式化,
* 分页与选中带照 ui_page_deadband.c 的列表页几何)
*/
/* 头文件包含区 */
#include <string.h>
#include "ui_page_runreport.h"
#include "ui_data.h"
#include "ui_tokens.h"
/* 私有宏定义区 */
#define RR_ROW_N 13u /* 行数(2 页:8 + 5) */
#define RR_INVALID "--"
#define RR_SEC_PER_DAY 86400u
/* 复位原因编码(与 App/util/boot_stats.h 的 BOOT_STATS_CAUSE_* 一一对应;
* 这里刻意写成数字常量并在注释里钉死映射——BSP 不得 include App 头,
* 编码变更由 test/host/ui_data 的搬运断言与 App/log/README 口径联动发现 */
#define RR_CAUSE_UNKNOWN 0u
#define RR_CAUSE_IWDG 1u
#define RR_CAUSE_WWDG 2u
#define RR_CAUSE_SFT 3u
#define RR_CAUSE_POR 4u
#define RR_CAUSE_PIN 5u
#define RR_CAUSE_BOR 6u
/* 上电次数可信度编码(BOOT_STATS_SEQ_*) */
#define RR_SEQ_UNKNOWN 0u
#define RR_SEQ_FRESH 1u
#define RR_SEQ_CONTINUED 2u
#define RR_SEQ_RESTARTED 3u
/* 静态变量定义区 */
/* 行名表(Flash;四数各自挂范围行,口径不许含糊) */
static const char *const s_names[RR_ROW_N] = {
"上电次数", "计数范围", "计数可信", "计数写回", "复位原因",
"复位范围", "运行时长", "时长范围", "主站接入",
"发送帧数", "发送失败", "接收字节", "统计范围",
};
/* 帧缓存:发布序号变化才整帧拷一次(同装置信息页口径) */
static ui_data_info_t s_info;
static uint32_t s_seq;
/* 函数定义区 */
/*
* 函数功能:取用最新装置信息帧(只在发布序号变化时整帧拷)
* 入口参数:无
* 返 回 值:1 - 有可用帧;0 - 首帧未到或本帧无效 uint8_t
* 限定条件:uiTask 绘制上下文
*/
static uint8_t rr_frame_ready(void) {
uint32_t now = ui_data_info_seq();
if (now != s_seq) {
s_seq = now;
if (ui_data_info(&s_info) != 0) {
(void)memset(&s_info, 0, sizeof(s_info));
return 0u;
}
}
return (s_info.valid != 0u) ? 1u : 0u;
}
/*
* 函数功能:开页复位缓存(强制下一次绘制重取最新帧,避免停在上一帧的计数上)
* 入口参数:无
* 返 回 值:无 void
* 限定条件:开页时由框架调用
*/
static void rr_init(void) {
s_seq = 0u;
(void)memset(&s_info, 0, sizeof(s_info));
}
/*
* 函数功能:复位原因编码 → 屏上中文(5 字以内,避免挤压值列)
* 入口参数:cause - 复位原因编码(RR_CAUSE_*) uint8_t
* 返 回 值:中文标签(Flash 字面量,恒非 NULL) const char *
* 限定条件:编码越界(含 SD2506 诊断混进来的位)一律落"未知",不猜
*/
static const char *rr_cause_str(uint8_t cause) {
const char *p;
switch (cause) {
case RR_CAUSE_IWDG: p = "独立看门狗"; break;
case RR_CAUSE_WWDG: p = "窗口看门狗"; break;
case RR_CAUSE_SFT: p = "软件复位"; break;
case RR_CAUSE_POR: p = "上电复位"; break;
case RR_CAUSE_PIN: p = "引脚复位"; break;
case RR_CAUSE_BOR: p = "掉电复位"; break;
default: p = "未知"; break;
}
return p;
}
/*
* 函数功能:上电次数可信度编码 → 屏上中文
* 入口参数:state - 可信度编码(RR_SEQ_*) uint8_t
* 返 回 值:中文标签(Flash 字面量,恒非 NULL) const char *
* 限定条件:编码越界一律"未知"
* 函数说明:RESTARTED 的屏上话是"掉电重开"——它指的是 RTC 电池域掉过电
* (计数值本身还在,但跨不掉电那段已经不可信),不是"整机重启过"
*/
static const char *rr_seq_str(uint8_t state) {
const char *p;
switch (state) {
case RR_SEQ_FRESH: p = "首次启用"; break;
case RR_SEQ_CONTINUED: p = "延续"; break;
case RR_SEQ_RESTARTED: p = "掉电重开"; break;
default: p = "未知"; break;
}
return p;
}
/*
* 函数功能:格式化运行时长(本次开机以来,秒)
* 入口参数:sec - 秒数 uint32_t
* a_buf - 输出缓冲 char *
* a_cap - 缓冲容量 uint32_t
* 返 回 值:无 void
* 限定条件:a_buf/a_cap 有效
* 函数说明:>= 1 天走 "%ud%02u:%02u"(ASCII 小写 d,避免为"天"字扩字模);
* < 1 天走 "%02u:%02u:%02u"。与装置信息页同一记法,两页不许各写一套
*/
static void rr_fmt_uptime(uint32_t sec, char *a_buf, uint32_t a_cap) {
uint32_t day = sec / RR_SEC_PER_DAY;
uint32_t rem = sec % RR_SEC_PER_DAY;
if (day > 0u) {
(void)lv_snprintf(a_buf, a_cap, "%luud%02lu:%02lu",
(unsigned long)day, (unsigned long)(rem / 3600u),
(unsigned long)((rem % 3600u) / 60u));
} else {
(void)lv_snprintf(a_buf, a_cap, "%02lu:%02lu:%02lu",
(unsigned long)(rem / 3600u),
(unsigned long)((rem % 3600u) / 60u),
(unsigned long)(rem % 60u));
}
}
/*
* 函数功能:总行数(固定 12 行,分 2 页)
* 入口参数:无
* 返 回 值:行数 uint16_t
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static uint16_t rr_count(void) {
return RR_ROW_N;
}
/*
* 函数功能:逐行取名/值(13 行,见 s_names 表)
* 入口参数:row - 行下标 uint16_t
* name - 名输出缓冲 char *
* value - 值输出缓冲 char *
* 返 回 值:无 void
* 限定条件:uiTask 绘制上下文;首帧未到时数值行一律 "--"(不显示 0 冒充有数)
*/
static void rr_refresh(uint16_t row, char *name, char *value) {
const uint32_t cap = (uint32_t)UI_BUF_STRLEN;
uint8_t ready;
if (row >= RR_ROW_N) {
value[0] = (char)0;
return;
}
(void)lv_snprintf(name, cap, "%s", s_names[row]);
ready = rr_frame_ready();
if (ready == 0u) {
(void)lv_snprintf(value, cap, "%s", RR_INVALID);
return;
}
switch (row) {
case 0u: /* 上电次数 */
if ((s_info.boot_ready == 0u) || (s_info.boot_seq_state == RR_SEQ_UNKNOWN)) {
(void)lv_snprintf(value, cap, "%s", RR_INVALID);
} else {
(void)lv_snprintf(value, cap, "%lu", (unsigned long)s_info.boot_count);
}
break;
case 1u: /* 计数范围 */
(void)lv_snprintf(value, cap, "%s", (s_info.boot_ready == 0u) ? "未知" : "自电池周期");
break;
case 2u: /* 计数可信(四态;未初始化落"未知") */
(void)lv_snprintf(value, cap, "%s", rr_seq_str(s_info.boot_seq_state));
break;
case 3u: /* 计数写回 */
(void)lv_snprintf(value, cap, "%s",
(s_info.boot_write_failed != 0u) ? "未写回" : "正常");
break;
case 4u: /* 复位原因 */
(void)lv_snprintf(value, cap, "%s", rr_cause_str(s_info.rst_cause));
break;
case 5u: /* 复位范围 */
(void)lv_snprintf(value, cap, "%s", "本次开机");
break;
case 6u: /* 运行时长 */
rr_fmt_uptime(s_info.uptime_s, value, cap);
break;
case 7u: /* 时长范围 */
(void)lv_snprintf(value, cap, "%s", "本次开机");
break;
case 8u:
(void)lv_snprintf(value, cap, "%lu", (unsigned long)s_info.iec104_conn_up);
break;
case 9u:
(void)lv_snprintf(value, cap, "%lu", (unsigned long)s_info.iec104_apdu_tx);
break;
case 10u:
(void)lv_snprintf(value, cap, "%lu", (unsigned long)s_info.iec104_tx_fail);
break;
case 11u:
(void)lv_snprintf(value, cap, "%lu", (unsigned long)s_info.iec104_rx_bytes);
break;
default: /* 统计范围 */
(void)lv_snprintf(value, cap, "%s", "本次开机");
break;
}
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=runreport 绑定引用):
* 只读列表页——selectable=1 走真分页(13 行 / UI_LIST_ROWS 行 = 2 页,页脚真实页码);
* band_h=UI_ROW_BAND_H(选中行黑字须配白带);无写入口,故无保存态/无三态
*/
const content_page_def_t ui_page_runreport_desc = {
.id = "runreport",
.title = "运行报告",
.selectable = 1u,
.top_y = UI_LIST_TOP,
.pitch = UI_ROW_PITCH,
.band_h = UI_ROW_BAND_H,
.text_dy = 0,
.left_x = UI_LIST_LEFT_X,
.right_x = UI_LIST_RIGHT_X,
.rows_per_page = UI_LIST_ROWS,
.count_cb = rr_count,
.init_cb = rr_init,
.refresh = rr_refresh,
};
+27
View File
@@ -0,0 +1,27 @@
/*
* 模块名称:UI Page RunReport(运行报告内容页)
* 模块功能:运行报告叶子节点(node 41,父节点「记录查询」)的内容页数据——12 行只读
* 统计(上电次数/计数范围/计数写回/复位原因/复位范围/运行时长/时长范围/
* 主站接入/发送帧数/发送失败/接收字节/统计范围),数据全部取自 ui_data 装置
* 信息帧(App 层装配,本文件零 App include);向框架 ui_content_page 提供
* 页面描述符(零 LVGL 对象)
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「运行报告」;数据面 = 道G task-12 的
* boot_stats 开机账本 + iec104_serv 观测计数 + 现成
* uptime_s,本批只做搬运与屏上文案)
*/
#ifndef UI_PAGE_RUNREPORT_H
#define UI_PAGE_RUNREPORT_H
#include "ui_content_page.h"
/*
* 页面描述符(Flash const):运行报告页(描述符 .id = "runreport");
* 由生成物 ui_page_registry.c 按菜单树 #page=runreport 注记绑定引用(定义于 ui_page_runreport.c)
*/
extern const content_page_def_t ui_page_runreport_desc;
#endif /* UI_PAGE_RUNREPORT_H */
+79
View File
@@ -0,0 +1,79 @@
/*
* 模块名称:UI Page 保护启动(保护启动内容页)
* 模块功能:保护启动叶子节点(node 37,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经 ui_w_records
* 注入 reader 取自 sys_log(/log/start.log,容量上限 1024 条,满时删除重建);
* 空日志显示单条伪行"无记录";向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 记录口径(本文件只读显示、不实现写入方;权威表 App/log/README.md §五类记录):
* 触发判据 = 元件 picked 上升沿(越限电平,早于或等于动作);
* 写入点 = App/task/protect_task.c 的 s_log_active_edge();
* "记录类型 = 日志 ID 本身"(一类记录一个文件,记录体内没有类型字段位,
* Lead 裁定 2026-10-26)——本页只读 start.log 一个文件,不做跨文件混排。
* 台架待补(不在本批,已登记 docs/任务规划/登记簿.md):真 NAND 上真实记录的翻页读取、
* 掉电后记录保持、清除记录后本页归零这三件事都要上板复核;模拟器侧该文件
* 没有写入方,像素黄金只能验空态"无记录"。
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」:照 ui_page_runlog.c 同构,
* 分页 / 空态 / 按实例读盘缓存全部复用 ui_w_records,
* 本文件不重复实现,也不改共享组件)
*/
/* 头文件包含区 */
#include "ui_page_start.h"
#include "ui_w_records.h"
#include "ui_tokens.h"
/* 静态变量定义区 */
/*
* 记录页薄跳板:内容全部走 ui_w_records 共享组件(W6 合并先例)。
* 实例 s_rec 携带记录源编号与**本实例自己的**读盘缓存——多页共用组件代码,
* 但缓存不得共享,否则切页会命中上一记录号而显示另一页的陈旧行(静默错数据)。
*/
static ui_w_records_t s_rec = { UI_W_REC_LOG_START };
/*
* 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录")
* 入口参数:无
* 返 回 值:总行数 uint16_t
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static uint16_t pg_count(void) {
return ui_w_records_count(&s_rec);
}
/*
* 函数功能:逐行取数(转调共享组件;偶数行 = 时间戳、奇数行 = 描述)
* 入口参数:row - 全局行下标 uint16_t
* name - 名输出缓冲 char *
* value - 值输出缓冲(本组件恒写空串) char *
* 返 回 值:无 void
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static void pg_refresh(uint16_t row, char *name, char *value) {
ui_w_records_refresh(&s_rec, row, name, value);
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=start 绑定引用):
* 动态列表页——每记录 2 行、UI_LIST_ROWS 行/页;band_h=UI_ROW_BAND_H(同 AC/DC 约定:
* selectable 页选中行黑字必须配白带,band_h=0 会致选中行不可见)
*/
const content_page_def_t ui_page_start_desc = {
.id = "start",
.title = "保护启动",
.selectable = 1u,
.top_y = UI_LIST_TOP,
.pitch = UI_ROW_PITCH,
.band_h = UI_ROW_BAND_H,
.text_dy = 0,
.left_x = UI_LIST_LEFT_X,
.right_x = UI_LIST_RIGHT_X,
.rows_per_page = UI_LIST_ROWS,
.count_cb = pg_count,
.refresh = pg_refresh,
};
+26
View File
@@ -0,0 +1,26 @@
/*
* 模块名称:UI Page 保护启动(保护启动内容页)
* 模块功能:保护启动叶子节点(node 37,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经
* ui_w_records 注入 reader 取自 sys_log(/log/start.log;本文件不 include
* sys_log.h——task-6 分层收紧);空日志显示单条伪行"无记录";
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」;记录层与写入点已由
* 道F task-10 / 道G task-12 落地,本批只补页面)
*/
#ifndef UI_PAGE_START_H
#define UI_PAGE_START_H
#include "ui_content_page.h"
/*
* 页面描述符(Flash const):保护启动页(描述符 .id = "start");
* 由生成物 ui_page_registry.c 按菜单树 #page=start 注记绑定引用(定义于 ui_page_start.c)
*/
extern const content_page_def_t ui_page_start_desc;
#endif /* UI_PAGE_START_H */
+79
View File
@@ -0,0 +1,79 @@
/*
* 模块名称:UI Page 遥控记录(遥控记录内容页)
* 模块功能:遥控记录叶子节点(node 38,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经 ui_w_records
* 注入 reader 取自 sys_log(/log/yk.log,容量上限 256 条,满时删除重建);
* 空日志显示单条伪行"无记录";向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 记录口径(本文件只读显示、不实现写入方;权威表 App/log/README.md §五类记录):
* 触发判据 = 104 遥控的选择 / 执行 / 拒绝(含未知类型与参数越界);
* 写入点 = App/protocol/iec104/iec104_pts.c 的遥控段;
* "记录类型 = 日志 ID 本身"(一类记录一个文件,记录体内没有类型字段位,
* Lead 裁定 2026-10-26)——本页只读 yk.log 一个文件,不做跨文件混排。
* 台架待补(不在本批,已登记 docs/任务规划/登记簿.md):真 NAND 上真实记录的翻页读取、
* 掉电后记录保持、清除记录后本页归零这三件事都要上板复核;模拟器侧该文件
* 没有写入方,像素黄金只能验空态"无记录"。
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」:照 ui_page_runlog.c 同构,
* 分页 / 空态 / 按实例读盘缓存全部复用 ui_w_records,
* 本文件不重复实现,也不改共享组件)
*/
/* 头文件包含区 */
#include "ui_page_yk.h"
#include "ui_w_records.h"
#include "ui_tokens.h"
/* 静态变量定义区 */
/*
* 记录页薄跳板:内容全部走 ui_w_records 共享组件(W6 合并先例)。
* 实例 s_rec 携带记录源编号与**本实例自己的**读盘缓存——多页共用组件代码,
* 但缓存不得共享,否则切页会命中上一记录号而显示另一页的陈旧行(静默错数据)。
*/
static ui_w_records_t s_rec = { UI_W_REC_LOG_YK };
/*
* 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录")
* 入口参数:无
* 返 回 值:总行数 uint16_t
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static uint16_t pg_count(void) {
return ui_w_records_count(&s_rec);
}
/*
* 函数功能:逐行取数(转调共享组件;偶数行 = 时间戳、奇数行 = 描述)
* 入口参数:row - 全局行下标 uint16_t
* name - 名输出缓冲 char *
* value - 值输出缓冲(本组件恒写空串) char *
* 返 回 值:无 void
* 限定条件:uiTask 绘制上下文(经框架回调)
*/
static void pg_refresh(uint16_t row, char *name, char *value) {
ui_w_records_refresh(&s_rec, row, name, value);
}
/*
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=yk 绑定引用):
* 动态列表页——每记录 2 行、UI_LIST_ROWS 行/页;band_h=UI_ROW_BAND_H(同 AC/DC 约定:
* selectable 页选中行黑字必须配白带,band_h=0 会致选中行不可见)
*/
const content_page_def_t ui_page_yk_desc = {
.id = "yk",
.title = "遥控记录",
.selectable = 1u,
.top_y = UI_LIST_TOP,
.pitch = UI_ROW_PITCH,
.band_h = UI_ROW_BAND_H,
.text_dy = 0,
.left_x = UI_LIST_LEFT_X,
.right_x = UI_LIST_RIGHT_X,
.rows_per_page = UI_LIST_ROWS,
.count_cb = pg_count,
.refresh = pg_refresh,
};
+26
View File
@@ -0,0 +1,26 @@
/*
* 模块名称:UI Page 遥控记录(遥控记录内容页)
* 模块功能:遥控记录叶子节点(node 38,父节点「记录查询」)的内容页数据——动态列表,
* 每条记录 2 行(偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据经
* ui_w_records 注入 reader 取自 sys_log(/log/yk.log;本文件不 include
* sys_log.h——task-6 分层收紧);空日志显示单条伪行"无记录";
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
* 作者:DTU 项目组
* 创建日期:2026-10-28
* 修改记录:
* v1.0 2026-10-28 DTU 项目组 创建(UI 补齐「记录 5 页」;记录层与写入点已由
* 道F task-10 / 道G task-12 落地,本批只补页面)
*/
#ifndef UI_PAGE_YK_H
#define UI_PAGE_YK_H
#include "ui_content_page.h"
/*
* 页面描述符(Flash const):遥控记录页(描述符 .id = "yk");
* 由生成物 ui_page_registry.c 按菜单树 #page=yk 注记绑定引用(定义于 ui_page_yk.c)
*/
extern const content_page_def_t ui_page_yk_desc;
#endif /* UI_PAGE_YK_H */
+1 -1
View File
@@ -52,7 +52,7 @@ static const char *const s_type_name[UI_W_SOE_T_COUNT] = {
"压板投入", /* 4 软压板投入 */
"采样闭锁", /* 5 采样故障闭锁 */
"采样恢复", /* 6 采样故障恢复 */
"未标定闭锁", /* 7 未标定闭锁(照 App/log/soe_rec.h 与 数据可信 卡5 的原词,
"未标定闭锁", /* 7 未标定闭锁(照 App/log/soe_rec.h 与「数据可信」未标定即闭锁的原词,
* 不缩成"标定闭锁"——那个写法可以读成"把标定闭锁了",
* 而这一行要说的是"因未标定而闭锁",一字之差含义相反) */
"标定复归", /* 8 标定复归 */
+30
View File
@@ -3646,6 +3646,36 @@
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\UI\ui_page_comm.c</FilePath>
</File>
<File>
<FileName>ui_page_accident.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\UI\ui_page_accident.c</FilePath>
</File>
<File>
<FileName>ui_page_alarm.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\UI\ui_page_alarm.c</FilePath>
</File>
<File>
<FileName>ui_page_oper.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\UI\ui_page_oper.c</FilePath>
</File>
<File>
<FileName>ui_page_runreport.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\UI\ui_page_runreport.c</FilePath>
</File>
<File>
<FileName>ui_page_start.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\UI\ui_page_start.c</FilePath>
</File>
<File>
<FileName>ui_page_yk.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\UI\ui_page_yk.c</FilePath>
</File>
</Files>
</Group>
<Group>
+2 -2
View File
@@ -122,7 +122,7 @@ docs/
| [`链路延迟测试说明.md`](测试说明/链路延迟测试说明.md) | 网络链路时延分段定义、判定基线、执行流程 |
| [`模拟器差距清单.md`](测试说明/模拟器差距清单.md) | **PC 模拟器 vs 真机差距登记册**(L3 门禁可信度依据;改动涉及网络/日志/硬件层前必查 §3 决策规则) |
| [`实机测试实施指南.md`](测试说明/实机测试实施指南.md) | **上板(真机)测试执行流程**(按顺序:环境预检 → `@test`+自检判定 → IWDG 注入/长跑 → 堆告警 → GD5F 错误通道 → 网络基线 → 工程卫生;每步含判据/命令/状态);已完成事项证据去向见 §10 |
| [`ADC前端注入验证流程.md`](测试说明/ADC前端注入验证流程.md) | **ADC 前端与两片转换器的台架注入验证**(`docs/任务规划/数据可信.md` 卡 0 的执行侧):注入点清单 / 期望码值表 / 零点·线性·映射·极性·节奏五步(每步自带现场记录表,边做边填);**不需示波器与信号源**,一块万用表即可 |
| [`ADC前端注入验证流程.md`](测试说明/ADC前端注入验证流程.md) | **ADC 前端与两片转换器的台架注入验证**(已知电压注入验证的执行侧,实测证据 → `docs/硬件平台/ADC通道映射说明.md` §8.1):注入点清单 / 期望码值表 / 零点·线性·映射·极性·节奏五步(每步自带现场记录表,边做边填);**不需示波器与信号源**,一块万用表即可 |
**主机侧单元测试(L0.5)**
@@ -241,7 +241,7 @@ docs/
| 位置 | 内容 |
|---|---|
| [`任务规划/`](任务规划/README.md) | **统一待办入口(6 个文件)**:`README.md` = 现在做什么与全项目顺序;`UI补齐.md` = 当前唯一执行清单;`登记簿.md` = 后续任务、外部窗口与长期观察;`数据可信.md` = 三项阻塞任务及代码引用的设计约束;`暂缓-RS485.md` 与 `测试与架构专项.md` = 两个专项。完成即删,重复内容只保留一个归属 |
| [`任务规划/`](任务规划/README.md) | **统一待办入口(6 个文件)**:`README.md` = 现在做什么与全项目顺序;`UI补齐.md` = 当前唯一执行清单;`登记簿.md` = 后续任务、外部窗口与长期观察;`数据可信.md` = 两项阻塞任务及代码引用的设计约束;`暂缓-RS485.md` 与 `测试与架构专项.md` = 两个专项。完成即删,重复内容只保留一个归属 |
| `硬件平台/` | 网表详细分析报告与语义图(V0.0 / V0.1);**[`ADC通道映射说明.md`](硬件平台/ADC通道映射说明.md)——V0.1 十七路 ADC 语义/网名/通道号权威映射表(固件取数、UI 显示、自检注入以此为准)** |
| `芯片手册/` | 外部芯片数据手册转录(CH395F / GD5F2GQ5UE / SD2506 / TPAFE5160 / RTL8305NBI 等) |
| `images/` | 文档技术配图(`.svg` 产物,由 `tools/arch_diagram/`、`tools/refgraph/` 生成) |
@@ -55,7 +55,7 @@ scanned 13 files; unique non-ASCII chars: 78
-> D:\Code\DTU Code\STM32F4-Base\ui_cn_chars.txt
```
产物 `ui_cn_chars.txt` 为本工程实际显示的汉字清单(当前 183 字,含 ▶/,/: 等符号;其中 60 字为 2026-10-25 按页面扩充规划显示串预置,同日道E 落 SOE 记录显示名映射时新用 采/样/恢/效 4 字;清单里源码暂未在用的字由 font-charset 门禁记 WARN 放行),可留作字符集记录。
产物 `ui_cn_chars.txt` 为本工程实际显示的汉字清单(当前 218 字,含 ▶/,/: 等符号;2026-10-28 UI 补齐批「记录 5 页 + 运行报告」+33 字,185→218——本行旧数 183 是未回填的历史值,改前实测 185;其中 60 字为 2026-10-25 按页面扩充规划显示串预置,同日道E 落 SOE 记录显示名映射时新用 采/样/恢/效 4 字;清单里源码暂未在用的字由 font-charset 门禁记 WARN 放行),可留作字符集记录。
---
@@ -85,9 +85,9 @@ npm i -g lv_font_conv # TTF/OTF -> LVGL 字体 离线转换器
```
extracted SimSun regular (face0) -> C:\Users\...\Temp\simsun_regular.ttf
RUN: lv_font_conv.cmd --font ... --size 12 --bpp 1 -r 0x20-0x7E --symbols ... --no-compress --format lvgl --lv-font-name ui_font_cn_12 -o ...\ui_font_cn_12.c
已合并箭头 U+25B6:位图+10 字节,glyph_id=274
已合并箭头 U+25B6:位图+10 字节,glyph_id=313
U+FF0C ',' 已可经既有 cmap 解析,跳过合并
OK 58192 bytes -> ...\Drivers\BSP\UI\ui_font_cn_12.c
OK 67325 bytes -> ...\Drivers\BSP\UI\ui_font_cn_12.c
```
> **▶ 箭头自动合并**:宋体(`simsun.ttc`)没有 U+25B6(▶)字形,`lv_font_conv` 会静默跳过 → 真机显示成方框。`make_font.py` 在生成后自动调用 `merge_arrow_glyph()`,把从 **Segoe UI Symbol**(`seguisym.ttf`,Windows 自带)预提取的箭头字形(位图 10 字节 + `glyph_dsc` + `cmap`)补回 `ui_font_cn_12.c`。该合并**幂等**(已存在则跳过),所以重生成字体后箭头不会丢。换用自带 ▶ 的字体(如黑体/Segoe)时可忽略此步。
@@ -152,7 +152,7 @@ OK 58192 bytes -> ...\Drivers\BSP\UI\ui_font_cn_12.c
1. **1bpp 细笔画发虚**:宋体在 1bpp 下可能丢像素。若上板/客户端中文偏淡,把第 4 节 `--bpp` 改为 `2` 重生成即可(子集小,体积可接受)。
2. **字符集变更**:以后新增中文菜单项,须重跑第 3、4 节(重新提取 `ui_cn_chars.txt` 并生成),否则新字显示为方框。
3. **编码**:UI 源文件须为 **UTF-8(带 BOM)**,LVGL 按 UTF-8 解码中文串;字体 `.c` 为纯 ASCII,无编码风险。当前 Keil 已加 Misc Controls 抑制项,无需额外 `--locale=english`。
4. **字体体积**:12px + 1bpp + 183 字(含 ASCII/符号,共 278 字形)源文件 ≈ 57.8KB;ROM 增量以 `.map` 为准(2026-10-25 扩 60 字实测 `RO-data` +1,528 B、RAM 0;同日 SOE 显示名再用 4 字实测 `RO-data` +108 B、RAM 0——1bpp 12px 一个字约 27 B,含字形描述符);改 bpp 2 约翻倍,仍在 F407 Flash 余量内。
4. **字体体积**:12px + 1bpp + 218 字(含 ASCII/符号,共 313 字形)源文件 ≈ 65.7KB(2026-10-28 实测 67,325 B;改前 185 字/280 字形/58.2KB,旧文本 183 字/278 字形系未回填);ROM 增量以 `.map` 为准(2026-10-25 扩 60 字实测 `RO-data` +1,528 B、RAM 0;同日 SOE 显示名再用 4 字实测 `RO-data` +108 B、RAM 0——1bpp 12px 一个字约 27 B,含字形描述符);改 bpp 2 约翻倍,仍在 F407 Flash 余量内。
5. **换字体**:黑体用 `simhei.ttf`(单文件免抽取);其余字体同理替换 `--font` 路径后重生成。
---
+26 -1
View File
@@ -247,6 +247,31 @@ typedef struct {
- 结构与两条主通道同构:`seq` + `valid` 打头、定长字符数组、零指针、由 `ui_data` 盖章序号、由 `App/app/ui_data_feed.c` 独家填充,随实时帧同节拍发布。
- **公共地址 CA 故意不在本帧**:固件里 CA 是逐帧从 ASDU 头解析的,没有集中常量可取;等 104 侧给出查询点再按 `docs/UI设计/UI_数据供给设计说明.md` §4.3 的扩展规则追加字段并升 `UI_DATA_VER`。
- 版本类字段目前是 `App/app/ui_data_feed.c` 里的宏(仓库内没有产品级版本登记表,值沿用页面既有显示值,有正式口径后只改那一处);**软件校验位在拿到构建期 CRC 生成步骤之前一律显示 `--`**,不抄参考项目遗留值。
**2026-10-28 追加(「运行报告」页落地)**:info 帧尾部追加 9 个字段,把运行报告要用的四个数从 App 侧搬下来——
`boot_count` / `boot_seq_state` / `boot_write_failed` / `rst_cause` / `boot_ready`(来自 `App/util/boot_stats.h` 的开机账本)与
`iec104_conn_up` / `iec104_apdu_tx` / `iec104_tx_fail` / `iec104_rx_bytes`(来自 `App/task/iec104_serv.h` 的四个只读观测计数)。
- **为什么不另开第二条注入通道**:这些量与装置身份同属`慢变、非节拍、零指针`的一批,info 帧已是它们的属主;
再开一个 reader 就是把 task-6 刚收紧的分层反向边接回来(记录页那套注入表是因为要读**盘**,本批不读盘)。
- **搬运不算第二份口径**:`feed_fill_info()` 只做逐字段拷贝,不换算、不在别处再算一份时长(`uptime_s` 仍由本函数按 tick 差算)。
- **屏上文案归 UI**:四个数各自的类别标签(「自电池周期」「本次开机」)、`boot_ready == 0` 显 `--` 而不是 0、
以及「禁写终身次数」「跨开机累计不做」这两条口径,落在 `Drivers/BSP/UI/ui_page_runreport.c` 文件头;口径出处只在
`App/util/boot_stats.h` 四数台账与本节各述一次(同一事实只在一处详述,`docs/文档规范.md` 同此要求)。
- 代价(本批
`@build` 实测,0 错 0 警):
`Program Size` 由本批前
Code=235536 RO=26392 RW=1572 ZI=136924 变为 Code=236456 RO=28124 RW=1876 ZI=137084(ROM 合计 +2,652 B)
→ **RAM 合计 +464 B**(RW +304 / ZI +160)。逐对象(.map):5 个记录页各 60 B
`.data`(每页一份
`ui_w_records_t` 读盘缓存,
按实例存是记录页注入改造时定下的纪律,共享会串页);`ui_page_runreport.o` 116 B
`.bss`(信息帧本地缓存 + 发布序号);
info 帧字段增量落在 `ui_data.o`(1,192 B
`.bss`,同对象还装 rt / par 两通道的双区)与 `ui_data_feed.o`(217 B)里。
随帧发布不新增拷贝节拍。水位:
`RW_IRAM1` 62.2% / `RW_CCM` 87.9%(阈值 92%),
`mem-budget` PASS,
台账已由 `scripts/ram_baseline.py --update` / `--write` 回填(docs/内存管理/RAM预算台账.md)。 `@build` 后回填),未触 `mem-budget` 92% 红线。
> 另一处落地细化:`ui_data_rt_t` 除 `yc[]`(语义通道序基波有效值)外还带一条 `ph[]` 相量实例槽带(`ph_n` 给实际槽数)。原因是谐波(`Ia` 的二次/五次)无法在"语义通道"下标空间里表达——同一通道的谐波会与基波撞位,而交流量页要显示它们(`docs/UI设计/页面扩充详细方案.md` §3.1.1 第 4/5 行)。两条带的元素同形(数值 + 品质),页面行表按需选一条。
@@ -669,7 +694,7 @@ typedef struct {
| 4 | 未标定时页面明确标识(不把码值当伏特) | 目检 + 文本断言(`eng=0` 时带标记) |
| 5 | 首帧前显示 `--` 而非 `0.000` | 模拟器:不 publish 直接开页,断言文本 |
| 6 | 定值整定全链闭环 | 就地改 → 保存 → 重启 → 值保持 + 校验和自检通过 + 主站 C_RD 一致。**半收口(2026-10-26)**:模拟器侧「改 → 保存 → OK → 回首屏新值已在帧里」已由像素 + 文本断言覆盖(黄金用例 `sparam_save` / `sparam_landed`,越界侧 `sparam_oob`);**重启保持与主站 C_RD 一致只能上板**——模拟器没有 NAND,`apply()` 到 `prot_set_set_sealed()` 就是终点,这条差距已登记在 `docs/测试说明/模拟器差距清单.md`;另注意 40 项里有 13 项 `comm_addr=0`(纯本地项),主站侧根本读不到,不能拿 C_RD 当它们的判据 |
| 7 | 像素回归稳定 | `ui-golden` 连续两次运行零差异。**已验(2026-10-26,当时下限为 27 页)**:27 页连跑两次逐字节一致(含整定 9 态)——**集合现已扩至 53 页**,双次一致需按同口径重跑回填;轮询定时器不影响——无头模式不调 `lv_timer_handler()`(§9.2 注 6) |
| 7 | 像素回归稳定 | `ui-golden` 连续两次运行零差异。**已验(2026-10-26,当时下限为 27 页)**:27 页连跑两次逐字节一致(含整定 9 态)——**集合现已扩至 60 页**,双次一致需按同口径重跑回填;轮询定时器不影响——无头模式不调 `lv_timer_handler()`(§9.2 注 6) |
| 9 | 「写不进去」与「改了不动作」两条事实互不冒充 | 反向文本断言(`check_content_pages.py` 的 `ABSENT`:查看页与只读态不得出现「未标定」徽标与「保存」行)+ 台架:未制造该态——要它必须改坏 /prot_set.bin(破坏产品配置存储,用户裁定 2026-10-26 不做),故 LOCK 态目前只有代码级证据与三重反证(ENTER 被正常消费、遥信 YX31=OFF、开机 CORRUPT=0),**没有像素证据** |
| 8 | 主机单测覆盖数据模块 | `test/host/ui_data` 全绿并挂 pre-commit 钩子 |
+2 -1
View File
@@ -48,7 +48,7 @@ flowchart TD
|---|---|---|---|
| C1 | 屏幕 | 160×160,1bpp 单色(`LV_COLOR_FORMAT_I1`),无物理屏(远端客户端显示) | `ui_port.h` |
| C2 | 字体 | **唯一**:`ui_font_cn_12`(宋体 12px 1bpp)。汉字 12px/字,ASCII 6px/字,行高 13px。需要其他字号 = 大工程(新字体 + 双端 `lv_conf.h`),默认禁止 | `ui_font_cn_12.c` |
| C3 | 字符集 | 子集字体(当前 183 汉字/符号 + ASCII 0x20-0x7E,共 278 字形);**缺字显示空白**;新字必须重生成字体 | `tools/font_gen/` |
| C3 | 字符集 | 子集字体(当前 218 汉字/符号 + ASCII 0x20-0x7E,共 313 字形);**缺字显示空白**;新字必须重生成字体 | `tools/font_gen/` |
| C4 | LVGL 内存池 | 16KB(`LV_MEM_SIZE`,2026-10-15 由 40KB 收缩;实测峰值 6,568 B = 池的 40%);任一时刻只放"当前导航路径 + 当前内容页" | `Lib/lv_conf.h` |
| C5 | 文本 | 一律静态字符串(`lv_label_set_text_static`),禁止动态字符串/strdup | 架构文档 |
| C6 | 编码 | `Drivers/BSP/UI/*`、`ui_task.c`、`Lib/lv_conf.h` 为 **UTF-8 带 BOM**;改动只用 Edit 工具,**禁止** PowerShell/cmd 整文件重写(U+FFFD 不可逆) | AGENTS.md 铁律 |
@@ -413,3 +413,4 @@ P4 [ ] UI_设计架构.md 变更记录更新
| 2026-09-13 | 移除 HTML 样机阶段:五阶段 → **四阶段管线**(P0 需求录入+设计规格 / P1 规格→代码 / P2 模拟器 / P3 MCU / P4 归档);设计基准改为"规格布局参数表 + 参考图",P2 比对基准由"样机渲染图"改为"参考图 + 规格参数表"(根因分流:修代码 / 回 P0 修规格);用户视觉确认点由 HTML 浏览器移到 P2 模拟器窗口/出图;删除 `mockups/01_主界面.html`、`render_01.png`、`tools/ui_mock/render_mockup.py`(**均已删除**),保留 `NN_说明.md` 规格与原始参考图;`NN_说明.md` 升格为唯一设计基准(P1 照参数表翻译代码,P2 出图对照参数表 + 原图);`UI_自动化测试流程.md` 门禁编号同步改为 P2/P3 |
| 2026-09-14 | 运行记录/自检记录页 + 待机屏落地后回填:C3 字符集 111→122 字(217 字形,补输/入/错/误/上/电/重/芯/片/异/常——**故障描述串在非 UI 源码中 extract_cn 扫不到,须手动补字**);新文案走 P4 字体重生成 + `check_content_pages.py` pwc 态参考更新(密码错误提示);池基线 4784→5440 / 往返 4864→5520(+656B = 待机模块常驻屏+容器,见两测试脚本头部注记) |
| 2026-10-25 | 字库扩充(页面扩充规划预置字):C3 字符集 122→179 字(217→274 字形;上次入表后 2026-10-15 字体瘦身实测 119 字/214 字形未回填本表,本次一并校正)。+60 字取自 `docs/UI设计/页面补齐规划.md`、`docs/UI设计/页面扩充详细方案.md` 的页面显示串(段/投/延/零/频/荷/闸/跳/低/过/Ⅰ/Ⅱ/Ⅲ 等 + 年/月/分/秒/分合/已请求/确认/取消/越界用字);源码未用期间 font-charset 记 [WARN] 属预期,批 2 页面接线后自然转"在用"。顺带修复 `make_font.py` 两处缺陷:补回字形 cmap 条目被宽稀疏 range 吞掉(Ⅰ 下探起点 0x2160 → ▶ 全变方框,A/B 同树实测)与 `verify_coverage()` 非首命中判定;菜单 8 状态 + 内容页 11 页黄金参考逐字节不变;ROM +1,528 B、RAM 0。详见 `docs/UI设计/UI_中文字体生成与配置.md` §4 与文末事故记录 |
| 2026-10-28 | UI 补齐批接线(单写者):记录 5 页 + 运行报告六叶在 `ui_menu_tree.txt` 加 ` #page=` 并重跑 `tools/menu_gen/gen_menu.py`(绑定叶 22→28、`UI_PAGE_MAP_COUNT` 22→28,节点 42 / 叶 33 不变)、6 个页面 `.c` 双端注册;C3 字库链重跑 185→218 字(280→313 字形,新增 33 字取自六页新文案(含运行报告补「计数可信」行用的「可」字);本行旧数 183/278 系 2026-10-26 之后未回填,改前实测 185 字/280 字形);`check_content_pages.py` 内容页黄金 53→59 页;ROM/RAM 增量待 Lead `@build` 后按 `.map` 实测回填 |
+9 -4
View File
@@ -26,7 +26,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
| 步 | 脚本/命令 | 门禁内容 | 预期输出 |
|---|---|---|---|
| 1 | `simulator/tests/check_menu_rows.py` | 菜单 8 状态:选中行白带 / 非选行黑底白字 / 框体 1px 边框 / 往返像素一致(MENU-STATE-03==MENU-STATE-01、MENU-STATE-06==MENU-STATE-01、MENU-STATE-07==MENU-STATE-02)+ MENU-STATE-00 池基线 | `PASS: 8 状态全部断言通过(8 图,池基线 5368 B)` |
| 2 | `simulator/tests/check_content_pages.py` | ① 文本级断言(字形模板匹配,310 条,独立于 `ref/`)→ ② 53 页截图与 `ref/` 黄金参考**逐字节**比对 + 开页-关页往返池水位 | `PASS: 53 内容页 + 往返池水位全部通过`(文本断言先于像素比对,失败即中止) |
| 2 | `simulator/tests/check_content_pages.py` | ① 文本级断言(字形模板匹配,正向 425 条 + 反向 36 条,独立于 `ref/`)→ ② 60 页截图与 `ref/` 黄金参考**逐字节**比对 + 开页-关页往返池水位 | `PASS: 60 内容页 + 往返池水位全部通过`(文本断言先于像素比对,失败即中止) |
| 3 | `keil-build` skill(`keil_build.py`) | MCU 端编译(UI 源码双端共用,改一端必须过另一端) | 退出码 0 = BUILD_OK |
| 4 | `scripts/check_coding_standard.py` | 代码规范 V1.0 机械检查 | PASS |
@@ -37,6 +37,9 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
> **先于**像素比对运行,失败即中止(不误刷参考)。文本断言覆盖确定文案,像素参考仍负责几何/样式/
> 光标反显等其余视觉。规模与覆盖面(2026-10-26 实跑 `check_content_pages.py` 取数):文本断言 **310 条**、覆盖当时 40 页中的
> **37 页**——`pwd` / `pwe` / `pwc` 三张密码态只进像素比对、未登记文本断言,改这几页的文案没有文本层兜底。
> 2026-10-28 再取数(接线道,`PAGES` 60 项时实测):正向 **425 条** / 反向 **36 条**、覆盖 60 页中的
> **57 页**(仍缺那三张密码态)。更正留痕:上一句登记的是「2026-10-26 实跑取数 310 条」,而当时脚本
> 的真值是**正向 380 / 反向 29**——历史行按当时冻结不改数,差值只在这里说明,避免下一个人再抄一遍旧数。
**退出码约定**:两个脚本均为 0=PASS / 1=断言失败 / 2=环境错误(exe 缺失、参考缺失)。
失败时脚本打印差异明细(文本断言未命中项 / ink runs 对照 / 像素差数),内容页脚本保留现场截图于临时目录并提示路径。
@@ -49,7 +52,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
| `POOL_AFTER_ROUNDTRIP` | check_content_pages.py | **5448 B** | 开页-关页往返后水位 = 基线 + 一次性残留 80 B |
> 水位历史:4784 →(2026-09-14 待机模块常驻 +656)5440 / 5520 →(2026-10-11 裁剪 LVGL 控件类 −72)5368 / 5448。
> 后一次漂移已核实为**有意且更优**:像素逐字节未变(**裁剪当时黄金参考只有 11 页**,在裁剪**前**生成、裁剪后全部一致;该集合现已扩至 53 页),
> 后一次漂移已核实为**有意且更优**:像素逐字节未变(**裁剪当时黄金参考只有 11 页**,在裁剪**前**生成、裁剪后全部一致;该集合现已扩至 60 页),
> 且一次性残留仍是 80 B(5448 − 5368)→ 泄漏特征未变,只是 `lv_theme_apply` 不再为已不存在的控件类登记样式条目。
**漂移处理**:菜单/页面结构或样式变更导致门禁失败时,先确认新值合理(残留分解见
@@ -58,7 +61,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
## 四、黄金参考(入库)与目检 PNG(本地产物)
`simulator/tests/ref/*.bin`(像素黄金参考,53 页 × 3200 B)**随仓库入库**;派生的 `.png`
`simulator/tests/ref/*.bin`(像素黄金参考,60 页 × 3200 B)**随仓库入库**;派生的 `.png`
目检图仍是本地产物(`.gitignore`)。入库的理由:比对是**逐字节**的,基线不入库时任何新克隆
或新工作树跑 `ui-golden` 都必然 FAIL(缺基准),这条门禁就只在"有老副本的机器"上真实存在。
可复现性实测(2026-10-22):两份各自独立构建的 `lvgl_sim`(不同构建目录、相隔 11 天的代码)
@@ -145,7 +148,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
### 7.3 用法与门禁档位
```powershell
# 认屏快检:53 张黄金参考(+ 若有台架留档帧),秒级,不需要构建产物
# 认屏快检:60 张黄金参考(+ 若有台架留档帧),秒级,不需要构建产物
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --selftest-quick
# 完整自检:再加全绑定页闭环导航(需模拟器可执行文件,约 30 s)
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --selftest
@@ -223,3 +226,5 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
| 2026-10-26 | **内容页页数口径统一为 27**:正文里残留的「11 页 / 其余 10 页 / 18 张」按现状改正(判据本体 = `simulator/tests/ref/shot_*.bin` 入库实数 27 个、`check_content_pages.py` 的 `PAGES` 27 项,含整定 9 态);下方变更记录里的「11 页」是当时事实,按历史冻结不动。同类陈述同步在 `测试开发标准流程.md`、`自动化测试流程.md`、`主机单测覆盖率口径.md`、`内容页架构.md`、`simulator/tests/README.md`、`scripts/board_ui_nav.py` 改正 |
| 2026-10-26 | **文本级断言规模口径修正**:门禁表里的「50 条」是 2026-09-10 首版数字,现值 **242 条 / 覆盖 27 页中的 24 页**(`pwd` `pwe` `pwc` 三张密码态只进像素比对、未登记文本断言);正文的文本层说明补写了覆盖面与这条盲区。下方变更记录里的 50 条属历史,不动 |
| 2026-10-26 | **内容页黄金参考下限 27 → 40 页**(UI 三页落地,机器实测:`simulator/tests/ref/` 入库 `shot_*.bin` 40 个、`check_content_pages.py` 的 `PAGES` 40 项);文本断言随之 **242 → 310 条**、覆盖 **40 页中的 37 页**(`pwd` `pwe` `pwc` 三张密码态仍只进像素比对、无文本断言);27 张旧参考逐字节未变,往返池 5448 B 与菜单常驻堆 5368 B 均未变,字库仍 183 字。本文其余各处与 `AGENTS.md`、`docs/门禁说明/`、`simulator/tests/README.md`、`docs/测试说明/` 三篇同批改齐;**历史行里的 27 / 11 一律保留**(当时下限就是那个数,不改数造连续性)|
| 2026-10-28 | **内容页黄金参考 53 → 60 页**(UI 补齐收口批接线:记录 5 页 accident / oper / alarm / start / yk 与运行报告 runreport 两页,运行报告 13 行分 2 页故第 2 页单独拍一张 `shot_runreport_p2.bin` 钉「第 2 页,共 2 页」与 104 三枚计数,所以是 60 而非 59)。判据实测:`simulator/tests/ref/` 60 张 `shot_*.bin`、`git status --porcelain` 恰好 7 个 `??`、`git diff --name-only -- simulator/tests/ref` 为空 ⇒ **存量 53 张逐字节零漂移**(本批字库两轮共 +33 字、185→218 字 / 280→313 字形均未动既有字形,跑 `--update` 前后各测一次);文本断言 **425 正向 + 36 反向**、覆盖 60 页中的 57 页;`MENU_POOL_BASELINE` 5368 / `POOL_AFTER_ROUNDTRIP` 5448 **一字未动**(往返实测仍 5448 B) |
| 2026-10-28 | `check_content_pages.py` 新增 **`FRESH_CWD`**(记录 5 页各在**独立空目录**里跑,其余 55 页环境不变):模拟器把「人工操作留痕」当真记录写**当前工作目录**的 `sim_oper.log`(`simulator/main.c` 的 `sim_post_oper` → `syslog_post(SYSLOG_OPER, ...)`),60 页共用一个 tmp 时 `clock_save` / `netcfg_save` / `sparam_save` 已写满 3 条(192 B)→ **操作记录页拍不到空态**。这不是判据问题而是环境被前面的写路径污染,故隔离环境、不改页面也不改断言。反向断言同时补两组互钉:运行报告第 1 页不许出现「发送帧数」、第 2 页不许出现「上电次数」;五个记录页不许出现 SOE 假记录的时标串 |
+2 -1
View File
@@ -38,7 +38,7 @@ MCU **无物理屏幕**:LVGL 做 160×160 **1bpp 单色离屏渲染**,帧缓
| LVGL 内存池 | 16 KB(`LV_MEM_SIZE`,2026-10-15 由 40 KB 收缩;实测峰值 6,568 B = 池的 40%) | `Lib/lv_conf.h` |
| 刷新周期 | 10 ms(`ui_port_step(10)` + `osDelay(10)`) | `ui_task.c` |
| 推流端口 | 7003(TCP,与 DTU-RemoteLCD 客户端对齐) | `ui_net_sink.h` |
| 默认字体 | `ui_font_cn_12`(12px 1bpp,183 汉字/符号 + ASCII 0x20–0x7E,共 278 字形) | `Lib/lv_conf.h` |
| 默认字体 | `ui_font_cn_12`(12px 1bpp,218 汉字/符号 + ASCII 0x20–0x7E,共 313 字形) | `Lib/lv_conf.h` |
| uiTask 栈 | 16384 words(BelowNormal) | `Src/freertos.c` |
### 1.4 硬约束(改 UI 必须遵守)
@@ -309,3 +309,4 @@ ENTER/→ 进子框:
| 2026-09-14 | 运行记录/自检记录内容页 + 待机显示模块:新增 `App/log/sys_log`(定长 64B 文本记录引擎,MCU 落 NAND `/log/run.log`、`/log/selftest.log`,FTP 可直下)+ 页面插件 `ui_page_runlog` / `ui_page_selftest`(动态列表:count_cb + refresh,每条 2 行时间戳/描述)+ `ui_standby`(空闲超时自动切待机屏,仅确认键回菜单);密码页错误提示"密码输入错误"+清空重输;字体 111→122 字(217 字形);详见 `docs/子系统设计/运行与自检记录设计说明.md` |
| 2026-10-25 | **F3 推流心跳边界(§5.8)**:`ui_net_sink_set_beat_cb()` 回调注入,accept/recv_nb/send/close/重建三件套返回处喂 UI 心跳(2026-10-25 大窗 bit4 8 连击实证:单轮多慢往返之和串成 800ms 缺席);往返语义不改(上界归 E-27/E-28);未注册 = 零行为变化(模拟器/黄金回归形态);新增 `test/host/ui_sink/` 主机套件 17 断言 |
| 2026-10-25 | 字库扩充(页面扩充规划预置字 +60,含罗马数字 Ⅰ/Ⅱ/Ⅲ):默认字体升至 179 字符/274 字形,像素基线不变,ROM +1,528 B、RAM 0;修复生成器 `make_font.py` 的 cmap 插入顺序缺陷——LVGL `get_glyph_dsc_id()` 线性扫描首个包含即返回,补回字形(▶)单码位条目被下探后的宽稀疏 range 吞掉即全渲染方框,现按首命中语义插位/守卫/校验(详见 `docs/UI设计/UI_中文字体生成与配置.md` 文末事故记录) |
| 2026-10-28 | UI 补齐批接线(单写者):事故/操作/保护告警/保护启动/遥控/运行报告六叶绑定内容页(生成物 `UI_PAGE_MAP_COUNT` 22→28,节点 42 / 叶 33 不变)+ 6 个页面 `.c` 双端注册;默认字体 185 字符/280 字形 → 218 字符/313 字形(+33 字,§1 概况表"默认字体"行同步,旧数 183/278 系未回填);内容页像素黄金参考 53 → 59 页;ROM/RAM 增量待 `@build` 后按 `.map` 实测回填 |
+1 -1
View File
@@ -453,7 +453,7 @@ extern const content_page_def_t ui_page_device_info_desc; /* 描述符(Flash
## 八、验证与回归
- **门禁**(`ui-verify` skill / `UI_自动化测试流程.md`):
0) 模拟器构建 0 警告 → 1) 菜单 8 状态像素回归 + 池基线 → 2) 内容页文本断言 + 53 页黄金参考逐字节比对
0) 模拟器构建 0 警告 → 1) 菜单 8 状态像素回归 + 池基线 → 2) 内容页文本断言 + 60 页黄金参考逐字节比对
(网口设置 4 态 + 密码页 4 态等)+ 开页-关页往返水位 → 3) Keil 构建 0 错 0 警 → 4) 代码规范检查
- **门禁常量**(脚本头部):`MENU_POOL_BASELINE = 5368 B`、`POOL_AFTER_ROUNDTRIP = 5448 B`
- **失败处置**:像素不一致 = 代码 bug(修代码,**禁止**刷参考掩盖);**有意**改视觉 →
+1 -1
View File
@@ -792,7 +792,7 @@ ESC/LEFT : d>0 → menu_back() (根框 d=0 不响
1. 本 LVGL v9.3 的 `lv_text_get_width(txt, length, font, letter_space)` **length=0 时返回 0**(不是"整串");必须传 `strlen`——否则框宽计算全 0(根框退化 8 px)。
2. 无头模式**不得**调 `lv_timer_handler()` / `lv_refr_now()`:I1 + `LV_DISPLAY_RENDER_MODE_FULL` 全屏刷新会进渲染死循环(截图因此走 `lv_snapshot`);`--keys` 注键是同步处理,无需驱动帧。
3. 选中行**保留 ▶**(随反色变黑):参考图 02/04 原图即"选中行箭头仍在、仅随反色变黑",勿实现成"选中隐箭头"(§4.4)。
4. 字体缺字形 = 方框:菜单树新增/改名的汉字必须同步加入字符集 `ui_cn_chars.txt`(当前 122 唯一字)并重生成字体(重跑 `extract_cn.py` + `make_font.py`),否则新字显示为方框(流程见 `UI_中文字体生成与配置.md`)。
4. 字体缺字形 = 方框:菜单树新增/改名的汉字必须同步加入字符集 `ui_cn_chars.txt`(当前 218 唯一字,2026-10-28 实测)并重生成字体(重跑 `extract_cn.py` + `make_font.py`),否则新字显示为方框(流程见 `UI_中文字体生成与配置.md`)。
5. **参考图保真度**:参考图为手工 mockup,4 个样本(子框顶位置)不满足单一公式;实现采用自洽规则(顶对齐/底对齐上移),实测与参考图偏差:顶位置 2/4/6/1 px(三遥/装置维护/通讯参数/记录查询),框宽 2/8/0/2 px(4字+箭头/4字/3字/2字+箭头)。两端极例(三遥、记录查询)精确吻合;统一规则优于逐屏特调,偏差范围内不影响识读与操作。
6. 装饰"浅 V"两腿线宽必须 3(水平线 2):1bpp 下细斜线边缘被阈值吃掉,腿不粗于水平线即消失;且依赖 `LV_DRAW_SW_COMPLEX=1`(见 `UI_设计架构.md` §1.4 约束 7)。
+1 -1
View File
@@ -624,7 +624,7 @@ SNTP 客户端 ──────→ 批4 SNTP设置
| 4 | 无源点显示 `--` | 遥信量无效点、直流量直流通道 |
| 5 | 定值整定闭环 | 改 → 保存 → 重启 → 值保持 + 校验和自检通过 + 主站 C_RD 一致。**2026-10-26 半收口**:模拟器侧「改 → 保存 → `OK` → 回首屏新值已在帧里」与「越界被拒、值不落盘」已由像素 + 文本断言覆盖(`sparam_save` / `sparam_landed` / `sparam_oob`);**重启保持与 C_RD 一致只能上板**(模拟器无 NAND)。另注意 40 项里 **13 项 `comm_addr = 0`**(投退、返回系数、过频/低频段、全局软压板)主站不可寻址,不能拿 C_RD 当它们的判据 |
| 6 | 分层门禁无新增 | `check_layer_deps.py` 退出码 0,基线 6 → 3。**现状:3**(记录 reader 已削 3 条;写路径走注入式 ops 函数表,未新增 include,见 `docs/UI设计/UI_数据供给设计说明.md` §6.2) |
| 7 | 像素回归稳定 | `ui-golden` 连续两次零差异。**已验(2026-10-26)**:27 页连跑两次逐字节一致——**该下限此后已扩至 53 页**(新增 clock / reset / clear 系列 13 张),53 页上的双次逐字节一致需按同口径重跑一次再回填本行 |
| 7 | 像素回归稳定 | `ui-golden` 连续两次零差异。**已验(2026-10-26)**:27 页连跑两次逐字节一致——**该下限此后已扩至 60 页**(新增 clock / reset / clear 系列 13 张,其后 47→53→60),60 页上的双次逐字节一致需按同口径重跑一次再回填本行 |
| 8 | 每个新页有 golden 参考 | `simulator/tests/ref/` 新增对应 `.bin`。**整定 4 页已有 9 张**(含保存/越界/落定/回绕各态);参考图入库,改它 = 改判据,须逐页过目 |
---
+11 -9
View File
@@ -27,7 +27,7 @@
### 2.1 规模
> ⚠ **本表是 2026-10-23 立项当天快照**(节点 42 / 有内容页叶子 6 / 空叶子 27 / 黄金参考 11 份均为当日实数,按"完成即冻结"不回改)。
> 页面扩充落地后现值已变——黄金参考现为 53 份(`simulator/tests/ref/` 入库的 `shot_*.bin` 实数),现状口径见
> 页面扩充落地后现值已变——黄金参考现为 60 份(`simulator/tests/ref/` 入库的 `shot_*.bin` 实数,2026-10-28 记录 5 页与运行报告页落地 +7 张),现状口径见
> `docs/UI设计/页面扩充详细方案.md` 与 `docs/UI设计/UI_数据供给设计说明.md`。
| 项 | 数 |
@@ -70,8 +70,8 @@
| 14 | 定值(查看) | 列表(18 项 / 3 页) | 同 9 | ✅(需快照层) |
| 15 | 控制字(查看) | 列表(4 项) | 同 10 | ✅(需快照层) |
| 16 | 软压板(查看) | 列表(10 项 / 2 页) | 同 11 | ✅(需快照层) |
| 18 | 遥测死区 | 可编辑列表(4 项) | `[run_par]` 9 键死区 | ✅ 数据层已落地(卡 10),**页面未做** |
| 19 | 遥测系数 | 可编辑列表(9 项) | `[adc_cal]` 的 k / b | ✅ 数据层已落地(卡 2),**页面未做** |
| 18 | 遥测死区 | 可编辑列表(4 项) | `[run_par]` 9 键死区 | ✅ 已落地(ui_page_deadband.c,2026-10-27) |
| 19 | 遥测系数 | 可编辑列表(9 项) | `[adc_cal]` 的 k / b | ✅ 已落地(ui_page_calib.c,2026-10-27) |
| 20 | 遥信类型 | 可编辑列表 | 开入量 | ❌ 开入未实现 |
| 21 | 遥信防抖 | 可编辑列表(1 项) | 运行参数 0x8030 | ❌ 同上 |
| 22 | 双点遥信 | 可编辑列表 | 开入量 | ❌ 同上 |
@@ -82,15 +82,17 @@
| 29 | 通讯设置 | 可编辑列表(4~6 项) | 104 公共地址/端口/主站(当前固定) | 🔶 需 `comm_cfg` |
| 31 | SNTP设置 | 可编辑列表(3 项) | SNTP 客户端 | ❌ 未实现(产品口径亦未定) |
| 33 | SOE记录 | 动态列表(每记录 2 行) | `/log/soe.log` 二进制 64B | ✅ 已落地(`ui_page_soe.c`) |
| 34 | 事故记录 | 动态列表 | 跳闸记录 | ❌ 记录类型未实现 |
| 35 | 操作记录 | 动态列表 | 操作记录 | ❌ 同上 |
| 36 | 保护告警 | 动态列表 | 告警记录 | ❌ 同上 |
| 37 | 保护启动 | 动态列表 | 启动记录 | ❌ 同上 |
| 38 | 遥控记录 | 动态列表 | 遥控记录 | ❌ 同上 |
| 41 | 运行报告 | 信息页(统计) | 上电次数/运行时长/复位原因/通信统计 | ❌ 计数器未实现 |
| 34 | 事故记录 | 动态列表 | /log/accid.log(SYSLOG_ACCIDENT,写入点 protect_task.c) | ✅ 已落地(ui_page_accident.c,2026-10-28) |
| 35 | 操作记录 | 动态列表 | /log/oper.log(SYSLOG_OPER,写入点 4 处:定值保存 / 复归 / 对时 / 清除记录) | ✅ 已落地(ui_page_oper.c,2026-10-28) |
| 36 | 保护告警 | 动态列表 | /log/alarm.log(SYSLOG_ALARM,asserted 且跳闸投退=0) | ✅ 已落地(ui_page_alarm.c,2026-10-28) |
| 37 | 保护启动 | 动态列表 | /log/start.log(SYSLOG_START,picked 上升沿) | ✅ 已落地(ui_page_start.c,2026-10-28) |
| 38 | 遥控记录 | 动态列表 | /log/yk.log(SYSLOG_YK,写入点 iec104_pts.c 遥控段) | ✅ 已落地(ui_page_yk.c,2026-10-28) |
| 41 | 运行报告 | 列表页(12 行 / 2 页,四数逐个挂范围标签) | boot_stats(上电次数 + 复位原因)+ 四个 104 观测计数 + uptime_s,经 ui_data info 帧下发 | ✅ 已落地(ui_page_runreport.c,2026-10-28;跨开机累计按裁定不做) |
**统计(2026-10-25 复核)**:本表 27 叶中 **6 叶已落地**(遥信量 / 查看 4 页 / SOE),剩 21 叶 = 数据现成 **8** 项(整定 4 + 时钟 + 复归 + 死区 + 系数)· 需新数据层 **2** 项(清除记录 / 通讯设置)· 数据源不存在 **11** 项(遥信 3 + 手动录波 + SNTP + 记录 5 + 运行报告)。**分批与 DoD 见 `docs/任务规划/UI补齐.md`**——本表只讲逐页形态与数据源,不重复排期。
**2026-10-28 复核**:本表 27 叶中 **22 叶已落地**(本批 +6:记录 5 页与运行报告,见 docs/任务规划/UI补齐.md §2 与 docs/任务规划/登记簿.md §7);未落地的 5 叶 = 遥信类型 / 遥信防抖 / 双点遥信(无开入硬件)+ 手动录波(无录波模块)+ SNTP设置(产品口径未定),取舍与重开条件见 docs/任务规划/UI补齐.md §5。
---
## 3. 三个前置能力(不先做,页面只能显示假数据)
+15 -15
View File
@@ -1,6 +1,6 @@
# 任务规划
> **现在只做 UI 补齐。剩余两项按表序单道推进:记录 5 页 → 运行报告(通讯设置已入库)。**
> **UI 补齐执行清单已于 2026-10-28 清空(记录 5 页 + 运行报告页落地)。** 下一顺位 = net 层跨上下文收口,开工待用户点头;顺序权威见 docs/任务规划/README.md §2.0。
> 详细任务与验收见 `UI补齐.md`;UI 完成后的第一项是 net 层跨上下文收口。
## 怎么用这份规划
@@ -30,17 +30,17 @@
---
## 1. 当前执行:UI 补齐
## 1. UI 补齐(执行清单已于 2026-10-28 清空)
菜单树共 33 叶(节点行合计 42):按行内 `#page=` 实测**已绑 22 叶、未绑 11 叶**(2026-10-27 复核,
判定规则与重跑命令见 `docs/任务规划/UI补齐.md` §1「叶数判定与复核」)。未绑里 **6 叶纳入当前执行**
(记录 5 + 运行报告 1),另外 5 叶因缺少开入硬件、录波模块或 SNTP 产品定义而不做。
装置维护 3 页、遥测死区与系数 2 页、通讯设置页已于 2026-10-27 陆续落地入库。唯一执行清单见 `UI补齐.md`。
菜单树共 33 叶(节点行合计 42):按行内 #page= 实测**已绑 28 叶、未绑 5 叶**(2026-10-28 复核,
判定规则与重跑命令见 docs/任务规划/UI补齐.md §1「叶数判定与复核」)。未绑的 5 叶因缺少开入硬件、
录波模块或 SNTP 产品定义而不做(原因与重开条件见 docs/任务规划/UI补齐.md §5)。
| 顺序 | 要做的事 | 交付结果 |
|---|---|---|
| 1 | 记录 5 页 | 事故、操作、保护告警、保护启动、遥控记录有写入方并可查看 |
| 2 | 运行报告 | 上电次数、运行时长、复位原因、104 统计 |
**UI 补齐执行清单已于 2026-10-28 清空**:记录 5 页(事故 / 操作 / 保护告警 / 保护启动 / 遥控)与
运行报告页同日落地并绑页,内容页黄金参考 53 → 60 页(runreport 分 2 页,第 2 页单独一张)。
上板判据(真记录翻页、掉电保持、清除后归零、boot_count 自增、RESTARTED、rst_cause=IWDG、conn_up +1)
已登记登记簿 §7「UI 六页真机判据」,六页文件头各留「台架待补」段;模拟器差距见
docs/测试说明/模拟器差距清单.md §2.3「开机账本 boot_stats」一行。
**执行纪律:单道串行。** 菜单树与页面注册表是生成物,字库也是整文件生成物;
不要同时开多条 UI 页面分支。上板验证可累积成一批,但保存、重启、主站读回等判据不能删除。
@@ -55,10 +55,10 @@
| 顺序 | 工作 | 当前状态 | 开始或切换条件 |
|---|---|---|---|
| **1** | **UI 补齐** | **当前执行** | 已开始;剩余 3 项按 §1 的 1→3 顺序推进(原第 1、2 两项已落地) |
| **2** | **net 层跨上下文收口** | 下一步 | UI 当前清单完成后;裸指针收口与 reconcile 突发饿死 uiTask 同批评估 |
| **1** | **UI 补齐** | **清单已清空(2026-10-28)** | 记录 5 页与运行报告页已落地并绑页;余下 5 叶属 §5「当前不做」,重开条件见 docs/任务规划/UI补齐.md §5;上板判据见 docs/任务规划/登记簿.md §7 |
| **2** | **net 层跨上下文收口** | **下一顺位(未开工)** | UI 清单已清空,切换条件已满足;**开工需用户点头**——换主线是产品决策,不由本批顺带做掉 |
| **3** | 其余结构与可靠性评估 | 排队 | net 收口后;逐项见 `登记簿.md`,观察项不为了“清清单”而强做 |
| **4** | 数据可信剩余三项 | 等待台架或外部资源 | 已知电压注入 → 端子变比 → 标准源两点标定;资源到位可插入优先处理 |
| **4** | 数据可信剩余两项 | 等待外部资源 | 端子/子板变比确认 → 标准源两点标定(已知电压注入已于 2026-10-27 台架闭环并销项);资源到位可插入优先处理 |
| **5** | 标准源送检与第三方 104 主站验收 | 等待标定完成 | 两点标定完成且保护 VALID 已置位;送检窗口前 2 日冻结特性 |
| **6** | 保护元件与采集增强 | 等待标准源或硬件改版 | 保护先解除未标定闭锁;三相同时刻类功能等 V0.2 硬件 |
| **7** | 验证窗口事项 | 逢条件顺带 | CI runner、PC peer、CH340、负向故障注入条件到位时执行 |
@@ -68,7 +68,7 @@
- **UI**:写路径、整定 4 页、装置维护 3 页与遥测死区/系数 2 页已收口(含上板判据与真机回读);
菜单树、页面注册表与字库都是生成物,同刻只允许一条道写。
- **送检**:已知电压注入 → 端子变比确认 → 标准源两点标定 → 保护解除闭锁 → 送检。
- **送检**:已知电压注入(✅ 2026-10-27 闭环)→ 端子/子板变比确认 → 标准源两点标定 → 保护解除闭锁 → 送检。
- **保护扩展**:标准源未到位前不新增无法验证的判据;跨转换器相位、功率、对称分量类
功能必须等 V0.2 硬件。
- **结构债**:UI 完成后先做 net 收口;RS-485 白名单、内存优化、仓库体积等观察项不抢占
@@ -82,7 +82,7 @@
历史由 `git log` 保留。
2. **当前任务只改 `UI补齐.md`,后续事项只改 `登记簿.md`**;顺序变化才改本文件 §2。
3. `数据可信.md` 的 §2、§4、§7~§10 仍被代码头注释引用为设计依据,不能按“已完成”
删掉;其待办只认 §5 的三项。
删掉;其待办只认 §5 的两项。
4. `测试与架构专项.md` 的断言与体积门禁章节仍是代码和门禁的规格锚点,即使事项已完成
也不能删;当前未闭环的只有 RS-485 侧采集链路测试约束。
5. 任务分支不直接修改 `docs/任务规划/**`;状态更新与销项由主工作树统一处理。
+20 -22
View File
@@ -1,34 +1,34 @@
# 当前任务:UI 补齐
> **从第 1 项「记录 5 页」开始,按表序单道串行推进。**(通讯设置页已于 2026-10-27 入库)
> 本文件是当前唯一执行清单;全项目顺序见 `docs/任务规划/README.md` §2。
> **执行清单已清空(2026-10-28)**:记录 5 页与运行报告页已落地、绑页并纳入像素黄金回归。
> 本文件保留为 UI 补齐的**范围与判据口径**(§1 叶数、§4 每页统一动作、§5 不做的取舍);
> 下一顺位见 docs/任务规划/README.md §2.0(换主线待用户点头),上板待复核项见 docs/任务规划/登记簿.md §7。
## 1. 目标与范围
菜单树共 **33 叶**(节点行合计 42,缩进即层级):按行内 `#page=` 实测**已绑 22 叶、未绑 11 叶**,
页面映射表 `UI_PAGE_MAP_COUNT` = 22(与已绑叶数一致)。未绑 11 叶 = 下方第 1~2 项的 **6 叶**
+ §5 明确不做的 **5 叶**(遥信 3 / 手动录波 1 / SNTP 1),与分类表逐项对得上(6 + 5 = 11)。
菜单树共 **33 叶**(节点行合计 42,缩进即层级):按行内 `#page=` 实测**已绑 28 叶、未绑 5 叶**,
页面映射表 `UI_PAGE_MAP_COUNT` = 28(与已绑叶数一致)。未绑 5 叶 = §5 明确不做的 **5 叶**
(遥信 3 / 手动录波 1 / SNTP 1),与下面分类表逐项对得上;2026-10-28 记录 5 页与运行报告页
落地后,原「需补配置或写入方」的 6 叶缺口清零并按销项删行(该行内容见本节末与 §3)。
| 分类 | 数量 | 当前怎么处理 |
|---|---:|---|
| 需补配置或写入方 | 6 | 当前执行:记录 5 + 运行报告 1(即下方第 1~2 项) |
| 无开入硬件 | 3 | 不做:遥信类型、遥信防抖、双点遥信 |
| 缺独立模块或产品定义 | 2 | 不做:手动录波、SNTP 设置 |
现有基础:`ui_w_editor` / `ui_w_setlist` / `ui_page_action` 已就绪;`ui_data` 已扩到**四通道**
(rt / par / info + 遥测死区与系数用的第四张注入表);像素黄金用例与字符集门禁已存在,内容页黄金
现有 **53 页**(菜单 8 状态另计)。**装置维护 3 页与遥测死区/系数 2 页已把这套基础接上了真实消费者,
剩余两项继续用它,不另发明一套机制。**
现有 **60 页**(菜单 8 状态另计)。**装置维护 3 页、遥测死区/系数 2 页、通讯设置页、记录 5 页与
运行报告页都是把这套基础接上真实消费者做出来的,不另发明一套机制。**
逐页形态见 `docs/UI设计/页面补齐规划.md`;数据契约见
`docs/UI设计/UI_数据供给设计说明.md`。本文件只维护执行顺序和完成判据。
`docs/UI设计/UI_数据供给设计说明.md`。本文件保留范围、完成判据与不做的取舍口径(执行清单已于 2026-10-28 清空)。
### 叶数判定与复核(2026-10-27 实测)
### 叶数判定与复核(2026-10-28 复核)
1. **节点行** = `ui_menu_tree.txt` 里非空、非 `#` 开头的行(当前 **42** 行,含根「主界面」)。
2. **缩进即层级**(每级 2 空格;Tab 会被 `gen_menu.py` 直接拒绝):某节点行之后再没有更深缩进的行 = **叶**
(当前 **33** 叶);有更深缩进后继者 = 菜单节点(当前 **9** 个)。等价于生成物口径 `ui_menu_tab_has_children(node) == false`。
3. **绑定**:叶行行尾带 ` #page=` = 已绑(当前 **22** 叶);不带的 = 未绑(当前 **11** 叶)。
3. **绑定**:叶行行尾带 ` #page=` = 已绑(当前 **28** 叶);不带的 = 未绑(当前 **5** 叶)。
复核命令(复用生成器自己的解析器 `tools/menu_gen/gen_menu.py` 的 `parse_tree`,不另写一套计数逻辑,免得与生成物脱钩):
@@ -36,11 +36,11 @@
& '.venv\Scripts\python.exe' -c "import io,sys; sys.path.insert(0,'tools/menu_gen'); import gen_menu as g; n,_=g.parse_tree(io.open('ui_menu_tree.txt',encoding='utf-8').read()); leaf=[i for i,x in enumerate(n) if all(y[0]!=i for y in n)]; b=sum(1 for i in leaf if n[i][4]); print('nodes=%d leaves=%d bound=%d unbound=%d' % (len(n),len(leaf),b,len(leaf)-b))"
```
输出 `nodes=42 leaves=33 bound=22 unbound=11`;交叉核对生成物:`ui_menu_tab.h` 的 `UI_MENU_TAB_COUNT` = 42(节点行数)、
`ui_page_registry.h` 的 `UI_PAGE_MAP_COUNT` = 22(已绑叶数)——一对 42、一对 22,与上面逐项对得上。
输出 `nodes=42 leaves=33 bound=28 unbound=5`;交叉核对生成物:`ui_menu_tab.h` 的 `UI_MENU_TAB_COUNT` = 42(节点行数)、
`ui_page_registry.h` 的 `UI_PAGE_MAP_COUNT` = 28(已绑叶数)——一对 42、一对 28,与上面逐项对得上。
三个已踩过的错算法:**把 42 个节点行当叶子**(多算 9 个菜单节点,得出「未绑 21」);**`grep -c '#page='` 得 23**(比已绑多 1:文件头注释第 5 行有 `#page=<模块名>` 示例字样,必须先剔注释行);**按叶子名去重得 29**(`参数`/`定值`/
`控制字`/`软压板` 在「整定」「查看」下各一份,4 对同名不能合并)。
`控制字`/`软压板` 在「整定」「查看」下各一份,4 对同名不能合并)。(21 / 23 / 29 三个错数是 2026-10-27 当时的实测产物,只用来说明错法,不代表现值。)
---
@@ -48,15 +48,13 @@
> 状态只在这里维护。完成一项就删除对应行,并同步调整后续顺序;不要在本文件留完成史。
| 顺序 | 任务 | 完成判据 | 主要写范围 | 状态 |
|---|---|---|---|---|
| **1** | **记录 5 页** | 事故、操作、保护告警、保护启动、遥控各有一个写入点和记录类型;可翻最近 20 条;空记录明确显示“无记录”;共用 reader | `App/log/`、`Drivers/BSP/UI/` | 未开始 |
| **2** | **运行报告** | 四个数的现成度已查实,判据按此写死:复位原因**解析有但 RCC 标志读后即清** ⇒ 需开机快照驻留;上电次数**无现成计数器** ⇒ 正源建议 SD2506 用户 SRAM(电池保持、零 NAND 磨损,文案写「自 RTC 电池周期起」,**禁写终身次数**);运行时长**用户裁定 2026-10-27 = 只报本次开机以来**(直接用现成 `uptime_s`,**不引** RTC 用户 SRAM 存秒数,UI 该栏必须**明写「本次开机以来」**免被误读为累计值);104 统计现有量全是控制量 ⇒ 需新增只读计数与 getter。落点 `App/util/boot_stats.{c,h}`(双端注册同笔),104 计数就近留 `iec104_serv.c` 不并进 | `App/util/`、`App/protocol/iec104/`、`Drivers/BSP/UI/` | 未开始(时长口径已定,其余三项待做) |
> 当前无待做项:最后两项(记录 5 页、运行报告)已于 2026-10-28 落地并销项删行。
> 下一批 UI 页面开工时在本节重新起表;完成一项就删除对应行,本文件不留完成史。
### 依赖关系
- 各项虽可独立开发,但当前仍按表序单道执行(菜单树、页面注册表与字库都是生成物)。
- 记录 5 页与运行报告先补真实写入方或计数器,再做页面;不允许用静态演示数据充数。
- **不允许用静态演示数据充数**:记录 5 页与运行报告页都是先有真实写入方 / 真实计数器(道F task-10、道G task-12),再补页面(2026-10-28 交付口径),下一批沿用。
- 历史教训(已完成的装置维护 3 页留下的口径,后续项沿用):**执行类页面不得做成「点了个按钮但没效果」**——清除记录必须按 `syslog_clear_state()` 出真反馈;遥测死区/系数两页的三态用
`run_par_dirty_peek()` 区分「已受理」与「已落盘」,且黄金必须出 WAIT 与 OK 两张(假件保留脏位、只由
headless pump 清),否则真机的 WAIT 态永远不会被像素回归覆盖。
@@ -68,8 +66,8 @@
| 页面 | 现有数据源 | 还缺什么 |
|---|---|---|
| 通讯设置 | 页面与六态黄金已随 `728d6067` 入库;`[comm]` 段与端口真源在 `App/protocol/iec104/iec104_comm.{c,h}` | 「改后重启即生效」真机判据、配置段数与键数上限核对(台架窗口统一补做并留证) |
| 记录 5 页 | SOE、自检、运行记录已有 reader 先例 | 五类写入方与记录类型 |
| 运行报告 | `uptime_s`(本次开机内)、复位原因解析(标志读后即清) | 上电次数正源、复位原因开机快照、104 只读计数(**跨开机累计不做**,用户已裁定只报本次开机) |
| 记录 5 页 | 五类记录 ID / 文件 / 写入点已齐(docs/任务规划/登记簿.md §7 与 App/log/README.md §五类记录);reader 注入两端已映射 7 个记录源 | 页面已交付;只剩真机判据(真记录翻页、掉电保持、清除后归零),见 docs/任务规划/登记簿.md §7 |
| 运行报告 | boot_stats(SD2506 用户 SRAM 上电次数 + 本次复位原因快照,道G task-12)、iec104_serv 四个只读观测计数、现成 uptime_s | 页面已交付;**跨开机累计不做**(用户裁定只报本次开机)。真机待复核 SRAM 自增与四态判定,见 docs/测试说明/模拟器差距清单.md §2.3 |
---
+47 -50
View File
@@ -1,22 +1,25 @@
# 数据可信(等待台架与外部资源)
> **只想知道要做什么:直接看 §5。** 当前只剩**两项**:卡 0b 端子变比(子板)→
> 卡 12 标准源两点标定。它们都等待台架或外部资源,
> **当前不占编码道;现在做 UI,见 `UI补齐.md`。**
> (卡 0 已知电压注入已于 2026-10-27 台架闭环、六项判据全 PASS,实测见
> `docs/硬件平台/ADC通道映射说明.md` §8.1;**该行按"口径锚点"保留并标 ✅,不按"完成即删"删行**,
> 原因见下条。)
> **只想知道要做什么:直接看 §5。** 当前只剩**两项**:端子/子板变比确认(等子板或原理图)→
> 两点标定(等标准源)。它们都等待台架或外部资源,
> **当前不占编码道。**「UI 补齐」执行清单已于 2026-10-28 清空(记录 5 页与运行报告页落地),
> 本道继续等外部资源;下一顺位见 docs/任务规划/README.md §2.0 顺序表(换主线待用户点头)。
> ("已知电压注入验证"已于 2026-10-27 台架闭环、六项判据全 PASS,实测记录与两项残留口径的属主是
> `docs/硬件平台/ADC通道映射说明.md` §8.1 与 `docs/测试说明/ADC前端注入验证流程.md` §6/§7 → 已按登记簿
> "完成即销项"纪律从 §5 表删行,任务卡编号族同步清退,见下条。)
>
> **本文同时是设计约束的归属文件,不是纯任务卡。** 排序只看
> `docs/任务规划/README.md` §2;后续事项统一索引在 `登记簿.md` §7。
> ⚠ §2.1 / §2.3 / §2.6 / §4.1~§4.5 / §7 / §8 / §9 / §10 与卡 0 / 0b / 12 都被**代码头注释**引用为
> 口径出处(`adc_cal.*` / `meas.*` / `cfg_file.*` / `prot_elm` / `protect_task.c` / `ui_data*`)——
> 它们是现行规范、不是"已完成记录",不要当历史删掉。**卡 0 已闭环但仍留在 §5 表里**,
> 就是因为 `App/task/adc_task.c` 的 v3.3 修订行与 `adc:` 行注释都按"卡 0"指称那行日志的用途;
> 删行会让代码头注释失去出处。上游分析见
> ⚠ §2.1 / §2.3 / §2.6 / §4.1~§4.5 / §7 / §8 / §9 / §10 都被**代码头注释**引用为口径出处(`adc_cal.*` / `meas.*` / `cfg_file.*` / `prot_elm` / `protect_task.c` / `ui_data*`)——
> 它们是现行规范、不是"已完成记录",不要当历史删掉。
> ⚠ **原任务卡编号(形态 = 中文「卡」+ 数字:0、0b、1~12 共 14 个)整族已于 2026-10-27 清退**
> (用户裁定:已完成内容销项删除、去除相关编号);代码头注释与文档里的引用全改成语义短语,
> **换算表见 `docs/编号规范.md` §9.3**——旧号永久作废、不得再指,也不得重新取走
> (销项后不留痕迹曾导致撞号,见 `docs/任务规划/README.md` §0)。
> 上游分析见
> `docs/问题记录/采集与数据处理短板评测.md`。
>
> **修订**:2026-10-23 建档。
> **修订**:2026-10-23 建档;2026-10-27 注入验证销项 + 任务卡号整族清退。
> ⚠ **保护现处于未标定闭锁态**:`protect_task.c:98` 要求 UA/UN/IA 的 `ADC_CAL_F_VALID`
> 全置位才走判据,而 VALID 只在标定写入 `[adc_cal]` 的 `valid` 位图后才置位
> (`adc_cal.c:338`)。用户裁定(2026-10-25)**保持闭锁到标准源到位**,不缩短解锁路径。
@@ -48,12 +51,12 @@
(拓扑图见 `docs/硬件平台/ADC通道映射说明.md` §7.1)。
- ✅ **量程口径(2026-10-25 定)**:`docs/硬件平台/ADC通道映射说明.md` §1/§7 统一为
"±5 V 满量程 = 10 V 跨度、LSB 152.59 µV"("±10 V" 仅作芯片可选档括注,本板 RANGE 接 GND 未用);
全仓搜 `±10 V` 无本板口径残留。分段链路口径(引脚侧已冻结 / ③ 已定 1:1 / 变比待卡 0b)
全仓搜 `±10 V` 无本板口径残留。分段链路口径(引脚侧已冻结 / ③ 已定 1:1 / 变比待"端子/子板变比确认")
见同文档 §7.1。
- ⚠ **上表的"板级系数"只到 ADC 引脚,不到端子**:③ 段已定 1:1,但端子到 `AINn` 之间还有一级
子板/端子板变比(④ 段),而**仓库里没有任何文档给出该变比**
(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图)。故
"端子二次值 = 码 × 上表系数"**不成立**,详见 §2.6 与卡 0b。
"端子二次值 = 码 × 上表系数"**不成立**,详见 §2.6 与 §5"端子/子板变比确认"。
### 2.3 三个必须同步重定的下游常数
@@ -79,12 +82,12 @@
> 这不否定本波价值——"码值 → 引脚电压"本身就是巨大进步(保护判据从"跟码值比"
> 变成"跟电压比")。但它决定 M4 的**承诺边界**:M4 承诺到"引脚电压",
> "端子二次值"要等卡 0b 拿到变比。
> "端子二次值"要等"端子/子板变比确认"拿到变比。
>
> 另一个必须查清的现象:2026-10-10 首帧读数 TPAFE 侧 `UA=11429 / UN=11454 / IA=11452`、
> STM32 侧 `UB=1018 / UC=1044 / IB=943 / IC=1069 / IN=1052`——**同片各通道几乎相同**,
> 而"1k 到地"在无输入时本应把节点拉到 0 V。首帧本就不是稳态值,不能据此定论,
> 但也不能当成"已正常"。**卡 0 的零点判据已查清(2026-10-27)**:8 路短接 AGND 后零点
> 但也不能当成"已正常"。**注入验证的零点判据已查清(2026-10-27)**:8 路短接 AGND 后零点
> 0~5 码(TPAFE ≤4.6 mV / STM32 ≤4.0 mV),远小于首帧的 ~1000——首帧是上电瞬态,
> 不能当零点用。另注:TPAFE ~11450 与 STM32 ~1000 是两个转换器**各自**的零位,不是同一问题。
@@ -96,11 +99,11 @@
| 里程碑 | 退出判据(全部满足才算完成) | 服务分类 | 状态(2026-10-25) |
|---|---|---|---|
| **M4 系数与量纲** | ① **至少 1 路电压通道经已知电压注入验证**(卡 0),斜率与理论 LSB 偏差 ≤2 %;② `adc_cal` 折算落地,采样环里是**引脚电压 V**而非码值(`eng=0`;若卡 0b 已给变比则直接到二次值 `eng=1`);③ 8 通道系数/零点可落盘、上电加载失败回退 ROM 默认;④ 三处下游常数按工程量重定并注明依据;⑤ "未标定 → 保护闭锁"生效;⑥ 量纲回归用例(不该动作时不动作)通过 | Standard | 🔶 **未收口**:①②③④⑥ 已达成(① 于 2026-10-27 台架实测闭环,UA 斜率偏差 −0.14 %,见 `docs/硬件平台/ADC通道映射说明.md` §8.1),**只剩 ⑤ 的台架面待卡 12**(需标准源置 `VALID` 才能验闭锁→解锁) |
| **M4 系数与量纲** | ① **至少 1 路电压通道经已知电压注入验证**,斜率与理论 LSB 偏差 ≤2 %;② `adc_cal` 折算落地,采样环里是**引脚电压 V**而非码值(`eng=0`;若变比确认已给变比则直接到二次值 `eng=1`);③ 8 通道系数/零点可落盘、上电加载失败回退 ROM 默认;④ 三处下游常数按工程量重定并注明依据;⑤ "未标定 → 保护闭锁"生效;⑥ 量纲回归用例(不该动作时不动作)通过 | Standard | 🔶 **未收口**:①②③④⑥ 已达成(① 于 2026-10-27 台架实测闭环,UA 斜率偏差 −0.14 %,见 `docs/硬件平台/ADC通道映射说明.md` §8.1),**只剩 ⑤ 的台架面待两点标定**(需标准源置 `VALID` 才能验闭锁→解锁) |
**M5 遥测链 / M6 运行参数与点表**:均已达成,口径沉淀在 `App/algo/meas.h`、`App/algo/run_par.h`
头注释与 §4.5;M5 的"104 上送值与**工程量**一致"仍挂卡 0b / 卡 12(卡 0 只证到"引脚电压"口径,
二次值要等 0b 的变比)。
头注释与 §4.5;M5 的"104 上送值与**工程量**一致"仍挂"端子/子板变比确认"与"两点标定"(注入验证只证到"引脚电压"口径,
二次值要等变比确认拿到变比)。
> **不进本波退出判据的两项增强**:谐波**方和根真有效值**(挂
> `docs/算法/继电保护功能复现规划.md` 「遥测谐波轨(可选)」)与快照**4 点平均平滑**——随谐波轨立项一起做;
@@ -215,43 +218,37 @@ typedef struct {
---
## 5. 任务卡(五字段;完成即销项删行,例外见状态图例)
## 5. 任务卡(完成即销项删行;标识列用语义短语,不配编号)
> 资源图例:🔴 台架(COM6/ST-LINK,`bench.lock` 独占)· 🟡 外部(标准源 / 子板原理图)· 🟢 纯软件。
> 状态:⬜ 未开始 · 🟦 进行中 · ✅ 已闭环(**仅限被代码头注释指称的卡,保留行不删**)。
> 状态:⬜ 未开始 · 🟦 进行中。**已闭环 = 直接删行**(2026-10-27 起取消"被代码注释指称就保留行"的
> 例外——引用侧已全部改成语义短语,删行不再会让任何注释失去出处)。
> **新条目一律用语义标识,不新增字母+数字编号**(规则见 `docs/任务规划/README.md` §0)。
> 序栏 0 / 0b 只为阅读顺序(补的是 §2.6 这一前置验证),1~12 的编号与外部引用保持不变。
> **顺序:0 ✅ → 0b → 12**。卡 0 已于 2026-10-27 台架闭环,是 M4 ①、卡 12 与 B10 送检的前置**已解除**;
> **下一步做卡 0b**(等子板实物或原理图)。
> **卡 0 的台架执行步骤**(注入点清单、期望码值、五步流程与现场记录表)见
> `docs/测试说明/ADC前端注入验证流程.md`——本表只写判据,不写怎么接表笔。
> 上面那种「卡」+ 数字的形态已整族清退(换算表 `docs/编号规范.md` §9.3),旧号永久作废、不得重新取走。
> **顺序:已知电压注入验证(✅ 已闭环 → 已删行)→ 端子/子板变比确认 → 两点标定**;注入验证是
> M4 ①、两点标定与 B10 送检的前置,**2026-10-27 已解除**;**下一步做变比确认**(等子板实物或原理图)。
> 已闭环那张卡的台架执行步骤(注入点清单、期望码值、五步流程与现场记录表)在
> `docs/测试说明/ADC前端注入验证流程.md`,实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1——
> 本表只写判据,不写怎么接表笔。
| 序 | 任务 | DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|---|---|---|---|---|---|---|
| **0** | **已知电压注入验证(首次功能级 ADC 验证)** | 在**可安全接触的最低一级**(ADC 引脚侧或端子侧,二选一并在证据里写明注入点)用板载 3.3 V 轨经电位器注入 **3 个直流点**(≈0.3 / 1.0 / 2.0 V),每点**同时**用万用表读注入点实际电压 + 读 `adc_input_raw()` 码值:① 三点线性拟合 **R² ≥ 0.999**;② 注入点在引脚侧时,斜率须与 §2.1 理论值(TPAFE 6553 码/V、STM32 1241 码/V)偏差 **≤2 %**;在端子侧时把斜率记为**实测变比**;③ 注入 0 V(短接 AGND)零点 \|码\| ≤ 30(TPAFE)/ ≤ 5(STM32),并解释首帧 ~1000 码的来源;④ **逐通道映射确认**:8 路电气量逐个注入,确认"注入哪一路、哪一路语义变化",语义与下标不符即映射错;⑤ TPAFE 侧原"BUSY 有脉冲"判据**改用固件帧计数**(注入前后 `tpafe5160_frame_seq()` 仍严格 1000 Hz 递增)——不需要示波器;⑥ 结论写回 `docs/硬件平台/ADC通道映射说明.md` §8,把"尚未执行"改为实测值 + 日期 | — | 🔴 + 万用表(**不需信号源 / 示波器**) | `docs/硬件平台/ADC通道映射说明.md`、`docs/测试说明/boot_log_data/` | ✅ |
| **0b** | **端子 / 子板变比确认** | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 `docs/硬件平台/ADC通道映射说明.md`;据此判定 `eng` 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 | 0 | 🟡 子板实物或原理图 | `docs/硬件平台/` | ⬜ |
| **12** | **8 通道两点标定与精度验收** | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 `[adc_cal]` 并置 `VALID`;误差 ≤ 目标精度(待定:0.5 级 / 1 级);证据归档 | 0、0b | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/boot_log_data/` | ⬜ |
| 标识(任务名)| DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|---|---|---|---|---|---|
| **端子/子板变比确认** | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 `docs/硬件平台/ADC通道映射说明.md`;据此判定 `eng` 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 | 已知电压注入验证(✅ 已闭环) | 🟡 子板实物或原理图 | `docs/硬件平台/` | ⬜ |
| **两点标定与精度验收** | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 `[adc_cal]` 并置 `VALID`;误差 ≤ 目标精度(待定:0.5 级 / 1 级);证据归档 | 端子/子板变比确认 | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/boot_log_data/` | ⬜ |
> 三张卡的分工:**0b 与 12 都是外部依赖**(子板 / 标准源),0 没有。M4 用板级 LSB 常数即可
> 收口(`eng=0`),但"二次值"真正成立要靠 0b 的变比、`VALID` 置位要靠 12。
>
> **卡 0 闭环结论(2026-10-27,注入点 = 端子侧 `U5` 排针,判据 ①~⑥ 全 PASS)**:零点 0~5 码 ·
> 三点拟合 R² = 0.9999997 · 斜率 6544.2 码/V(vs 引脚侧理论 6553.6,偏差 −0.14 %,**故 ③ 段确为 1:1,
> 判据 ② 按"端子侧斜率 = 实测变比"记为 ≈ 0.999**)· 8 路逐通道映射一一对应 · 极性对称性 ≤0.34 % ·
> 注入前后 `frames` 均 Δ9998/10 s(1000 Hz)。明细与两项残留口径见
> `docs/硬件平台/ADC通道映射说明.md` §8.1。**残差**:最小二乘残差 −2.03/+3.45/−1.42 码(无系统性弓形);
> IB 零点 2~5 码最贴近 ≤5 上限,若后续变大先查 R49 / `AIN9`。
> 两张卡的分工:**变比确认与两点标定都是外部依赖**(子板 / 标准源),软件道已无待做项。M4 用板级
> LSB 常数即可收口(`eng=0`),但"二次值"真正成立要靠变比确认拿到的变比、`VALID` 置位要靠两点标定。
---
## 6. 并行与顺序
```
0 ✅ 注入验证(万用表)→ 0b 变比(子板)→ 12 两点标定(标准源)
0 ✅ ─→ 闭锁验证(VALID 置位后保护才走判据)→ B10 送检
注入验证 ✅(万用表,已闭环)→ 变比确认(子板)→ 两点标定(标准源)
注入验证 ✅ ─→ 闭锁验证(VALID 置位后保护才走判据)→ B10 送检
```
- **卡 0 斜率规则**:实测斜率与理论 LSB 偏差 >2 % 时**先查前端(分压/变比/焊接)再改系数**——
- **实测斜率偏差规则**(注入验证定下的口径):实测斜率与理论 LSB 偏差 >2 % 时**先查前端(分压/变比/焊接)再改系数**——
用系数凑斜率会把硬件的错固化成"标定值"。**2026-10-27 实测偏差 −0.14 %,规则未触发**;
这条规则的第一次实战价值在于**反向确认**:若 ③ 段真是 2:1 分压,斜率会掉到 ~3277 码/V,
实测 6544.2 直接把它排除。
@@ -267,7 +264,7 @@ typedef struct {
| # | 问题 | 备选 | 建议 / 现状 |
|---|---|---|---|
| 1 | **精度目标** | 0.5 级 / 1 级 | 决定卡 12 的判据。**仍未拍板**——保护判据本身只需 3~5 %,0.5 级是计量口径;**卡 12 开跑前必须定**,否则"误差 ≤ 目标精度"这条 DoD 无法判定 |
| 1 | **精度目标** | 0.5 级 / 1 级 | 决定两点标定的判据。**仍未拍板**——保护判据本身只需 3~5 %,0.5 级是计量口径;**两点标定开跑前必须定**,否则"误差 ≤ 目标精度"这条 DoD 无法判定 |
| 2 | **端子 / 子板变比从哪来** | ① 有子板原理图(直接算)② 只有子板实物(万用表同时量端子与引脚)③ 都没有 | 决定 `eng` 能否置 1。②同样可行且够用;③则本波只交付"ADC 引脚电压",二次值登记为缺口。**未拍板**(取决于子板是否到手) |
**已定案(不再讨论)**:未标定即闭锁(2026-10-25 用户裁定**保持闭锁到标准源到位**,
@@ -283,11 +280,11 @@ typedef struct {
| 风险 | 触发条件 | 缓解 |
|---|---|---|
| **`cfg` 键数顶格** | 后续给 `[adc_cal]` 加键 | 已按 8+1 / 8 拆段;加键前先看 `CFG_FILE_MAX_KEYS`,必要时再拆 |
| **标定值把保护"调坏"** | 卡 12 写入错误系数 | `adc_cal_set()` 校验范围(`k` 必须在板级系数 × [0.5, 2.0] 内)+ 写入后回读校验;越界拒绝并留 `[ERR]` |
| **标定值把保护"调坏"** | 两点标定写入错误系数 | `adc_cal_set()` 校验范围(`k` 必须在板级系数 × [0.5, 2.0] 内)+ 写入后回读校验;越界拒绝并留 `[ERR]` |
| **削顶通道被当成可测** | 消费者只看 `k` 不看 `flags` | `adc_cal_flags()` 是唯一查询入口,`adc_cal_apply()` 不返回可用性;单测覆盖"CLIPPED 通道 104 恒 IV" |
| **快照双写** | 104 或 UI 侧也加一个 200 ms 计时器 | 设计约定"唯一发布者 = `adc_task`";其余侧只读,评审时看 `meas_tick()` 的调用点数量 = 1 |
| **未验证的系数被当成定论** | 跳过卡 0 直接冻结 ROM 默认系数 | ✅ **风险已解除(2026-10-27)**:卡 0 实测斜率 6544.2 码/V,与 ROM 默认系数所依据的理论 LSB(6553.6)偏差 **−0.14 %**,默认系数被实测支持。规则保留:日后若某路偏差 >2 %,**先查前端**(分压/变比/焊接),不用系数去凑 |
| **加压烧板** | 变比未确认就往端子加额定电压 | 卡 0 已按 ≤2 V 直流执行完毕;**端子级上额定值仍必须在卡 0b 之后**,且先量"端子对地通断"确认无直流通路 |
| **未验证的系数被当成定论** | 跳过注入验证直接冻结 ROM 默认系数 | ✅ **风险已解除(2026-10-27)**:注入验证实测斜率 6544.2 码/V,与 ROM 默认系数所依据的理论 LSB(6553.6)偏差 **−0.14 %**,默认系数被实测支持。规则保留:日后若某路偏差 >2 %,**先查前端**(分压/变比/焊接),不用系数去凑 |
| **加压烧板** | 变比未确认就往端子加额定电压 | 注入验证已按 ≤2 V 直流执行完毕;**端子级上额定值仍必须在变比确认之后**,且先量"端子对地通断"确认无直流通路 |
---
@@ -301,7 +298,7 @@ typedef struct {
| PT 断线判据 | 需要 `flags` 与遥信配合,而 V0.1 **无开入硬件** → 与下一行同归开入波次 |
| 开入 / 开出固件 | 固件里**完全没有**这两类代码(`docs/问题记录/采集与数据处理短板评测.md` 登记),是另一个波次的量级 |
| 温度非线性折算 | 见 §7 已定案行"温度不纳入线性标定" |
| 端子二次值(一次/二次变比换算) | **条件项**:卡 0b 拿到变比才做;拿不到则本波只到"ADC 引脚电压",`eng` 保持 0,缺口登记进 `docs/任务规划/登记簿.md` |
| 端子二次值(一次/二次变比换算) | **条件项**:变比确认拿到变比才做;拿不到则本波只到"ADC 引脚电压",`eng` 保持 0,缺口登记进 `docs/任务规划/登记簿.md` |
| UI 页面(含交流量回炉) | 归「UI 扩展」;本波只保证 `meas_snap_t` 可供其消费 |
---
@@ -310,7 +307,7 @@ typedef struct {
| 工作 | 关系 |
|---|---|
| **送检验收** | 标准源送检的标定复核依赖本波卡 12;验收索引见 `登记簿.md` §7 |
| **UI 补齐** | 已交付的 `meas_snap_t` + `adc_cal_flags()` 供 `ui_data_rt_t` 填 `eng`:现为 0 = 引脚电压,卡 0b 拿到变比后才升 1 = 二次值,交流量页"标定状态"才有真值。当前 UI 任务见 `UI补齐.md`,不必等卡 0b |
| **送检验收** | 标准源送检的标定复核依赖本波两点标定;验收索引见 `登记簿.md` §7 |
| **UI 补齐** | 已交付的 `meas_snap_t` + `adc_cal_flags()` 供 `ui_data_rt_t` 填 `eng`:现为 0 = 引脚电压,变比确认拿到变比后才升 1 = 二次值,交流量页"标定状态"才有真值。当前 UI 任务见 `UI补齐.md`,不必等变比确认 |
| **结构债** | 无交集 |
| **双转换器无共同采样触发(V0.2 硬件改版)** | 本波的 `CLIPPED` 位就是「双转换器无共同采样触发」在软件里的可见形态;V0.2 改版后该位恒 0,页面与 104 绑定零改动 |
+2 -1
View File
@@ -60,12 +60,13 @@
| 条目 | 需要条件 | 要做的事 | 去向 |
|---|---|---|---|
| **数据可信三项** | 台架与万用表;子板实物或原理图;标准源 | 已知电压注入 → 端子变比 → 8 通道两点标定 | 唯一任务卡与验收在 `数据可信.md` §5 |
| **数据可信两项** | 子板实物或原理图;标准源 | 端子/子板变比确认 → 8 通道两点标定 | 唯一任务卡与验收在 `数据可信.md` §5 |
| **标准源送检与第三方 104 验收** | 两点标定完成、保护 VALID 置位、第三方主站 | 标准源注入判据全部通过;总召、周期、变位、遥控全流程通过;证据归档。送检窗口前 2 日冻结特性 | `../子系统设计/IEC104上行设计说明.md` §7/§8 |
| **L5 队列往返基线待重验** | 台架 + PC peer | 下次 Phase 13 窗口重锁基线 | 本文件 §1 |
| **网络负向场景台架验证** | 拔线、SPI 故障注入、远显压力条件 | PHY 拔线、芯片级 `net_init` 失败、短写压测 | 本文件 §1 |
| **串口助手正路径补验** | CH340 接入 | 补齐尚未覆盖的正路径 | `../测试说明/串口助手设计说明.md` |
| **CI 远端闭环未验证** | runner 与第二台机器 | 验证远端两 job 闭环和不同工具路径 | 本文件 §4 |
| **UI 六页真机判据(记录 5 页 + 运行报告)** | 台架:NAND 里有真实事件记录、SD2506 电池域可控、104 主站可连 | 上板复核六件事:真记录翻页与掉电后保持、清除记录后对应页归零、上电一次看 `boot_count` +1、拔 RTC 电池后 `seq_state` 落 RESTARTED、IWDG 复位后 `rst_cause` 落 IWDG、主站连一次看 `conn_up` +1(模拟器侧这些记录文件无写入方、无 `boot_stats`、无 104 协议栈,黄金只拍得到空态「无记录」与固定假数据的显示口径) | 六个页面模块文件头「台架待补」段 + `../测试说明/模拟器差距清单.md` §2.3 开机账本一行 |
**送检顺序不可倒过来**:产品构建当前要求 UA/UN/IA 的标定 VALID 全部置位才走保护判据。
未完成标准源标定就送检,保护会表现为不动作。保持该闭锁,不用非标准源标定走捷径。
@@ -47,10 +47,10 @@ dhara 失败类 +84;RO 另 +208,全是该失败类名表)→ `ER_IROM1`
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ER_IROM1 | 261,928 B (255.79 KB) | 1,048,576 B (1024 KB) | 25.0% |
| RW_IRAM1 | 81,072 B (79.17 KB) | 131,072 B (128 KB) | 61.9% |
| ER_IROM1 | 264,580 B (258.38 KB) | 1,048,576 B (1024 KB) | 25.2% |
| RW_IRAM1 | 81,536 B (79.62 KB) | 131,072 B (128 KB) | 62.2% |
| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
| **Flash (ROM 合计)** | **263,500 B (257.3 KB)** | 1,048,576 B (1024 KB) | **25.1%** |
| **Flash (ROM 合计)** | **266,456 B (260.2 KB)** | 1,048,576 B (1024 KB) | **25.4%** |
<!-- MEM_SNAPSHOT:END -->
各区的容量与常量来源:
+3 -3
View File
@@ -15,16 +15,16 @@
<!-- MEM_BUDGET:BEGIN generated by scripts/ram_baseline.py -->
| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |
|---|---|---|---|---|
| ER_IROM1 (Flash) | 261,928 B | 1,048,576 B | 25.0% | 参考 |
| ER_IROM1 (Flash) | 264,580 B | 1,048,576 B | 25.2% | 参考 |
| RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS |
| UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 |
| RW_IRAM1 | 81,072 B | 131,072 B | 61.9% | PASS |
| RW_IRAM1 | 81,536 B | 131,072 B | 62.2% | PASS |
| 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 |
|---|---|---|---|
| 网络 | 13,702 B | 12 KB | ⚠ 超 1.4 KB |
| 存储 | 7,072 B | 12 KB | OK |
| UI | 34,188 B | 16 KB | ⚠ 超 17.4 KB |
| UI | 34,656 B | 16 KB | ⚠ 超 17.8 KB |
| RTOS 堆 | 57,376 B | 56 KB | 堆=配额 |
| 应用 | 15,552 B | 8 KB | ⚠ 超 7.2 KB |
| 其它 | 10,553 B | — | 参考 |
@@ -37,26 +37,26 @@
| IOA | 点 | 来源 | V0.1 状态 |
|---|---|---|---|
| 0x4011 | 1Ua | L2 遥测快照槽 `ADC_SEM_UA`(卡 9) | ✅ 有效 |
| 0x4011 | 1Ua | L2 遥测快照槽 `ADC_SEM_UA`(104 改读快照) | ✅ 有效 |
| 0x4012/0x4013 | 1Ub/1Uc | 同表槽位;STM32 侧削顶(`docs/算法/继电保护功能复现规划.md` §1.6) | ❌ 发 IV——**品质驱动**(快照 CLIPPED 位映射,非点表绑死;V0.2 消除双转换器无共同采样触发后零改动自动启用) |
| 0x4014 | 1U0 | 快照槽 `ADC_SEM_UN`(外部零序专用通道) | ✅ 有效 |
| 0x4015 | 1Ia | 快照槽 `ADC_SEM_IA` | ✅ 有效 |
| 0x4016~0x4018 | 1Ib/1Ic/1I0 | 同 Ub/Uc:绑槽 + 品质驱动 | ❌ 发 IV |
| 0x401D | 1f 频率 | 快照 `freq_hz`(卡 11 绑源;B8 自适应窗测频 `freq_get()` 同源) | ✅ 随测频收敛生效;`freq_valid()==0` → IV(卡 11 DoD) |
| 0x401D | 1f 频率 | 快照 `freq_hz`(频率点绑定;B8 自适应窗测频 `freq_get()` 同源) | ✅ 随测频收敛生效;`freq_valid()==0` → IV(该点 DoD 原句) |
- **数据源 = L2 遥测快照**(`App/algo/meas.h`,「数据可信」卡 8/9):200 ms 基波有效值
- **数据源 = L2 遥测快照**(`App/algo/meas.h`,「数据可信」遥测快照发布与 104 消费):200 ms 基波有效值
+ 每点品质,104 与 UI 共用同一份上游;读数单位 = ADC 引脚电压(eng=0,`App/algo/adc_cal`
折算层 2026-10-25 落地;二次值等卡 12 标定置 VALID)。槽位值/品质整体透传,本层
折算层 2026-10-25 落地;二次值等两点标定置 VALID)。槽位值/品质整体透传,本层
**不再自行判新旧**(快照 `seq` 仅供 COV 去重)。
- 品质映射:快照 `MEAS_QDS_*` 低字节与线上 QDS 同值直传;**CLIPPED → IV**(「削顶通道
恒 IV」口径不变、改由品质驱动,docs/任务规划/数据可信.md §8 风险表末行的单测要求);
快照从未发布(开机 <200 ms)→ IV|NT;判定顺序 IV 优先于 NT。
- 死区(卡 9):从「越死区即报」改为**连续 2 个新测量点越限才确认**——板端测量点 =
- 死区(104 改读快照):从「越死区即报」改为**连续 2 个新测量点越限才确认**——板端测量点 =
快照换帧(100 ms 轮询 vs 200 ms 快照按 `seq` 去重,防同一帧把单点噪声重复计满 2 点;
基准恒为**上次上送值**,非上次读值——防慢漂移把基准吃掉,参考系统同款);品质翻转
当拍直报、不计数。死区数值 = 运行时副本(`iec104_pts_yc_set_deadband`,ROM 默认沿
卡 6 额定 0.5% 档:0.5 V / 0.005 A / 0.5 Hz;卡 10 接 8020H 段后主站可读写);
标准源注入复核(卡 12)待台架。
下游常数按工程量重定的额定 0.5% 档:0.5 V / 0.005 A / 0.5 Hz;运行参数段接 8020H 段后主站可读写);
标准源注入复核(两点标定)待台架。
### 3.2 遥信 YX(IOA 1~33)
@@ -113,7 +113,7 @@
开机在 STORAGE_READY 屏障前装载,损坏/越界/版本换代 = 整表拒绝保持出厂默认
(all-or-nothing)+ 自检留痕 `prot set corrupt`;写盘失败脏标志保留 = 下轮重试。
**运行参数段 `0x8020H~0x8058H`(「数据可信」卡 10,2026-10-25 落实)**:
**运行参数段 `0x8020H~0x8058H`(「数据可信」交付项,2026-10-25 落实)**:
> ⚠ 逐项地址为**本仓自定**(`docs/算法/继电保护功能复现规划.md` §5.4 的权威表不在仓——
参考项目 `CommPara_ConfigTable` 拿不到,送检点表到位后**以送检为准替换常量表**,
@@ -121,7 +121,7 @@
| 地址 | 项 | 域(C_SE/C_RD 浮点工程量) | 工厂默认 | 真源与守卫 |
|---|---|---|---|---|
| 0x8030~0x8038 | 遥测死区 UA/UB/UC/UN/IA/IB/IC/IN/FREQ | V / A / Hz,分档上限 50/1/5 | 卡 6 额定 0.5 % 档(0.5 V ×4 / 0.005 A ×4 / 0.5 Hz) | `run_par` [run_par] 段 9 键 int32 毫单位;落盘键表 → `docs/子系统设计/网络配置说明.md` §3.5 |
| 0x8030~0x8038 | 遥测死区 UA/UB/UC/UN/IA/IB/IC/IN/FREQ | V / A / Hz,分档上限 50/1/5 | 下游常数按工程量重定的额定 0.5 % 档(0.5 V ×4 / 0.005 A ×4 / 0.5 Hz) | `run_par` [run_par] 段 9 键 int32 毫单位;落盘键表 → `docs/子系统设计/网络配置说明.md` §3.5 |
| 0x8040~0x8047 | 通道 k 覆盖(µV/码) | 正浮点;adc_cal 合法带 ROM×[0.5,2.0] 执行段裁决 | 回显生效值(ROM = 152.587890625 / 805.6640625) | **写 = `adc_cal_set` 代理,系数唯一真源在 [adc_cal] 段,run_par 不存系数**(防后人拿 run_par 表当真源表) |
| 0x8048~0x804F | 通道 b 覆盖(码值,可负) | ±8192(adc_cal 带) | 0(回显) | 同上;单侧写 RMW 用另一侧**当前生效值** |
| 其余 | 留白(PT/CT 变比等未启用类别) | — | — | C_RD → COT14+EVI / C_SE → actcon+PN |
@@ -132,11 +132,11 @@
- 现行门控 = 两段式 + 范围/合法带校验(与保护定值同款),**无「仅暂停/测试态可写」
门控**——文档现行如此,不造新语义;若送检点表要求该类门控,接线点在
`run_par_104_write` 执行段入口,加一处即可。
- 持久化(卡 10):任一写成功置 `run_par` 脏 → iec104Task 同款 peek 投递
- 持久化(运行参数段):任一写成功置 `run_par` 脏 → iec104Task 同款 peek 投递
`SYS_EVT_RUN_PAR_SAVE`(1<<8) → defaultTask `run_par_store_save()` 调 `cfg_file_save()`
整档外科保存(一趟覆盖 [run_par] 9 键 + 被代理改写的 [adc_cal]/[adc_cal_ofs],
lead 裁②一条事件位一趟够用);失败脏保留 = 下轮重试。消费侧(COV 判定)**实时读
引擎副本**,无缓存无投递(卡 9 的 pts 层 s_yc_db 副本已收编进 run_par)。
引擎副本**,无缓存无投递(104 改读快照时的 pts 层 s_yc_db 副本已收编进 run_par)。
## 4. 链路与流程
@@ -148,7 +148,7 @@
YC 组 SQ=1 → 频率单点)→ actterm;首召/ RBT 位 → COT=4(初始化),否则 COT=2。
单次 poll 发送预算 4 个 ASDU(防大扫描饿死宿主任务)。
- 突发:COV = 遥信变位 + 遥测**死区 2 点确认 + 品质翻转直报**(`iec104_pts_cov_check`,
卡 9 语义见 §3.1 注),COT=3 逐点 SQ=0。
104 改读快照语义见 §3.1 注),COT=3 逐点 SQ=0。
- 周期:RUN 态 60 s 全 YC 上送 COT=1。
- 遥控/定值写:两段式,失配/越界 → COT|PN 否定确认;未知 IOA → COT=14+EVI、
错公共地址 → COT=13+EVI、未知类型 → COT=12+EVI。
@@ -229,7 +229,7 @@
| 层 | 内容 |
|---|---|
| L0.5 | `test/host/iec104/`:APCI 重组/坏帧、STARTDT 握手、总召全流程(含 RBT/分片/预算)、COV、k/w 窗、t1/t2/t3(假时基)、遥控两段式与 PN、YK12 软压板两段转真 + 置脏(B7)、定值两段写 + set_sealed 后 selfcheck、C_RD(含本地项不可寻址)、C_CS(含闰年)、错地址/错类型 EVI;**板端默认源真实链**(ring→phasor→freq→meas 快照,非桩):值/品质透传、CLIPPED→IV、0x401D 绑频(收敛 ±0.02 Hz / 未新鲜 IV)、死区运行时化 + 2 点确认/回摆撤销、seq 去重(卡 9/11,TC-IEC104-025~028)+ 运行参数段路由/两段式/RMW(卡 10,TC-IEC104-029)+ `[comm]` 段真链(道G task-8,TC-IEC104-031~033:注册/出厂模板/沉降重载/带外自愈/setter 守卫/ca 端到端 = C_RD 正答与旧写死 ca=1 转 COT13+EVI);`test/host/iec104_serv/` 钉端口与 ca 取值来源(TC-I104SRV-001b/c);`test/host/cfg_file/` 钉段/键容量上限(TC-CONFIG-056/057);`test/host/run_par/`:[run_par] 注册/落盘往返/守卫/系数直通合法带(TC-RUNPAR-001~008);`test/host/prot_set/`:blob 往返 + 损坏整表拒绝(all-or-nothing)|
| L0.5 | `test/host/iec104/`:APCI 重组/坏帧、STARTDT 握手、总召全流程(含 RBT/分片/预算)、COV、k/w 窗、t1/t2/t3(假时基)、遥控两段式与 PN、YK12 软压板两段转真 + 置脏(B7)、定值两段写 + set_sealed 后 selfcheck、C_RD(含本地项不可寻址)、C_CS(含闰年)、错地址/错类型 EVI;**板端默认源真实链**(ring→phasor→freq→meas 快照,非桩):值/品质透传、CLIPPED→IV、0x401D 绑频(收敛 ±0.02 Hz / 未新鲜 IV)、死区运行时化 + 2 点确认/回摆撤销、seq 去重(104 改读快照与频率点绑定,TC-IEC104-025~028)+ 运行参数段路由/两段式/RMW(TC-IEC104-029)+ `[comm]` 段真链(道G task-8,TC-IEC104-031~033:注册/出厂模板/沉降重载/带外自愈/setter 守卫/ca 端到端 = C_RD 正答与旧写死 ca=1 转 COT13+EVI);`test/host/iec104_serv/` 钉端口与 ca 取值来源(TC-I104SRV-001b/c);`test/host/cfg_file/` 钉段/键容量上限(TC-CONFIG-056/057);`test/host/run_par/`:[run_par] 注册/落盘往返/守卫/系数直通合法带(TC-RUNPAR-001~008);`test/host/prot_set/`:blob 往返 + 损坏整表拒绝(all-or-nothing)|
| L0 | `iec104-unit-test` 钩子 + cppcheck/coding-standard |
| 台架 | `@test` 锚点(104 服务启动/监听行);**PC 主站客户端 `test/host/iec104_master.py`(纯标准库,B6 2026-10-12 就绪)**:STARTDT/总召四组+actterm/C_SE 定值两段写→YX15·16 变位(COT=3)/恢复复归/YK11 两段正答/C_RD 读回,台架往返 **18/18 PASS**(证据 `../测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt`);**B7 持久化模式 `--b7-pre/--b7-post/--b7-mark/--b7-check`**(中间 ST-LINK 复位):YK12 两段投退→保护退出/联动、**定值与压板态跨复位保持**(含非默认 7.5 往返),**21/21 + 13/13 + 4/4+4/4 PASS**(证据 `../测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt`);**B9 SOE 腿**(同工具同轮回归):自发 YX 断言 **M_SP_TB_1 带 ts**(工具解析 type 30/1 双型)+ FTP 下载 `/log/soe.log` 经 `test/host/soe/decode_soe.py` 解码断言(校验和/seq 单调/CP56↔epoch UTC 交叉),pre 21/21 + post 13/13 不回归;lib60870 级第三方全流程归 B10 |
@@ -239,8 +239,8 @@
2. ~~SOE 带时标~~ **突发单点已带 CP56 时标 = M_SP_TB_1(B9 落地,见 §3.2)**;
双点带时标不做(V0.1 双点恒 IV,无意义)。
3. YK1~4/13/14 否定确认——出口硬件确认后(R7)转真执行(YK12 已于 B7 转真)。
4. ~~遥测死区 10.0 码值为拟定值~~——工程量死区已于 2026-10-25 卡 6 落地(额定 0.5%);
卡 9 已加 2 点确认;卡 10(2026-10-25)已落地 **0x8020~0x8058 读写映射 + [run_par]
4. ~~遥测死区 10.0 码值为拟定值~~——工程量死区已于 2026-10-25 随下游常数按工程量重定落地(额定 0.5%);
104 改读快照已加 2 点确认;运行参数段(2026-10-25)已落地 **0x8020~0x8058 读写映射 + [run_par]
持久化 + 系数覆盖直通 adc_cal**——死区系数唯一真源 = cfg 引擎副本(run_par 存死区、
**不存系数**,系数真源在 [adc_cal] 段,见 §3.4 表注),`iec104_pts_yc_set_deadband`
降级为转发壳。
@@ -264,8 +264,8 @@
| 2026-10-12 | B4 落地回填:承载改**专用 iec104Task**(netTask 承载会 RPC 自死锁);§5 全量回填(门控/代次/拆链/对时/看门狗位 7);抢占策略修正为**首到优先**(§8 第 7 条);§6 实测(640 words,链 1456 B,余 43% PASS) |
| 2026-10-12 | **B7 定值持久化 + 软压板**:YK12 转真(§3.3,两段式 → `PS_GLOBAL_EN`);定值执行段改 `prot_set_set_sealed` 原子写+封存(§3.4,收口 B5 竞态窗口);本地项 `comm_addr=0` 不可寻址;持久化 = 脏标志 → `SYS_EVT_PROT_SET_SAVE` → defaultTask 原子写 `/prot_set.bin`,开机屏障前整表原子装载(损坏拒绝保默认 + 自检留痕);单测 +7(iec104 94 断言)+ prot_set blob 往返/损坏 33 断言 |
| 2026-10-12 | **B7 台架腿闭环**(§7 台架行回填):主站工具加 `--b7-pre/--b7-post/--b7-mark/--b7-check` 四模式(中间 ST-LINK 复位);pre 21/21(YK12 OFF→低定值不动作 / ON→YX15·16 即动作)、post 13/13(**压板退出态跨复位保持** + 重启后联动在位)、mark/check 4/4+4/4(**非默认定值 7.5 跨复位保持**);开机日志 `[CFG] prot set loaded (/prot_set.bin)`;证据 `../测试说明/boot_log_data/20261012_B7_*` |
| 2026-10-25 | **标定折算落地联动(卡 6)**:遥测读数由原始码值改工程量(§3.1 注已重写);死区按额定 0.5% 逐点重定(0.5 V / 0.005 A / 0.5 Hz),§8 第 4 条改「已落地,8020H 段仍归卡 10」 |
| 2026-10-25 | **卡 10(道D,「数据可信」M6-①)**:新增 `App/algo/run_par.c/h`——遥测死区 9 点真源收编([run_par] 段 9 键 int32 毫单位落盘,工厂默认 = 卡 6 档;pts 层 s_yc_db 副本删除、set/get 转转发壳并保留清确认计数语义);104 **0x8020~0x8058 读写映射**(§3.4 新表:逐项地址本仓自定、送检点表到位后替换常量段;0x8027~0x802A 永不覆盖,路由 run_par 先 prot_set 后);**k/b 系数覆盖 = adc_cal_set 代理**(合法带/越带留痕复用,run_par 不存系数);持久化走新事件位 `SYS_EVT_RUN_PAR_SAVE`(1<<8) 整档外科 save;单测 test/host/run_par 新建(TC-RUNPAR-001~008,67 断言)+ iec104 套 +TC-IEC104-029 路由钉(141 断言);台架/送检腿待排窗 |
| 2026-10-25 | **卡 9/卡 11(道D,「数据可信」M5/M6)**:YC 板端源改读 L2 遥测快照(削顶五路从点表绑死 -1 改为**槽位绑定 + 快照品质 CLIPPED→IV**,V0.2/N-18 零改动启用);`0x401D` 绑频率源(`freq_valid()==0` → IV);死区改运行时副本 + `iec104_pts_yc_set_deadband()`(卡 10 接线点);COV 遥测腿 = 死区连续 2 点确认(快照 `seq` 去重)+ 品质翻转直报;`iec104_pts_src_t` 表尾追加 `yc_read_ex`(旧源退路语义不变);单测 97→127(TC-IEC104-025~028 走真实 L2 链);台架腿(总召读回一致 / 频率 ±0.01 Hz)待排窗——主站工具已记 val+qds,无需改工具 |
| 2026-10-25 | **标定折算落地联动(下游常数按工程量重定)**:遥测读数由原始码值改工程量(§3.1 注已重写);死区按额定 0.5% 逐点重定(0.5 V / 0.005 A / 0.5 Hz),§8 第 4 条改「已落地,8020H 段仍归运行参数段」 |
| 2026-10-25 | **运行参数段(道D,「数据可信」M6-①)**:新增 `App/algo/run_par.c/h`——遥测死区 9 点真源收编([run_par] 段 9 键 int32 毫单位落盘,工厂默认 = 下游常数按工程量重定的档位;pts 层 s_yc_db 副本删除、set/get 转转发壳并保留清确认计数语义);104 **0x8020~0x8058 读写映射**(§3.4 新表:逐项地址本仓自定、送检点表到位后替换常量段;0x8027~0x802A 永不覆盖,路由 run_par 先 prot_set 后);**k/b 系数覆盖 = adc_cal_set 代理**(合法带/越带留痕复用,run_par 不存系数);持久化走新事件位 `SYS_EVT_RUN_PAR_SAVE`(1<<8) 整档外科 save;单测 test/host/run_par 新建(TC-RUNPAR-001~008,67 断言)+ iec104 套 +TC-IEC104-029 路由钉(141 断言);台架/送检腿待排窗 |
| 2026-10-25 | **104 改读快照与频率点绑定(道D,「数据可信」M5/M6)**:YC 板端源改读 L2 遥测快照(削顶五路从点表绑死 -1 改为**槽位绑定 + 快照品质 CLIPPED→IV**,V0.2/N-18 零改动启用);`0x401D` 绑频率源(`freq_valid()==0` → IV);死区改运行时副本 + `iec104_pts_yc_set_deadband()`(运行参数段接线点);COV 遥测腿 = 死区连续 2 点确认(快照 `seq` 去重)+ 品质翻转直报;`iec104_pts_src_t` 表尾追加 `yc_read_ex`(旧源退路语义不变);单测 97→127(TC-IEC104-025~028 走真实 L2 链);台架腿(总召读回一致 / 频率 ±0.01 Hz)待排窗——主站工具已记 val+qds,无需改工具 |
| 2026-10-12 | **B9 时标 SOE**:自发单点 YX 换 **M_SP_TB_1(30)**(SIQ+CP56,§3.2 注;总召/周期保持 NA 型);link cfg 增 `epoch_ms` 时标源(NULL/无效 → IV 如实);serv 绑 `sys_clock`(秒域 → ms 域=秒×1000);主站工具解析 type 30/1 双型;单测 iec104 94→97(TB 时标 + IV 路径,两种类型都断言);台架腿见 §7 B9 行;落盘侧见 `App/log/README.md` soe 节 |
| 2026-10-26 | **道G task-8:`[comm]` 段落地(「UI 补齐」卡 5 非 UI 前置)**——ca/端口从写死改 `[comm]` 可配(getter 合法带自愈,键表 → `docs/子系统设计/网络配置说明.md` §3.6);`iec104_comm_init()` 内核前注册于 `app_main_init`(先注册后 load 契约,同 [adc_cal]/[run_par]);生效 = 改后重启(ca 任务启动读一次;port 下次重 bind 自然生效),不挂回调不新增事件位;§5/§8 同步销项,**主站地址不做**的理由登记 §8 第 8 条;死 define `IEC104_PORT` 删除(零 .c 消费);`IEC104_SERV_PORT` 降为快照兼容出口(真源 getter,task-9 切 ui_data_feed);单测 = `test/host/iec104` TC-IEC104-031~033(套件 174/174 PASS)+ `test/host/iec104_serv` TC-I104SRV-001b/c(37/37 PASS)+ `test/host/cfg_file` TC-CONFIG-056/057(207/207 PASS)|
| 2026-10-26 | **道G task-8:`[comm]` 段落地(「UI 补齐」波次里的非 UI 前置项)**——ca/端口从写死改 `[comm]` 可配(getter 合法带自愈,键表 → `docs/子系统设计/网络配置说明.md` §3.6);`iec104_comm_init()` 内核前注册于 `app_main_init`(先注册后 load 契约,同 [adc_cal]/[run_par]);生效 = 改后重启(ca 任务启动读一次;port 下次重 bind 自然生效),不挂回调不新增事件位;§5/§8 同步销项,**主站地址不做**的理由登记 §8 第 8 条;死 define `IEC104_PORT` 删除(零 .c 消费);`IEC104_SERV_PORT` 降为快照兼容出口(真源 getter,task-9 切 ui_data_feed);单测 = `test/host/iec104` TC-IEC104-031~033(套件 174/174 PASS)+ `test/host/iec104_serv` TC-I104SRV-001b/c(37/37 PASS)+ `test/host/cfg_file` TC-CONFIG-056/057(207/207 PASS)|
+6 -6
View File
@@ -150,7 +150,7 @@ write=1
> **诚实边界**:FTP 协议**明文传输口令**——本方案挡的是**未授权访问**,不挡**网络嗅探**(CH395F 上实现 TLS 不现实)。`pwd_hash` 只防 `/config.ini` 泄露后的**离线口令还原**,盐 = 用户名(无每机随机盐,局域网威胁模型下够用)。
### 3.5 `[run_par]` 段:运行参数(2026-10-25 新增,「数据可信」卡 10)
### 3.5 `[run_par]` 段:运行参数(2026-10-25 新增,「数据可信」运行参数段一项)
遥测死区 9 点的持久载体(引擎属主 defaultTask;**现场远程写入口 = 104 段
`0x8030~0x8038`**,本段键供 FTP 手改 / 排障直读,逐项语义与地址表 →
@@ -164,14 +164,14 @@ write=1
| `db_freq` | 频率死区 | 500 | 0 ~ 5000(5 Hz) |
- 键数 9 ≤ 16,**通道系数覆盖不落本段**——系数唯一真源 = `[adc_cal]` / `[adc_cal_ofs]`
两段(卡 4 布局,docs/任务规划/数据可信.md §4.4;104 `0x8040~0x804F` 写 =
两段(标定落盘与整定入口布局,docs/任务规划/数据可信.md §4.4;104 `0x8040~0x804F` 写 =
`adc_cal_set` 代理,lead 裁②a)。
- 守卫在**写路径**(104/壳 API 拒 NaN/负/越程);**文件通路引擎照收**(同 adc_cal 的
「人工编辑 + 沉降去抖」契约)——死区超程只让上送变钝、不毁量纲,无合法带哨兵。
- 生效链路:load/poll 原地改副本 → 104 COV 每拍实时读(无回调,卡 9/10 契约);
- 生效链路:load/poll 原地改副本 → 104 COV 每拍实时读(无回调,104 改读快照与运行参数段契约);
104 写成功 → `SYS_EVT_RUN_PAR_SAVE` → 本任务 `cfg_file_save()` 整档外科落盘。
### 3.6 `[comm]` 段:IEC 60870-5-104 通讯参数(2026-10-26 新增,「UI 补齐」卡 5 非 UI 前置,道G task-8)
### 3.6 `[comm]` 段:IEC 60870-5-104 通讯参数(2026-10-26 新增,「UI 补齐」波次里的非 UI 前置项,道G task-8)
104 被控站的公共地址与监听端口持久载体(段属主 = `App/protocol/iec104/` 配对模块:
工厂默认与合法带见 `iec104_comm.h`、键表与实现见 `iec104_comm.c`;注册
@@ -355,8 +355,8 @@ ENTER 进入选中地址行 → `↑/↓` 调活动字节(0..255 **环绕**)
| 日期 | 变更 |
|---|---|
| 2026-10-26 | v2.5:**新增 §3.6 `[comm]` 段(道G task-8,「UI 补齐」卡 5 非 UI 前置)**——104 公共地址/监听端口 2 键、改后重启生效口径、主站地址不做的理由登记、段容量台账 6/8 与机器钉 |
| 2026-10-25 | v2.4:**新增 §3.5 `[run_par]` 段(「数据可信」卡 10)**——遥测死区 9 键毫单位布局、104 写路径合法域、系数覆盖不落本段(真源 [adc_cal])、守卫仅在写路径、事件化落盘 |
| 2026-10-26 | v2.5:**新增 §3.6 `[comm]` 段(道G task-8,「UI 补齐」波次里的非 UI 前置项)**——104 公共地址/监听端口 2 键、改后重启生效口径、主站地址不做的理由登记、段容量台账 6/8 与机器钉 |
| 2026-10-25 | v2.4:**新增 §3.5 `[run_par]` 段(「数据可信」运行参数段一项)**——遥测死区 9 键毫单位布局、104 写路径合法域、系数覆盖不落本段(真源 [adc_cal])、守卫仅在写路径、事件化落盘 |
| 2026-10-11 | v2.3:**新增 §3.4 `[ftp]` 段(N-19 FTP 鉴权)**——`user` / `pwd_hash`(SHA-256(user‖password))/ `write` 字段表、鉴权流程(USER 恒 331 / 恒定时间比较 / 未登录命令门 / 5 败锁 60 s)、改口令步骤与忘口令恢复路径、出厂默认口令启动告警、明文嗅探边界 |
| 2026-10-10 | v2.2:**删除旧档 NCFG 迁移**——`net_cfg_legacy.c/h` 整体移除、`cfg_store_legacy_path()` 撤销;旧档 `/cfg/netcfg.bin` 若存在则被忽略(不读、不删、不迁移),配置回落工厂默认。理由:该一次性路径把整条配置写链挂进启动期调用图,defaultTask 静态最坏栈链 +600 B,且本仓库无携带旧档的设备 |
| 2026-09-14 | v2.1:存储迁移至**通用配置文件** `/config.ini`(INI `[network]` 段,cfg_file 引擎:逐键校验 / 外科手术式保存 / 原子写 / 旧档首启迁移 / 沉降轮询);`net_cfg_store.*` 弃用(由 `cfg_file_store.*` 取代);对外 API 不变 |
@@ -588,4 +588,4 @@ void adc_cfg_init(void)
| 2026-10-03 | v1.13:**真机验证 PASS(A1 闭环)**——v1.11 的 P0-1 堆分配改造在真机上验证通过:`[CFG] load: OK (523B, heap free 8840B)`(**经 FreeRTOS 堆分配**,即 512B C 堆约束的验收点);Forbidden `FAIL`/`[ERR]` 零命中;FTP 改配置 IP→`192.168.1.101` 后**复位即加载生效**(`[NET_CFG] load: OK ip=192.168.1.101` + 芯片 `IP_INF` .101 + 21 端口探测可达),原档恢复后复测回 .100。真机全闭环 `@test` PASS 7/7。**台架步骤与判据见 `测试说明/实机测试实施指南.md` §3 / §10** |
| 2026-10-04 | **P0-1 真机独立复跑 PASS(二次确认,代码零改动)**——`@build` 0/0(增量,无源文件新于镜像)→ `@test` **VERDICT PASS(rc=0)**:`[2026-10-04 00:01:21][CFG] load: OK (523B, heap free 8840B)` + `[NET_CFG] load: OK ip=192.168.1.100`,Forbidden `FAIL`/`ERROR`/`HardFault`/`[ERR]` 零命中,`selftest: no fault record`(先清掉 2026-10-02/03 故障注入窗口遗留的 67 条台账)→ ST-LINK 全片回读 `No difference found`(`0x08000000~0x08040F9B`)。**本次为 `待处理内容.md` §4.1「待验证」唯一未闭环项(P0-1)的收口**,该节现已清空 |
| 2026-10-10 | v1.14:**删除旧档 NCFG 迁移(D10 撤销)**——`Drivers/BSP/NETCFG/net_cfg_legacy.{c,h}` 整体移除、`cfg_store_legacy_path()` 撤销(MCU / 模拟器后端与主机单测 `test/host/cfg_file/cfg_file_test.c` 同步删除),`net_cfg_load` 不再调用 `net_cfg_legacy_migrate()`;旧档 `/cfg/netcfg.bin` 若存在则被**忽略**(不读、不删、不迁移),配置回落工厂默认。理由:该一次性路径把整条配置写链挂进启动期调用图,defaultTask 静态最坏栈链 **+600 B**(该链整体 5312 → 2776 B,另三个杠杆见 `docs/内存管理/RAM使用分析与优化方案.md`),而本仓库不存在携带旧档的设备。连带影响:`App/util` 的 CRC-16/MODBUS 失去唯一调用者(现为零调用者);模拟器 `--cfgtest` 不再覆盖迁移场景;§2 D10 / §3.5 / §4.2 / §5.1 / §6.2 / §6.4 / §7 / §9 / §11.1 同步 |
| 2026-10-26 | v1.15:**新增 `[comm]` 段(道G task-8,「UI 补齐」卡 5 非 UI 前置)**——`App/protocol/iec104/iec104_comm.h/.c` 配对模块(104 公共地址 / 监听端口 2 键,getter 合法带自愈,adc_cal 先例);内核前 `iec104_comm_init()` 注册([adc_cal] / [run_par] 同「先注册后 load」契约);生效 = **改后重启**(不挂回调、不新增事件位,区别于 [network] 免重启重建);段占位 5→6 / 8,键表与主站地址不做理由 → `docs/子系统设计/网络配置说明.md` §3.6;机器钉 = `test/host/cfg_file` TC-CONFIG-056/057(段/键上限)+ `test/host/iec104` TC-IEC104-031~033(模板/重载/带外/ca 端到端)
| 2026-10-26 | v1.15:**新增 `[comm]` 段(道G task-8,「UI 补齐」波次里的非 UI 前置项)**——`App/protocol/iec104/iec104_comm.h/.c` 配对模块(104 公共地址 / 监听端口 2 键,getter 合法带自愈,adc_cal 先例);内核前 `iec104_comm_init()` 注册([adc_cal] / [run_par] 同「先注册后 load」契约);生效 = **改后重启**(不挂回调、不新增事件位,区别于 [network] 免重启重建);段占位 5→6 / 8,键表与主站地址不做理由 → `docs/子系统设计/网络配置说明.md` §3.6;机器钉 = `test/host/cfg_file` TC-CONFIG-056/057(段/键上限)+ `test/host/iec104` TC-IEC104-031~033(模板/重载/带外/ca 端到端)
@@ -1,12 +1,12 @@
# ADC 前端注入验证流程(台架)
> **这篇是什么**:把「ADC 采到的数到底对不对」从"没人验过"推进到"有实测斜率与零点"的固定动作。
> 它是 `docs/任务规划/数据可信.md` 卡 0 的**执行侧**——那边写判据,这边写怎么接表笔、读哪一行日志、
> 它是已知电压注入验证的**执行侧**——判据与实测记录在 `docs/硬件平台/ADC通道映射说明.md` §8.1,这边写怎么接表笔、读哪一行日志、
> 填哪张表、结果往哪回写。补的是 `docs/硬件平台/ADC通道映射说明.md` §8「逐通道验证方法」
> 长期挂账的"尚未执行"(挂账自 2026-10-09)。
>
> **只验直流**:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源,且 V0.1 有五路
> 单极性削顶(`UB/UC/IB/IC/IN`),交流精度要等标准源到位后的两点标定(`docs/任务规划/数据可信.md` 卡 12)。
> 单极性削顶(`UB/UC/IB/IC/IN`),交流精度要等标准源到位后的两点标定(`docs/任务规划/数据可信.md` §5)。
>
> **不需要**示波器、信号源、标准源。**只需要**一块万用表 + 一个电位器 + 串口日志。
@@ -37,7 +37,7 @@
1. **不存在 2:1 分压**。旧口径"板级系数 305.18 / 1611.3 µV/码"(按 2:1 折算到 `AINn` 侧的条件值)
在本板上不成立;`docs/任务规划/数据可信.md` §2.1 已于 2026-10-27 改为引脚侧系数(152.59 / 805.66)。
所以卡 0 只需**确认转换器 LSB 与逐通道映射**,不必再判别两种读法。
所以已知电压注入验证只需**确认转换器 LSB 与逐通道映射**,不必再判别两种读法。
2. **端子侧斜率 = 引脚侧斜率**。所以在**端子侧**注入既安全(有 1k 串阻护着芯片)又能直接验 LSB,
不必去碰 LQFP 引脚。
@@ -224,7 +224,7 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
| 注入前(20:58) | 29997 → 39995 | 9998 | 1000.5 Hz |
| 注入后(21:29) | 1819639 → 1829637 | 9998 | 1000.1 Hz |
⚠ **口径说明**:这两次是"注入**前后**",不是"注入**进行中**"——卡 0 判据 ⑤ 要的正是"注入前后
⚠ **口径说明**:这两次是"注入**前后**",不是"注入**进行中**"——已知电压注入验证判据 ⑤ 要的正是"注入前后
`tpafe5160_frame_seq()` 仍严格 1000 Hz 递增",故按此口径已达标。若日后要连"进行中"也钉住,
在任一注入过程里再抓两行即可(注入不改变 TIM3 硬件触发,理论上无影响,但没测过就不算证过)。
@@ -237,9 +237,10 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
实测值 + 日期;
2. 若实测确认无分压,同步在 `docs/硬件平台/ADC通道映射说明.md` §7.1 的链路分段表把第 ③ 段
(`AINn` ↔ 转换器引脚)从"待台架实测"改为实测结论;
3. `docs/任务规划/数据可信.md` 卡 0 销项。**注意:实际处置是标 ✅ 保留行,不是删行**——
该文件卷首明文规定卡 0 被 `App/task/adc_task.c` 的 v3.3 修订行与 `adc:` 行注释引用为口径出处,
删行会让代码头注释失去出处;这是"完成即删"在该文件的**既定例外**。
3. `docs/任务规划/数据可信.md` 已知电压注入验证销项。**2026-10-27 用户裁定:该行按"完成即删"删行**,
此前"标 ✅ 保留行"的**例外已撤销**——例外当初的理由是该文件卷首规定此行被 `App/task/adc_task.c` 的
v3.3 修订行与 `adc:` 行注释按卡号当口径出处引用,而本次卡号整族清退成语义短语后该理由不再成立;
判据与实测证据的属主是 `docs/硬件平台/ADC通道映射说明.md` §8.1。
## 6. 判据汇总
@@ -256,7 +257,7 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
① ③ 段(`AINn` ↔ 转换器引脚)**变比确为 1:1**,无隐藏分压(斜率偏差 −0.14 %);
② 8 路语义 ↔ 物理端子**一一对应**(零点步骤逐路代偿);
③ TPAFE 补码符号位解释正确(对称性 ≤0.34 %)。
`docs/任务规划/数据可信.md` 卡 0 的判据 ①②③④⑤⑥ 至此全部闭环。
已知电压注入验证的判据 ①②③④⑤⑥ 至此全部闭环(判据与实测记录 → `docs/硬件平台/ADC通道映射说明.md` §8.1)。
⚠ **两项残留口径**(不影响本轮 PASS,但别当成已验证):**串扰**未单独证(见上表"映射"行);
**节奏**只测了注入前后、没测注入进行中。两项若日后怀疑,各自的补做方法已写在对应小节。
@@ -267,6 +268,6 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
1. **STM32 侧严禁超过 3.3 V**(VDDA + 0.3 V 即击穿),电位器上限就接 3.3 V 轨,不要接 5 V。
2. **TPAFE 侧按判据只到 ±2 V**,虽芯片容 ±5 V,但判据不需要更大。
3. **端子侧不许直接上额定电压**(220 V / 100 V 二次值)。本次是直流低压注入,
与"加压试保护"是两件事,后者要等变比确认(`docs/任务规划/数据可信.md` 卡 0b)之后单独排。
与"加压试保护"是两件事,后者要等端子/子板变比确认(`docs/硬件平台/ADC通道映射说明.md` §7.1 链路分段表 ④ 行)之后单独排。
4. **引脚侧注入必须外串 10 k**,且先接线后上电、先断电后拆线。
5. 注入源与板子**共地**;电位器一端接 3.3 V、一端接 AGND、中间抽头串 10 k 到注入点。
@@ -704,7 +704,7 @@ uint16_t ch395f_link_change_count(void);
| 类别 | 体量 | 为什么不做 | 那它靠什么把关 |
|---|---|---|---|
| 芯片驱动(寄存器/时序) | `ch395f.c`(801)、`gd5f2gq5ue.c`(689)、`sd2506.c`(264)、`tpafe5160.c`(157)、`rs485.c`(79) = **1,990 行** | 把 HAL 与寄存器假到底 ≈ **重写一遍驱动**,测的是自己的桩而不是硬件行为(SPI 分频必须 8、DMA 流、I2C 时序在桩里怎么编都"对") | 板级套件(`board-test-suite` skill)+ `@test` 真机日志 + 4 个 Fault 现场;陷阱逐条登记在 `docs/问题记录/CH395F_Trap_Records.md`、`docs/问题记录/GD5F2GQ5UE_Trap_Records.md`、`docs/问题记录/SD2506_Trap_Records.md` |
| UI 侧 | 17 个 `.c` = **1,942 行** | 与 PC 模拟器是**同一份源码**,行为回归已由 `ui-golden`(菜单 8 状态 + 内容页 53 页像素黄金参考)覆盖;再写单测是第三份重复投资 | `ui-verify` skill 五步 + `docs/UI设计/UI_自动化测试流程.md` |
| UI 侧 | 17 个 `.c` = **1,942 行** | 与 PC 模拟器是**同一份源码**,行为回归已由 `ui-golden`(菜单 8 状态 + 内容页 60 页像素黄金参考)覆盖;再写单测是第三份重复投资 | `ui-verify` skill 五步 + `docs/UI设计/UI_自动化测试流程.md` |
| 任务编排 | `default_task.c`(281)、`adc_task.c`(171)、`net_task.c`(123)、`protect_task.c`(90)、`ui_task.c`(71)、`rs485_task.c`(11) = **747 行** | 每个只有 4~5 个函数,主体是"按顺序调别人";真逻辑在被调模块里(那些已测或在 P1/P2)。给编排层写单测最容易写成"断言我调了几次"的自证 | 真机启动锚点计数 + IWDG `required_mask`(`@test`)+ `docs/架构设计/项目启动顺序管理.md` |
| 内核前装配 | `app_main.c`(135) | 被测对象本身就是"`osKernelStart` 之前不许调内核 API"的时序,主机侧无法忠实复现(PC 上没有那个约束) | 同上 + `cubemx-survival` 审计 |
@@ -56,6 +56,7 @@
| **无应用回调(空操作)** | 模拟器不注册段回调,`cfg_file_poll` 重载后回调为空 | 各段回调真正执行(如网络重配置) | "配置变更 → 触发回调 → 副作用"链路在模拟器上**只验证到写盘**,回调逻辑不覆盖 | `@test`(配置保存 → UI 生效) |
| **「清除记录」两端时序不同** | `syslog_request_clear()` 在调用内**同步**删除宿主文件(`sim_syslog.c` 单线程,没有卷锁、没有队列),返回后状态立刻是 `OK`/`FAIL`,`SYSLOG_CLEAR_WAIT` 永不出现 | 非写者上下文只置标志,真正的 `f_unlink` 排在 defaultTask 的 `syslog_drain()` 尾部(卷锁 try:拿不到锁就顺延,见 `App/log/sys_log_mcu.c`) | 「按了按钮 → 下一拍才见结果」这条异步链、卷占用顺延、以及删除与写者重建的交错,在模拟器上**结构上不存在**;UI 页面若把 WAIT 当失败,模拟器上看不出来 | 主机单测 `test/host/sys_log_mcu/`(TC-SYSLOG-110..122:请求侧零盘触点 / 落地只在 drain / 卷占用顺延 / 幂等 / 不误删;TC-SYSLOG-133/133b:清除成功投一条操作记录、清 oper 自己时不投)+ 台架装置维护页目检 |
| **两条投递口在宿主端合一** | `syslog_post_quiet()` = `syslog_post()` 的别名(直写宿主文件,没有队列/待发数组),`syslog_post_dropped()` **恒返 0** | 两个口分开且判据不同:quiet 的调用链上不许内联日志行缓冲(protectTask / iec104Task 的静态最坏链硬线),丢弃只累加计数、由 defaultTask 在 `syslog_drain()` 里按差值补留痕 | 五类记录(事故 / 告警 / 启动 / 操作 / 遥控)在模拟器上**永不丢弃**,"队列满丢记录"、"丢了几条"、"投递侧不许打日志"这三件事在模拟器上结构上不可见;UI 若把"投了"当成"落盘了",模拟器看不出来 | 主机单测 `test/host/sys_log_mcu/`(TC-SYSLOG-132 / 134 / 135:队列侧与启动前数组侧各自的计数与零留痕)+ `scripts/stack_report.py` 静态最坏链(真机侧唯一手段) |
| **宿主 cwd 的记录文件互相污染** | 七类记录在模拟器落**当前工作目录**的 `sim_<id>.log`(如 `sim_oper.log`);`sim_post_oper()` 在时钟保存 / 网口保存 / 定值保存等**动作页**用例里真投记录 | 每条记录进 `/log/` 下各自 8.3 短名文件,跨页不互相影响(同一进程内不同页读的是同一份 NAND 文件,本来就该看见彼此写入的记录) | 回归若在**同一个 tmp 目录**跑全部页,前面动作页写的 3 条操作留痕会让「操作记录」页拍不到空态 → 空态判据被环境污染掩盖(真机上没有这个问题:写者只有 defaultTask 与事件边沿) | `simulator/tests/check_content_pages.py` 的 `FRESH_CWD` 表:记录 5 页各在独立空目录里跑(其余 55 页环境不变);手工跑 `lvgl_sim.exe` 前先确认当前目录没有 `sim_*.log`/`sim_config.ini` 残留 |
| **堆后端不同** | `cfg_store_alloc` = 宿主 `malloc`(堆余量以 MB 计) | FreeRTOS 堆(`configTOTAL_HEAP_SIZE` 48 KB,实测最低水位 ~4.8 KB) | **分配失败路径在模拟器上永不触发**——"KB 级分配必然返回 NULL"这类缺陷模拟器照不出来(`AGENTS.md` 已列为铁律) | 内存预算门禁 + 真机 `[HEAP]` 水位告警(S11) |
### 2.3 硬件专属(模拟器完全无对应)
@@ -66,6 +67,7 @@
| **CH395F 芯片** | 无(Winsock 代其 BSD API) | SPI 寄存器/命令/中断、PHY 协商、真实以太网帧 | 寄存器时序、命令回复、中断风暴、PHY 100M 全双工强制 | 板端 CH395F 套件(52 断言点)+ `@test` |
| **GD5F NAND** | 无 | SPI NAND:BBT 扫描、ECC、坏块管理、dhara FTL | 坏块/ECC/写入失败等路径完全不可测 | 板端 GD5F 套件(76 断言点)+ `@test` |
| **SD2506 RTC** | 无 | I2C RTC:时间读写、闹钟、温度、电池电压 | 时间源相关(`sys_clock_init` 降级路径)在模拟器上不可触发 | 板端 RTC 套件(18 断言点)+ `sys_clock` L0.5(已覆盖算术面) |
| **开机账本 boot_stats(上电次数 / 复位原因快照)** | **不编译** `App/util/boot_stats.c`(依赖 SD2506 用户 SRAM 与 `RCC_CSR`);UI「运行报告」页的四个数在模拟器上是 `simulator/main.c` 的**固定假数据**(`boot_count=7`、`seq_state=延续`、`rst_cause=上电复位`、104 四枚 3 / 128 / 0 / 4096、`uptime_s=0`) |`boot_stats_init()` 读 SRAM → 自增 → 写回 → 快照驻留;四个 104 观测计数由 iec104Task 真实累加(跨重连不清零、断电归零) | 「自增有没有真落 SRAM」「电池域掉电后是否落 RESTARTED」「写失败是否只少计不重复」「104 计数是否跨重连累计」四类事在模拟器上**结构上不可见**;黄金参考只拍得到显示口径(范围标签在不在屏上、值有没有串行、`boot_ready=0` 是否显 `--` 而不是 0) | 主机单测 `test/host/boot_stats/`(SRAM 状态机与四态判定)+ 真机 `@test`:上电一次看 `boot_count` +1、拔电池后落 RESTARTED、IWDG 复位后 `rst_cause=IWDG`、主站连一次看 `conn_up` +1 |
| **TPAFE5160 ADC** | 无 | SPI ADC + BUSY EXTI 中断 | 中断驱动采集链路 | 待功能实现(上游 B1) |
| **RS-485 半双工** | 无 | UART4 + DE 方向控制,DWT 微秒延时 | DE 收发切换时序(特有陷阱) | 待功能实现(上游 B2) |
| **启动段硬件初始化** | 只跑纯软件部分 | I2C/SPI 外设初始化、BBT 扫描耗时、FatFS 挂载 | 启动段死机(无看门狗保护窗口)**只能在真机复现** | 真机开机日志判读(`项目启动顺序管理.md` §6 已落地) |
@@ -111,5 +113,6 @@
| 日期 | 变更 |
|---|---|
| 2026-10-28 | **新增 `§2.3`「开机账本 `boot_stats`」一行**(UI 补齐「运行报告」页联动):模拟器不编译 `boot_stats.c`(依赖 SD2506 用户 SRAM 与 `RCC_CSR`),运行报告页四个数在 PC 侧是 `simulator/main.c` 的固定假数据 → 像素黄金只验**显示口径**,累计 / 落盘 / 电池域掉电 / 跨重连语义必须回真机(触发条件 = 本批改 `simulator/main.c` 的 info 帧装配) |
| 2026-10-13 | **自愈收敛阶段 1.5 recv 语义主流化**:`net_socket_sim.c` 镜像 `net_recv_nb` / `net_recv_to` / `net_setblocking`,阻塞语义改按控制块 `blocking` 属性在包装层模拟(Winsock 句柄仍恒 FIONBIO)——N-3 的 `net_recv_to` 缺失部分**已消除**(划线留档),N-6 改写为"模式属性 + 包装层模拟";内部挂起模型(N-1)不变 |
| 2026-10-02 | 初版(S13):收录 6 条网络差距(N-1~N-6)、4 条日志/配置差距(L-1~L-4)、7 条硬件专属差距(H-1~H-7)、4 条"有意对齐"项。证据来源:`net_socket_sim.c` 文件头设计要点 + 双端导出函数逐一对比(MCU 有而 sim 缺 9 个)+ 各子系统文档既有记载汇总。§3 给出 6 条"必须回真机"决策规则 |
@@ -373,7 +373,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
| 层 | 载体 | 抓住什么 |
|---|---|---|
| 文本层 | `check_content_pages.py` 字形模板匹配(310 条、覆盖当时 37 页,解析字体 cmap / glyph_dsc / bitmap) | 缺字显示空白 / 标签写错等**静默失败**(不依赖 `ref/`,先于像素比对运行、失败即中止防误刷参考) |
| 像素层 | 53 内容页 + 菜单 8 状态,与黄金参考逐字节比对 | 几何 / 样式 / 光标反显 / 整体外观 |
| 像素层 | 60 内容页 + 菜单 8 状态,与黄金参考逐字节比对 | 几何 / 样式 / 光标反显 / 整体外观 |
| 池水位层 | `MENU_POOL_BASELINE=5368 B` / `POOL_AFTER_ROUNDTRIP=5448 B` | LVGL 内存池泄漏 / 结构性漂移(量的是 `used`,与 `LV_MEM_SIZE` 总大小无关) |
### 5.3 黄金参考与字体纪律
+1 -1
View File
@@ -119,7 +119,7 @@
- **初始化回归**:`App/task/ui_task.c` 已有 `UI port init: OK` / `UI menu init: OK` / `UI net sink: started`
打印(见 `@test` 命令示例);将其加入 `-Required` 即可经串口自动回归 UI 初始化。
- **屏幕内容回归**:由 LVGL 模拟器像素回归覆盖(文本级断言 + 53 页黄金参考 + 池水位门禁,
- **屏幕内容回归**:由 LVGL 模拟器像素回归覆盖(文本级断言 + 60 页黄金参考 + 池水位门禁,
见 `docs/UI设计/UI_自动化测试流程.md`);上机屏幕仍需人工目检(L3 层,见 `测试开发标准流程.md` §1)。
## 扩展用法
@@ -117,7 +117,7 @@ test/host/cfg_file/cfg_file_test.c
| **TC-CONFIG-003** | IP4:`0.0.0.0` / `255.255.255.255` / 常规;段数不足/超、>255、非数字、尾点、空 | 点分四段 |
| **TC-CONFIG-004** | MAC:`:` / `-` / `.` 三种分隔符、大小写;过短/过长/非十六进制/坏分隔符 | 分隔符 = **字节边界**替代 |
| **TC-CONFIG-005** | STR:正常 + NUL;恰好 `len-1` 放下;`len` 字符拒绝;空串 | 长度边界 |
| **TC-CONFIG-006** | INT 合法:0 / `-1` / INT32_MIN / INT32_MAX / int8·int16 正负边界 / 前导 `+` / `-0` / 前导零 | 有符号十进制解码(数据可信卡 3,引擎 v1.5) |
| **TC-CONFIG-006** | INT 合法:0 / `-1` / INT32_MIN / INT32_MAX / int8·int16 正负边界 / 前导 `+` / `-0` / 前导零 | 有符号十进制解码(「数据可信」有符号零点类型,引擎 v1.5) |
| **TC-CONFIG-007** | INT 非法:空 / 非数字 / 尾随垃圾 / 裸符号 / 小数点 / `0x` 文本 / 各宽度越界(含 strtol 饱和带 `2147483648`)/ 坏 len | ERANGE + 宽度上下界双校验(两端 long=32 位) |
| **TC-CONFIG-008** | INT 编码带负号(`%ld`);`[sys]` 段 load→save→load 全链往返一致、出厂模板带负号默认;越界键拒收留默认并留痕;注册拒绝 INT len=3 | 有符号落盘闭环(负零点偏移可表达) |
@@ -285,4 +285,4 @@ if (s_encode(p_key, ..., v, sizeof(v)) >= 0) {
| 日期 | 变更 |
|---|---|
| 2026-10-02 | 创建;20 用例 / 139 断言点全绿;抓出并修复 `s_encode` 返回值误判 P0 缺陷(外科手术保存死码);挂 pre-commit 钩子 `cfg-file-unit-test` |
| 2026-10-25 | 随配置引擎新增 `CFG_VAL_INT`(数据可信卡 3)补登记 TC-CONFIG-006~008;套件 200/200 PASS |
| 2026-10-25 | 随配置引擎新增 `CFG_VAL_INT`(「数据可信」有符号零点类型)补登记 TC-CONFIG-006~008;套件 200/200 PASS |
+14 -14
View File
@@ -135,12 +135,12 @@ STM32(U17)为 LQFP144 脚号。
| `adc_task` | **已实现(B1,2026-10-10;L1 层 v2.3;P1-5 事件驱动消费,2026-10-10)**:`App/task/adc_task.c` 每拍调 `adc_input_poll()`(`App/algo/adc_input.c`)= TPAFE `tpafe5160_snapshot()` 原子快照(8 通道)+ 消费一帧 STM32 ADC1 DMA 乒乓缓冲,**经 `adc_input_raw()` 按语义取数**(不再直接索引驱动缓冲);**消费唤醒由 TIM3 ISR 置位 `ADC_WAKE_FLAG`**(不再 1 ms 轮询);任务在 `Src/freertos.c` 的 `USER CODE` 区创建为 `adcTask`(512 words / **AboveNormal**) | 数据路径已通(台架 `@test`:`frames` 严格 1000 Hz 递增、**`idle=0`**、`adc1_rc=0` / `adc1_err=0`) |
| TPAFE 采样触发 | **周期 CONVST 已实现(2026-10-10)**:`Src/main.c` 的 `HAL_TIM_PeriodElapsedCallback` 在 **TIM3 更新事件(1 kHz)** 内调 `tpafe5160_start_conv_irq()`;`app_main_init()` 用 `HAL_TIM_Base_Start_IT(&htim3)` 启动节拍(在 `tpafe5160_init()` 之后)。同一 TIM3 更新事件还经 **TRGO** 硬件触发 ADC1 一轮 9 通道(DMA 搬运),并调 `adc_tick_irq_notify()` **唤醒消费者**(P1-5 方案 a,2026-10-10;内含"消费者就绪"门)→ 两片转换器由同一硬件事件同源对齐 | 连续波形(1 kHz);详见 `docs/子系统设计/ADC采样节拍设计说明.md` §4(DMA 乒乓搬运)与 §6(事件驱动唤醒) |
| 前端偏置 | 每路 1k 串联 + 滤波 C 跨接差分输入;差分负端(`*_GND` 网)经 1k 拴 AGND。**不是对地分压**(2026-10-27 网表追线定死,拓扑图见 §7.1),**无中点偏置** | TPAFE 输入阻抗 **1 MΩ 恒定**(`../芯片手册/TPAFE5160.md` "Analog Input Impedance" 节),故端子对 AGND 的直流通路 = 1k + 1 MΩ + 1k ≈ **1.002 MΩ**,不是 1 kΩ。两侧各 1 kΩ 是手册要求的**源阻抗匹配**(AIN_nP / AIN_nGND 外接源阻抗相等以抵消失调),**不是分压**。STM32 侧只能测 **0~3.3 V 单极性**,交流量负半周被削顶;主板侧只做监视可接受,若要算 RMS/功率需硬件补偏置或明确算法口径 |
| TPAFE 量程(**2026-10-25 卡 1 定死**) | 板上 RANGE 接 GND → **±5 V 双极性量程**(芯片手册输入量程表:RANGE = 0 → −5 ~ +5 V),16 位二进制补码,**±5 V 满量程 = 10 V 跨度**,LSB = 10 V / 65536 ≈ **152.59 µV/码(@ 转换器引脚)**。“±10 V” 是芯片的另一可选档(RANGE = HIGH,跨度 20 V、LSB ≈ 305.18 µV),**本板未用**——历史版本曾把本板误标为“±10 V 双极性”,与 §7 本行矛盾、且会让 TPAFE 侧系数差一倍,更正记录见 §9 | 用 `tpafe5160_to_voltage()` 换算;端到端口径见 §7.1 |
| TPAFE 量程(**2026-10-25 量程口径冻结定死**) | 板上 RANGE 接 GND → **±5 V 双极性量程**(芯片手册输入量程表:RANGE = 0 → −5 ~ +5 V),16 位二进制补码,**±5 V 满量程 = 10 V 跨度**,LSB = 10 V / 65536 ≈ **152.59 µV/码(@ 转换器引脚)**。“±10 V” 是芯片的另一可选档(RANGE = HIGH,跨度 20 V、LSB ≈ 305.18 µV),**本板未用**——历史版本曾把本板误标为“±10 V 双极性”,与 §7 本行矛盾、且会让 TPAFE 侧系数差一倍,更正记录见 §9 | 用 `tpafe5160_to_voltage()` 换算;端到端口径见 §7.1 |
| 取数契约(**2026-10-10 已修**,E-44 / E-45 / E-58 闭环) | 旧的 `get_buf` / `data_ready` / `clear_ready` **已删除**(删除前确认全仓库零调用者):`get_buf` 只给指针、任务再拷 → 被 BUSY EXTI 抢占就是**两帧混合**;`s_ready` 电平标志被 `start_conv_irq` 触发前清 0 → **重触发即丢未消费帧**;`read_all` 从不看 FRSTDATA(宏有定义、代码零引用)→ 芯片死亡时返回 OK + 常量垃圾。现口径:**`tpafe5160_snapshot(dst, count)`**(临界区原子拷贝,返回 1/0/-1,**仅任务上下文**)+ **`tpafe5160_frame_seq()`**(帧序号只增不清)+ **`tpafe5160_frstdata_err()`**(无跳变帧计数);`tpafe5160_init()` 增**首帧自检**——一帧读下来 FRSTDATA 无跳变(芯片不驱动并行总线;板上 R24 4.7k 上拉会把它钉死为高)→ 返回 `-3` + `[ERR]` | 消费者**只能**用 `snapshot()` 取数(`AGENTS.md` 已立为铁律);真机实测开机 `[ADC] Init OK` 现只在自检帧通过后才打印 → 判据在本板成立、非空转 |
### 7.1 端到端量纲链路口径(网名 AINn → 端子 → 变比 → 码值 → 满量程,2026-10-25 卡 1 定死)
### 7.1 端到端量纲链路口径(网名 AINn → 端子 → 变比 → 码值 → 满量程,2026-10-25 量程口径冻结定死)
> 出处:`docs/任务规划/数据可信.md` 卡 1。本节把 **语义端子(二次侧)→ 子板/端子板 → 网名 `AINn` → 主板电阻网络 → 板级网名 `ADCn` → 转换器引脚 → 码值 → 满量程** 的链路**逐段**定口径;
> 出处:`docs/任务规划/数据可信.md` §2.1(量程口径冻结)。本节把 **语义端子(二次侧)→ 子板/端子板 → 网名 `AINn` → 主板电阻网络 → 板级网名 `ADCn` → 转换器引脚 → 码值 → 满量程** 的链路**逐段**定口径;
> 待实测段只给**口径与判据**,不填任何实测数值(本轮按用户指示跳过台架,标注“待台架实测”)。
**芯片级口径(定死,与前端网络无关)**:
@@ -152,7 +152,7 @@ STM32(U17)为 LQFP144 脚号。
| TPAFE LSB(@ 引脚) | 10 V / 65536 ≈ **152.59 µV/码**(≈6553 码/V) | 由上两行推得;与 §7“TPAFE 量程”行、驱动注释一致 |
| STM32 ADC1 LSB(@ 引脚) | 12 位单极性 0 ~ 3.3 V:3.3 V / 4096 ≈ **805.66 µV/码**(≈1241 码/V) | §7 生成配置行;`docs/任务规划/数据可信.md` §2.1 同口径 |
“±10 V”只允许出现在“芯片可选档”语境。本文件 2026-10-09 建档时曾把文首摘要写成“TPAFE … ±10 V 双极性”,与 §7 的 ±5 V 档矛盾、**TPAFE 侧系数因此会差一倍**——2026-10-23 `docs/任务规划/数据可信.md` §2.1 挂账该冲突并要求卡 1 定死;现**定死为“±5 V 满量程 = 10 V 跨度、LSB 152.59 µV”**,文首摘要与 §7 已按此更正。全仓其余“±10 V”字样仅剩芯片手册转写与 `tpafe5160.h` 中 RANGE 枚举可选档注释(均为芯片能力描述,非本板配置口径),不构成歧义。
“±10 V”只允许出现在“芯片可选档”语境。本文件 2026-10-09 建档时曾把文首摘要写成“TPAFE … ±10 V 双极性”,与 §7 的 ±5 V 档矛盾、**TPAFE 侧系数因此会差一倍**——2026-10-23 `docs/任务规划/数据可信.md` §2.1 挂账该冲突并要求量程口径冻结定死;现**定死为“±5 V 满量程 = 10 V 跨度、LSB 152.59 µV”**,文首摘要与 §7 已按此更正。全仓其余“±10 V”字样仅剩芯片手册转写与 `tpafe5160.h` 中 RANGE 枚举可选档注释(均为芯片能力描述,非本板配置口径),不构成歧义。
**③ 段的实际拓扑**(2026-10-27 按 `V0.1.tel` 逐通道追线,UA 为例;图由
`tools/arch_diagram/gen_adc_frontend_svg.py` 生成,改图请改脚本重跑,勿手改 SVG):
@@ -169,17 +169,17 @@ STM32(U17)为 LQFP144 脚号。
|---|---|---|
| ① 语义 ↔ 网名 ↔ 板级网名 ↔ 转换器代码通道 | §2/§3/§4/§5 的 17 路映射表 | **定死**(本文件为唯一权威) |
| ② 转换器引脚电压 ↔ 码值 | TPAFE `U_pin = code × 152.59 µV`(code 带符号);STM32 `U_pin = code × 805.66 µV` | **定死**(纯转换器事实,上表) |
| ③ `AINn`(串联电阻子板侧)↔ `ADCn`/转换器引脚 | **变比 = 1:1(2026-10-27 定死)**:`ADCn` 节点只有 {串阻.2, 滤波 C, 转换器引脚},无对地元件(拓扑图见上)。旧"读法 A(2:1 分压 → 305.18 / 1611.3 µV/码)"**作废**——它是把接在差分负端的 1k 误读成对地分压 | **定死**(网表级结论 + **2026-10-27 台架实测确认**,见 §8.1:端子侧注入斜率 6544.2 码/V,与引脚侧理论 6553.6 差 0.14 %,不存在 2:1 分压)。卡 0 已闭环 |
| ④ 语义端子(二次端子)↔ `AINn` | 子板/端子板变比:仓库内**无任何文档**(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图;§8 步骤 4) | **缺口**——卡 0b 实测确认;拿不到变比则"端子二次值"不成立、`eng` 保持 0 |
| ③ `AINn`(串联电阻子板侧)↔ `ADCn`/转换器引脚 | **变比 = 1:1(2026-10-27 定死)**:`ADCn` 节点只有 {串阻.2, 滤波 C, 转换器引脚},无对地元件(拓扑图见上)。旧"读法 A(2:1 分压 → 305.18 / 1611.3 µV/码)"**作废**——它是把接在差分负端的 1k 误读成对地分压 | **定死**(网表级结论 + **2026-10-27 台架实测确认**,见 §8.1:端子侧注入斜率 6544.2 码/V,与引脚侧理论 6553.6 差 0.14 %,不存在 2:1 分压)。已知电压注入验证已闭环 |
| ④ 语义端子(二次端子)↔ `AINn` | 子板/端子板变比:仓库内**无任何文档**(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图;§8 步骤 4) | **缺口**——待「端子/子板变比确认」实测确认;拿不到变比则"端子二次值"不成立、`eng` 保持 0 |
**可评审结论**:
1. **ROM 默认系数按 ② 引脚口径冻结**:TPAFE 通道 `k = 152.59 µV/码`、STM32 通道 `k = 805.66 µV/码`;标定折算的输出单位 = **ADC 引脚电压 V**(`eng = 0`)。该口径**不依赖** ③④ 两个未决项,自本卡定死即成立——这就是 M4 承诺边界止于“引脚电压”的依据(`docs/任务规划/数据可信.md` §2.6)。
1. **ROM 默认系数按 ② 引脚口径冻结**:TPAFE 通道 `k = 152.59 µV/码`、STM32 通道 `k = 805.66 µV/码`;标定折算的输出单位 = **ADC 引脚电压 V**(`eng = 0`)。该口径**不依赖** ③④ 两个未决项,自本节点死即成立——这就是 M4 承诺边界止于“引脚电压”的依据(`docs/任务规划/数据可信.md` §2.6)。
2. `docs/任务规划/数据可信.md` §2.1 旧表的“板级系数(输入侧)305.18 / 1611.3 µV/码”**已随 ③ 段定死而删除**(2026-10-27):该值按 2:1 分压折算,而网表证明 `ADCn` 节点无对地元件。板级系数 = 引脚侧系数(152.59 / 805.66);305.18 / 1611.3 今后只允许出现在“±10 V 档 LSB”语境(芯片手册口径),不得再当本板系数。
3. **满量程必须写明参考点**:TPAFE 通道满量程 = ±5 V **@ 引脚**(跨度 10 V);③ 已定 1:1、④ 仍未知,故端子侧满量程只允许写“引脚侧数值 × ④ 比”,**严禁**把“码 × 152.59 µV”当端子二次值写进代码/文档(那是引脚电压)。
4. **卡 0 已于 2026-10-27 闭环**(六项判据全 PASS,实测见 §8.1):③ 段 1:1 由台架直接证实,
4. **已知电压注入验证已于 2026-10-27 闭环**(六项判据全 PASS,实测见 §8.1):③ 段 1:1 由台架直接证实,
② 引脚侧 LSB 与实测斜率差 0.14 %,逐通道映射与极性均已验。**仍待实测的是 ④**(端子→引脚
变比,卡 0b)与卡 12(两点标定);两者完成前 `eng` 保持 0、输出单位仍是 ADC 引脚电压。
变比,即端子/子板变比确认)与两点标定;两者完成前 `eng` 保持 0、输出单位仍是 ADC 引脚电压。
实测斜率与 ② 理论值偏差 >2 % 时**先查前端**(分压/变比/焊接),不得用系数凑错斜率
(`docs/任务规划/数据可信.md` §8 风险表)。
@@ -187,10 +187,10 @@ STM32(U17)为 LQFP144 脚号。
## 8. 逐通道验证方法(上板自检口径)
1. **TPAFE 侧**:对目标 `AIN` 注入 1 V DC → 观察对应 `buf[i]` 变化(UA→`buf[6]`、UN→`buf[5]`、IA→`buf[2]`),同时 U3.14 `BUSY` 有脉冲;**语义与下标不符即映射错**。✅ **2026-10-27 已执行**(原 2026-10-23 挂账的"无执行记录"已消除;`docs/硬件平台/V0.0_网表详细分析报告.md` §5.1 第 6 条的同一验证随之关闭)。判据按 `docs/任务规划/数据可信.md` 卡 0 的**不需要示波器**口径执行:① "`BUSY` 有脉冲"改用固件帧计数——注入前后 `tpafe5160_frame_seq()` 仍严格 1000 Hz 递增即等价;② 幅值判据改用万用表读注入点实际电压 + 同时读 `adc_input_raw()` 码值,三点线性拟合(R² ≥ 0.999)。
1. **TPAFE 侧**:对目标 `AIN` 注入 1 V DC → 观察对应 `buf[i]` 变化(UA→`buf[6]`、UN→`buf[5]`、IA→`buf[2]`),同时 U3.14 `BUSY` 有脉冲;**语义与下标不符即映射错**。✅ **2026-10-27 已执行**(原 2026-10-23 挂账的"无执行记录"已消除;`docs/硬件平台/V0.0_网表详细分析报告.md` §5.1 第 6 条的同一验证随之关闭)。判据按已知电压注入验证的**不需要示波器**口径执行:① "`BUSY` 有脉冲"改用固件帧计数——注入前后 `tpafe5160_frame_seq()` 仍严格 1000 Hz 递增即等价;② 幅值判据改用万用表读注入点实际电压 + 同时读 `adc_input_raw()` 码值,三点线性拟合(R² ≥ 0.999)。
2. **STM32 侧**:对目标引脚(如 PC4=UB)注入 0.5 V → 读 `ADC_CHANNEL_14` 应变化;若不变而相邻通道变化 → 通道宏写错(见 §5 警告)。✅ **2026-10-27 已执行**(原 2026-10-10 的"尚未执行"已消除;当时台架只验证了"9 通道全部转换成功 + 零超时 + 互异非饱和 + 跨次开机读数不同",台架无信号源);映射的**代码侧**一致性有两道保证:① `App/algo/adc_input.c` 的 `k_adc_map[]` 与 CubeMX 标签(`ADC17_UB`=PC4 等)逐条对齐;② 开机自检 `adc_input_init()` 校验每个 STM32 语义通道都落在 `k_stm32_rank_ch[]` 扫描序列内(挡"映射到不扫描的通道 → 恒读陈旧值")。
3. **备用通道**:RESERVED 路不接入任何语义,UI 与上报里不得出现;若实测有读数漂移,只记录不消费。
4. **端子侧变比(2026-10-23 补,2026-10-27 收窄)**:上面 1/2 两条都只到 **ADC 引脚**。③ 段(`AINn` ↔ 转换器引脚)已由网表追线定死为 **1:1**(`ADCn` 节点无对地元件,拓扑图见 §7.1),**板内不再有未知比值**;剩下的未知量只有 ④ **子板/端子板变比**——它在仓库里没有任何文档给出(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图)。故**不得**用"2:1 分压"换算出二次值;该变比由 `docs/任务规划/数据可信.md` 卡 0b 实测确认。
4. **端子侧变比(2026-10-23 补,2026-10-27 收窄)**:上面 1/2 两条都只到 **ADC 引脚**。③ 段(`AINn` ↔ 转换器引脚)已由网表追线定死为 **1:1**(`ADCn` 节点无对地元件,拓扑图见 §7.1),**板内不再有未知比值**;剩下的未知量只有 ④ **子板/端子板变比**——它在仓库里没有任何文档给出(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图)。故**不得**用"2:1 分压"换算出二次值;该变比由「端子/子板变比确认」实测确认。
### 8.1 2026-10-27 实测记录(首次执行,六项判据全 PASS)
@@ -228,6 +228,6 @@ STM32(U17)为 LQFP144 脚号。
| 2026-10-09 | **CubeMX 生成 ADC1(9 通道)落地**:新增 `Src/adc.c`/`Inc/adc.h` + HAL adc 三文件并挂进 uvprojx、`HAL_ADC_MODULE_ENABLED` 生效、`MX_ADC1_Init()` 入 `main.c`;分频 PCLK2/4 = 21 MHz——面板里 DIV2 已被 `FadcConstraint`(36 MHz)约束禁掉,**故不加 `.ioc` 键 / 代码守卫 / 审计项等额外防护**(曾加过,按决定撤除,理由见 §7"ADC 时钟"行);修正 PA0 标签笔误 `AD9_RES`→`ADC9_RES`。⚠ 本次重生成打回了 5 处定制(IWDG 延迟启动锚点、HardFault + 3 个 Fault 手工 Handler、`FreeRTOSConfig.h` 加固区、`freertos.c` 三处栈核算注释),已全部复原;存活审计新增 1 项 `adc1-hal-enabled`(共 19 项),现 19 通过 / 1 警告(timeSyncTask 手工定义)/ 0 失败,`@build` 0 错 0 警 |
| 2026-10-10 | **口径更正**:8 路电气量分属 TPAFE / STM32 两片转换器**定性为 V0.1 硬件缺陷**,撤销 2026-10-09 建档时"有意分配、不要修正"的说法;补记缺陷实质(跨转换器无同一时刻性、16 位双极性 vs 12 位单极性、语义与归属交叉)与 **V0.2 改版要求**(8 路电气量全部接 TPAFE,与 5 路备用路对调串联电阻目的地,BOM 不变);§7 新增"通道归属"行,明确 V0.1 上禁止跨转换器做相位/功率类运算。同步更正 `V0.1_网表详细分析报告.md` §1.4(新增 V10)/ §6-3,登记簿新增 **N-18** |
| 2026-10-10 | **STM32 ADC1 消费者落地(L1-3/L1-4)**:新增 `App/algo/adc_input.c/h`——语义映射表 `k_adc_map[]` 按本文件 §3/§5 逐条落地(`UA/UN/IA`→TPAFE `buf[6]/[5]/[2]`,`UB/UC/IB/IC/IN/TEMP`→`CH14/3/6/1/2/5`),并提供 `adc_input_raw()` **按语义取数**;`stm32_scan()` 实现 9 通道软件触发顺序扫描;`adc_input_init()` 增**映射自检**(STM32 映射通道必在扫描序列内)。§7 的"STM32 ADC 外设 / `adc_task` / TPAFE 采样触发"三行同步更新(后两者原为陈旧描述:TIM6 周期触发、L1 层取数)。§8 步骤 2 标注**引脚级注入验证尚未执行**。台架 `@test` PASS(`adc1_rc=0` / `adc1_err=0`、`ADC input layer init: OK`;首帧 `UA=11429 UN=11454 IA=11452`、`UB=1018 UC=1044 IB=943 IC=1069 IN=1052 T=850`——互异非饱和,且两次开机读数不同 → 实时转换而非常量),证据 `测试说明/boot_log_data/20261010_prod_adc_l1_boot_log.txt` |
| 2026-10-23 | **验证现状核查与排期**:确认 §8 步骤 1/2 与 `V0.0_网表详细分析报告.md` §5.1 第 6 条的"首次功能级 ADC 验证"**均无执行记录**——现有台架判据只证"通路活"(9 通道转换成功、零超时、互异非饱和、跨次开机不同),不证读数正确,连极性都未验。新增 §8 步骤 4:**"端子电压 → ADC 引脚电压"的变比在仓库内无任何文档**(无子板原理图),且 `1k 串联 + 1k 到地` 已被 §4.7 定性为"源阻抗匹配、非分压",故撤销"按 2:1 换算二次值"的用法。验证方法同步降为**不需要示波器 / 信号源**:`BUSY` 脉冲改用 `tpafe5160_frame_seq()` 帧计数,幅值改用万用表 + 三点线性拟合。排期见 `docs/任务规划/数据可信.md` 卡 0 / 0b |
| 2026-10-25 | **量程口径定死(本波卡 1)**:文首摘要行“TPAFE5160(16 位、8 通道同步、±10 V 双极性)”更正为“±5 V 满量程 = 10 V 跨度、LSB ≈ 152.59 µV(板上 RANGE 接 GND)”;§1“缺陷实质 2”补“满量程 = 10 V 跨度”;§7“TPAFE 量程”行重写并括注“±10 V 是芯片可选档(RANGE=HIGH)、本板未用”;新增 §7.1 固化“端子 → 子板变比 → 网名 AINn → 电阻网络 → 引脚 → 码值 → 满量程”链路分段口径——② 引脚侧 LSB 系数(TPAFE 152.59 / STM32 805.66 µV/码)**定死**,③ 1k+1k 网络“2:1 分压 vs 源阻抗匹配”两读法待卡 0 斜率判别,④ 端子变比为仓库缺口待卡 0b;“板级系数 305.18 / 1611.3 µV/码”定性为读法 A 条件值、判别前禁入代码;新增内容全部收进 §7.1 子节、本章编号刻意保持 §9 不动(`docs/算法/继电保护功能复现规划.md` §4 有指向本文件 §9 的既有跨文档引用,挪号会打断 doc-links 章节校验)。实测数值本轮按用户指示未采(台架未跑),相关段均标“待台架实测” |
| 2026-10-27 | **③ 段定死为 1:1(网表追线)**:逐通道追 `V0.1.tel`,`ADCn` 节点(如 UA 的 `ADC7`,第 241 行 `ADC7 ; C44.2 R31.2 U3.61`)只有 {串阻.2, 滤波 C, 转换器引脚} 三者,**无对地元件**——"1k 到地"实际接在差分负端(`ADC7_GND` → R32 → AGND,第 151 行),属差分滤波。故 ③ 段不是分压器、变比 1:1,旧"读法 A(2:1 分压 → 305.18 / 1611.3 µV/码)"**作废**,`docs/任务规划/数据可信.md` §2.1 旧表同步改为引脚侧系数。§7.1 新增拓扑 SVG(`docs/images/ADC前端电路.svg`,生成器 `tools/arch_diagram/gen_adc_frontend_svg.py`),含 STM32 侧对照面板;§7"前端偏置"行、§8 步骤 4 同步改写。卡 0 的判据随之从"判别 A/B 读法"降为"确认转换器 LSB 与逐通道映射" |
| 2026-10-23 | **验证现状核查与排期**:确认 §8 步骤 1/2 与 `V0.0_网表详细分析报告.md` §5.1 第 6 条的"首次功能级 ADC 验证"**均无执行记录**——现有台架判据只证"通路活"(9 通道转换成功、零超时、互异非饱和、跨次开机不同),不证读数正确,连极性都未验。新增 §8 步骤 4:**"端子电压 → ADC 引脚电压"的变比在仓库内无任何文档**(无子板原理图),且 `1k 串联 + 1k 到地` 已被 §4.7 定性为"源阻抗匹配、非分压",故撤销"按 2:1 换算二次值"的用法。验证方法同步降为**不需要示波器 / 信号源**:`BUSY` 脉冲改用 `tpafe5160_frame_seq()` 帧计数,幅值改用万用表 + 三点线性拟合。排期见 `docs/任务规划/数据可信.md`(已知电压注入验证 / 端子/子板变比确认) |
| 2026-10-25 | **量程口径定死(本波)**:文首摘要行“TPAFE5160(16 位、8 通道同步、±10 V 双极性)”更正为“±5 V 满量程 = 10 V 跨度、LSB ≈ 152.59 µV(板上 RANGE 接 GND)”;§1“缺陷实质 2”补“满量程 = 10 V 跨度”;§7“TPAFE 量程”行重写并括注“±10 V 是芯片可选档(RANGE=HIGH)、本板未用”;新增 §7.1 固化“端子 → 子板变比 → 网名 AINn → 电阻网络 → 引脚 → 码值 → 满量程”链路分段口径——② 引脚侧 LSB 系数(TPAFE 152.59 / STM32 805.66 µV/码)**定死**,③ 1k+1k 网络“2:1 分压 vs 源阻抗匹配”两读法待已知电压注入验证斜率判别,④ 端子变比为仓库缺口待「端子/子板变比确认」;“板级系数 305.18 / 1611.3 µV/码”定性为读法 A 条件值、判别前禁入代码;新增内容全部收进 §7.1 子节、本章编号刻意保持 §9 不动(`docs/算法/继电保护功能复现规划.md` §4 有指向本文件 §9 的既有跨文档引用,挪号会打断 doc-links 章节校验)。实测数值本轮按用户指示未采(台架未跑),相关段均标“待台架实测” |
| 2026-10-27 | **③ 段定死为 1:1(网表追线)**:逐通道追 `V0.1.tel`,`ADCn` 节点(如 UA 的 `ADC7`,第 241 行 `ADC7 ; C44.2 R31.2 U3.61`)只有 {串阻.2, 滤波 C, 转换器引脚} 三者,**无对地元件**——"1k 到地"实际接在差分负端(`ADC7_GND` → R32 → AGND,第 151 行),属差分滤波。故 ③ 段不是分压器、变比 1:1,旧"读法 A(2:1 分压 → 305.18 / 1611.3 µV/码)"**作废**,`docs/任务规划/数据可信.md` §2.1 旧表同步改为引脚侧系数。§7.1 新增拓扑 SVG(`docs/images/ADC前端电路.svg`,生成器 `tools/arch_diagram/gen_adc_frontend_svg.py`),含 STM32 侧对照面板;§7"前端偏置"行、§8 步骤 4 同步改写。已知电压注入验证的判据随之从"判别 A/B 读法"降为"确认转换器 LSB 与逐通道映射" |
@@ -409,7 +409,7 @@
> ⚠️ **待补**:逐项**取值范围 / 步长 / 默认值**取自参考项目 `APP/EquipCfg/Const_CommPara.c` 的 `CommPara_ConfigTable`(`0x8020~0x8882`);本表在实现各保护元件时逐项落实(见 §10.3)。
>
> **2026-10-25 运行参数段落实进度**:卡 10 已落 `App/algo/run_par.c`——本仓自定逐项地址
> **2026-10-25 运行参数段落实进度**:这一项已落 `App/algo/run_par.c`——本仓自定逐项地址
> 0x8030~0x8038(死区 9 点)/ 0x8040~0x804F(k/b 覆盖直通 adc_cal),表与理由见
> `docs/子系统设计/IEC104上行设计说明.md` §3.4;**送检点表到位后以送检为准替换常量段**。
> 变比/报警/录波/功率置负等其余运行参数类项目前无消费者,留白不预埋。
@@ -5,8 +5,8 @@
> 边界与代价。**目录级索引(文件清单、构建与测试命令、新增模块动作)在 `App/algo/README.md`**,
> 本文不重复其内容;本文不写历史演进、门禁复测记录与修订日志(需要时查 git 历史)。
> **状态**:L1 → L2 → L3 主线已闭环到板端消费者(`protectTask`,20 ms 判据节拍);
> 标定折算层 `App/algo/adc_cal` 已于 2026-10-25 落地(`docs/任务规划/数据可信.md` 卡 2/4,
> 引脚电压量纲 + 系数落盘 + 未标定闭锁);**幅值精度判据**仍待标准源两点注入复核(卡 12)。
> 标定折算层 `App/algo/adc_cal` 已于 2026-10-25 落地(标定折算与落盘整定,`docs/任务规划/数据可信.md` §4.1,
> 引脚电压量纲 + 系数落盘 + 未标定闭锁);**幅值精度判据**仍待标准源两点注入复核(两点标定,`docs/任务规划/数据可信.md` §5)。
> **相关文档**:
> 分层与功能项(L1~L5)的唯一属主登记处:`docs/算法/继电保护功能复现规划.md` §2.1(分层)、§3(功能清单)、§4.2(精度)、§7(路线图)
> `docs/硬件平台/ADC通道映射说明.md`(**语义映射唯一权威口径**)
@@ -228,7 +228,7 @@ flowchart TD
40.5~60.5 Hz(参考 `CN_HERTZ_SOFTFR_MIN/MAX`,见
`docs/算法/继电保护功能复现规划.md` §10.1),仍能拦住建"窗滑 2 拍"造成的 ≈2f(90~110 Hz)
与相位跳变假值;系统合理带由 OF / UF 的**定值范围**在消费侧把关,不在这里重复把关。
- **幅值门** `FREQ_AMP_MIN = 50.0`(2026-10-25 卡 6 语义重定为**二次值 V**:50 V = 0.5×Un,
- **幅值门** `FREQ_AMP_MIN = 50.0`(2026-10-25 下游常数按工程量重定后语义为**二次值 V**:50 V = 0.5×Un,
数值沿旧 50.0 属巧合,量纲依据 `App/algo/prot_set.c` 头部量纲基准块):低于门视为
无有效波形(浮空 / PT 断线时 rms ≈ 0,相位无意义)→ 停止更新、`valid` 清零、读数保持,
台架浮空因此**不发散**;信号刚消失的过渡段(≤20 ms 残窗)读数漂移有界 ≤0.3 Hz。
@@ -342,7 +342,7 @@ UA 无幅值落 IA → 0.0020 Hz。
STM32 ADC1,两片转换器没有共同采样触发 → 无同一时刻性、相位不确定。故本层**不做**跨转换器的
相位 / 功率 / 功率因数 / 负序零序类矢量运算;**8 路全接 TPAFE(V0.2 硬件)后方可解禁**。
3. **标定折算已落地、精度复核未做**(2026-10-25 `App/algo/adc_cal`;标准源两点注入见
`docs/任务规划/数据可信.md` 卡 12):帧值现 = 引脚侧工程量(ROM 默认系数 = 转换器 LSB 事实值),
`docs/任务规划/数据可信.md` §5(两点标定):帧值现 = 引脚侧工程量(ROM 默认系数 = 转换器 LSB 事实值),
前端分压读法判别与端子变比仍待台架——**精度结论前不得把幅值当计量证据**。
4. **本层无副作用外溢**:不建任务、不等事件、不写日志(日志由调用侧打)、不碰寄存器
(例外只有 `adc_input.c` 驱动 ADC1)。
+44
View File
@@ -144,6 +144,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
|---|---|---|
| 登记簿 `N-x` / `S-x` / `T-x`、专项 `A-x`、已删报告的 UI 簇 `U1~U5`(2026-10-26 方案 B) | 语义短语——**登记簿表首格本身就是短语**,如「双转换器无共同采样触发」「CI 远端闭环未验证」 | `scripts/id_aliases.json` 标 `retired-to-phrase` |
| 网络设计条目 `F-NET/F-DRV/F-MS-<nn>`(12 个,2026-10-27 批次一) | 「§7 + 条目名」短语,如 `(§7「全局读即清搁浅事件」)`;条目名的权威清单 = `docs/网络/网络自愈架构设计.md` §7「条目名」列;那个 DRV 段孤儿号按本节末句**删号留事实**、未补定义 | `scripts/id_aliases.json` 标 `retired-to-phrase`(13 条)+属主文档 §7 编号列仅作历史对照 |
| 「数据可信」任务卡号(中文前缀「卡」+ 数字,形态见 §9.3;2026-10-27 批次五) | §5 表的**标识列直接写任务名**(「端子/子板变比确认」「两点标定与精度验收」),代码注释与文档写语义短语(「标定折算落地」「未标定闭锁」「遥测快照发布」…);**逐号换算表见本文 §9.3** | ⚠ **机器面空白**:中文前缀不进 `scripts/check_ids.py` 语料(族 pattern 全是拉丁形态)→ 门禁咬不到,今天只有本表 + §9.3 + 评审三条兜;`id_aliases.json` 刻意不登记(登记了机器也看不见,只多一张没人核的表) |
| `E-xx` 审计发现、`P0-x`~`P3-x` 审计条目、报告六族 `D/R/F/N/U/S`、复审残号 `S1~S14`/`A-x`/`B1~B10`/`T-x`、模拟器差距 `H-x`/`L-x`、`TM-*` 阶段号、`DP-*`、`gen`/`round`/会话临时号 | 写条目本身("原子快照取数"、"队头阻塞"、"台架日志代次 288"、"第 3 轮台架") | 别名表标 `void`;**部分死号故意不进别名表**,好让门禁继续咬残留引用 |
| 规范曾规划却从未启用的前缀族(`DEF`/`WI`/`DR`/`OQ`/`RSK`/`GAP`/`SC`/`GEN`/`MS`/`UL`/`LAT`/`CS` 等) | 同上,写事实 | 无定义,本就不该存在 |
@@ -269,6 +270,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
| 二 | 保护功能号 28 个 | 代码与测试 215 处 + 文档 194 处 + 配置注释 3 处 + 入口文档 2 处;活文档只剩
**冻结的变更记录行 40 处**与**一处原始串口日志**(真机抓包证据,改它等于篡改现场,永久保留) |
| 三 | 测试用例族 561 站点 | **用户裁定不做**:该族保留,但**即日停发**(游标冻结,新用例不再配号) |
| 五 | 「数据可信」任务卡号 14 个(中文前缀「卡」+ 数字),随注入验证卡销项整族清退 | 全仓 288 站点 / 56 文件改语义短语(代码与测试 191 / 文档 56 / 门禁配置与本文 41),活引用收口 **0**;门禁字面量与不可判定绝对数**零变化**(本族从不在计数内)——换算表与机器面空白见 §9.3(批次四记在上面的复测段,未进本表) |
编号字面量 **8,787 → 7,828**;不可判定绝对数 **1,161 → 982**(上限 1,166,余量从 5 格宽到 184 格)。
比值 86.79% → 87.46% 属**纯稀释**(删的都是可判定引用,分子分母同缩),**基线不下调**,见本节末裁定。
@@ -381,6 +383,47 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
「编号说明」这件事本身应该继续变薄:每多一个族,就多一处需要有人记得它的地方;每多发一个号,就多一个
将来没人敢删的字符串。要新增族之前,请把 §4.1 的「允许继续发号」那 5 行当作反对你的第一手证据。
### 9.3 批次五换算表:「数据可信」任务卡号(2026-10-27 整族清退)
用户指令(2026-10-27):「**数据可信.md 已经完成的内容请进行销项删除,去除相关编号**」。两件事同做:
1. **销项**:`docs/任务规划/数据可信.md` §5 里 2026-10-27 台架闭环的「已知电压注入验证」行**删行**。
上一笔曾特意标 ✅ 保留,理由是该行被 `App/task/adc_task.c` 的 v3.3 修订行按卡号当口径出处引用;
引用侧改成语义短语后该理由不再成立 → **例外撤销**。判据与实测记录的属主 =
`docs/硬件平台/ADC通道映射说明.md` §8.1(六项判据全 PASS、斜率 6544.2 码/V、偏差 −0.14 %),
执行侧 = `docs/测试说明/ADC前端注入验证流程.md`(含两项残留口径与残差表)。
2. **整族清退**:「卡」+ 数字 1~11 那 11 行早在 2026-10-25 就删完了,代码注释里剩下的这种形态今天
**查无此行**——按 §4.1.1 末句,正确动作是**删号留事实**(换成语义短语),不是回去补一个定义。
| 旧号形态 | 语义短语 | 现行口径出处 |
|---|---|---|
| 「卡」+ 数字 0 | 已知电压注入验证 | `docs/硬件平台/ADC通道映射说明.md` §8.1(✅ 2026-10-27,已销项删行) |
| 「卡」+ 数字 0b | 端子/子板变比确认 | `docs/任务规划/数据可信.md` §5;缺口面 = `docs/硬件平台/ADC通道映射说明.md` §7.1 链路分段表 ④ 行 |
| 「卡」+ 数字 1 | 量程口径冻结 | `docs/任务规划/数据可信.md` §2.1 |
| 「卡」+ 数字 2 | 标定折算落地 | `docs/任务规划/数据可信.md` §4.1 |
| 「卡」+ 数字 3 | 有符号零点类型(CFG_VAL_INT) | `docs/任务规划/数据可信.md` §4.4 |
| 「卡」+ 数字 4 | 标定落盘与整定入口 | `docs/任务规划/数据可信.md` §4.4 |
| 「卡」+ 数字 5 | 未标定即闭锁 | `docs/任务规划/数据可信.md` §4.3 |
| 「卡」+ 数字 6 | 下游常数按工程量重定 | `docs/任务规划/数据可信.md` §2.3 |
| 「卡」+ 数字 7 | 量纲回归用例 | `docs/任务规划/数据可信.md` §3 退出判据第 ⑥ 条;用例在 `test/host/prot_dim` |
| 「卡」+ 数字 8 | 遥测快照发布 | `docs/任务规划/数据可信.md` §4.5 |
| 「卡」+ 数字 9 | 104 改读快照 | `docs/任务规划/数据可信.md` §4.5 |
| 「卡」+ 数字 10 | 运行参数段 | `App/algo/run_par.h` 头注释 + `docs/子系统设计/IEC104上行设计说明.md` |
| 「卡」+ 数字 11 | 频率点绑定 | `docs/子系统设计/IEC104上行设计说明.md` 的 `0x401D` 行 |
| 「卡」+ 数字 12 | 两点标定 | `docs/任务规划/数据可信.md` §5(未开始,等标准源) |
**本表把形态写成「卡」+ 数字、不复述字面量**:本文是门禁语料,复述形态会把"讲规则的文档"变成
自己的引用站点(§9.1 批次四第 2 条同一条教训);要查旧号,看左列形态 + 属主文档的历史行。
- **旧号永久作废、不得重新取走**:这一族**没有机器识别面**(中文前缀不进语料),停发今天只有
§4.1.1 本行 + 本表 + 评审兜住。要机械化,得先给"中文前缀 + 数字"设计候选形态——那与 §9.1 末尾
「族级加字面量上限」同属追溯机制改造,**按 §7.3 单独开卡**,别夹在清退批里顺手做。
- **同形态不同属主**:`docs/任务规划/UI补齐.md` 的条目现在写「第 N 项」,历史上被别处写成同一形态的
4 处(其实指已入库的 `[comm]` 段前置项)已随本批改成不带号的语义形态。同一裸形态跨两个属主文档,
正是 §4.1「别拿同形当同族」的实证——清号必须**按属主文档逐处判语义**,不许全局查找替换。
- **不在本批的**:里程碑号(字母 M + 数字)与并行道号(道A/道D/道G)一律保持原样,是否清退等用户
单独裁定,**不要顺手做**。
## 10. 速查
- 看到一个不认识的号 → 先查 `id_aliases.json` 与属主登记表;查不到就**删号留事实**,不要补定义。
- 想给待办 / 缺陷 / 差距 / 风险发号 → 不许,写短语(§3.3)。
@@ -396,6 +439,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
| 日期 | 变更 | 说明 |
|---|---|---|
| 2026-10-27 | **批次五:「数据可信」任务卡号整族清退 + 注入验证卡销项删行** | 用户指令「数据可信.md 已经完成的内容请进行销项删除,去除相关编号」。实测 **288 站点 / 56 文件**(代码与测试 191 / 文档 56 / 门禁配置与本文 41)全改语义短语;§5 表首列由「序」改「标识(任务名)」、14 个旧号进 §9.3 换算表;顺带按属主文档判语义清掉同形态的悬空引用 4 处(「UI 补齐」波次的 `[comm]` 段前置项)。门禁面:编号字面量与不可判定绝对数**零变化**(中文前缀不在语料),收口复跑 `check_ids.py --strict` 与 `check_doc_links.py --all --sections-strict` |
| 2026-10-27 | **批次四:`L-PROT` / `FEAT` 发号口关闭(§4.1 七行→五行)+ 本文自述形态化 + 登记 `T-TEST` 机器面空白** | 用户指令「语义标识已定为默认形态,看看还有哪些编号族仍被引用、各自还剩多少,把能清的族清掉一批」。按门禁 `Checker` 实测三口径重打 §9 存量表:**真编号活引用只剩 `TC-*`(保留、水位 497/81 未涨)、`TRAP-*`、`CODE-RULE-*`、`MENU-STATE-*` 四族**,批次一/二涉及的 `N-*`/`TM-*`/`T-TEST`/`L-PROT`/`FEAT` 活引用均已归零。本笔:① §4.1 把 `L<n>-<nn>`、`F-<MOD>-<nn>` 从『允许继续发号』整行移出并在『已停发』栏各写一行(含探针证据:新形态号 → 校验 3 错误级);② 本文 6 处形态自述改「字母+数字」描述,使四个族门禁命中归零、lesson 不丢;③ registry 给 `L-PROT`/`FEAT` 补 `retired`、给 `T-TEST` 补 cursor_note(pattern 上限即 3 → 冻结游标是空操作,停发今天只有规范效力);④ 分类登记 §4.4 误判面(版本记号 / 活表代号 / 状态组合 / 位号)与 §4.3 冻结波次号两类**不清**的理由。未改门禁判定逻辑、未动冻结历史与原始串口日志、未新增任何号。 |
| 2026-10-27 | **批次一 `F-*` 收口:网络设计 12 个条目号转「条目名」语义短语,§7 表加「条目名」列为权威对照** | 用户指令「把网络设计里的 `F-*` 条目号换成语义短语,别改坏硬件资料的 T1/T2/T3 位号和 Mermaid 节点名」。走 `scripts/rename_ids.py`(映射 `scripts/rename_maps/batch7-f-net-semantic.json`,`--no-alias` 后手工写别名),10 处定点改写=属主文档正文 9 处(含 1 处孤儿号删号留事实)+ `test/host/net_socket/net_socket_test.c` 注释 1 处;孤儿号 `F-DRV-9`(§7 从无定义行)删号留事实、不补定义;13 个旧号标 `retired-to-phrase`。刻意不动:§7 编号列(历史对照)、`BSD_Socket_API_使用指南.md` 变更记录行、`docs/硬件平台/` 位号、Mermaid 节点名。`scripts/id_registry.json` FEAT `cursor_note` 改记停发口径(三模块各有最高号 → 不冻结游标的理由写在里面)。零代码语义变更。 |
| 2026-10-27 | **停发机械化落地:34 个 `TC-HOST-*` 子族游标冻结,§8 校验 5 开始咬新配的 TC 号** | 上一笔把缺口登记为「停发今天只有规范效力」并写明机械化怎么做;本笔照它落地、把话兑现:`scripts/id_registry.json` 37 个 TC 类族全部 `frozen: true`,34 个子族的 `cursor` 冻结在裁定日存量最高号(字符串形态——整型比较静默不生效;5 个低于存量的已抬:`TC-PROTELEM-013→015`、`TC-SYSLOG-108→137`、`TC-ADCHEALTH-011→023`、`TC-ADCCAL-017→023`、`TC-I104SRV-041→053`),理由记在顶层 `tc_freeze_2026_10_27`。探针(Checker `_check_frozen`):在 `TC-PROTSET-` 段存量最高号之上再加一号 → 命中 1 条校验 5,写存量最高号本身 → 零误伤;`check_ids.py --only 5` = 0 处;plain 与 `--strict` 的错误级 findings 与本笔前逐条相同(**12 条 `TC-TIMESYNC-0xx` 悬空引用属另一道在飞的 time_sync 改动,不在本笔写域,也没替它改**);台账 0 条、可判定 87.67%、不可判定 979 / 上限 1,166,不动 §8.1。**没有把主族 `TC` 说成已冻结**:它 `cursor` 仍为 `null`,§4.1 框内第三条与 §9.1 末段把这块空白及其兜底(校验 3 + 冻结水位 564/474/79 只减不增 + 评审)写明,并规定「给这些模块补号即使在文档里补了定义行也算违令」。§9.1 末段由「效力边界」改写为「机器口径已落地」,当日实测留作历史不抹。零代码、零编号增删。 |
+1 -1
View File
@@ -53,7 +53,7 @@
| [`cubemx-survival.md`](cubemx-survival.md) | `cubemx-survival` | CubeMX 重生成会不会把定制静默抹掉(L3 审计兜底) | `.ioc`、`Src/`、`Inc/` | 已写 |
| [`test-suite-switch.md`](test-suite-switch.md) | `test-suite-switch` | 板级套件开关必须互斥;全注释 = 产品构建 | `test/board/test_config.h` | 已写 |
| [`font-charset.md`](font-charset.md) | `font-charset` | UI 用到的汉字是否都在子集字体里(缺字 = 白框) | `Drivers/BSP/UI/**`、字体脚本 | 已写 |
| [`ui-golden.md`](ui-golden.md) | `ui-golden` | UI 像素回归:菜单 8 状态 + 内容页 53 页黄金参考图比对 | UI 源码、模拟器 | 已写 |
| [`ui-golden.md`](ui-golden.md) | `ui-golden` | UI 像素回归:菜单 8 状态 + 内容页 60 页黄金参考图比对 | UI 源码、模拟器 | 已写 |
| [`bom-guard.md`](bom-guard.md) | `bom-guard` | 带 BOM 的文件被编辑工具剥掉 BOM(ARMCC 换解码 → 假语法错) | `Drivers/BSP/UI/**` 等名单内文件 | 已写 |
| [`setview-check.md`](setview-check.md) | `setview-check` | 定值查看行表与 `prot_set` 枚举序 / `g_prot_set_meta` 上下限是否同一份口径 | `tools/setview_check/**`、`ui_w_setview.*` | 已写 |
| (专篇待补,档位与限度正文在 [`../UI设计/UI_自动化测试流程.md`](../UI设计/UI_自动化测试流程.md) §7.3) | `uinav-selftest` | 板端 UI 导航器认屏快检(黄金参考帧分类;完整闭环档=合入前/上板前手工跑,快检不互替) | `scripts/board_ui_nav.py`、`simulator/tests/ref/*.bin` | 指针 |
+4 -3
View File
@@ -1,4 +1,4 @@
# `ui-golden` — UI 像素回归(菜单 8 状态 + 内容页 53 页黄金参考)
# `ui-golden` — UI 像素回归(菜单 8 状态 + 内容页 60 页黄金参考)
> 一句话:改 UI 源码时,把模拟器增量重编 + 两条 golden 回归串成一次提交门禁,**像素对不上就拦**。
> 它是包装器:真正的判据在被包装的两条脚本与参考图里。
@@ -11,7 +11,7 @@
## 1. 它在查什么
- 菜单侧:整棵菜单树的行渲染结果(8 个状态)与参考图逐像素比对;
- 内容页侧:53 个内容页的渲染结果与参考图比对;
- 内容页侧:60 个内容页的渲染结果与参考图比对;
- 参考图 `simulator/tests/ref/*.bin` **就是判据本身**。
## 2. 为什么要它(有牙的实测)
@@ -57,7 +57,7 @@
1. **参考图即判据**:刷新参考图 = 修改判据。评审时必须盯 `simulator/tests/ref/` 的 diff;
一旦"顺手更新",此后所有回归都只在和错的基线比。**门禁无法阻止这件事**,只能靠评审。
2. 只覆盖 8 个菜单状态 + 53 个内容页:未列入的状态(密码错误态、超长文本、缺字渲染、
2. 只覆盖 8 个菜单状态 + 60 个内容页:未列入的状态(密码错误态、超长文本、缺字渲染、
无 SD 卡 / 挂载失败的降级显示)**不会有任何回归**。
3. 跑的是**模拟器那份配置**,不是固件那份 —— 两份 `lv_conf.h` 漂移时,回归结论不能外推到固件
(所以 `lv-conf-sync` 是本门有效性的前提)。
@@ -84,4 +84,5 @@
| 2026-10-23 | 首篇逐项文档(含 +3 像素注入实验与"有基线 ≠ 有门禁"的缺口来源) |
| 2026-10-27 | 内容页黄金参考 **40 → 47 页**(遥测死区与系数 2 页落地,`simulator/tests/ref/` 实测 47 张:7 张新增、存量 40 张逐字节零漂移);本文件的当前态计数同步改 47,历史行 27 → 40 原样保留 |
| 2026-10-27 | 内容页黄金参考 **47 → 53 页**(通讯设置页落地并绑 `#page=comm`;判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 53 张,`git diff --name-status 31ca4a1f HEAD -- simulator/tests/ref` 实测只有 6 个 `A`、零 `M` ⇒ 存量 47 张逐字节零漂移);本文件的当前态计数已同步 |
| 2026-10-28 | 内容页黄金参考 **53 → 60 页**(「UI 补齐」清单清空:记录 5 页 accident / oper / alarm / start / yk 与运行报告 runreport 六页落地并在菜单树绑 #page=。运行报告 13 行分 2 页(8 + 5),第 2 页单独拍一张 shot_runreport_p2.bin 钉「第 2 页,共 2 页」页脚与 104 三枚计数,故 60 而非 59。判据 = simulator/tests/ref/ 入库 shot_*.bin 实数 60 张(tracked 53 + 新增 7)+ 存量 53 张逐字节零漂移(本批字库净新增 33 字:185→218 字 / 280→313 字形,两轮 make_font 后对既有 58 页像素零影响);文本断言 425 正向 / 36 反向(2026-10-26 写的 310 条为当时数)|
| 2026-10-26 | 内容页黄金参考下限 **27 → 40 页**(UI 三页落地;`simulator/tests/ref/` 入库 `shot_*.bin` 实测 40 个、`check_content_pages.py` 的 `PAGES` 40 项 / 文本断言 310 条覆盖 37 页 / 反向断言 29 条 16 页),标题与「拦不住什么」段同步;未列入状态那一段的覆盖面口径不变 |
+1 -1
View File
@@ -993,7 +993,7 @@ def selftest_board_frames(clf):
def selftest_refs(clf):
"""仓库黄金参考(53 页)逐帧分类自检:每张图的期望值 = 它的文件名。
"""仓库黄金参考(60 页)逐帧分类自检:每张图的期望值 = 它的文件名。
这一组是**语义正确的基线**(模拟器与板端同一份 UI 源码),用来把"分类器错了"与
"留档帧本来就是走歪的"分开——两类失败含义完全不同,混在一起就只能靠猜。
+1 -1
View File
@@ -96,7 +96,7 @@ SIM_EXEMPT = [
("App/log/soe_store.c", "SOE 落盘 MCU 胶水(队列+FatFs 单写者,B9),模拟器无消费路径"),
("App/algo/sample_ring.c", "L2 环形缓冲纯算法,模拟器无消费路径"),
("App/algo/adc_cal.c", "L1.5 标定折算纯算法 + cfg 段注册(消费者 = MCU 侧 adcTask 每拍;模拟器不跑采样任务),模拟器无消费路径"),
("App/algo/meas.c", "L2 遥测快照发布纯算法(唯一发布者 = MCU 侧 adcTask 200 ms 分频;104/UI 侧消费属卡 9/UI 波次另行接线,模拟器无消费路径;L0.5 单测 test/host/meas 覆盖),模拟器无消费路径"),
("App/algo/meas.c", "L2 遥测快照发布纯算法(唯一发布者 = MCU 侧 adcTask 200 ms 分频;104 改读快照与 UI 侧消费属另一波次另行接线,模拟器无消费路径;L0.5 单测 test/host/meas 覆盖),模拟器无消费路径"),
("App/algo/run_par.c", "运行参数段纯算法 + [run_par] cfg 段注册 + 104 地址映射(写者 = iec104Task 直通、属主落盘 defaultTask;模拟器不跑 104 协议,模拟器无消费路径;L0.5 单测 test/host/run_par 覆盖),模拟器无消费路径"),
("App/app/app_main.c", "固件启动/就绪屏障,MCU 专属"),
("App/app/ui_data_feed.c", "UI 快照装配器(依赖 phasor/prot_set/iec104 端口常量等固件侧数据源);模拟器不跑装配链,快照由 simulator/main.c 直接发布固定帧,模拟器无消费路径"),
+8 -8
View File
@@ -1700,7 +1700,7 @@
{
"name": "TC-HOST-ADCCAL",
"class": "TC",
"title": "主机侧单测用例号:L1.5 通道标定折算(test/host/adc_cal,道A 卡2/4)",
"title": "主机侧单测用例号:L1.5 通道标定折算(test/host/adc_cal,道A 标定折算与落盘整定)",
"pattern": "\\bTC-ADCCAL-[0-9]{1,4}[a-z]?\\b",
"digit_width": [
2,
@@ -1716,7 +1716,7 @@
"check_dangling": true,
"allow_orphans": true,
"subitem_ok": true,
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-ADCHEALTH 先例;2026-10-25 道A 卡2 建族):属主登记处 = 单测代码目录,不逐号补文档",
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-ADCHEALTH 先例;2026-10-25 道A 标定折算建族):属主登记处 = 单测代码目录,不逐号补文档",
"cursor_note": "游标按建族时实测最大号收录(2026-10-25):越界即视为未登记的冒号牌"
},
{
@@ -1744,7 +1744,7 @@
{
"name": "TC-HOST-PROTDIM",
"class": "TC",
"title": "主机侧单测用例号:量纲回归(test/host/prot_dim,道A 卡7)",
"title": "主机侧单测用例号:量纲回归(test/host/prot_dim,道A 量纲回归用例)",
"pattern": "\\bTC-PROTDIM-[0-9]{1,4}[a-z]?\\b",
"digit_width": [
2,
@@ -1760,7 +1760,7 @@
"check_dangling": true,
"allow_orphans": true,
"subitem_ok": true,
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-ADCHEALTH/TC-HOST-ADCCAL 先例;2026-10-25 道A 卡7 建族):属主登记处 = 单测代码目录,不逐号补文档",
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-ADCHEALTH/TC-HOST-ADCCAL 先例;2026-10-25 道A 量纲回归用例建族):属主登记处 = 单测代码目录,不逐号补文档",
"cursor_note": "游标按建族时实测最大号收录(2026-10-25):越界即视为未登记的冒号牌"
},
{
@@ -1788,7 +1788,7 @@
{
"name": "TC-HOST-MEAS",
"class": "TC",
"title": "主机侧单测用例号:遥测快照层(test/host/meas,道D 卡8)",
"title": "主机侧单测用例号:遥测快照层(test/host/meas,道D 遥测快照发布)",
"pattern": "\\bTC-MEAS-[0-9]{1,4}[a-z]?\\b",
"digit_width": [
2,
@@ -1804,13 +1804,13 @@
"check_dangling": true,
"allow_orphans": true,
"subitem_ok": true,
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-ADCHEALTH/TC-HOST-ADCCAL 先例;2026-10-25 道D 卡8 建族):属主登记处 = 单测代码目录,不逐号补文档",
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-ADCHEALTH/TC-HOST-ADCCAL 先例;2026-10-25 道D 遥测快照发布建族):属主登记处 = 单测代码目录,不逐号补文档",
"cursor_note": "游标按建族时实测最大号收录(2026-10-25):越界即视为未登记的冒号牌"
},
{
"name": "TC-HOST-RUNPAR",
"class": "TC",
"title": "主机侧单测用例号:运行参数段(test/host/run_par,道D 卡10)",
"title": "主机侧单测用例号:运行参数段(test/host/run_par,道D 已交付)",
"pattern": "\\bTC-RUNPAR-[0-9]{1,4}[a-z]?\\b",
"digit_width": [
2,
@@ -1826,7 +1826,7 @@
"check_dangling": true,
"allow_orphans": true,
"subitem_ok": true,
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-MEAS/TC-HOST-ADCCAL 先例;2026-10-25 道D 卡 10 建族):属主登记处 = 单测代码目录,不逐号补文档;路由顺序证据链在 TC-IEC104-029(test/host/iec104)",
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-MEAS/TC-HOST-ADCCAL 先例;2026-10-25 道D 运行参数段建族):属主登记处 = 单测代码目录,不逐号补文档;路由顺序证据链在 TC-IEC104-029(test/host/iec104)",
"cursor_note": "游标按建族时实测最大号收录(2026-10-25):越界即视为未登记的冒号牌"
},
{
+1
View File
@@ -10,3 +10,4 @@ date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi
2026-10-25 224860 24640 1332 135100 249500 23.8 79008 60.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
2026-10-26 231712 25560 1520 136216 257272 24.5 80312 61.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4132;sys_log_mcu.o=4003;default_task.o=2736
2026-10-27 235372 26392 1572 136924 261764 25.0 81072 61.9 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4132;sys_log_mcu.o=4055;default_task.o=2736
2026-10-28 236456 28124 1876 137084 264580 25.2 81536 62.2 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4132;sys_log_mcu.o=4055;default_task.o=2736
1 date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi
10 2026-10-25 224860 24640 1332 135100 249500 23.8 79008 60.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
11 2026-10-26 231712 25560 1520 136216 257272 24.5 80312 61.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4132;sys_log_mcu.o=4003;default_task.o=2736
12 2026-10-27 235372 26392 1572 136924 261764 25.0 81072 61.9 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4132;sys_log_mcu.o=4055;default_task.o=2736
13 2026-10-28 236456 28124 1876 137084 264580 25.2 81536 62.2 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4132;sys_log_mcu.o=4055;default_task.o=2736
+13 -13
View File
@@ -1,25 +1,25 @@
{
"built_at": "2026-10-27T15:11:51+08:00",
"fingerprint": "a05b8080445881c36969628b3aff1d98ce74c0f35bcc57c1a8a31d31762b30f2",
"fingerprint_files": 1440,
"built_at": "2026-10-28T07:12:48+08:00",
"fingerprint": "4e4d74f95dd9e07c6c89258a37e32b064981fa02ec1a43978de4801a02b2f1a6",
"fingerprint_files": 1452,
"fingerprint_source": "git-index",
"gated_regions": [
"RW_IRAM1",
"RW_CCM"
],
"git_head": "103e26e111505b9c091fe1d47b205d222a7c9cc5",
"git_head": "8f7c141a0ba824e5239f7fc9418de956d5b51064",
"map": "MDK-ARM/STM32F407-Demo/STM32F407-Demo.map",
"map_mtime": 1793084971,
"map_mtime": 1793123126,
"pct": {
"ER_IROM1": 24.96,
"ER_IROM1": 25.23,
"RW_CCM": 87.89,
"RW_IRAM1": 61.85,
"RW_IRAM1": 62.21,
"UNINIT_CCM": 18.75
},
"regions": {
"ER_IROM1": {
"max": 1048576,
"size": 261764
"size": 264580
},
"RW_CCM": {
"max": 65280,
@@ -27,7 +27,7 @@
},
"RW_IRAM1": {
"max": 131072,
"size": 81072
"size": 81536
},
"UNINIT_CCM": {
"max": 256,
@@ -37,10 +37,10 @@
"schema": 2,
"scope_note": "\u540c\u7801\u51ed\u8bc1\uff1a\u6307\u7eb9\u8986\u76d6\u56fa\u4ef6\u4f53\u79ef\u76f8\u5173\u6e90\u7801\uff0c\u53e3\u5f84\u89c1\u672c\u811a\u672c docstring",
"sizes": {
"code": 235372,
"ro_data": 26392,
"rw_data": 1572,
"zi_data": 136924
"code": 236456,
"ro_data": 28124,
"rw_data": 1876,
"zi_data": 137084
},
"threshold_pct": 92.0,
"worktree_dirt_at_stamp": 0,
+6
View File
@@ -118,6 +118,12 @@ set(UI_SOURCES
${UI_DIR}/ui_page_calib.c
${UI_DIR}/ui_page_deadband.c
${UI_DIR}/ui_page_comm.c
${UI_DIR}/ui_page_accident.c
${UI_DIR}/ui_page_alarm.c
${UI_DIR}/ui_page_oper.c
${UI_DIR}/ui_page_runreport.c
${UI_DIR}/ui_page_start.c
${UI_DIR}/ui_page_yk.c
)
# 运行/自检记录引擎(双端共享核心 + 平台存储后端;MCU 端编 sys_log_mcu.c,见 Keil 工程)
+3 -3
View File
@@ -53,7 +53,7 @@ simulator/
| `build_sim.bat` / `build_sim.ps1` | 一键构建入口:vswhere 探测本机 VS 大版本(16=2019 / 17=2022 / 18=2026,取已装最高)→ 映射 CMake 生成器;`build/` 缓存生成器与本机不符(换机/升级 VS)时自动删除重建(带重试,抗文件锁)。**构建入口一律走它,文档/命令中勿写死生成器版本**;`.bat` 仅负责绕过 PowerShell 执行策略并转交 `.ps1` |
| `CMakeLists.txt` | 收集 LVGL 源码(`../Lib/lvgl`)+ 共享 UI 源码(`../Drivers/BSP/UI`)+ 通用配置文件引擎(`../App/cfg_file.c`、`../Drivers/BSP/NETCFG` 的 net_cfg;`net_cfg_legacy` 已于 2026-10-10 删除)+ `sim/` 平台层,链接预编译 SDL2,产出 `lvgl_sim.exe` |
| `i1_to_png.py` | 把 `--screenshot` 产出的 I1(1bpp) 原始位图转成 PNG,便于离线比对设计稿。详见 §3.5 |
| `tests/` | 无头回归脚本(菜单 8 状态像素回归 + 内容页 53 页:文本断言 / 反向断言 / 黄金参考逐字节比对);`ref/shot_*.bin` **随仓库入库**(判据本体,改动等于改判据,评审须逐页过目),`ref/*.png` 是本地派生的目检图(`.gitignore` 挡掉)。详见 §3.6 |
| `tests/` | 无头回归脚本(菜单 8 状态像素回归 + 内容页 60 页:文本断言 / 反向断言 / 黄金参考逐字节比对);`ref/shot_*.bin` **随仓库入库**(判据本体,改动等于改判据,评审须逐页过目),`ref/*.png` 是本地派生的目检图(`.gitignore` 挡掉)。详见 §3.6 |
> **共享代码不复制**:`ui_menu.c` / `ui_font_cn_12.c` / `ui_net_sink.c` 直接引用 `Drivers/BSP/UI/` 下的原件,
> MCU 与 PC 两端永远同步。**不要**在本目录内复制 UI 源码。
@@ -222,7 +222,7 @@ UI 改动的自动化门禁脚本(完整流程见 `docs/UI设计/UI_自动化
| 脚本 | 原理 | 失败输出 |
|------|------|----------|
| `check_menu_rows.py` | 键序注入(u/d/e/s)跑 8 个菜单状态,断言选中行白带、非选行黑底白字、框体边框、往返状态逐像素一致;MENU-STATE-00 池水位须等于脚本内 `MENU_POOL_BASELINE` | 未过断言清单 + 保留临时截图 |
| `check_content_pages.py` | ① 文本断言(解析字体字形,在截图 y 带内精确匹配期望串,不依赖 `ref/`)② **反向断言**(`ABSENT` 表:某串**不该**出现,如查看页/只读态不得出现「未标定」徽标与「保存」行——像素参考会被 `--update` 刷成"自证正确",反向断言不依赖参考图)③ **53 页**无头截图与 `tests/ref/shot_*.bin` **逐字节**比对(含 2026-10-26 新增的整定 9 态:进页 / 保存行 / 只读态 / 编辑态 / 越界 / 保存 OK / 落定后可读 / 二态回绕);另校验开页-关页往返池水位 = `POOL_AFTER_ROUNDTRIP` | 文本未命中项 / 反向断言被命中 / 差异像素数 + 双方 ink runs 对照 |
| `check_content_pages.py` | ① 文本断言(解析字体字形,在截图 y 带内精确匹配期望串,不依赖 `ref/`)② **反向断言**(`ABSENT` 表:某串**不该**出现,如查看页/只读态不得出现「未标定」徽标与「保存」行——像素参考会被 `--update` 刷成"自证正确",反向断言不依赖参考图)③ **60 页**无头截图与 `tests/ref/shot_*.bin` **逐字节**比对(含 2026-10-26 新增的整定 9 态:进页 / 保存行 / 只读态 / 编辑态 / 越界 / 保存 OK / 落定后可读 / 二态回绕);另校验开页-关页往返池水位 = `POOL_AFTER_ROUNDTRIP` | 文本未命中项 / 反向断言被命中 / 差异像素数 + 双方 ink runs 对照 |
| `check_remo_sink.py` | 启动**窗口**模拟器(非无头,`CREATE_NEW_PROCESS_GROUP` 防管道阻塞),经 TCP 7003 发 LCDMEM 取 1bpp 帧;断言首帧=LCDMEM(无 INIT 污染)/位图 3200 字节/非平凡;复用 `i1_to_png` 出目检 PNG;与无头参考(`lvgl_sim --screenshot`)逐位比对 <2% 判 MATCH。守护"INIT 污染 / 快照卡死"两个历史缺陷 | 各判据失败原因 + `sim_err.txt` 尾部 + 保留 PNG(默认不删,`--clean` 才删) |
- **黄金参考与目检 PNG**(`ref/*.bin` **入库**、`ref/*.png` 本地派生不入库):换机或想目检时——
@@ -274,7 +274,7 @@ UI 改动的自动化门禁脚本(完整流程见 `docs/UI设计/UI_自动化
- `LV_USE_THEME_MONO = 1` 且 `sim_port_init` 中调用了 `lv_theme_mono_init`
- 主循环调用了 `lv_refr_now(NULL)`(PARTIAL 模式保证首帧)
- 没有重复设置 tick(SDL 驱动内部已 `lv_tick_set_cb`,**不要**再 `SDL_AddTimer` + `lv_tick_inc`)
4. **中文显示空白**:字体 `ui_font_cn_12` 是子集字体(当前 183 汉字/符号 + ASCII,共 278 字形),缺字渲染为空白。
4. **中文显示空白**:字体 `ui_font_cn_12` 是子集字体(当前 218 汉字/符号 + ASCII,共 313 字形;2026-10-28 UI 补齐批 +33 字,旧数 183/278 系未回填、改前实测 185/280),缺字渲染为空白。
补字流程见 `docs/UI设计/UI_中文字体生成与配置.md`(`tools/font_gen/` 两步脚本)。
5. **改了 UI 代码但模拟器没变化**:确认改的是 `Drivers/BSP/UI/ui_menu.c`(共享原件)而非本目录副本(本目录无副本),然后重新 `cmake --build`。
6. **编码**:UI 源码为 UTF-8(带 BOM),MSVC 已加 `/utf-8`。**不要**用 PowerShell `Set-Content` 等重写含中文的文件(编码铁律,见根目录 `AGENTS.md`)。
+13
View File
@@ -670,6 +670,19 @@ static void sim_publish_data_frames(void) {
(void)snprintf(info.build_date, sizeof(info.build_date), "%s", "Oct 25 2026");
(void)snprintf(info.sw_sum, sizeof(info.sw_sum), "%s", "--");
(void)snprintf(info.ftp_user, sizeof(info.ftp_user), "%s", "admin");
/* 运行报告四数:模拟器**没有** boot_stats(依赖 SD2506 I2C 与 RCC_CSR,模拟器不编译
* 该模块)也没有 104 协议栈 → 填确定值假数据,只为像素黄金可复现;真机走
* App/app/ui_data_feed.c 的 boot_stats_get()/iec104_serv_get_stats() 真源。
* 差异已登记 docs/测试说明/模拟器差距清单.md(2026-10-28 UI 补齐「运行报告」) */
info.boot_ready = 1u;
info.boot_count = 7u;
info.boot_seq_state = 2u; /* 延续(自 RTC 电池周期起) */
info.boot_write_failed = 0u;
info.rst_cause = 4u; /* 上电复位(BOOT_STATS_CAUSE_POR) */
info.iec104_conn_up = 3u;
info.iec104_apdu_tx = 128u;
info.iec104_tx_fail = 0u;
info.iec104_rx_bytes = 4096u;
(void)ui_data_publish_info(&info);
}
+1 -1
View File
@@ -11,7 +11,7 @@
| `check_content_pages.py` | **内容页回归**:各内容页渲染比对 |
| `check_remo_sink.py` | **推流(RemoDispBus)回归**:接收端渲染比对 |
| `regen_ref_png.py` | 由 `ref/*.bin` 批量出**目检 PNG**(不产生基准;基准由 `check_content_pages.py --update` 刷) |
| `ref/*.bin` | **像素黄金参考(入库)**:53 页 × 3200 B,160×160 单色打包 |
| `ref/*.bin` | **像素黄金参考(入库)**:60 页 × 3200 B,160×160 单色打包 |
## 使用方式
+123 -2
View File
@@ -131,6 +131,27 @@ PAGES = [
("comm_reject", "ddddd ee uruuruuue e d e"), # CA 编到 0(< min=1)→ ENTER 拒退
("comm_wait", "ddddd ee uruuruuue e u e dd e"), # CA 1→2 提交 → 下移到保存行 ENTER:WAIT(+--comm-nopump)
("comm_ok", "ddddd ee uruuruuue e u e dd e"), # 同键序、pump 正常 → OK(脏位真被清)
# ── 接线道 task-6:记录 5 页 + 运行报告(六叶同一笔绑 #page= 注记)────────────────
# 键序 = 主界面第 7 项「记录查询」(6 下)→ e 进子框(进框后首项 SOE记录 即被选中)
# → 再按 n 下选到目标叶 → e 开页。实测下数与 node 号严格对应:
# 1=事故 34 / 2=操作 35 / 3=保护告警 36 / 4=保护启动 37 / 5=遥控 38 /
# 6=自检 39 / 7=运行 40 / 8=运行报告 41(与 Lead 交接口径同源,逐个键序实测过)。
# 这五页在**模拟器侧没有写入方**(sim_rec_count 对这些编号恒 0)→ 拍到的是空态判据:
# 伪行"无记录"落在第 0 行,而第 0 行正是选中行(白底黑字)→ 文本断言一律 inv=True
# (实测 inv=False 匹不上,这是 ui_content_page 选中带的实现事实,不是 bug)。
("accident", "dddddde d e"),
("oper", "dddddde dd e"),
("alarm", "dddddde ddd e"),
("start", "dddddde dddd e"),
("yk", "dddddde ddddd e"),
# 运行报告(node 41):12 行 / UI_LIST_ROWS=8 → 真 2 页。**四个数逐个挂范围标签**是判据
# (docs/任务规划/UI补齐.md §2「运行报告」行),所以两张都必须拍——首屏钉上电次数/
# 计数范围/复位原因/主站接入 + 范围标签"本次开机",第 2 页钉 104 另外三枚(发送帧数
# 128 / 发送失败 0 / 接收字节 4096)与页脚真实页码 2/2。四枚假数据值互不相同是刻意的:
# 行错位/串行只有"像素 + 逐行文本断言"两把尺子同时才照得出来(Lead 裁定 2026-10-28,
# 因此用例是 53+7=60 张,不是 53+6=59)。
("runreport", "dddddde dddddddd e"),
("runreport_p2", "dddddde dddddddd e dddddddd"), # 页内再 8 下 → 第 2 页(选中落 r0=发送帧数)
]
# 文本级断言表:页名 -> [(名称, 期望串, y 带, 是否反显)]
@@ -590,6 +611,72 @@ TEXTS = {
("r0名", "公共地址", (24, 38), False), ("r0值", "2", (24, 38), False),
("保存名", "保存", (52, 66), True), ("保存值", "OK", (52, 66), True), # 脏位被 pump 清 = 已落盘
],
# ── 接线道 task-6:记录 5 页(空态判据)+ 运行报告两页 ───────────────────────────
# 五个记录页只钉空态:模拟器侧这五个日志文件没有写入方,能钉的正是判据"空记录显示
# 无记录"(App/log/README.md §五类记录)。第 0 行 = 选中行(白底黑字)→ inv=True;
# 页脚钉"第 1 页,共 1 页"同时钉住分页数学(1 条伪行 = 1 页,不是 0 页也不是 2 页)。
"accident": [
("标题", "事故记录", (0, 24), False),
("r0空态", "无记录", (24, 38), True),
("页脚", "第 1 页,共 1 页", (140, 160), False),
],
"oper": [
("标题", "操作记录", (0, 24), False),
("r0空态", "无记录", (24, 38), True),
("页脚", "第 1 页,共 1 页", (140, 160), False),
],
"alarm": [
("标题", "保护告警", (0, 24), False),
("r0空态", "无记录", (24, 38), True),
("页脚", "第 1 页,共 1 页", (140, 160), False),
],
"start": [
("标题", "保护启动", (0, 24), False),
("r0空态", "无记录", (24, 38), True),
("页脚", "第 1 页,共 1 页", (140, 160), False),
],
"yk": [
("标题", "遥控记录", (0, 24), False),
("r0空态", "无记录", (24, 38), True),
("页脚", "第 1 页,共 1 页", (140, 160), False),
],
# 运行报告首屏 8 行。四个数各自挂范围标签是判据(上电次数=自电池周期、其余=本次开机),
# 所以**标签与值成对断言**:只钉值不钉标签,就等于把"终身次数"这种口径错画放过去。
# 值 = simulator/main.c 的确定假数据(boot_count 7 / rst_cause 4 上电复位 / conn_up 3 /
# uptime_s 0);四枚 104 数互不相同是刻意的,行错位在第 2 页那张里同样看得出来。
# 运行报告首屏 8 行(13 行 = 8 + 5 两页,Lead 2026-10-28 补「计数可信」行使四态可辨)。
# 四个数各自挂范围标签是判据(上电次数=自电池周期、其余=本次开机),所以**标签与值
# 成对断言**:只钉值不钉标签,等于把"终身次数"这种口径错画放过去。「延续」= 模拟器
# 假数据 boot_seq_state=2(CONTINUED),与 UNKNOWN 的 "--" 是两回事。
# 值 = simulator/main.c 的确定假数据(boot_count 7 / rst_cause 4 上电复位 / uptime_s 0)。
"runreport": [
("标题", "运行报告", (0, 24), False),
("r0名", "上电次数", (24, 38), True), ("r0值", "7", (24, 38), True),
("r1名", "计数范围", (38, 52), False), ("r1范围标签", "自电池周期", (38, 52), False),
("r2名", "计数可信", (52, 66), False), ("r2可信度", "延续", (52, 66), False),
("r3名", "计数写回", (66, 80), False), ("r3值", "正常", (66, 80), False),
("r4名", "复位原因", (80, 94), False), ("r4值", "上电复位", (80, 94), False),
("r5名", "复位范围", (94, 108), False), ("r5范围标签", "本次开机", (94, 108), False),
("r6名", "运行时长", (108, 122), False), ("r6值", "00:00:00", (108, 122), False),
("r7名", "时长范围", (122, 136), False), ("r7范围标签", "本次开机", (122, 136), False),
("页脚", "第 1 页,共 2 页", (140, 160), False),
],
# 运行报告第 2 页:104 另外三枚 + 统计范围标签 + 真实页码 2/2(分页数学的像素证据)
# 运行报告第 2 页(13 行 → 第 2 页 5 行):104 四枚 + 统计范围标签 + 真实页码 2/2。
# 选中行随翻页落在 r0(主站接入)→ inv=True;四枚值 3/128/0/4096 互不相同是刻意的,
# 行错位或分页窗口算错只有"像素 + 逐行文本"两把尺子同时才照得出来(Lead 裁定)。
"runreport_p2": [
("标题", "运行报告", (0, 24), False),
("r0名", "主站接入", (24, 38), True), ("r0值", "3", (24, 38), True),
("r1名", "发送帧数", (38, 52), False), ("r1值", "128", (38, 52), False),
("r2名", "发送失败", (52, 66), False), ("r2值", "0", (52, 66), False),
("r3名", "接收字节", (66, 80), False), ("r3值", "4096", (66, 80), False),
("r4名", "统计范围", (80, 94), False), ("r4范围标签", "本次开机", (80, 94), False),
("页脚", "第 2 页,共 2 页", (140, 160), False),
],
}
# 反向文本断言表:页名 -> [(名称, 期望**不出现**的串, y 带, 是否反显态)]
@@ -667,6 +754,26 @@ ABSENT = {
# 反过来正向断言"100"是没有意义的——它是"100V"甚至"10000V"的子串,
# 字形匹配器只保证 bbox 内干净、不检查词边界(实测在上一行的 10000V 上命中)
"sparam_edit": [("编辑态不打单位后缀", "100V", (38, 52), True)],
# ── 接线道 task-6:反向断言钉"分页不串行 / 记录源不串页"(同样不依赖参考图)──
# 运行报告两页互为反证:第 1 页不许出现只有第 2 页才有的行、反之亦然——分页窗口
# 一旦算错(比如 rows_per_page 与页脚页码不同源),只有一张图会露馅,这里两把都上。
# 五个记录页钉"空态页上不许出现别的页的时标串":SOE 页屏上有固定 3 条假记录,时标
# 2026-10-25(ui_w_soe 的显示假数据)。一旦有人图省事把记录页接到那份假数据上,
# 或把两端记录源映射表(simulator/main.c 的 s_sim_log_map 与 App/task/ui_task.c 的
# s_log_map)接错号,让这几页读到 SOE 的数据,屏上就会冒出这个时标——这条不依赖参考图就会响。
"runreport": [
("第 1 页不出现第 2 页的行", "发送帧数", (0, 160), False),
],
"runreport_p2": [
("第 2 页不出现第 1 页的行", "上电次数", (0, 160), False),
],
"accident": [("空态不串 SOE 假记录", "2026-10-25", (0, 160), False)],
"oper": [("空态不串 SOE 假记录", "2026-10-25", (0, 160), False)],
"alarm": [("空态不串 SOE 假记录", "2026-10-25", (0, 160), False)],
"start": [("空态不串 SOE 假记录", "2026-10-25", (0, 160), False)],
"yk": [("空态不串 SOE 假记录", "2026-10-25", (0, 160), False)],
}
W = H = 160
@@ -694,6 +801,16 @@ EXTRA = {
"comm_wait": ["--comm-nopump"],
}
# 接线道 task-6:记录 5 页在**各自独立的空目录**里跑(不共用回归的那个 tmp)。
# 诱因(实测,不是猜):模拟器把"人工操作留痕"镜像成了真记录——simulator/main.c 的
# sim_post_oper() 走 syslog_post(SYSLOG_OPER, ...) 落盘**当前工作目录**的 sim_oper.log;
# 而 60 页原本共用一个 tmp,clock_save / netcfg_save / sparam_save 这些"保存"态跑完之后
# sim_oper.log 已经攒了 3 条(192 B = 3×64 B)→ "操作记录"页读到的是真记录,
# 空态判据(第 0 行"无记录")根本拍不到。**判据本身没错,错在跑它的环境被前面的写路径
# 污染了**,所以给这 5 页各开一个空目录 = 现场"这些日志文件还不存在"的确定态;
# 其余 55 页环境一字不变(对存量 53 张黄金零影响,实测逐字节零漂移)。
FRESH_CWD = ("accident", "oper", "alarm", "start", "yk")
def run_sim(seq, out, cwd, extra=()):
"""在指定工作目录里跑一次无头截图。
@@ -867,8 +984,12 @@ def main():
# 1) 跑全部页面 + 文本级断言预检(先于像素比对/刷新:失败即中止,避免误刷参考)
shots = {}
for name, seq in PAGES:
shot = os.path.join(tmp, "shot_%s.bin" % name)
run_sim(seq, shot, tmp, EXTRA.get(name, ()))
cwd = tmp
if name in FRESH_CWD:
# 记录页的空态判据要求"日志文件此刻不存在",理由见 FRESH_CWD 上方说明
cwd = tempfile.mkdtemp(prefix="fresh_%s_" % name, dir=tmp)
shot = os.path.join(cwd, "shot_%s.bin" % name)
run_sim(seq, shot, cwd, EXTRA.get(name, ()))
shots[name] = open(shot, "rb").read()
n_pos = 0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+11 -11
View File
@@ -1,7 +1,7 @@
/*
* 模块名称:通道标定层(L1.5,adc_cal)主机侧单元测试
* 被测对象:真实源文件 App/algo/adc_cal.c + App/cfg/cfg_file.c(均 #include
* 原样纳入——卡 4 的落盘契约必须用真引擎测,不造轮子替身)。
* 原样纳入——标定落盘与整定入口的持久化契约必须用真引擎测,不造轮子替身)。
* 平台依赖桩:dbg_log.h(stub/ 计数宏)、cfg_store_*(本文件内存
* 虚拟盘,同 cfg_file 套件先例)、syslog_post(计数)、
* adc_input_desc()(按 ADC通道映射说明.md 权威表给 V0.1 来源映射)。
@@ -14,7 +14,7 @@
* TC-ADCCAL-001 init 注册两段:名称/键数/data_size/无回调/默认表指向
* TC-ADCCAL-002 UA(TPAFE)折算:0 / 8192 / 32767 / -32768 对 10V/65536 独立推导
* TC-ADCCAL-003 UB(STM32)折算:0 / 2048 / 4095 对 3.3V/4096
* TC-ADCCAL-004 其余 6 路各 1 点(合计 8 通道 × ≥3 码值点,卡 2 DoD)
* TC-ADCCAL-004 其余 6 路各 1 点(合计 8 通道 × ≥3 码值点,标定折算落地 DoD)
* TC-ADCCAL-005 TEMP 透传 + flags/k_uv 恒 0;sem 越界守卫
* TC-ADCCAL-006 默认 flags 三态:VALID 全 0;CLIPPED = UB/UC/IB/IC/IN(0xE6)
* TC-ADCCAL-007 k_uv 精确值:152.587890625 / 805.6640625(Q16 无舍入验证)
@@ -23,14 +23,14 @@
* flags 不报 VALID(即便位图置位)+ init 重置观测窗
* TC-ADCCAL-014 零点 b 生效(set 路径):(code+b)×k 逐项可算
* TC-ADCCAL-015 两点标定公式:合成数据还原 k/b + 写回往返 + 参数/斜率/
* 零点越界(-2)守卫(卡 12 的算术核,台架注入待跑)
* 零点越界(-2)守卫(两点标定的算术核,台架注入待跑)
* TC-ADCCAL-016 rail_ths 门限:TPAFE ±32112 / STM32 4013·81 / TEMP 不监视
* TC-ADCCAL-017 init 幂等:重复调用 RAM 复位默认 + 重新注册
* —— 以下走真实 cfg_file 引擎(卡 4 DoD)——
* —— 以下走真实 cfg_file 引擎(标定落盘与整定入口 DoD)——
* TC-ADCCAL-010 文件值生效:k_ua/b_ua 经 load 改变折算结果,VALID 置位
* TC-ADCCAL-011 越界文件值:k=999 / k=-999 被引擎收下后由哨兵兜住:
* 折算 = ROM、VALID 不报(位图置位也不报)、[ERR] 留痕
* TC-ADCCAL-012 段损坏(超长文件)→ 回退 ROM 且 flags 无 VALID(卡 4 DoD)
* TC-ADCCAL-012 段损坏(超长文件)→ 回退 ROM 且 flags 无 VALID(标定落盘与整定入口 DoD)
* TC-ADCCAL-013 段缺失(文件无本段)→ ROM 默认、VALID 全 0
* TC-ADCCAL-018 未标定闭锁单点 adc_cal_prot_blocked()(道F task-16):开机态必须
* 闭锁 / 两路齐第三路缺仍闭锁(全或无)/ 三路齐放行且 UB 仍无 VALID
@@ -46,7 +46,7 @@
* TC-ADCCAL-023 空转回执不倒挂:水位永不越过 set_ok(uint32 相减一绕回就是巨大的假差额)
*
* 通过:全部 TC PASS(main 返回 0)。
* 创建日期:2026-10-25(道A 卡 2/卡 4)
* 创建日期:2026-10-25(道A 标定折算与落盘整定)
*/
#include <stdint.h>
@@ -176,7 +176,7 @@ static int s_total = 0, s_passed = 0, s_failed = 0;
/* ===================== 独立推导的期望值 ===================== */
/* 期望一律用 **double 直接除**(10/65536、3.3/4096),不引用被测的 Q16 常量,
* 满足卡 2 DoD「期望值由 LSB 常数独立算得(不是抄实现)」;容差只需盖住
* 满足标定折算落地 DoD「期望值由 LSB 常数独立算得(不是抄实现)」;容差只需盖住
* float32 中间积舍入(相对 ~1e-7)与打印粒度。 */
static double exp_tpafe(int32_t code) { return (double)code * (10.0 / 65536.0); }
static double exp_stm32(int32_t code) { return (double)code * (3.3 / 4096.0); }
@@ -239,7 +239,7 @@ static void tc_001_init_registers(void) {
CHECK(s_sections[2].used == 0u, "only two sections registered");
}
/* TC-ADCCAL-002/003/004:8 通道 × ≥3 码值点折算,期望独立推导(卡 2 DoD) */
/* TC-ADCCAL-002/003/004:8 通道 × ≥3 码值点折算,期望独立推导(标定折算落地 DoD) */
static void tc_002_004_apply(void) {
printf("[TC-ADCCAL-002] UA (TPAFE) apply\n");
reset_all();
@@ -430,7 +430,7 @@ static void tc_00d_idempotent(void) {
CHECK(adc_cal_flags(ADC_SEM_UA) == 0u, "re-init clears VALID too");
}
/* ===================== 用例(引擎集成组,卡 4 DoD) ===================== */
/* ===================== 用例(引擎集成组,标定落盘与整定入口 DoD) ===================== */
/* TC-ADCCAL-010:文件值经 load 生效 + VALID */
static void tc_010_file_apply(void) {
@@ -464,7 +464,7 @@ static void tc_011_file_bad(void) {
CHECK(g_caltest_err_count >= 2, "both sanitizations logged");
}
/* TC-ADCCAL-012:段损坏(超长文件)→ 回退默认且 flags 无 VALID(卡 4 DoD 原句) */
/* TC-ADCCAL-012:段损坏(超长文件)→ 回退默认且 flags 无 VALID(标定落盘与整定入口 DoD 原句) */
static void tc_012_file_corrupt(void) {
char big[CFG_FILE_MAX_LEN + 64];
size_t i;
@@ -496,7 +496,7 @@ static void tc_013_section_missing(void) {
CHECK(adc_cal_flags(ADC_SEM_IA) == 0u, "no VALID with missing sections");
}
/* TC-ADCCAL-018:未标定闭锁判定单点(「数据可信」卡 5 / 道F task-16)
/* TC-ADCCAL-018:未标定闭锁判定单点(「数据可信」未标定即闭锁 / 道F task-16)
* 为什么值得单独钉:这条谓词此前在 App/task/protect_task.c 与
* App/app/ui_data_feed.c 各写一份,**没有任何一份被主机测到**(ui_data 套件只编
* 快照层,不编组装器)。收敛到本层后它跟着被测源文件一起进来,第一次拿到
+1 -1
View File
@@ -18,7 +18,7 @@
python test/host/adc_cal/run_unit_test.py
退出码:0=PASS / 1=测试失败 / 2=环境错误。
设计依据:docs/任务规划/数据可信.md 卡 2 / 卡 4(道A);
设计依据:docs/任务规划/数据可信.md 标定折算与落盘整定(道A);
创建日期:2026-10-25
"""
import os
+1 -1
View File
@@ -31,7 +31,7 @@
* TC-ADCHEALTH-015 帧年龄纯判据:tick 与序号跨 0xFFFFFFFF 不误判、停滞仍判老
* TC-ADCHEALTH-016 帧年龄纯判据:序号倒退按「有变化」处理,不判老(判据分工)
* TC-ADCHEALTH-017 帧年龄纯判据:两个 age 对象互不干扰;空指针不判老
* —— 采样通道自检 残余「码值越界(贴轨)检出」(2026-10-25 道A,卡 2 分支加入)——
* —— 采样通道自检 残余「码值越界(贴轨)检出」(2026-10-25 道A,标定折算落地分支加入)——
* TC-ADCHEALTH-018 释放沿后连续 20 拍贴上轨 -> 锁存 + 边沿只报一次
* TC-ADCHEALTH-019 无释放沿(开机/空载恒 0)永不锁存(合法工况不误报)
* TC-ADCHEALTH-020 中带样本清零连续计数(19+19 不锁);触轨含等号边界
+4 -4
View File
@@ -22,7 +22,7 @@
* TC-CONFIG-004 MAC 三种分隔符 + 大小写 + 非法
* TC-CONFIG-005 STR 正常 / 超长拒绝 / 边界(恰好放下)
* TC-CONFIG-006 INT 合法解码:0 / -1 / INT32_MIN / INT32_MAX / 各宽度边界 /
* 前导 + / 前导 0(数据可信卡 3:负零点偏移可落盘)
* 前导 + / 前导 0(「数据可信」有符号零点类型:负零点偏移可落盘)
* TC-CONFIG-007 INT 非法拒绝:空 / 非数字 / 带后缀 / 越界(含 strtol 饱和带,
* 即超 INT32 但钳位后恰落界内的文本)/ 坏 len
* TC-CONFIG-008 INT 编码带负号输出 + 注册校验(INT len=3 拒绝)+
@@ -235,7 +235,7 @@ static const cfg_key_def_t s_net_keys[] = {
{ "name", CFG_VAL_STR, offsetof(sec_net_t, name), 12u },
};
/* 段 B:[sys],无回调,用于验证多段、超长字段拒绝与 INT 有符号往返(卡 3)。
/* 段 B:[sys],无回调,用于验证多段、超长字段拒绝与 INT 有符号往返(有符号零点类型)。
* 字段按自然对齐排布:u32@0 / i8@4 / i16@6 / i32@8,offset 用 offsetof 取真值 */
typedef struct {
uint32_t baud; /* offset 0 len 4 UINT */
@@ -380,7 +380,7 @@ static void tc_capacity(void)
cfg_section_reg_t r;
/* 数字钉:段上限必须是 8(cfg_file.h:39);改数字 = 容量台账变化,必须
* 同步 docs/子系统设计/配置文件设计说明.md 与本卡生产占位说明 */
* 同步 docs/子系统设计/配置文件设计说明.md 与本用例生产占位说明 */
CHECK(CFG_FILE_MAX_SECTIONS == 8u, "CFG_FILE_MAX_SECTIONS pinned to 8");
vfs_reset();
CHECK(register_fill((int)CFG_FILE_MAX_SECTIONS) == 1, "filling exactly 8 sections all accepted");
@@ -521,7 +521,7 @@ static void tc_str(void) {
CHECK(s_decode_str(d, 8u, "") == 0 && d[0] == '\0', "empty string ok");
}
/* TC-CONFIG-006/007:INT 解码(数据可信卡 3——有符号零点偏移) */
/* TC-CONFIG-006/007:INT 解码(「数据可信」有符号零点类型——负零点偏移) */
static void tc_int_decode(void) {
uint8_t d[4];

Some files were not shown because too many files have changed in this diff Show More