Files
STM32F4-Base/App/task/iec104_serv.h
T
wandering1 0b84c43d2e feat(屏板): 状态灯位映射 sb_led_map + 104 RUN 观测口(批 3);附 4-1 并发压测脚本
批 3(LOGO 按用户裁定出局,不实现、sb_proto 的 LOGO 组帧挂待删标注):
- 新增 App/algo/sb_led_map.c/h:业务状态 → 屏板 LED 位掩码的唯一映射表
  (纯逻辑,主机单测可跑)。ID1 运行心跳 500ms 半周期闪(与主板 LED 同拍)、
  ID2 保护动作、ID3 104 链路 RUN、ID4 采样电平故障(不选 sticky——灯要能灭)、
  ID5 保护启动 picked;bit0 与 ID 6~19 恒 0。这张表参考源码里没有,属自定,
  出处 docs/产品需求/产品需求设计文档.md §5.16.3 ①。
- iec104_serv 新增 iec104_serv_link_run()(透传 link 状态机,不另存镜像量)。
- ui_task.c 帧组装块每拍现采四路状态源(均为任意上下文可读观测口)折算后
  传 sb_link_frame_update——替换批 2 的恒 0 占位;掩码变了帧就重组,
  复用 busy/dirty 机制,无新通路。
- 主机单测 test/host/sb_led_map 17/17(位语义/恒零位/闪烁相位/tick 回绕/
  NULL 契约);注册豁免走 SIM_EXEMPT(模拟器无屏板串口)。

批 4 的 4-1 双通道并发回归(真屏板在线实测):
- 新增 test/host/remolcd_pull_test.py:RemoDispBus 拉帧压测客户端
  (INIT→LCDMEM 10 Hz、逐帧 XOR+长度校验、往返延迟统计、--dump PBM)。
- 实测:网络侧两轮 2200 拉帧零错零超时(min 35/avg 63/max 131 ms);
  屏板侧 60 s 隔离窗口 rx +233 全收、drop 零新增、bad=0、off=0、无
  OFFLINE——两侧互不拖。观察项 len=7(断帧尺寸≠6,累计 7 次)出现窗口
  无法归因压测、隔离窗口零新增、有效帧零损失,已挂设计说明 §5.7 待查。

附带:sb_link.h frame_update 注释回填实测耗时(509/688 µs 取代旧估算)。
Keil 0 错误 0 警告;ci_local 全绿(SKIP=nested-comment,主树脚本另查 0 新发);
Code=239,064 B / RW_IRAM1 65.5 % / RW_CCM 87.9 %;覆盖率 90.1 % / 44 套件。
2026-10-30 00:39:57 +08:00

69 lines
3.7 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.
/*
* 模块名称:IEC 60870-5-104 被控站服务(对外接口)
* 模块功能:声明 iec104Task 任务体与监听端口;协议实现在 App/protocol/iec104/,
* 本接口仅供 Src/freertos.c 创建任务使用。
* 创建日期:2026-10-12(B4)
*/
#ifndef IEC104_SERV_H
#define IEC104_SERV_H
#include <stdint.h> /* uint32_t(观测计数声明):头文件自含——2026-10-27 @build 实测
* 本头此前全靠包含者先带 stdint,feed 换 include 即断链报 #20 */
/* 监听端口的宏出口已删除(道G task-9 收口 task-8 交接痕):运行期真源 =
* [comm] 段 getter(App/protocol/iec104/iec104_comm.h 的 iec104_comm_port(),
* 工厂默认 IEC104_COMM_DEF_PORT = 2404 = DL/T 634.5104 标准端口)。 */
/*
* 函数功能:iec104Task 任务体(在 Src/freertos.c USER CODE 区 osThreadNew 创建)
* 入口参数:argument - 未用
* 返回值:无(任务不返回)
*/
void iec104_serv_task(void *argument);
/*
* 104 只读观测计数(道G task-12):四个数都是**上电以来**、跨重连不清零,语义各自
* 独立、不得互相换算:
* conn_up = 主站接入次数(accept 成功并建立协议层链路)
* apdu_tx = 成功发出的 APDU 帧数(短写算 tx_fail,不算这里)
* tx_fail = 发送短写/失败次数(含拆链前那几次连败)
* rx_bytes = 收到的**字节**数(不是帧数:帧边界在 link 层重组,serv 看不见)
* ⚠ 与 App/task/iec104_serv.c 里 s_liveness_ctr / s_send_fail_run / s_conn_dead 三枚
* **控制量**无关:那三枚会被复位、只有 8 位,为"要不要拆链"服务,拿来当统计必错。
* 到顶饱和在 0xFFFFFFF0,不回绕(回绕成个位数会被读成"刚上电")。
* 页面这一栏要写「本次开机以来」,与运行时长同一类,别让人读成终身值。
*/
typedef struct {
uint32_t conn_up;
uint32_t apdu_tx;
uint32_t tx_fail;
uint32_t rx_bytes;
} iec104_serv_stats_t;
/*
* 函数功能:读 104 观测计数(纯拷字段)
* 入口参数:p_out - 输出缓冲;NULL 时无害返回 iec104_serv_stats_t *
* 返 回 值:无 void
* 限定条件:**任意上下文可读**——不取锁、不读时刻、不碰 socket、不阻塞(照
* adc_cal_get_stats() / boot_stats_get() 的形态:观测口一旦去抢总线或等锁,
* 观测就成了故障的一部分)
* 函数说明:写者 = iec104Task,读者 = uiTask/喂数据侧;u32 单字读写原子,跨字段
* **不保证同一瞬间**——四枚之间没有"合起来才成立"的判据,混窗对显示无害。
* 本函数无任何清零能力(能清零的统计口不是统计口)。
*/
void iec104_serv_get_stats(iec104_serv_stats_t *p_out);
/*
* 函数功能:读 104 链路是否处于 RUN 态(STARTDT 已确认 = 主站在线在轮询)
* 返 回 值:1 = RUN;0 = 其它(IDLE/OPEN/STOPPED 或未创建任务) uint8_t
* 限定条件:**任意上下文可读**——单枚举字读,不取锁、不碰 socket、不阻塞
* (与 iec104_serv_get_stats 同一形态与同一读者群)。
* 函数说明:写者 = iec104Task(link 状态机推进),读者按需采样;单字读写在
* Cortex-M4 上原子,最多读到"晚一拍"的状态,无撕裂风险。
* 消费点 = 屏板状态灯 ID 3(App/algo/sb_led_map.h 的通信灯)。
* ⚠ 别拿它换算 conn_up:RUN 是电平,conn_up 是累计边沿,语义不可互换
* (同文件统计注释里的"不得互相换算"纪律)。
*/
uint8_t iec104_serv_link_run(void);
#endif /* IEC104_SERV_H */