94b0d79026
本笔含两组收尾工作(同一工作区内交错在 6 个共享文档/门禁配置里, 拆开会产生"文档声称的页数与树里黄金数不一致"的中间提交,故合为一笔): 一、UI 补齐(清单清空) - 新建 6 个内容页模块:ui_page_accident / oper / alarm / start / yk 复用 ui_w_records 共享组件(分页、空态"无记录"、按实例读盘缓存), 记录层与五个写入点已由道F task-10 / 道G task-12 落地,本批只补页面; ui_page_runreport 为 13 行 2 页只读统计,四个数逐个挂范围标签 (自电池周期 / 本次开机),boot_ready=0 显 "--" 不显 0。 - 数据面:ui_data_info_t 尾部追加 9 字段,ui_data_feed 用 boot_stats_get() + iec104_serv_get_stats() 纯搬运;模拟器填确定值假数据 (差异登记 docs/测试说明/模拟器差距清单.md §2.3 两行)。 - 接线:菜单树 6 叶绑 #page=,绑定叶 22→28、UI_PAGE_MAP_COUNT=28; 字库 185→218 字 / 280→313 字形;双端注册 uvprojx +30、CMakeLists +6。 - 回归:内容页黄金 53→60(含 runreport_p2 真拍第 2 页),文本断言 425 正向 / 36 反向;存量 53 张逐字节零漂移;记录 5 页各用独立空目录 (模拟器把操作留痕写进 cwd 的 sim_oper.log,共用 tmp 会让空态拍不到)。 二、数据可信销项 + 「数据可信」任务卡号整族清退 - 删除已闭环的"已知电压注入验证"行与闭环结论块(证据在 docs/硬件平台/ADC通道映射说明.md §8.1 与 docs/测试说明/ADC前端注入验证流程.md §5~§7),§5 标识列改语义短语。 - 卡 0/0b/1~12 共 14 个号全仓 288 站点 / 56 文件清退成语义短语, 代码注释、测试、门禁配置与文档一并改;换算表入 docs/编号规范.md §9.3。 这一族是中文前缀,不进 check_ids 语料,刻意不入 id_aliases.json。 验证(实测) - @build 0 错 0 警:Code=236456 RO=28124 RW=1876 ZI=137084; RAM +464 B(RW +304 / ZI +160),RW_IRAM1 62.2% / RW_CCM 87.9%, 体积同码凭证与 RAM 台账已回填。 - check_menu_rows 8 状态 rc=0(池 5368/5448 常量未动); check_content_pages 60 页 rc=0;check_font_charset / registration / coding-standard / bom-drift / mojibake / doc-links --all / layer-deps / nested-comment 全 rc=0;check_ids --strict 无错误;主机单测 ui_data 295 / boot_stats 21 / sys_log_mcu 141 / soe 32 / soe_store 27。 未做(不是遗漏) - 六页真机判据(真记录翻页、掉电保持、清除后归零、boot_count 自增、 拔 RTC 电池落 RESTARTED、IWDG 复位落 rst_cause、主站连一次 conn_up+1) 已登记 docs/任务规划/登记簿.md §7;模拟器结构上照不到。 - docs/产品需求/产品需求设计文档.md 属另一条在飞改动,本笔不含; 其中我已同步 6 处现状数字(28 叶 / 60 页 / 218 字),随该笔入库。
126 lines
5.5 KiB
C
126 lines
5.5 KiB
C
/*
|
||
* 模块名称:SOE Record — 事件顺序记录编解码(纯逻辑,双端可测)
|
||
* 模块功能:定长 64B SOE(Sequence-of-Events)记录的构建与解析:
|
||
* CP56Time2a 时标 + 记录类型 + 元件号 + 单调序号 + 值 + 校验和。
|
||
* **零 I/O、零 OS 依赖**(仅 stdint/string)→ 主机侧 L0.5 离线单测
|
||
* (分层约束:协议/记录与硬件 I/O 分离)。
|
||
* 记录口径(docs/算法/继电保护功能复现规划.md §3.4「SOE 记录」「动作记录」,B9):
|
||
* 落盘文件 = /log/soe.log(8.3 合规;FF_USE_LFN=0 约束),定长 64B 一条
|
||
* (照 run.log 先例:count = filesize/64 O(1)、容量满删除重建)。
|
||
* 独立于 run.log 的理由:run.log 是文本记录(时间戳+epoch+UTF-8 描述,
|
||
* syslog_get_record/UI 按文本读),SOE 是二进制结构化记录(时标/类型/
|
||
* 序号/值),混入同一文件会破坏现有文本读者。
|
||
* 记录布局(64B,多字节字段一律小端):
|
||
* [0] 版本 SOE_REC_VER
|
||
* [1] 类型 soe_type_t
|
||
* [2] 元件号(prot_elm_id_t;SOE_ELM_NONE=0xFF = 非元件事件)
|
||
* [3] 标志位(bit7 IV = 记录时时钟无效,CP56 IV 位同步置位)
|
||
* [4..7] 序号 seq(uint32 小端;上电内单调,跨复位重启计数——见 soe_store.h)
|
||
* [8..14] CP56Time2a(7B,IEC 60870-5-4 §5.1.6;秒域时基 → ms 字段恒 0)
|
||
* [15..18] epoch 秒(uint32 小端;IV 时置 0,主机解码交叉校验用)
|
||
* [19..22] 值 value(uint32 小端;语义随类型,见 soe_type_t 注释)
|
||
* [23..62] 保留(恒 0)
|
||
* [63] 校验和 = sum8([0..62])(撕裂/半写检测,解析侧拒绝不匹配)
|
||
* 创建日期:2026-10-12(B9)
|
||
*/
|
||
#ifndef SOE_REC_H
|
||
#define SOE_REC_H
|
||
|
||
#include <stdint.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* 记录尺寸与版本(定长;改布局必须升 SOE_REC_VER) */
|
||
#define SOE_REC_SIZE 64u
|
||
#define SOE_REC_VER 1u
|
||
|
||
/* 字段偏移(解析/主机解码工具共用口径) */
|
||
#define SOE_OFF_VER 0u
|
||
#define SOE_OFF_TYPE 1u
|
||
#define SOE_OFF_ELM 2u
|
||
#define SOE_OFF_FLAGS 3u
|
||
#define SOE_OFF_SEQ 4u /* 4B */
|
||
#define SOE_OFF_CP56 8u /* 7B */
|
||
#define SOE_OFF_EPOCH 15u /* 4B */
|
||
#define SOE_OFF_VALUE 19u /* 4B */
|
||
#define SOE_OFF_SUM 63u
|
||
|
||
/* 标志位 */
|
||
#define SOE_FLG_IV 0x80u /* bit7:记录时时钟无效(CP56 IV 位同步置位) */
|
||
|
||
/* 非元件事件的元件号 */
|
||
#define SOE_ELM_NONE 0xFFu
|
||
|
||
/*
|
||
* 记录类型(值语义随类型):
|
||
* 1 元件动作 value = 元件状态打包(bit0 asserted / bit1 picked / bit2 enabled)
|
||
* 2 元件返回 value = 同上(返回瞬间的旧状态快照)
|
||
* 3 软压板退出 value = 0
|
||
* 4 软压板投入 value = 1
|
||
* 5 采样闭锁 value = adc_health 闭锁位图(触发时的 hf & mask)
|
||
* 6 采样恢复 value = 0
|
||
* 7 标定闭锁 value = UA/UN/IA VALID 未齐的通道位图(未标定即闭锁,2026-10-25)
|
||
* 8 标定复归 value = 0
|
||
*/
|
||
typedef enum {
|
||
SOE_T_ELM_ASSERT = 1u,
|
||
SOE_T_ELM_RETURN,
|
||
SOE_T_PLATE_OUT,
|
||
SOE_T_PLATE_IN,
|
||
SOE_T_SAMPLE_BLOCK,
|
||
SOE_T_SAMPLE_RESUME,
|
||
/* 未标定闭锁(「数据可信」未标定即闭锁一项,2026-10-25 道A 追加):UA/UN/IA 的 VALID
|
||
* 未全置位 → 判据停走;与采样闭锁分型,边沿各留一条记录 */
|
||
SOE_T_CAL_BLOCK,
|
||
SOE_T_CAL_RESUME,
|
||
SOE_T_COUNT /* 哨兵值,非有效类型 */
|
||
} soe_type_t;
|
||
|
||
/* 解析产物(字段原样拷贝;CP56 不在此层换算,主机工具解码) */
|
||
typedef struct {
|
||
uint8_t ver;
|
||
uint8_t type;
|
||
uint8_t elm_id;
|
||
uint8_t flags;
|
||
uint32_t seq;
|
||
uint8_t cp56[7];
|
||
uint32_t epoch_s;
|
||
uint32_t value;
|
||
} soe_rec_t;
|
||
|
||
/*
|
||
* 函数功能:构建一条 64B SOE 记录(纯计算,无 I/O;任意上下文可调)
|
||
* 入口参数:rec - 输出缓冲(SOE_REC_SIZE 字节,不可为 NULL) uint8_t *
|
||
* type - 记录类型 soe_type_t(越界按 SOE_T_COUNT 处理为保留 0)
|
||
* elm_id - 元件号(非元件事件传 SOE_ELM_NONE) uint8_t
|
||
* flags - 标志位(SOE_FLG_IV = 时钟无效) uint8_t
|
||
* seq - 单调序号 uint32_t
|
||
* epoch_s - 墙钟 epoch 秒(IV 时传 0;同时 flags 须带 SOE_FLG_IV)
|
||
* value - 类型相关值 uint32_t
|
||
* 返回值:无
|
||
* 函数说明:epoch_s → CP56Time2a(UTC 分解,Hinnant civil 日历算法,与
|
||
* iec104_asdu.c 同一算法族;钳位 [2000-01-01, 2127-12-31],
|
||
* ms 字段恒 0——sys_clock 秒域时基,如实登记)。
|
||
* flags 带 IV 时 CP56 byte2 bit7 置位(标准"时间无效"语义)。
|
||
*/
|
||
void soe_rec_build(uint8_t *rec, uint8_t type, uint8_t elm_id, uint8_t flags,
|
||
uint32_t seq, uint32_t epoch_s, uint32_t value);
|
||
|
||
/*
|
||
* 函数功能:解析一条 64B SOE 记录(校验版本 + 校验和)
|
||
* 入口参数:rec - 原始记录(SOE_REC_SIZE 字节,不可为 NULL) const uint8_t *
|
||
* out - 解析输出(不可为 NULL) soe_rec_t *
|
||
* 返回值:0 成功 / -1 参数错 / -2 版本不符 / -3 校验和不符(撕裂/半写) int
|
||
* 函数说明:只读,不改动 rec。类型/标志不做强校验(前向兼容:新版本类型
|
||
* 旧解析器可读),版本与校验和是硬门槛。
|
||
*/
|
||
int soe_rec_parse(const uint8_t *rec, soe_rec_t *out);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* SOE_REC_H */
|