c1e7e8c42c
L0 的 cppcheck 在 --all-files 下恒红四处,全在同一文件: App/protocol/iec104/iec104_comm.c 的 80 / 94 / 107 / 121 行,诊断为 compareValueOutOfTypeRangeError —— 拿 unsigned short 与 65535 比较, Condition is always false。根因是 IEC104_COMM_CA_MAX 与 PORT_MAX 都等于 65535u,而被比较的量是 uint16_t:那个上界判断在类型上就不可能成立。 这四处随上游 iec104_comm 落地进来,本地提交只跑暂存文件所以没人看见, CI 跑 --all-files 就每轮都红(同族盲区:暂存面与全量面不等价)。 处置走「语义不动」那一支(用户裁定 2026-10-27:A):只删恒假的半边、 改判 if (v < MIN),合法带口径一字未改(仍照 iec104_comm.h 的常量注释: ca 1..65535、port 1024..65535),只在第一处写清为何不再写上界、其余三处 短引用。没有把 MAX 改成 65534(按 60870-5-104 的 65535 = 未编址),因为 test/host/iec104/iec104_test.c:1521 明确断言 ca 设成 IEC104_COMM_CA_MAX 必须被接受——那会同时打断这条断言并改变现场设备行为(配 65535 的站会 突然回退工厂默认),属协议决定,不在本次范围;要改请单独裁。 验证:单文件 cppcheck 原样复刻钩子参数 → RC=0;cppcheck --all-files 由 红转绿;iec104-unit-test Passed(即 65535 那条合同照过);@build 0 错误 0 警告(Code 231732→231720,减 12 B,RO/RW/ZI 不变);凭证与两份台账 随之重盖(ER_IROM1 257,292→257,280、Flash 合计 258,812→258,800); 本次触发的 13 根钩子全 Passed,含 test-coverage(删掉 4 行已覆盖代码 未被判成回退)。
131 lines
5.4 KiB
C
131 lines
5.4 KiB
C
/*
|
||
* 模块名称:IEC 60870-5-104 通讯参数段([comm] 配置)实现
|
||
* 模块功能:/config.ini [comm] 段的 RAM 副本 / 工厂默认 / 键表与注册 +
|
||
* getter 合法带自愈 + setter 守卫。契约、线程约定与生效语义
|
||
* (改后重启生效、不挂回调不置事件位、主站地址不做)→
|
||
* iec104_comm.h 文件头;键表口径 → docs/子系统设计/网络配置说明.md
|
||
* §3.6;热生效代价分析 → docs/子系统设计/IEC104上行设计说明.md §8。
|
||
* 适用平台:STM32F407ZGTx / PC 模拟器(双端编译:模拟器运行期无 104 任务,
|
||
* 本 TU 不产生行为,按双端注册口径入 CMakeLists 保持构建事实一致)
|
||
* 创建日期:2026-10-26(道G task-8,「UI 补齐」第 5 项非 UI 前置)
|
||
* 修改记录:
|
||
* 2026-10-26 DTU 项目组 创建:实现体自 iec104_pts.c 尾段**同笔整体迁移**
|
||
* (零逻辑改动)。动因 = coding-standard
|
||
* CODE-RULE-17 (2.2)「非 static 函数须在配对头文件
|
||
* 声明」按文件名配对判定——初版把实现放 iec104_pts.c
|
||
* 而声明在 iec104_comm.h,钩子按规则判红;本模块
|
||
* 本就是独立配置段,配对拆分即正解。
|
||
*/
|
||
#include "iec104_comm.h"
|
||
|
||
#include <string.h>
|
||
|
||
#include "cfg_file.h"
|
||
|
||
/* ---------------- [comm] RAM 副本与工厂默认 ----------------
|
||
* 引擎属主 = defaultTask:本段只被 cfg_file_load/save/poll 通用遍历,本文件
|
||
* 不触引擎任何写路径;内核前注册点 = app_main.c(「先注册后 load」契约,同
|
||
* adc_cal_init / run_par_init)。App/protocol 零日志惯例保持——注册失败留痕
|
||
* 由调用方 app_main.c 锚点负责,getter/setter 纯 RAM 不打日志(iec104Task
|
||
* 深链省栈,AGENTS 日志成本口径)。 */
|
||
|
||
/* RAM 副本(引擎原地更新;u16 半字对齐读原子,撕裂域 = 单字段新旧值) */
|
||
typedef struct {
|
||
uint16_t ca; /* 公共地址(= 链路地址,ASDU 头 2B,点表 §1.5 口径) */
|
||
uint16_t port; /* 被控站 TCP 监听端口 */
|
||
} iec104_comm_t;
|
||
|
||
static iec104_comm_t s_comm;
|
||
static const iec104_comm_t s_comm_rom = {
|
||
IEC104_COMM_DEF_CA, IEC104_COMM_DEF_PORT
|
||
};
|
||
|
||
/* 键表(s_comm 布局内偏移,同 net_cfg/ftp_cfg 写法) */
|
||
static const cfg_key_def_t s_comm_keys[] = {
|
||
{ "ca", CFG_VAL_UINT, offsetof(iec104_comm_t, ca), 2u },
|
||
{ "port", CFG_VAL_UINT, offsetof(iec104_comm_t, port), 2u },
|
||
};
|
||
|
||
/* 函数定义区 */
|
||
|
||
/*
|
||
* 函数功能:置工厂默认并向引擎注册 [comm] 段(幂等,内核前)
|
||
* 返回值:0 注册成功;-1 重复注册/段数超限(RAM 副本已复位,adc_cal 同款) int
|
||
* 限定条件:先于 defaultTask 的 cfg_file_load;不挂回调(改后重启生效)
|
||
*/
|
||
int iec104_comm_init(void) {
|
||
cfg_section_reg_t reg;
|
||
|
||
(void)memcpy(&s_comm, &s_comm_rom, sizeof(s_comm));
|
||
|
||
(void)memset(®, 0, sizeof(reg));
|
||
reg.name = IEC104_COMM_SEC;
|
||
reg.p_data = &s_comm;
|
||
reg.p_defaults = &s_comm_rom;
|
||
reg.data_size = sizeof(s_comm);
|
||
reg.p_keys = s_comm_keys;
|
||
reg.key_count = (uint8_t)(sizeof(s_comm_keys) / sizeof(s_comm_keys[0]));
|
||
reg.p_cb = NULL; /* 不挂回调:iec104Task 启动读 getter(D5 口径) */
|
||
return cfg_file_register(®);
|
||
}
|
||
|
||
/*
|
||
* 函数功能:取生效公共地址
|
||
* 返回值:RAM 副本 ca,带外回退工厂默认;恒 ∈ IEC104_COMM_CA_MIN..MAX uint16_t
|
||
* 限定条件:无(任意上下文,纯读)
|
||
*/
|
||
uint16_t iec104_comm_ca(void) {
|
||
uint16_t v = s_comm.ca;
|
||
|
||
/* 只判下界。上界 IEC104_COMM_CA_MAX 就是 uint16_t 的最大值,写成
|
||
* 「v > 65535」对 uint16_t 恒假(cppcheck compareValueOutOfTypeRangeError),
|
||
* 留着只会让下一个读代码的人以为上界真被守过。合法带口径不变,
|
||
* 仍照 iec104_comm.h 的常量注释(ca 1..65535 / port 1024..65535)。 */
|
||
if (v < IEC104_COMM_CA_MIN) {
|
||
return IEC104_COMM_DEF_CA;
|
||
}
|
||
return v;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:取生效监听端口
|
||
* 返回值:RAM 副本 port,带外回退工厂默认;恒 ∈ IEC104_COMM_PORT_MIN..MAX uint16_t
|
||
* 限定条件:无(任意上下文,纯读)
|
||
*/
|
||
uint16_t iec104_comm_port(void) {
|
||
uint16_t v = s_comm.port;
|
||
|
||
if (v < IEC104_COMM_PORT_MIN) { /* 上界恒假,同 iec104_comm_ca 处注释 */
|
||
return IEC104_COMM_DEF_PORT;
|
||
}
|
||
return v;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:写 ca 进 RAM 副本(守卫 = getter 同带;非法不提交)
|
||
* 入口参数:ca - 公共地址 uint16_t
|
||
* 返回值:0 提交;-1 带外(副本不动) int
|
||
* 限定条件:UI 保存交接路(task-9);落盘走 SYS_EVT_CFG_SAVE 整档外科 save
|
||
*/
|
||
int iec104_comm_ca_set(uint16_t ca) {
|
||
if (ca < IEC104_COMM_CA_MIN) { /* 上界恒假,同 iec104_comm_ca 处注释 */
|
||
return -1;
|
||
}
|
||
s_comm.ca = ca;
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:写 port 进 RAM 副本(守卫 = getter 同带;非法不提交)
|
||
* 入口参数:port - 监听端口 uint16_t
|
||
* 返回值:0 提交;-1 带外(副本不动) int
|
||
* 限定条件:同 iec104_comm_ca_set
|
||
*/
|
||
int iec104_comm_port_set(uint16_t port) {
|
||
if (port < IEC104_COMM_PORT_MIN) { /* 上界恒假,同 iec104_comm_ca 处注释 */
|
||
return -1;
|
||
}
|
||
s_comm.port = port;
|
||
return 0;
|
||
}
|