feat(sntp): 板端 SNTP 校时接入——coreSNTP 序列化器 + [sntp] 段 + 设置页(#73)
- vendored coreSNTP v2.0.0 序列化器(MIT,仅 serializer+LICENSE,零堆), 48 字节报文编解码在库,节奏与准入判据在本方(RFC 4330 §10 调研口径) - App/sync/time_sntp.c 挂 timeSyncTask 的 8888 事件循环,等待切片 ≤50 ms, 不饿任务狗与 IWDG;懒建 UDP socket,代际变化/禁用/死错误码即关闭归还 - 防伪 = OriginTimestamp 逐位等于发出时 T1(含低 16 位随机小数位); mode/stratum/闰秒指示/KoD 按 RFC 拒收;DENY·RSTR 换服务器、RATE 只退避 - 主备轮换 + 失败指数退避(5 s 起、60 s 封顶)+ 首轮 1~5 分钟随机错峰; 成功恢复 poll_min 周期(1~1440 分,出厂默认 60,默认不启用不发包) - 钟面 = 本地时间:UTC+8 固定偏移落 sys_clock_set_unix(§1.1 时基裁定, 第三个写入口,装置仍不存时区);|offset|<2 s 只记日志不步进,冷启动或 更大偏差步进并回写 SD2506,留痕 [SNTP] step 与 syslog OPER - 首个校验通过的同步置 SYS_EVT_TIMESYNC_READY(就绪位,消费方按需 NoClear) - [sntp] 配置段(enable/server1/server2/poll_min)属主 sntp_cfg.c, 注册在 net_cfg_load();UI 页 31「SNTP 设置」(密码叶):启用开关 + 主/备服务器 octet 编辑 + 周期(分) + 保存,复用 net_cfg_save_request 链 - 测试与门禁:test/host/sntp 新套件(报文/防伪/KoD/退避周期/阶跃域/配置 注册表)、net_cfg 与 time_sync 套件补 fake、黄金参考 66→74 张零漂移、 字符集 228 字、Keil 0 错 0 警(RO +5,848 B 含字体)、覆盖率基线回填 - 文档:墙钟维护说明 §16、网络配置说明 [sntp] 节、配置文件设计说明变更记录、 产品需求 FR-TIME-3 与 8.3/9.1.2 台账、UI 补齐规划/UI补齐 31 叶口径、 登记簿销项并登记「SNTP 校时真机判据」等台架(PC 时间源 192.168.31.161/.13)
This commit is contained in:
@@ -694,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 态)——**集合现已扩至 66 张**,**双次一致已验(2026-10-29:同一批 66 张连跑三次逐字节一致,池水位 5,448 B;菜单 8 状态连跑三次亦一致,5,368 B)**;轮询定时器不影响——无头模式不调 `lv_timer_handler()`(§9.2 注 6) |
|
||||
| 7 | 像素回归稳定 | `ui-golden` 连续两次运行零差异。**已验(2026-10-26,当时下限为 27 页)**:27 页连跑两次逐字节一致(含整定 9 态)——**集合现已扩至 74 张**,**双次一致已验(2026-10-29:同一批 66 张连跑三次逐字节一致,池水位 5,448 B;菜单 8 状态连跑三次亦一致,5,368 B)**;轮询定时器不影响——无头模式不调 `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 钩子 |
|
||||
|
||||
|
||||
@@ -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` | ① 文本级断言(字形模板匹配,正向 444 条 + 反向 45 条,独立于 `ref/`)→ ② 66 张截图与 `ref/` 黄金参考**逐字节**比对 + 开页-关页往返池水位 | `PASS: 66 内容页 + 往返池水位全部通过`(文本断言先于像素比对,失败即中止) |
|
||||
| 2 | `simulator/tests/check_content_pages.py` | ① 文本级断言(字形模板匹配,正向 484 条 + 反向 45 条,独立于 `ref/`)→ ② 74 张截图与 `ref/` 黄金参考**逐字节**比对 + 开页-关页往返池水位 | `PASS: 74 内容页 + 往返池水位全部通过`(文本断言先于像素比对,失败即中止) |
|
||||
| 3 | `keil-build` skill(`keil_build.py`) | MCU 端编译(UI 源码双端共用,改一端必须过另一端) | 退出码 0 = BUILD_OK |
|
||||
| 4 | `scripts/check_coding_standard.py` | 代码规范 V1.0 机械检查 | PASS |
|
||||
|
||||
@@ -52,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 页**,在裁剪**前**生成、裁剪后全部一致;该集合现已扩至 66 张),
|
||||
> 后一次漂移已核实为**有意且更优**:像素逐字节未变(**裁剪当时黄金参考只有 11 页**,在裁剪**前**生成、裁剪后全部一致;该集合现已扩至 74 张),
|
||||
> 且一次性残留仍是 80 B(5448 − 5368)→ 泄漏特征未变,只是 `lv_theme_apply` 不再为已不存在的控件类登记样式条目。
|
||||
|
||||
**漂移处理**:菜单/页面结构或样式变更导致门禁失败时,先确认新值合理(残留分解见
|
||||
@@ -61,7 +61,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
|
||||
|
||||
## 四、黄金参考(入库)与目检 PNG(本地产物)
|
||||
|
||||
`simulator/tests/ref/*.bin`(像素黄金参考,66 张 × 3200 B)**随仓库入库**;派生的 `.png`
|
||||
`simulator/tests/ref/*.bin`(像素黄金参考,74 张 × 3200 B)**随仓库入库**;派生的 `.png`
|
||||
目检图仍是本地产物(`.gitignore`)。入库的理由:比对是**逐字节**的,基线不入库时任何新克隆
|
||||
或新工作树跑 `ui-golden` 都必然 FAIL(缺基准),这条门禁就只在"有老副本的机器"上真实存在。
|
||||
可复现性实测(2026-10-22):两份各自独立构建的 `lvgl_sim`(不同构建目录、相隔 11 天的代码)
|
||||
@@ -154,7 +154,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
|
||||
### 7.3 用法与门禁档位
|
||||
|
||||
```powershell
|
||||
# 认屏快检:66 张黄金参考(+ 若有台架留档帧),秒级,不需要构建产物
|
||||
# 认屏快检:74 张黄金参考(+ 若有台架留档帧),秒级,不需要构建产物
|
||||
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --selftest-quick
|
||||
# 完整自检:再加全绑定页闭环导航(需模拟器可执行文件,约 30 s)
|
||||
& '.venv\Scripts\python.exe' scripts/board_ui_nav.py --selftest
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
+1
-1
@@ -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) 内容页文本断言 + 66 张黄金参考逐字节比对
|
||||
0) 模拟器构建 0 警告 → 1) 菜单 8 状态像素回归 + 池基线 → 2) 内容页文本断言 + 74 张黄金参考逐字节比对
|
||||
(网口设置 4 态 + 密码页 4 态等)+ 开页-关页往返水位 → 3) Keil 构建 0 错 0 警 → 4) 代码规范检查
|
||||
- **门禁常量**(脚本头部):`MENU_POOL_BASELINE = 5368 B`、`POOL_AFTER_ROUNDTRIP = 5448 B`
|
||||
- **失败处置**:像素不一致 = 代码 bug(修代码,**禁止**刷参考掩盖);**有意**改视觉 →
|
||||
|
||||
+2
-1
@@ -81,7 +81,7 @@
|
||||
| 26 | 手动录波 | 操作页(确认) | `wave_ring_request` 手动触发经 `ui_data_wave_ops_t` 注入 | ✅ 已落地(`ui_page_wave_manual.c`,2026-10-29 录波 UI 道;配套新增「录波回放」叶 node 43 = `ui_page_wave_play.c`,不在本表 27 叶之列) |
|
||||
| 27 | 清除记录 | 操作页(选类型 + 确认) | `sys_log`(**缺删除 API**) | 🔶 需补 API |
|
||||
| 29 | 通讯设置 | 可编辑列表(4~6 项) | 104 公共地址/端口/主站(当前固定) | 🔶 需 `comm_cfg` |
|
||||
| 31 | SNTP设置 | 可编辑列表(3 项) | SNTP 客户端 | ❌ 未实现(产品口径亦未定) |
|
||||
| 31 | SNTP设置 | 可编辑列表(3 项) | SNTP 客户端 | ✅ 已落地(`ui_page_sntp.c`,2026-11-04 板端 SNTP 接入立项;形态较原规划多 1 行 = 启用/主服务器/备服务器/周期(分) + 保存行,编辑语义复刻网口设置页) |
|
||||
| 33 | SOE记录 | 动态列表(每记录 2 行) | `/log/soe.log` 二进制 64B | ✅ 已落地(`ui_page_soe.c`) |
|
||||
| 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) |
|
||||
@@ -94,6 +94,7 @@
|
||||
|
||||
**2026-10-28 复核**:本表 27 叶中 **22 叶已落地**(本批 +6:记录 5 页与运行报告,见 docs/任务规划/UI补齐.md §2 与 docs/任务规划/登记簿.md §7);未落地的 5 叶 = 遥信类型 / 遥信防抖 / 双点遥信(无开入硬件)+ 手动录波(无录波模块)+ SNTP设置(产品口径未定),取舍与重开条件见 docs/任务规划/UI补齐.md §5。口径闭合:本表 22 叶 + 立项前就已绑定、不在本表内的 6 叶(装置信息 / 交流量 / 直流量 / 网口设置 / 自检记录 / 运行记录)= 现值已绑 28 叶(= UI_PAGE_MAP_COUNT);本表未落地 5 叶 = 菜单树未绑 5 叶(33 − 28)。复核方法:按缩进判叶子(有更深缩进后继者即非叶子),再按行内 #page= 数已绑。**2026-10-29 补充**:「手动录波」已随故障录波独立立项(docs/子系统设计/故障录波设计说明.md;原卡片登记簿 2026-10-30 销项并入该文 §10),上面那行数字仍是 2026-10-28 当日复核值,未随立项改动。
|
||||
**2026-10-29 二补(录波 UI 道落地)**:本表「手动录波」转已落地(23 叶);菜单树另新增「录波回放」叶(node 43,不在本表立项快照内)——现值 43 节点 / 34 叶 / 已绑 30 / 未绑 4(= 遥信 3 + SNTP 1,UI_PAGE_MAP_COUNT = 30),口径复核方法与上一段相同
|
||||
**2026-11-04 复核(板端 SNTP 接入立项,#57 调研结论)**:本表「SNTP设置」转已落地(24 叶)——`ui_page_sntp.c` 绑 `#page=sntp`,[sntp] 段经 `net_cfg_load` 注册、SNTP 客户端在 timeSyncTask 轮询(`App/sync/time_sntp.c`);现值 43 节点 / 34 叶 / 已绑 31 / 未绑 3(= 遥信 3,UI_PAGE_MAP_COUNT = 31),口径复核方法与上一段相同
|
||||
|
||||
---
|
||||
|
||||
|
||||
+17
-11
@@ -324,6 +324,11 @@ flowchart LR
|
||||
- 实现:`timeSyncTask` 等 `NET_READY` → TCP listen :8888 → 收 PC 推送 → 写 RTC;30 s 无包则掉线重建监听。
|
||||
- 判据:对时后设备墙钟更新、日志时间戳正确。
|
||||
|
||||
**FR-TIME-3 SNTP 校时** ✅(2026-11-04)
|
||||
- 需求:设备作 SNTP(RFC 4330)客户端从配置的 IPv4 服务器经 UDP/123 取时写回 RTC;使能、主/备服务器、轮询周期可配(UI「SNTP 设置」页或 `/config.ini` `[sntp]` 段,保存后随下一轮生效)。
|
||||
- 实现:`timeSyncTask` 复用 8888 事件循环(≤50 ms 等待切片,不饿任务狗与 IWDG);48 字节报文由 vendored coreSNTP 序列化器(`Lib/coreSNTP/`)编解码,节奏与判据在本方;防伪 = OriginTimestamp 须逐位等于发出的 T1(含随机小数位),mode / stratum / 闰秒指示 / Kiss-o'-Death 按 RFC 拒绝;主备轮换 + 失败指数退避(5 s 起、60 s 封顶)+ 首轮 1~5 分钟随机;成功时 |offset| < 2 s 只记日志不阶跃,更大偏差阶跃写回 SD2506——钟面 = 本地时间(UTC+8,与 8888 同一时基口径,取舍见 docs/任务规划/UI补齐.md §4 时基口径注);首个校验通过的同步置 `SYS_EVT_TIMESYNC_READY`。
|
||||
- 判据:主机单测 `test/host/sntp`(报文格式 / 伪造拒收 / KoD 轮换 / 退避与周期 / 阶跃域守卫);真机 = 使能并配置服务器后时钟与时间源一致、`[SNTP] step offset=` 日志在场(台架窗口统一做)。
|
||||
|
||||
> **已知限制**:uint32 epoch → **2038 年**上限。
|
||||
|
||||
### 5.4 配置引擎(FR-CFG)✅
|
||||
@@ -613,7 +618,7 @@ flowchart LR
|
||||
上电次数 + 本次复位原因快照)与 iec104_serv 的四个只读观测计数,经 info 帧下发
|
||||
(口径 docs/UI设计/UI_数据供给设计说明.md §4.4)。
|
||||
- 判据:五类记录各有写入点、可翻最近 20 条、空记录明确显示"无记录"、共用 reader——**软件面已满足**
|
||||
(空态与四个范围标签由 66 张像素黄金钉住;模拟器侧这些文件没有写入方,只拍到空态)。
|
||||
(空态与四个范围标签由 74 张像素黄金钉住;模拟器侧这些文件没有写入方,只拍到空态)。
|
||||
真记录翻页、掉电后保持、清除记录后归零、boot_count 自增与四态判定**待台架复核**
|
||||
(docs/任务规划/登记簿.md §7)。
|
||||
|
||||
@@ -1539,10 +1544,11 @@ pre-commit run --all-files
|
||||
> 图里的节点数、绑页与密码门读数由 `tools/arch_diagram/gen_menu_tree_svg.py` 现算自真值 `ui_menu_tree.txt`(改菜单树 → 同步脚本内 `NODE_SRC` 重跑);级联框在屏上怎么摆(几何)→ `docs/UI设计/菜单页面设计.md` §4.1。
|
||||
|
||||
**规模**:菜单节点 **9** 个(含根)+ 叶子节点 **34** 个 = **43** 节点;最大深度 **4 级(主界面 / 一级 / 二级 / 三级菜单)**。
|
||||
**绑定现状**(2026-10-29 复扫):**已绑内容页 30 叶 / 未绑 4 叶**(页面注册表 `UI_PAGE_MAP_COUNT` = 30,
|
||||
与已绑叶数一致);未绑 4 叶 = 无开入硬件 3 + SNTP 1(取舍与重开条件见
|
||||
**绑定现状**(2026-11-04 复扫):**已绑内容页 31 叶 / 未绑 3 叶**(页面注册表 `UI_PAGE_MAP_COUNT` = 31,
|
||||
与已绑叶数一致);未绑 3 叶 = 无开入硬件 3(取舍与重开条件见
|
||||
docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5 页 + 运行报告)已于 2026-10-28 落地绑页,
|
||||
「手动录波」与「录波回放」两叶于 2026-10-29 随录波道绑页(判据见 docs/子系统设计/故障录波设计说明.md §4.1 与 §8.1)。
|
||||
「手动录波」与「录波回放」两叶于 2026-10-29 随录波道绑页(判据见 docs/子系统设计/故障录波设计说明.md §4.1 与 §8.1),
|
||||
「SNTP 设置」叶于 2026-11-04 随 SNTP 客户端立项绑页(判据见 §5.3 FR-TIME-3 与 docs/网络/BSD_Socket_API_使用指南.md §6.1)。
|
||||
|
||||
**根页(主界面)7 个一级条目**:装置信息 / 实时数据 / 参数定值 / 三遥设置 / 装置维护 / 通讯参数 / 记录查询。
|
||||
|
||||
@@ -1576,7 +1582,7 @@ docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5
|
||||
|
||||
### 8.3 内容页
|
||||
|
||||
**已绑 30 页**(按分组;逐页形态见 [`docs/UI设计/页面补齐规划.md`](../UI设计/页面补齐规划.md)):
|
||||
**已绑 31 页**(按分组;逐页形态见 [`docs/UI设计/页面补齐规划.md`](../UI设计/页面补齐规划.md)):
|
||||
|
||||
| 分组 | 页面 | 形态 |
|
||||
|---|---|---|
|
||||
@@ -1586,21 +1592,21 @@ docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5
|
||||
| 参数定值 | 整定 4 页(参数 / 定值 / 控制字 / 软压板) | 可编辑(写值 + 置脏 + 保存反馈) |
|
||||
| 三遥设置 | 遥测死区 / 遥测系数 | 可编辑(运行参数段,`0x8030~0x804F`) |
|
||||
| 装置维护 | 时钟设置 / 强制复归 / 清除记录 / 手动录波 | 操作页(执行类必须出真反馈,不得"点了没效果";手动录波触发后回读同一份计数,判据见 docs/子系统设计/故障录波设计说明.md §8.2) |
|
||||
| 通讯参数 | 通讯设置 / 网口设置 | 可编辑(`[comm]` / `[network]` 段,保存后按各自生效时机) |
|
||||
| 通讯参数 | 通讯设置 / 网口设置 / SNTP 设置 | 可编辑(`[comm]` / `[network]` / `[sntp]` 段,保存后按各自生效时机;SNTP 页改后立即随下一轮生效,判据见 §5.3 FR-TIME-3) |
|
||||
| 记录查询 | SOE 记录 / 自检记录 / 运行记录 | 记录列表(共用 reader) |
|
||||
| 记录查询 | 事故记录 / 操作记录 / 保护告警 / 保护启动 / 遥控记录 | 记录列表(每记录 2 行、空态显「无记录」;写入点与判据见 App/log/README.md §五类记录) |
|
||||
| 记录查询 | 运行报告 | 只读列表 13 行分 2 页;四个数逐个挂范围标签(自电池周期 / 本次开机),跨开机累计按裁定不做 |
|
||||
| 记录查询 | 录波回放 | 单通道波形页(阶梯线自绘、8 路切换、单位徽标、削顶标记、空态与不可读态显式文案);显示契约见 docs/子系统设计/故障录波设计说明.md §8.1 |
|
||||
|
||||
**未绑 4 叶**(2026-10-28:记录 5 页与运行报告页已落地绑页,原「当前执行 6 项」清零;2026-10-29:
|
||||
录波道落地,「手动录波」叶子随之一并绑页):
|
||||
遥信类型 / 遥信防抖 / 双点遥信 = 等开入硬件(§9.1.1「出口与开入」);SNTP 设置 = 等 SNTP 对时(§9.1.2「SNTP 对时」)。
|
||||
**未绑 3 叶**(2026-10-28:记录 5 页与运行报告页已落地绑页,原「当前执行 6 项」清零;2026-10-29:
|
||||
录波道落地,「手动录波」叶子随之一并绑页;2026-11-04:SNTP 客户端立项落地,「SNTP 设置」叶绑页):
|
||||
遥信类型 / 遥信防抖 / 双点遥信 = 等开入硬件(§9.1.1「出口与开入」)。
|
||||
|
||||
- 内容页为**独立全屏屏**,由框架一次性自绘(**零 LVGL 子对象**),`ESC` 返回菜单屏。
|
||||
- 菜单导航状态**不压层**,返回即原样还原;同一时刻至多一个内容页打开。
|
||||
- 节点→页映射在逻辑层 `menu_content_page_for(node)`;未绑叶子进入空白终点框(不伪造数据)。
|
||||
- 数据供给走**注入通道**(rt / par / info / 遥测死区与系数第四表),页面不直接触算法层;
|
||||
像素黄金用例当前 **66 张**(菜单 8 状态另计;2026-10-28 记录 5 页与运行报告 2 页落地 +7 张;2026-10-29 录波 UI 道 6 张:手动录波 3 态 + 录波回放 3 态)。
|
||||
像素黄金用例当前 **74 张**(菜单 8 状态另计;2026-10-28 记录 5 页与运行报告 2 页落地 +7 张;2026-10-29 录波 UI 道 6 张:手动录波 3 态 + 录波回放 3 态;2026-11-04 SNTP 设置页 +8 张)。
|
||||
|
||||
### 8.4 密码与权限
|
||||
|
||||
@@ -1664,7 +1670,7 @@ docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5
|
||||
| **多规约栈** | 17 | 12 种 | 1 种(104) | +11 种(101 / 102 / 103 / CDT / ModBus / Whm_GB / 61850 / CAN + 子站侧 3 类) |
|
||||
| **国密算法** | 18 | `Comm/Ecc/` 全套 | 0 | SM2 / SM3 / ECDSA |
|
||||
| **软压板铺开** | 11 | 9 面(表容量 32) | 1 面 | +8 面 |
|
||||
| **SNTP 对时** | 17 | 参考对时走 SNTP | 私有 TCP 8888 + 104 `C_CS` | SNTP 客户端 |
|
||||
| **SNTP 对时** | 17 | 参考对时走 SNTP | **SNTP 客户端已落地**(2026-11-04:coreSNTP 序列化器 + `[sntp]` 配置 + UI 设置页 + timeSyncTask 接入,判据 §5.3 FR-TIME-3);另有私有 TCP 8888 + 104 `C_CS` | 台架真机对时判据(现场时间源,docs/任务规划/登记簿.md) |
|
||||
| **固有参数** | 1 | `8001H~800AH` 字符串类参数 | 未实现(无法短浮点上送) | 随送检点表设计 |
|
||||
| **遥测增强** | 4、5 | k=1~9 谐波方和根 + 4 点平均 | 仅基波轨 | 谐波 / 等周波调频 / 零序自产外接切换 三条算法轨 |
|
||||
| **屏板链路对齐** | 20 | **串口屏板通道**(**700000 8N1 / USART1 TTL 直连、无 DE**,帧 A 6 B 召唤、帧 B **4208 B** 应答:显存 3200 B + **状态灯 4 B 位掩码** + 4 B info)+ **7003 四命令**(INIT **16 B**,单色口径)+ 续传 / 拒绝握手 / 链路监视 / F1·F2 | **串口通道已交付**(4208 B 应答 / 状态灯掩码 / 键上行 / 双出口并发,屏板链路设计说明 §9.1);7003 四命令(INIT **8 B**);无续传、无 `bNeedFlash` 拒绝、无 1 分钟监视、键值 6 个 | 7003 报文口径 6 项(`参考产品复刻明细.md` §11 第 2~9 条);串口侧验收尾巴见屏板链路设计说明 §9.2 |
|
||||
|
||||
+12
-11
@@ -8,20 +8,22 @@
|
||||
|
||||
## 1. 目标与范围
|
||||
|
||||
菜单树共 **34 叶**(节点行合计 43,缩进即层级):按行内 `#page=` 实测**已绑 30 叶、未绑 4 叶**,
|
||||
页面映射表 `UI_PAGE_MAP_COUNT` = 30(与已绑叶数一致)。未绑 4 叶 = §5 明确不做的 **4 叶**
|
||||
(遥信 3 / SNTP 1),与下面分类表逐项对得上;2026-10-29 录波 UI 道把「手动录波」从不做转为
|
||||
落地并新增「录波回放」叶,绑 +2(手动转绑 + 新叶)/ 叶 +1;2026-10-28 记录 5 页与运行报告页落地后,
|
||||
菜单树共 **34 叶**(节点行合计 43,缩进即层级):按行内 `#page=` 实测**已绑 31 叶、未绑 3 叶**,
|
||||
页面映射表 `UI_PAGE_MAP_COUNT` = 31(与已绑叶数一致)。未绑 3 叶 = §5 明确不做的 **遥信 3 叶**,
|
||||
与下面分类表逐项对得上;2026-10-29 录波 UI 道把「手动录波」从不做转为
|
||||
落地并新增「录波回放」叶,绑 +2(手动转绑 + 新叶);2026-11-04 SNTP 客户端立项(Issue #57 拍板
|
||||
选型、#73 拍板节奏),SNTP 设置叶转绑定(+1);2026-10-28 记录 5 页与运行报告页落地后,
|
||||
原「需补配置或写入方」的 6 叶缺口清零并按销项删行(该行内容见本节末与 §3)。
|
||||
|
||||
| 分类 | 数量 | 当前怎么处理 |
|
||||
|---|---:|---|
|
||||
| 无开入硬件 | 3 | 不做:遥信类型、遥信防抖、双点遥信 |
|
||||
| 缺独立模块或产品定义 | 1 | 不做:SNTP 设置(手动录波已于 2026-10-29 随故障录波 UI 道落地转绑定,不再列不做) |
|
||||
|
||||
(原「缺独立模块或产品定义:SNTP 设置」行已于 2026-11-04 随 SNTP 客户端立项转绑定销项;手动录波更早,2026-10-29 随故障录波 UI 道转绑。)
|
||||
|
||||
现有基础:`ui_w_editor` / `ui_w_setlist` / `ui_page_action` 已就绪;`ui_data` 已扩到**四通道**
|
||||
(rt / par / info + 遥测死区与系数用的第四张注入表);像素黄金用例与字符集门禁已存在,内容页黄金
|
||||
现有 **66 张**(菜单 8 状态另计;2026-10-29 录波 UI 道 +6 张:手动录波 3 态 + 录波回放 3 态)。**装置维护 3 页、遥测死区/系数 2 页、通讯设置页、记录 5 页与
|
||||
现有 **74 张**(菜单 8 状态另计;2026-10-29 录波 UI 道 +6 张:手动录波 3 态 + 录波回放 3 态;2026-11-04 SNTP 设置页 +8 张)。**装置维护 3 页、遥测死区/系数 2 页、通讯设置页、SNTP 设置页、记录 5 页与
|
||||
运行报告页都是把这套基础接上真实消费者做出来的,不另发明一套机制。**
|
||||
逐页形态见 `docs/UI设计/页面补齐规划.md`;数据契约见
|
||||
`docs/UI设计/UI_数据供给设计说明.md`。本文件保留范围、完成判据与不做的取舍口径(执行清单已于 2026-10-28 清空)。
|
||||
@@ -31,11 +33,11 @@
|
||||
1. **节点行** = `ui_menu_tree.txt` 里非空、非 `#` 开头的行(当前 **43** 行,含根「主界面」)。
|
||||
2. **缩进即层级**(每级 2 空格;Tab 会被 `gen_menu.py` 直接拒绝):某节点行之后再没有更深缩进的行 = **叶**
|
||||
(当前 **34** 叶);有更深缩进后继者 = 菜单节点(当前 **9** 个)。等价于生成物口径 `ui_menu_tab_has_children(node) == false`。
|
||||
3. **绑定**:叶行行尾带 ` #page=` = 已绑(当前 **30** 叶);不带的 = 未绑(当前 **4** 叶)。
|
||||
4. **闭合**:`未绑 = 待做 + 不做` —— 当前待做 **0**(§2 清单已清空)+ 不做 **4**(遥信 3 / SNTP 1)= **4**,
|
||||
3. **绑定**:叶行行尾带 ` #page=` = 已绑(当前 **31** 叶);不带的 = 未绑(当前 **3** 叶)。
|
||||
4. **闭合**:`未绑 = 待做 + 不做` —— 当前待做 **0**(§2 清单已清空)+ 不做 **3**(遥信 3)= **3**,
|
||||
与上面的分类表、§5「当前不做」表逐项对得上。
|
||||
5. **别拿 `grep -c '#page='` 当已绑叶数**:2026-10-28 实测它得 **29**,比真值多 1 —— 文件头第 5 行是规则说明里的
|
||||
` #page=<模块名>` 示例行(不是节点行),必须先剔注释/示例行;剔完的 30 才等于生成物 `UI_PAGE_MAP_COUNT`。
|
||||
` #page=<模块名>` 示例行(不是节点行),必须先剔注释/示例行;剔完的数才等于生成物 `UI_PAGE_MAP_COUNT`(现 31)。
|
||||
|
||||
复核命令(复用生成器自己的解析器 `tools/menu_gen/gen_menu.py` 的 `parse_tree`,不另写一套计数逻辑,免得与生成物脱钩):
|
||||
|
||||
@@ -49,7 +51,7 @@
|
||||
三个已踩过的错算法(每种都同时给**当时**与**2026-10-28 重跑**的产物——错法不会自己失效,只是错数跟着已绑叶数一起漂):
|
||||
**把 42 个节点行当叶子**(多算 9 个菜单节点:当时已绑 21 叶 → 得「未绑 21」,2026-10-28 同一错法得「未绑 14」= 42 − 28);
|
||||
**`grep -c '#page='` 当时得 23**(当时已绑 22 叶,多的那 1 正是文件头注释第 5 行的 `#page=<模块名>` 示例字样,必须先剔注释行;
|
||||
2026-10-28 同一命令得 29 = 当时已绑 28 + 该示例行 1;2026-10-29 现值 31 = 已绑 30 + 示例行 1);**按叶子名去重得 29**(`参数`/`定值`/`控制字`/`软压板` 在「整定」「查看」下各一份,
|
||||
2026-10-28 同一命令得 29 = 当时已绑 28 + 该示例行 1;2026-10-29 当时值 31 = 已绑 30 + 示例行 1;2026-11-04 现值 32 = 已绑 31 + 示例行 1);**按叶子名去重得 29**(`参数`/`定值`/`控制字`/`软压板` 在「整定」「查看」下各一份,
|
||||
4 对同名不能合并;2026-10-28 重跑仍是 29 = 33 叶 − 4 对同名)。
|
||||
(21 / 23 两个错数分属 2026-10-27「已绑 21 叶」与「已绑 22 叶」两个时点的实测,只用来说明错法,不代表现值;
|
||||
去重 29 与上面 grep 现值 29 **只是撞号**:一个是「合并同名叶」、一个是「不剔注释行」,都与真值 30(2026-10-29 现值)无关。)
|
||||
@@ -112,7 +114,6 @@ UTC 写入,后写者赢 ⇒ 装置墙钟与主机本地时刻恒差 8 小时
|
||||
| 项目 | 不做原因 | 重开条件 |
|
||||
|---|---|---|
|
||||
| 遥信类型 / 防抖 / 双点 3 页 | V0.1 无开入硬件,配置没有消费者 | 开入固件立项后,与开入开出一起做 |
|
||||
| SNTP 设置 | 当前使用 8888 私有对时协议,SNTP 链路与产品口径均未建立 | SNTP 客户端立项 |
|
||||
| net 层与其他结构债 | 当前只做 UI,避免两条主线互相拖慢 | UI 当前清单完成后,按 README §2 切换 |
|
||||
| RTC 时基统一 | 两套写入口径并存(面板与 8888 写本地钟面、104 写 UTC),恒差 8 小时;统一任一侧都要动 104 上行语义或 UI 判据 | 用户裁定时基方向后,作为跨模块变更单独立项 |
|
||||
| 主站地址白名单 | CH395F 单连接 socket 上「拒绝即 close+重 listen」等于给扫描风暴开门,且该值现在没有任何既有消费点 | 有真实消费场景或多连接后端立项时再评 |
|
||||
|
||||
+1
-1
@@ -67,6 +67,7 @@
|
||||
| **网络负向场景台架验证** | 拔线、SPI 故障注入、远显压力条件 | PHY 拔线、芯片级 `net_init` 失败、短写压测 | 本文件 §1 |
|
||||
| **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 开机账本一行 |
|
||||
| **SNTP 校时真机判据** | 台架:板与 PC SNTP 服务器(192.168.31.161 / .13)同网段可达 | `[sntp]` 使能 + 配服务器后上板复核:`[SNTP] step offset=` 步进日志、钟面与时间源一致(本地 UTC+8 口径)、`poll_min` 周期到点重对、拔线后指数退避与主备轮换、恢复后回到周期 | `../子系统设计/系统墙钟时间维护说明.md` §16 |
|
||||
|
||||
**送检顺序不可倒过来**:产品构建当前要求 UA/UN/IA 的标定 VALID 全部置位才走保护判据。
|
||||
未完成标准源标定就送检,保护会表现为不动作。保持该闭锁,不用非标准源标定走捷径。
|
||||
@@ -81,7 +82,6 @@
|
||||
| **开入开出与遥信配置 3 页** | 固件和 V0.1 硬件均无可配开入对象;出口还涉及 GPIO 安全电平、保持/脉冲和回读自检 | 开入开出作为独立模块立项,再与 UI 页面同批 |
|
||||
| **故障录波** | 独立子系统,不是补一个页面——**2026-10-29 已立项**:设计与板级判据属主 docs/子系统设计/故障录波设计说明.md(§10;原卡片登记簿 2026-10-30 销项并入后删除) | 已解除暂缓;执行按该文 §10 顺序图,UI 道互斥 |
|
||||
| **104 文件传输(规约侧读文件)** | 录波取回走现成 FTP 已够用,规约侧文件服务是另一件事 | 送检或第三方交接需求明确后单独立项 |
|
||||
| **SNTP 设置** | 当前对时走 8888 私有协议,SNTP 客户端与产品口径未定 | SNTP 客户端立项 |
|
||||
| **RS-485 整簇** | 用户决定暂缓 | `暂缓-RS485.md` |
|
||||
|
||||
## 9. 开放问题
|
||||
|
||||
@@ -47,10 +47,10 @@ dhara 失败类 +84;RO 另 +208,全是该失败类名表)→ `ER_IROM1`
|
||||
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
|
||||
| 区域 | 用量 | 容量 | 占比 |
|
||||
|---|---|---|---|
|
||||
| ER_IROM1 | 278,956 B (272.42 KB) | 1,048,576 B (1024 KB) | 26.6% |
|
||||
| RW_IRAM1 | 94,624 B (92.41 KB) | 131,072 B (128 KB) | 72.2% |
|
||||
| ER_IROM1 | 284,800 B (278.12 KB) | 1,048,576 B (1024 KB) | 27.2% |
|
||||
| RW_IRAM1 | 94,736 B (92.52 KB) | 131,072 B (128 KB) | 72.3% |
|
||||
| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
|
||||
| **Flash (ROM 合计)** | **281,008 B (274.4 KB)** | 1,048,576 B (1024 KB) | **26.8%** |
|
||||
| **Flash (ROM 合计)** | **286,872 B (280.1 KB)** | 1,048,576 B (1024 KB) | **27.4%** |
|
||||
<!-- MEM_SNAPSHOT:END -->
|
||||
|
||||
各区的容量与常量来源:
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
<!-- MEM_BUDGET:BEGIN generated by scripts/ram_baseline.py -->
|
||||
| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |
|
||||
|---|---|---|---|---|
|
||||
| ER_IROM1 (Flash) | 278,956 B | 1,048,576 B | 26.6% | 参考 |
|
||||
| ER_IROM1 (Flash) | 284,800 B | 1,048,576 B | 27.2% | 参考 |
|
||||
| RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS |
|
||||
| UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 |
|
||||
| RW_IRAM1 | 94,624 B | 131,072 B | 72.2% | PASS |
|
||||
| RW_IRAM1 | 94,736 B | 131,072 B | 72.3% | PASS |
|
||||
|
||||
| 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 |
|
||||
|---|---|---|---|
|
||||
| 网络 | 13,958 B | 12 KB | ⚠ 超 1.6 KB |
|
||||
| 存储 | 7,072 B | 12 KB | OK |
|
||||
| UI | 36,473 B | 16 KB | ⚠ 超 19.6 KB |
|
||||
| UI | 36,475 B | 16 KB | ⚠ 超 19.6 KB |
|
||||
| RTOS 堆 | 57,376 B | 56 KB | 堆=配额 |
|
||||
| 应用 | 26,333 B | 8 KB | ⚠ 超 17.7 KB |
|
||||
| 其它 | 10,780 B | — | 参考 |
|
||||
| 应用 | 26,433 B | 8 KB | ⚠ 超 17.8 KB |
|
||||
| 其它 | 10,792 B | — | 参考 |
|
||||
<!-- MEM_BUDGET:END -->
|
||||
|
||||
- **门禁**:pre-commit `mem-budget` 钩子(`scripts/ram_baseline.py --gate`)——
|
||||
|
||||
@@ -299,7 +299,7 @@ uint32_t now = sys_clock_get(); /* Unix 秒,可用于 FatFS 文件时间、
|
||||
|------|------|------------|
|
||||
| 时间范围 | 受 `uint32_t` 限制至 2038 | 改用 `uint64_t`/`time_t` 扩展 |
|
||||
| 运行期校准 | 30 天惰性再基准化已实现(§7):纯自我参照、零 I2C;**有意不**周期性重读 RTC 重锚——RTC 漂移(±20ppm ≈ ±1.7 s/天)远大于 Tick 漂移,重锚反而降低精度;时间纠偏由时间同步(§15)负责 |
|
||||
| 网络校时 | 已实现(PC 推送 / TCP,见第 15 节) | SNTP/NTP 公网校时仍可作为后续扩展 |
|
||||
| 网络校时 | 已实现两条:PC 推送 / TCP 8888(§15);**SNTP 客户端 / UDP 123(§16,2026-11-04 落地)** | NTP 公网源需现场路由,口径不变;104 `C_CS` 写入口径见 §1.1 末待决项 |
|
||||
| 时区 | **口径已定:内部一律本地钟面,不存时区**(用户裁定 2026-10-27,见 §1.1) | 「API 层加偏移参数」这条旧建议**作废**;唯一待决的是 104 上行是否要转 UTC(§1.1 末,送检前定) |
|
||||
|
||||
### 13.1 用户 SRAM 的占用分配(共享资源,用之前先在这里登记)
|
||||
@@ -334,6 +334,9 @@ SD2506 有 **70 字节电池保持用户 SRAM**(寄存器 `2CH~71H`,`Drivers
|
||||
| `App/app/app_main.c` | 初始化调用顺序:`sd2506_init()` → `boot_stats_init()`(用户 SRAM 上电账本,§13.1)→ `sys_clock_init()` |
|
||||
| `App/util/boot_stats.c` / `.h` | 用户 SRAM 上电账本 + 本次开机复位原因快照(占用见 §13.1;单测 `test/host/boot_stats/`) |
|
||||
| `App/sync/time_sync.c` / `time_sync.h` | 时间同步实现(TCP Server,`timeSyncTask`) |
|
||||
| `App/sync/time_sntp.c` / `time_sntp.h` | SNTP 校时客户端(§16,同一任务内挂 8888 事件循环);单测 `test/host/sntp/` |
|
||||
| `Drivers/BSP/NETCFG/sntp_cfg.c` / `.h` | `[sntp]` 配置段属主(注册在 `net_cfg_load()`) |
|
||||
| `Lib/coreSNTP/` | vendored coreSNTP v2.0.0 序列化器(MIT,仅 serializer + LICENSE;48 字节报文编解码) |
|
||||
| `test/host/time_sync_server.py` | PC 端时间推送客户端(TCP) |
|
||||
|
||||
---
|
||||
@@ -392,6 +395,7 @@ for (;;) {
|
||||
- `net_socket()` 从 0 开始分配第一个空闲 Socket 控制块(`alloc_socket()`),并把硬件 Socket 号设为该下标;调用时的第三个参数(0)仅为协议占位,不影响分配。
|
||||
- 当前启动顺序:FTP 任务(`NET_READY` + `STORAGE_READY` 屏障满足后,无魔法延时)先监听 → 占用一个 Socket(单连接模式下监听通道复用为数据通道);时间同步任务(`NET_READY` 后)后监听 → 占用另一个空闲 Socket。二者不冲突。
|
||||
- 单连接模式允许**任意** Socket 作为"监听 + 数据复用"通道,且总共 8 个 Socket,FTP 与时间同步各用 1 个,余量充足。
|
||||
- SNTP 客户端(§16)另占 1 个 UDP Socket:懒创建(首次到点才 `net_socket`+`net_bind` 本地口 0 = 芯片动态分配),断网代际变化、`enable=0` 或内核错误码时关闭归还;不监听、不参与端口台账。
|
||||
|
||||
### 15.6 客户端实现要点(避坑)
|
||||
|
||||
@@ -415,3 +419,22 @@ PC 端 `test/host/time_sync_server.py` 发送 8 字节后**必须保持连接打
|
||||
```
|
||||
|
||||
PC 端 `python test/host/time_sync_server.py` 每 `interval` 秒推送一次,epoch 随电脑本地时间递增即表示同步正常。
|
||||
|
||||
---
|
||||
|
||||
## 16. SNTP 校时(客户端,2026-11-04 落地)
|
||||
|
||||
- 模块:`App/sync/time_sntp.c/.h`(挂在 timeSyncTask 的 8888 事件循环里,等待切片 ≤50 ms,不饿任务狗);
|
||||
48 字节报文编解码 = vendored coreSNTP 序列化器(`Lib/coreSNTP/`,MIT,零堆),节奏与准入判据在本方。
|
||||
- 配置:`/config.ini` `[sntp]` 段(`enable` / `server1` / `server2` / `poll_min`,属主 `Drivers/BSP/NETCFG/sntp_cfg.c`,
|
||||
注册在 `net_cfg_load()`);现场改法 = UI「通讯参数 → SNTP 设置」页(密码叶)保存后随下一轮生效,或 FTP 改文件(4 s 落定)。
|
||||
出厂默认**不启用**、服务器为空——不配不发任何 UDP 包。
|
||||
- 时钟面换算:SNTP 给的是 UTC,落库前加固定东八区偏移(`SNTP_TZ_LOCAL_OFFSET_SECS 28800`)写 `sys_clock_set_unix()`
|
||||
(连带回写 SD2506)——这正是 §1.1 裁定「任何来源写入前先换算成本地钟面」的第三个写入口;装置仍不存时区。
|
||||
- 判据(RFC 4330 §10 口径):OriginTimestamp 逐位等于发出时的 T1(含低 16 位随机小数位,防伪造/防重放);
|
||||
mode=4、stratum 1~15、闰秒指示 ≠3、服务器 Kiss-o'-Death 按 DENY/RSTR(换服务器)与 RATE(退避)分流;
|
||||
响应源地址必须等于请求目的地址。失败:超时指数退避(5 s 起、60 s 封顶)+ 主备轮换;成功:恢复 `poll_min` 周期。
|
||||
- 步进策略:|offset| < 2 s 只记日志不步进;≥ 2 s 或冷启动直接步进并留痕 `[SNTP] step offset=`、`syslog` OPER
|
||||
「clock set by SNTP」;首个校验通过的同步置 `SYS_EVT_TIMESYNC_READY`(就绪位,不覆盖后续步进语义)。
|
||||
- 与 8888 的关系:同一任务、同一 `sys_clock_set_unix` 收口,**后写者赢**维持现状(两路并存是部署选择,不是冲突缺陷)。
|
||||
- 主机单测:`test/host/sntp/`(报文格式、防伪拒收、KoD、退避与周期、阶跃域守卫、配置注册表)。
|
||||
|
||||
+33
-1
@@ -197,6 +197,37 @@ write=1
|
||||
[adc_cal] 9 键 / [adc_cal_ofs] 8 键 / [run_par] 9 键 / [comm] 2 键);段/键上限
|
||||
的机器钉 = `test/host/cfg_file` TC-CONFIG-056/057。
|
||||
|
||||
### 3.7 `[sntp]` 段:SNTP 校时参数(2026-11-04 新增,板端 SNTP 客户端接入,#57 调研结论)
|
||||
|
||||
板端 SNTP 客户端的持久载体(消费方 = `App/sync/time_sntp.c`,挂在 timeSyncTask
|
||||
既有循环上,48 字节报文走 PR #74 后的 UDP socket 通道;数据本体 =
|
||||
`Drivers/BSP/NETCFG/sntp_cfg.h/.c`(纯段数据 + 读写出口,不依赖引擎头——分层门禁
|
||||
layer-deps 口径),段描述符由 `net_cfg.c` 的 `s_sntp_register()` 组装,注册编排 =
|
||||
`net_cfg_load()` 统一调用——与 [ftp] 同路径,「先注册后 load」成立):
|
||||
|
||||
| 键 | 含义 | 工厂默认 | getter 合法带(带外自愈回默认) |
|
||||
|---|---|---|---|
|
||||
| `enable` | 校时开关 | **0(出厂关闭)** | 0/1,非 1 一律视为关 |
|
||||
| `server1` | 主 SNTP 服务器 | **0.0.0.0(留空)** | 点分 IPv4 字面量(引擎 `s_decode_ip4` 解析;**无 DNS**) |
|
||||
| `server2` | 备 SNTP 服务器 | 0.0.0.0 | 同上;主服务器超时/拒绝(KoD DENY·RSTR)自动切换 |
|
||||
| `poll_min` | 轮询周期(分钟) | 60 | 1 ~ 1440(带外读回 60,**不写回 RAM**,`sntp_cfg_poll_min()`) |
|
||||
|
||||
- **零足迹口径**:出厂默认关闭 + 服务器留空 → 不开 socket、不发一个字节(与
|
||||
「FTP 未配置不监听」一致);配了可达时服务器的现场才启用。
|
||||
- **生效链路**:页面保存行 → `SYS_EVT_CFG_SAVE` 整档外科落盘(引擎属主 defaultTask
|
||||
不变);客户端每轮直接读 RAM 副本,**无段回调、不新增事件位**。网络重建
|
||||
(代次变化)时 UDP socket 随芯片复位被弃用,客户端检测 `net_get_generation()`
|
||||
变化后关闭旧 fd 并**重新 1~5 分钟随机散布**首轮(RFC 4330 §10 口径)——
|
||||
即 §4.2 自愈机制在 UDP 客户端侧的自然延伸(表内 TCP 三服务之外)。
|
||||
- **时钟面口径**:校验通过的服务器时间折算为 UTC 后**恒加 28800 s**(本地
|
||||
UTC+8,单一「本地钟面」口径,#56 裁决,见
|
||||
`docs/子系统设计/系统墙钟时间维护说明.md` §1.1;工程不存时区)再交
|
||||
`sys_clock_set_unix()`(内部含 SD2506 RTC 写回);`|offset| ≤ 2 s` 只记录
|
||||
不拨针(防 RTC 无谓磨损)。冷启动(钟面无效)直接采用服务器 T3。
|
||||
防欺骗/退避/KoD 细则 → `App/sync/time_sntp.c` 文件头 +
|
||||
`test/host/sntp`(TC 命名即判据)。
|
||||
- 容量台账:本段上线后 `/config.ini` 受管段 = **7/8**(前 6 段见 §3.6,本段 4 键)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 生效链路
|
||||
@@ -302,7 +333,8 @@ ENTER 进入选中地址行 → `↑/↓` 调活动字节(0..255 **环绕**)
|
||||
|
||||
| 文件 | 职责 |
|
||||
|---|---|
|
||||
| `Drivers/BSP/NETCFG/net_cfg.h/.c` | 配置核心:RAM 副本 + 工厂默认 + 加载/保存编排 + MAC 影子 + IPv4 格式化([network] 段注册) |
|
||||
| `Drivers/BSP/NETCFG/net_cfg.h/.c` | 配置核心:RAM 副本 + 工厂默认 + 加载/保存编排 + MAC 影子 + IPv4 格式化([network] 段注册;`net_cfg_load()` 一并注册 [ftp]/[sntp]) |
|
||||
| `Drivers/BSP/NETCFG/sntp_cfg.h/.c` | [sntp] 段核心:RAM 副本 + 工厂默认 + 注册 + `poll_min` 带外自愈出口(`App/sync/time_sntp.c` 每轮只读) |
|
||||
| `App/cfg/cfg_file.h/.c` | 通用配置文件引擎(双端共享核心:解析/校验/外科保存/模板/沉降轮询) |
|
||||
| `App/cfg/cfg_file_store.h` | 存储后端接口(带路径的文件操作) |
|
||||
| `App/cfg/cfg_file_store_mcu.c` | MCU 后端:FatFS `/config.ini`(`/config.TMP` + `f_rename` 原子写) |
|
||||
|
||||
@@ -156,6 +156,7 @@ mac=00:00:00:00:00:00
|
||||
| `App/util/sys_clock.c/.h` | 修改 | MCU | 新增 `sys_clock_get_time()`(日历时间获取器);改归 ④中间件层,自 `App/` 移入 `App/util/` |
|
||||
| `Drivers/BSP/NETCFG/net_cfg.h/.c` | 重构 | 双端 | `net_cfg_*` API 不变;load/save 走 cfg_file;注册 `[network]` 段 |
|
||||
| `App/protocol/iec104/iec104_comm.h/.c` | 新增(2026-10-26 道G task-8) | 双端(模拟器编译但无消费路径) | 配对模块注册 `[comm]` 段(104 ca/端口,ca 1..65535 / port 1024..65535 合法带 getter 自愈);内核前 `iec104_comm_init()` 注册(同 [adc_cal]/[run_par] 先注册后 load 契约);生效 = 改后重启(键表与理由 → `docs/子系统设计/网络配置说明.md` §3.6);**不走 scripts 白名单**——`.c` 按 new-source-file 口径同笔进 uvprojx + `simulator/CMakeLists.txt` |
|
||||
| `Drivers/BSP/NETCFG/sntp_cfg.h/.c` | **新增**(2026-11-04 板端 SNTP 接入) | 双端(模拟器编译但无 sync 消费路径) | 注册 `[sntp]` 段(enable / server1 / server2 IPv4 字面量 / poll_min 1..1440 getter 带外自愈,iec104_comm 先例);`net_cfg_load()` 内与 [ftp] 同编排注册;消费方 `App/sync/time_sntp.c`(MCU 单端链接);键表与生效口径 → `docs/子系统设计/网络配置说明.md` §3.7;new-source-file 口径 uvprojx + `simulator/CMakeLists.txt` 双登记 |
|
||||
| `Drivers/BSP/NETCFG/net_cfg_legacy.c` | **已删除**(2026-10-10;曾于 P3 新增) | — | 旧 NCFG blob 解析 + 迁移;随"不保留旧档兼容"整体移除(见 §9.1) |
|
||||
| `Drivers/BSP/NETCFG/net_cfg_store.h` / `net_cfg_store_mcu.c` | **删除** | — | 由 `cfg_file_store.*` 取代 |
|
||||
| `simulator/sim/net_cfg_store_sim.c` | **删除** | 模拟器 | 由 `cfg_file_store_sim.c` 取代 |
|
||||
@@ -589,3 +590,4 @@ void adc_cfg_init(void)
|
||||
| 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 补齐」波次里的非 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-11-04 | v1.16:**新增 `[sntp]` 段(板端 SNTP 客户端接入,#57 调研结论落地)**——`Drivers/BSP/NETCFG/sntp_cfg.h/.c`(enable / server1 / server2 / poll_min 4 键;出厂默认**关闭 + 服务器留空 + 60 分钟** = "未配置零网络足迹"口径;`poll_min` 带外自愈 1..1440 → 60 不写回 RAM);数据本体 = `Drivers/BSP/NETCFG/sntp_cfg.h/.c`(不依赖引擎头,分层门禁 layer-deps 口径),段描述符由 `net_cfg.c` 的 `s_sntp_register()` 组装,注册编排 = `net_cfg_load()`(与 [ftp] 同编排,先注册后 load);消费方 = `App/sync/time_sntp.c`(挂 timeSyncTask 既有循环,vendor `Lib/coreSNTP` serializer 做 48B 报文编解码/防欺骗校验);保存立即生效 = 每轮直读 RAM 副本 + 网络代次重建弃 UDP socket 重散布,**无段回调、不新增事件位**;段占位 6→7 / 8;键表与生效细则 → `docs/子系统设计/网络配置说明.md` §3.7;机器钉 = `test/host/net_cfg` TC-NETCFG-005/006b..d/007(段注册契约)+ `test/host/sntp`(RFC 4330 §10 节奏 / §5.3 防欺骗 / §5.5 步进策略 / poll 钳位)
|
||||
|
||||
@@ -736,7 +736,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)+ `/serial-boot-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 状态 + 内容页 66 张像素黄金参考)覆盖;再写单测是第三份重复投资 | `ui-verify` skill 五步 + `docs/UI设计/UI_自动化测试流程.md` |
|
||||
| UI 侧 | 18 个 `.c` = **2,373 行**(2026-11-04 随 `ui_page_sntp.c` 从 17 个/1,942 行递增) | 与 PC 模拟器是**同一份源码**,行为回归已由 `ui-golden`(菜单 8 状态 + 内容页 74 张像素黄金参考)覆盖;再写单测是第三份重复投资 | `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`(`/serial-boot-test`)+ `docs/架构设计/项目启动顺序管理.md` |
|
||||
| 内核前装配 | `app_main.c`(135) | 被测对象本身就是"`osKernelStart` 之前不许调内核 API"的时序,主机侧无法忠实复现(PC 上没有那个约束) | 同上 + `cubemx-survival` 审计 |
|
||||
|
||||
|
||||
@@ -373,7 +373,7 @@ cmake --build simulator/build --config Debug # 0) 构建模拟器(须 0 警
|
||||
| 层 | 载体 | 抓住什么 |
|
||||
|---|---|---|
|
||||
| 文本层 | `check_content_pages.py` 字形模板匹配(310 条、覆盖当时 37 页,解析字体 cmap / glyph_dsc / bitmap) | 缺字显示空白 / 标签写错等**静默失败**(不依赖 `ref/`,先于像素比对运行、失败即中止防误刷参考) |
|
||||
| 像素层 | 内容页黄金参考 66 张(64 页)+ 菜单 8 状态,与黄金参考逐字节比对 | 几何 / 样式 / 光标反显 / 整体外观 |
|
||||
| 像素层 | 内容页黄金参考 74 张 + 菜单 8 状态,与黄金参考逐字节比对 | 几何 / 样式 / 光标反显 / 整体外观 |
|
||||
| 池水位层 | `MENU_POOL_BASELINE=5368 B` / `POOL_AFTER_ROUNDTRIP=5448 B` | LVGL 内存池泄漏 / 结构性漂移(量的是 `used`,与 `LV_MEM_SIZE` 总大小无关) |
|
||||
|
||||
### 5.3 黄金参考与字体纪律
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
|
||||
- **初始化回归**:`App/task/ui_task.c` 已有 `UI port init: OK` / `UI menu init: OK` / `UI net sink: started`
|
||||
打印(见 `run_boot_test.py` 命令示例);将其加入 `--required` 即可经串口自动回归 UI 初始化。
|
||||
- **屏幕内容回归**:由 LVGL 模拟器像素回归覆盖(文本级断言 + 66 张黄金参考 + 池水位门禁,
|
||||
- **屏幕内容回归**:由 LVGL 模拟器像素回归覆盖(文本级断言 + 74 张黄金参考 + 池水位门禁,
|
||||
见 `docs/UI设计/UI_自动化测试流程.md`);上机屏幕仍需人工目检(见 `测试开发标准流程.md` §1)。
|
||||
|
||||
## 扩展用法
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@
|
||||
| [`cubemx-survival.md`](cubemx-survival.md) | `cubemx-survival` | CubeMX 重生成会不会把定制静默抹掉(人工目检审计兜底) | `.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 状态 + 内容页 66 张黄金参考图比对 | UI 源码、模拟器 | 已写 |
|
||||
| [`ui-golden.md`](ui-golden.md) | `ui-golden` | UI 像素回归:菜单 8 状态 + 内容页 74 张黄金参考图比对 | 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` | 指针 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# `ui-golden` — UI 像素回归(菜单 8 状态 + 内容页 66 张黄金参考)
|
||||
# `ui-golden` — UI 像素回归(菜单 8 状态 + 内容页 74 张黄金参考)
|
||||
|
||||
> 一句话:改 UI 源码时,把模拟器增量重编 + 两条 golden 回归串成一次提交门禁,**像素对不上就拦**。
|
||||
> 它是包装器:真正的判据在被包装的两条脚本与参考图里。
|
||||
@@ -11,7 +11,7 @@
|
||||
## 1. 它在查什么
|
||||
|
||||
- 菜单侧:整棵菜单树的行渲染结果(8 个状态)与参考图逐像素比对;
|
||||
- 内容页侧:66 张黄金参考(= 66 个截图态条目,同一内容页的多个状态各一张:分页页多拍的第 2 屏与确认链/录波的各态都单独计条目),逐张与参考图比对;
|
||||
- 内容页侧:74 张黄金参考(= 74 个截图态条目,同一内容页的多个状态各一张:分页页多拍的第 2 屏与确认链/录波的各态都单独计条目),逐张与参考图比对;
|
||||
- 参考图 `simulator/tests/ref/*.bin` **就是判据本身**。
|
||||
|
||||
## 2. 为什么要它(有牙的实测)
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
1. **参考图即判据**:刷新参考图 = 修改判据。评审时必须盯 `simulator/tests/ref/` 的 diff;
|
||||
一旦"顺手更新",此后所有回归都只在和错的基线比。**门禁无法阻止这件事**,只能靠评审。
|
||||
2. 只覆盖 8 个菜单状态 + 66 张内容页黄金参考:未列入的状态(密码错误态、超长文本、缺字渲染、
|
||||
2. 只覆盖 8 个菜单状态 + 74 张内容页黄金参考:未列入的状态(密码错误态、超长文本、缺字渲染、
|
||||
无 SD 卡 / 挂载失败的降级显示)**不会有任何回归**。
|
||||
3. 跑的是**模拟器那份配置**,不是固件那份 —— 两份 `lv_conf.h` 漂移时,回归结论不能外推到固件
|
||||
(所以 `lv-conf-sync` 是本门有效性的前提)。
|
||||
|
||||
Reference in New Issue
Block a user