Files
STM32F4-Base/App/algo/prot_set.h
T
wandering1 1fe163ba7b feat(protect): B7 定值持久化 + 全局软压板 + L5-1 竞态收口(W1 代码腿完成)
- prot_set:新增 PS_GLOBAL_EN(枚举尾追加);值区双缓冲 + 单字交换,
  prot_set_set_sealed 原子写+封存;selfcheck 改 seqlock 式复核
  (提交撞见 = 本轮跳过)→ 收口 B5 登记的 µs 级误锁窗口
- 持久化:新增 App/cfg/prot_set_store.c/h,/prot_set.bin blob
  (magic+版本+计数+值区+sum32 正/反码对,144 B)走 cfg_store_write_atomic;
  uvprojx 注册 + 模拟器豁免点名(check_registration 同步)
- 写路径:C_SE/YK12 执行段置脏 → iec104Task 投递 SYS_EVT_PROT_SET_SAVE
  (事件位 bit7)→ defaultTask(配置引擎属主)落盘,写失败脏回置 = 天然
  重试;装载 = STORAGE_READY 屏障前整表原子 parse(损坏保出厂默认 +
  自检留痕 prot set corrupt;文件缺失 = 首启静默)
- YK12 转真:两段式(选择段校验 DPC / 执行段 set_sealed),protectTask
  下一拍读退出态 → 复位元件 + 停判据(global plate OUT/IN 边沿日志);
  本地定值项 comm_addr=0 显式不可寻址(防 IOA=0 误命中首个本地项)
- 单测:prot_set 63 断言(+33:软压板/原子写/脏握手/blob 往返/损坏拒绝/
  伪造自洽越界对抗样本)、iec104 94 断言(+7:YK12 两段转真/置脏/本地项
  C_RD EVI)
- 文档:IEC104 设计说明 §3.3/§3.4/§7、保护规划 §3.5 L5-1/§7 P4/变更记录、
  App/algo 与 App/cfg README、W1 任务卡 B7→🟦(台架腿 🔴 待窗口,随 B6 同窗)
- 验证:@build 0 错 0 警(Code=205500,ZI +280 = 双缓冲+blob 缓冲);
  ci_local 全绿(L0 27 钩子 + L0.5 13 套件 826 断言);ram_baseline 台账
  受管区与内存快照已同步;19 个改动文件无 BOM / LF / 零乱码
2026-10-12 15:01:49 +08:00

162 lines
8.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:保护定值模型(P1,L5-1 载体)
* 模块功能:保护定值的 RAM 模型——编号 / 通讯地址 / 范围 / 默认值 / 校验和自检,
* 以及 B7 定值持久化的**纯逻辑层**(blob 序列化/解析 + 原子装载)。
* 文件读写胶水在 App/cfg/prot_set_store.c(MCU 端)。
*
* 设计口径(docs/算法/继电保护功能复现规划.md §5):
* - 定点存储:Q10(×1024),与参考系统定点系数 2^10 一致(§5.3);
* - 通讯地址:与参考 g_tCommSetParaTab(Comm/Pub/Const_CommSetPara.c)逐项对齐,
* 基址 0x8820(=34848);告警类沿用运行参数段 0x8027/0x8029;
* - 校验和(L5-1):sum32 正码 + 反码成对封存(参考 tagPRS 的
* dwTagSum/dwTagSumN 模式),selfcheck 失配 → 置闭锁;
* - ⚠ 默认值/范围为**拟定值**:参考 EEPROM 出厂默认表未在本仓库,
* 待对照后逐项修订(规划 §10.3 待补项);范围先按 DTU 馈线典型量级。
*
* 线程约定(B7 定):装载(init/store_parse)在 defaultTask(存储 bring-up,
* STORAGE_READY 前);单项写在 iec104Task(C_SE/YK12,经 set_sealed 原子路径);
* 落盘在 defaultTask(配置引擎属主)。读在保护消费者任务(快照值原子)。
* 双缓冲交换 = 单字写,读侧永远看到一致快照;写者之间靠启动时序串行
* (装载先于 NET_READY,104 写在其后)。
*
* 创建日期:2026-10-11
*/
#ifndef PROT_SET_H
#define PROT_SET_H
#include <stdint.h>
/* Q10 定点:工程量 × 1024(与参考 2^10 口径一致) */
#define PROT_SET_Q10(v) ((int32_t)(((double)(v)) * 1024.0))
#define PROT_SET_FROM_Q10(v) ((float)((double)(v) / 1024.0))
/* 定值项编号(枚举序 = RAM 数组序 = 校验和覆盖序,只增不删不改序) */
typedef enum {
/* --- 三段式相间过流(A 相,L3-1):投退/跳闸投退/电流/延时 --- */
PS_OC1_EN = 0, /* 0x8856 Ⅰ段投退 */
PS_OC1_TRIP, /* 0x8857 Ⅰ段跳闸投退(0 告警 / 1 跳闸) */
PS_OC1_CUR, /* 0x8858 Ⅰ段电流定值(A,二次值) */
PS_OC1_DLY, /* 0x8859 Ⅰ段延时(ms) */
PS_OC2_EN, /* 0x885A */
PS_OC2_TRIP, /* 0x885B */
PS_OC2_CUR, /* 0x885C */
PS_OC2_DLY, /* 0x885D */
PS_OC3_EN, /* 0x885E */
PS_OC3_TRIP, /* 0x885F */
PS_OC3_CUR, /* 0x8860 */
PS_OC3_DLY, /* 0x8861 */
/* --- 过负荷(A 相,L3-3) --- */
PS_OL_EN, /* 0x8871 */
PS_OL_TRIP, /* 0x8872 */
PS_OL_CUR, /* 0x8873 */
PS_OL_DLY, /* 0x8874 */
/* --- 过压 / 欠压(UA,L3-4;沿用参考告警段 0x8029/0x8027) --- */
PS_OV_EN, /* 本地投退(参考告警类无独立投退,V0.1 补) */
PS_OV_VOL, /* 0x8029 过电压门限(V,二次值) */
PS_OV_DLY, /* 0x802A 过电压延时(ms) */
PS_UV_EN, /* 本地投退 */
PS_UV_VOL, /* 0x8027 低电压门限(V,二次值) */
PS_UV_DLY, /* 0x8028 低电压延时(ms) */
/* --- 零序过压(UN,L3-6) --- */
PS_3U0_EN, /* 0x888E */
PS_3U0_VOL, /* 0x888F 3U0 定值(V,二次值) */
PS_3U0_DLY, /* 0x8890 延时(ms) */
/* --- 公共 --- */
PS_RET_OVER, /* 过量返回系数(返回门槛 = 定值 × 系数,<1) */
PS_RET_UNDER, /* 欠量返回系数(返回门槛 = 定值 × 系数,>1) */
PS_PT_PRI, /* 0x8820 PT 一次额定(V) */
PS_PT_SEC, /* 0x8821 PT 二次额定(V) */
PS_CT_PRI, /* 0x8825 CT 一次额定(A) */
PS_CT_SEC, /* 0x8826 CT 二次额定(A) */
/* --- 全局软压板(B7):104 YK12 两段式投退;0 = 保护退出服务 --- */
PS_GLOBAL_EN, /* 本地项(无通讯地址,经 YK12 写、C_RD 不可读) */
PS_ID_COUNT
} prot_set_id_t;
/* 定值项元数据(ROM 常量表,校验和自检不覆盖它——只覆盖 RAM 值区) */
typedef struct {
uint16_t comm_addr; /* 通讯信息体地址(0 = 本地项,不上送) */
uint8_t is_ctl; /* 1 = 投退/枚举项(0/1),0 = 模拟量项 */
int32_t def; /* 默认值(Q10;投退项为 0/1 的 Q10) */
int32_t min; /* 下限(Q10) */
int32_t max; /* 上限(Q10) */
} prot_set_meta_t;
extern const prot_set_meta_t g_prot_set_meta[PS_ID_COUNT];
/*
* 函数功能:装载出厂默认值并封存校验和(幂等,内核启动前可调)
*/
void prot_set_init(void);
/*
* 函数功能:整表装载外部值(P4 起由 cfg_file 定值段调用),逐项范围校验
* 入口参数:vals - PS_ID_COUNT 个 Q10 值
* 返 回 值:0 全部合法(已装载并封存)/ -1 存在越界项(**整表不装载**,
* 返回前可经 prot_set_bad_mask() 取越界位图)
*/
int prot_set_load_raw(const int32_t *vals);
/* 越界位图(bit i = 第 i 项越界;load_raw 失败后有效) */
uint32_t prot_set_bad_mask(void);
/*
* 函数功能:单项写入(范围校验;**不自动重封校验和**——批量改完必须
* 显式 prot_set_seal(),否则 selfcheck 判"定值被非法改写")
* 返 回 值:0 / -1 越界拒写
*/
int prot_set_set(prot_set_id_t id, int32_t q10);
int32_t prot_set_get(prot_set_id_t id); /* Q10 原值 */
float prot_set_get_f(prot_set_id_t id); /* 工程量浮点 */
uint8_t prot_set_get_ctl(prot_set_id_t id); /* 投退项:!=0 视为投入 */
/* 校验和(L5-1):sum32 覆盖 RAM 值区;seal 封存正/反码对 */
uint32_t prot_set_checksum(void);
void prot_set_seal(void);
/* 自检:重算并与封存值比对,失配 → 置闭锁并返回 -1(已闭锁也返回 -1) */
int prot_set_selfcheck(void);
uint8_t prot_set_locked(void);
/*
* 函数功能:单项**原子**写入+封存(B7,收口 B5 竞态窗口)
* 入口参数:id - 定值项编号;q10 - Q10 定点值
* 返 回 值:0 / -1 越界或非法编号拒写(原值不动)
* 函数说明:影子缓冲拷贝 → 改影子 → 重封校验和 → 单字交换活跃区。
* selfcheck 永远看到"值区与封存一致"的完整快照,不存在
* "已改值未封存"中间态(区别于 prot_set_set+seal 的批处理路径,
* 两条路径不得在一次批处理中途交错)。置脏标志(待持久化)。
*/
int prot_set_set_sealed(prot_set_id_t id, int32_t q10);
/* 脏标志(存在未落盘的定值改动):set_sealed 置位;load/init 不置 */
uint8_t prot_set_dirty_peek(void); /* 非消费(生产者用它通知属主任务) */
uint8_t prot_set_dirty_take(void); /* 消费(属主任务落盘前取) */
void prot_set_dirty_mark(void); /* 写盘失败回置(等下轮重试) */
/* ---------------- 持久化 blob(B7;纯逻辑,主机可单测) ----------------
* 格式(小端):magic 'PSET'(4B) + version u16 + count u16
* + values u32×count + sum32 u32 + ~sum32 u32
* 版本 1;count 必须等于 PS_ID_COUNT(定值表增项 → 旧 blob 整体作废,
* 编号不回收但格式换代,宁可用出厂默认也不半装载)。 */
#define PROT_SET_BLOB_MAGIC 0x50534554uL /* 字节序 P,S,E,T */
#define PROT_SET_BLOB_VER 1u
#define PROT_SET_BLOB_HDR_SZ 8u /* magic(4)+ver(2)+cnt(2) */
#define PROT_SET_BLOB_SZ (PROT_SET_BLOB_HDR_SZ + 4u * (uint32_t)PS_ID_COUNT + 8u)
/*
* 函数功能:把当前值区序列化为 blob(校验和按值区现算,不依赖封存值)
* 返 回 值:0 / -1 缓冲不足或参数非法;*p_len 输出实际长度
*/
int prot_set_store_serialize(uint8_t *p_buf, uint32_t cap, uint32_t *p_len);
/*
* 函数功能:解析 blob 并**整表原子**装载(all-or-nothing)
* 入口参数:p_buf/len - blob 字节流
* 返 回 值:0 已装载并封存 / -1 拒绝(magic/版本/长度/校验对不符或
* 任一项越界 → 值区一字不动;越界项经 prot_set_bad_mask() 指认)
*/
int prot_set_store_parse(const uint8_t *p_buf, uint32_t len);
#endif /* PROT_SET_H */