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 后)。
67 lines
3.2 KiB
C
67 lines
3.2 KiB
C
/*
|
||
* 模块名称:SOE Store — 事件顺序记录落盘(MCU 胶水,单写者)
|
||
* 模块功能:protectTask 动作/复归边沿 → soe_store_post() 投递(纯 RAM:
|
||
* sys_clock 取时 + soe_rec_build + 消息队列,**零文件系统**);
|
||
* defaultTask(/log 唯一写者,经 syslog_drain 尾部挂接)消费落盘
|
||
* /log/soe.log(定长 64B,容量满删除重建,照 run.log 先例)。
|
||
* 记录格式/类型:见 soe_rec.h(纯编解码在 soe_rec.c,主机单测覆盖)。
|
||
* 线程约定:post = protectTask(唯一生产者;内核启动后任意任务上下文亦可,
|
||
* 队列未建时走静态待发数组,照 syslog_post 先例);
|
||
* drain = 仅 defaultTask(syslog_drain 尾部调用,继承其卷就绪门)。
|
||
* seq 口径:RAM 计数器,上电内单调;容量满 unlink 重建**不重置**(计数继续),
|
||
* 仅设备复位后重置(主机解码断言单调性须按"同一 boot 段"分段看)。
|
||
* 创建日期:2026-10-12(B9)
|
||
*/
|
||
#ifndef SOE_STORE_H
|
||
#define SOE_STORE_H
|
||
|
||
#include <stdint.h>
|
||
|
||
#include "soe_rec.h" /* 记录类型/标志/SOE_ELM_NONE 常量(post 入参口径) */
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* 容量上限(条数;满时删除重建,照 SYSLOG_RUN_MAX 先例):1024 × 64B = 64KB */
|
||
#define SOE_STORE_MAX 1024u
|
||
|
||
/*
|
||
* 函数功能:投递一条 SOE 记录(构建 + 入队;非阻塞,队列满则丢弃并计数)
|
||
* 入口参数:type - 记录类型 soe_type_t uint8_t
|
||
* elm_id - 元件号(非元件事件传 SOE_ELM_NONE) uint8_t
|
||
* value - 类型相关值(见 soe_rec.h 类型表) uint32_t
|
||
* 返回值:无
|
||
* 限定条件:内核启动后调用(protectTask 上下文);**绝不触碰文件系统**——
|
||
* 取时标(sys_clock 纯 RAM)+ 组记录 + osMessageQueuePut(0 超时)。
|
||
* 队列未创建(defaultTask 首次 drain 前)走静态待发数组;数组满
|
||
* = 丢弃 + 计数 + 首次留痕日志(绝不阻塞、绝不崩)。
|
||
*/
|
||
void soe_store_post(uint8_t type, uint8_t elm_id, uint32_t value);
|
||
|
||
/*
|
||
* 函数功能:排空 SOE 待发(静态数组 + 队列,FIFO)并落 /log/soe.log
|
||
* 入口参数:无
|
||
* 返回值:无
|
||
* 限定条件:仅 defaultTask(唯一写者)调用,且由 syslog_drain 在"卷就绪"门
|
||
* 之后挂接(继承 s_fs_ready 语义,勿单独调用——/log 目录可能未建)
|
||
* 函数说明:写路径照 sys_log_mcu.c s_append 全套实证纪律:vol_lock try(busy
|
||
* = -2 顺延)、FA_WRITE|FA_OPEN_APPEND(本移植 OPEN_APPEND 不含
|
||
* WRITE)、校验写回字节数(FR_OK+短写=失败)、容量满 unlink 重建。
|
||
* unlink/名字类错误码**严禁**归入任何"卷损坏"触发集(存储架构
|
||
* §10.1 教训)——本模块无任何重格式化路径,故障只留痕不升级。
|
||
*/
|
||
void soe_store_drain(void);
|
||
|
||
/*
|
||
* 函数功能:累计丢弃计数(队列满/待发数组满;可观测性)
|
||
* 返回值:丢弃条数 uint32_t
|
||
*/
|
||
uint32_t soe_store_dropped(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* SOE_STORE_H */
|