1d96fc9f87
- 新增 App/log/soe_rec.{c,h}:64B 定长 SOE 记录纯编解码(CP56Time2a
时标 + 类型 + 元件号 + 单调序号 + 值 + sum8 撕裂校验),零 I/O 零 OS
依赖,主机 L0.5 覆盖(32 断言,含与 iec104 CP56 解码器交叉互证)
- 新增 App/log/soe_store.{c,h}:protectTask 边沿投递(取时标 + 组记录 +
SPSC 待发环/消息队列,零文件系统);defaultTask 经 syslog_drain 尾部
排空落 /log/soe.log(卷锁 try / FA_WRITE|FA_OPEN_APPEND / 校验字节数 /
容量满 unlink 重建,全套照 run.log 实证纪律;无卷损坏归类路径)
- protect_task.c:元件动作/返回、软压板投退、采样闭锁/恢复六类边沿
→ soe_store_post;post 内禁 DBG_*(protect 静态最坏链 872 B 不变,
改前/改后 stack_report 九任务逐字节一致),丢弃留痕挪 drain 侧
- iec104:单点 YX 自发改 M_SP_TB_1(30) 带 CP56 时标(总召/周期保持
M_SP_NA_1,单测两种都断言);link cfg 新增 epoch_ms 时标源回调
(NULL/无效 → IV 位如实置位);serv 绑 sys_clock(秒域时基,
ms 域 = 秒×1000,不造假亚秒)
- 主机单测:test/host/soe/(32 断言)+ iec104 94→97(TB 时标/IV);
iec104_master.py 解析 type 30(B6/B7 流不回归);decode_soe.py
台架解码断言工具(seq 单调/校验和/UTC 交叉)
- 注册:uvprojx + check_registration SIM_EXEMPT 点名(MCU-only 胶水)
- 文档(我方属主区):`App/log/README.md` 增 soe 节(64B 记录/单写者/
post 禁 DBG/UTC 交叉坑);`docs/子系统设计/IEC104上行设计说明.md`
§1 范围行 + §3.2 时标注 + §7 台架行 + §8 第 2 条销项 + 变更记录行
台架腿(bench 锁 B9,release --bench-pass):run_boot_test PASS;
--b7-pre 21/21、--b7-post 13/13(B6/B7 回归 + 确定性动作边沿);
自发 YX 上送 M_SP_TB_1 带 ts(11:00:51 动作 / 11:00:53 复归);
FTP 下载 /log/soe.log 30 条记录 decode PASS(seq 0..28 单调、
ELM_ASSERT 14 条、UTC 交叉一致);定值/压板已恢复默认。
台账 +1088 B(SPSC 环 512 + 静态 FIL 528 + 计数器)随合并由 Lead
回填(ram_baseline --write + check_mem_numbers --write)。
gate: only mem-budget/mem-numbers pending lead ledger backfill
(pre-commit --all-files: 29 Passed / 2 Failed / 0 Skipped;
hygiene self-check OK: no BOM/CRLF/mojibake/trailws/non-ASCII literal)
sync 追平 v2-on-ui(B8 freq + N33 抬栈)后复跑:@build 0/0
(Code=209492 RW=1104 ZI=154184);stack_report 九任务全 PASS、
protectTask 872 B/57% 不变;ci_local L0.5 15 runner 951/951
(freq 46 / soe 32 / iec104 97 / prot_set 90 / prot_elm 47)。
顺带修 protect_task.c 陈旧注释:定值巡检 31 项 → 40 项(B8 后)。
132 lines
7.0 KiB
C
132 lines
7.0 KiB
C
/*
|
||
* 模块名称:IEC 60870-5-104 ASDU 编解码(应用层,纯逻辑)
|
||
* 模块功能:104 规约应用服务数据单元(ASDU)的类型/传送原因常量、组帧与解析。
|
||
* **零 I/O、零平台依赖**(仅 stdint.h)→ 主机侧 L0.5 可离线单测
|
||
* (登记簿 A-4 约束 1"协议解析与硬件 I/O 分离")。
|
||
* 口径来源:docs/算法/继电保护功能复现规划.md §1.5(B0 产品定义)——
|
||
* 公共地址 2 字节、传送原因 2 字节、信息体地址 IOA **3 字节**(101 为 2 字节);
|
||
* 遥测上送**短浮点** M_ME_NC_1(系数 = 1);遥信双点上双点、其余单点;
|
||
* 遥控**双点命令**(选择 82H / 执行 02H,即 QDC 的 S 位 + 值 2)。
|
||
* 帧结构(本层只管 ASDU,APCI 6 字节头归 iec104_link):
|
||
* [type 1B][vsq 1B][cot 2B][ca 2B]( [ioa 3B][元素...] )*n
|
||
* 多信息体地址对象(SQ=0)每对象带独立 IOA;顺序对象(SQ=1)单 IOA + n 元素。
|
||
* 创建日期:2026-10-12(B4,W1 功能主线,登记簿见 docs/任务规划/)
|
||
*/
|
||
#ifndef IEC104_ASDU_H
|
||
#define IEC104_ASDU_H
|
||
|
||
#include <stdint.h>
|
||
|
||
/* ---------------- 类型标识(DL/T 634.5104,仅定义本期子集) ---------------- */
|
||
#define IEC104_T_M_SP_NA_1 1U /* 单点遥信 SIQ */
|
||
#define IEC104_T_M_DP_NA_1 3U /* 双点遥信 DIQ */
|
||
#define IEC104_T_M_SP_TB_1 30U /* 单点遥信+CP56时标 SIQ+7B(B9 SOE 自发) */
|
||
#define IEC104_T_M_ME_NC_1 13U /* 遥测短浮点 float+QDS(§1.5 口径) */
|
||
#define IEC104_T_C_SE_NC_1 50U /* 定值写(短浮点)float+QDS */
|
||
#define IEC104_T_C_DC_NA_1 52U /* 双点遥控 QDC(82H 选 / 02H 执行) */
|
||
#define IEC104_T_C_IC_NA_1 100U /* 总召 RQT */
|
||
#define IEC104_T_C_RD_NA_1 102U /* 读单个测量值 IOA only */
|
||
#define IEC104_T_C_CS_NA_1 103U /* 时钟同步 CP56Time2a */
|
||
#define IEC104_T_C_TS_NA_1 104U /* 试验 FBP 2B */
|
||
#define IEC104_T_C_RP_NA_1 105U /* 进程复位 RPA 1B */
|
||
|
||
/* ---------------- 传送原因 COT(低字节 6bit;高字节 T|PN|RBT/…) ---------- */
|
||
#define IEC104_COT_PERIODIC 1U /* 周期/循环 */
|
||
#define IEC104_COT_BG_SCAN 2U /* 背景扫描(总召响应) */
|
||
#define IEC104_COT_SPONT 3U /* 突发(cos) */
|
||
#define IEC104_COT_INIT 4U /* 初始化(总召 + RBT=1 时用) */
|
||
#define IEC104_COT_REQ 5U /* 请求(C_RD 响应) */
|
||
#define IEC104_COT_ACT 6U /* 激活 */
|
||
#define IEC104_COT_ACTCON 7U /* 激活确认 */
|
||
#define IEC104_COT_ACTTERM 8U /* 激活终止 */
|
||
#define IEC104_COT_DEACT 9U /* deactivate */
|
||
#define IEC104_COT_DEACTCON 10U /* 停止激活确认 */
|
||
#define IEC104_COT_UNK_COT 12U /* 未知传送原因 */
|
||
#define IEC104_COT_UNK_CA 13U /* 未知公共地址 */
|
||
#define IEC104_COT_UNK_IOA 14U /* 未知信息体地址(+EVI) */
|
||
#define IEC104_COT_BIT_T 0x80U /* COT 高字节 bit7:试验 */
|
||
#define IEC104_COT_BIT_PN 0x40U /* COT 高字节 bit6:否定确认 */
|
||
#define IEC104_COT_BIT_RBT 0x10U /* COT 高字节 bit4:请求链路仿真(总召初始化) */
|
||
|
||
/* ---------------- VSQ ---------------- */
|
||
#define IEC104_VSQ_SQ 0x80U /* 1 = 顺序地址(单 IOA + n 元素) */
|
||
#define IEC104_VSQ_N(n) ((uint8_t)((n) & 0x7FU))
|
||
|
||
/* ---------------- 遥信/遥测品质描述位(本期只用溢出/异常/非当前) --------- */
|
||
#define IEC104_QDS_OV 0x01U
|
||
#define IEC104_QDS_BL 0x10U /* blocked(闭锁) */
|
||
#define IEC104_QDS_NT 0x20U /* not top(暂态品质,遥测未就绪用) */
|
||
#define IEC104_QDS_IV 0x80U /* invalid(无效,通道不可用用) */
|
||
#define IEC104_DIQ_IV 0x80U
|
||
#define IEC104_SIQ_IV 0x80U
|
||
|
||
/* ---------------- 双点值(DIQ/QDC 低 2bit) ---------------- */
|
||
#define IEC104_DPC_DONTCARE 0U
|
||
#define IEC104_DPC_OFF 1U
|
||
#define IEC104_DPC_ON 2U
|
||
#define IEC104_QDC_S 0x80U /* 1 = 选择,0 = 执行(§1.5:82H/02H) */
|
||
|
||
/* ---------------- 总召 RQT ---------------- */
|
||
#define IEC104_RQT_GROUP1 20U /* 总查询(组 1) */
|
||
|
||
/* ---------------- ASDU 头(解析产物) ---------------- */
|
||
typedef struct {
|
||
uint8_t type; /* 类型标识 */
|
||
uint8_t vsq; /* 可变结构限定词 */
|
||
uint8_t cot; /* 传送原因低 6bit */
|
||
uint8_t cot_hi; /* COT 首字节的高位标志(T=0x80 / PN=0x40 / RBT=0x10 原样保留) */
|
||
uint8_t oa; /* 源发站地址(第 2 COT 字节;bit7 = EVI) */
|
||
uint16_t ca; /* 公共地址(链路地址 = ASDU 公共地址,2B) */
|
||
const uint8_t *obj; /* 信息体区首址(指向调用方缓冲,生命周期同 on_rx) */
|
||
uint16_t obj_len; /* 信息体区长度 */
|
||
} iec104_asdu_hdr_t;
|
||
|
||
/*
|
||
* 函数功能:解析 ASDU 头(不解析信息体——各命令的体解析在 iec104_link 内做)
|
||
* 入口参数:buf - ASDU 首址(不含 APCI);len - ASDU 长度
|
||
* hdr - 输出头
|
||
* 返 回 值:0 成功 / -1 参数或长度错(len < 6)
|
||
* 函数说明:纯只读,不改动 buf。
|
||
*/
|
||
int iec104_asdu_parse_hdr(const uint8_t *buf, uint16_t len, iec104_asdu_hdr_t *hdr);
|
||
|
||
/*
|
||
* 函数功能:写 ASDU 头
|
||
* 入口参数:buf - 目标缓冲(容量须 ≥ 6);type/vsq/cot/cot_hi/ca 见常量
|
||
* 返 回 值:固定 6(已写字节数)
|
||
*/
|
||
uint16_t iec104_asdu_put_hdr(uint8_t *buf, uint8_t type, uint8_t vsq,
|
||
uint8_t cot, uint8_t cot_hi, uint16_t ca);
|
||
|
||
/* ---------------- 小工具(IOA 3B 小端 / IEEE 短浮点小端) ---------------- */
|
||
|
||
/* IOA(3 字节小端)写入 */
|
||
void iec104_put_ioa(uint8_t *buf, uint32_t ioa);
|
||
/* IOA(3 字节小端)读取 */
|
||
uint32_t iec104_get_ioa(const uint8_t *buf);
|
||
/* IEEE754 float 按 104 小端写入(memcpy 位模式,不做字节序假设) */
|
||
void iec104_put_float(uint8_t *buf, float v);
|
||
/* IEEE754 float 按 104 小端读取 */
|
||
float iec104_get_float(const uint8_t *buf);
|
||
|
||
/* ---------------- CP56Time2a(C_CS 时钟同步用) ---------------- */
|
||
|
||
/*
|
||
* 函数功能:解析 CP56Time2a(7 字节)为 epoch 毫秒
|
||
* 入口参数:buf - 7B 首址;epoch_ms - 输出(UTC 毫秒)
|
||
* 返 回 值:0 成功 / -1 参数错 / -2 IV 位置起(时间无效,调用方应拒绝)
|
||
* 函数说明:年字段仅 7bit(0..127,基准 2000);月/日/时/分按 1.. 语义;
|
||
* 不处理 SU(夏令时)位——忽略。
|
||
*/
|
||
int iec104_cp56_to_epoch_ms(const uint8_t *buf, uint64_t *epoch_ms);
|
||
|
||
/*
|
||
* 函数功能:epoch 毫秒 → CP56Time2a(7 字节,UTC 分解)
|
||
* 入口参数:epoch_ms - UTC 毫秒;buf - 目标 7B
|
||
* 返 回 值:固定 7
|
||
* 函数说明:epoch_ms < 2000-01-01 时钳到 2000(年字段下限);IV 清 0。
|
||
*/
|
||
uint16_t iec104_epoch_ms_to_cp56(uint64_t epoch_ms, uint8_t *buf);
|
||
|
||
#endif /* IEC104_ASDU_H */
|