728d60675f
三条道在同一棵树上交付,故合并成**一次权威构建**(@build 0 错 0 警,Code=235236 RO=26308 RW=1572
ZI=136924)后同笔入库;台账已按该构建回填(`ram_baseline.py --update` + `--write`、`chec
k_mem_numbers.py
--write`),凭证与实际 .map 同源。归属如下:
· **通讯设置页**(道G task-9):新增 `Drivers/BSP/UI/ui_page_comm.{c,h}`(通道六注入,与死
区页同骨架同纪
律),`#page=comm` 绑定使 bound **21 → 22**、内容页黄金 **47 → 53**(旧 47 页字节零变化,
新增六态含
WAIT/OK 两张);`iec104_comm` 脏位 + store_save(**无事件位**)挂 defaultTask 同点位
轮询;`port_104` 由
宏改走 getter、`IEC104_SERV_PORT` 删除;字体 +听/监(185 字全覆)。**实机链已闭环**:FTP 外改
[comm]
的 ca/port → 复位 → 串口出现 `section 'comm' (2 keys)` 与 `i104: listening o
n 9004` → 还原 2404,全程无
FAIL ⇒「重启即生效 + 端口真值」不是推断是实测。上限核对 6/8 段、2/16 键,超限现象由 TC-CONFIG-056/057
钉死(注册 -1 + `comm init: FAIL` 锚 + getter 回 ROM),**不抬宏**。
· **开机账本**(道F task-12):新增 `App/util/boot_stats.{c,h}`——上电次数落 SD2506 用户
SRAM(magic +
小端计数 + 版本 + 异或校验),一次上电 = 1 读 + ≤1 写,**零 NAND、零卷锁、零配置段**;四态互斥
UNKNOWN / FRESH / CONTINUED / RESTARTED(BLF=1 才算电池域掉过电),**读失败绝不回写**;
文案口径「自 RTC
电池周期起」,**禁写终身次数**。复位原因优先级链从 `app_main.c` 的 if-else 收进一份真源(串口与屏幕同
源);104 四个只增不清计数 + `iec104_serv_get_stats()` 留在 serv、未塞进 link(会被 open
/close 洗掉)。
运行时长按用户裁定 = **只报本次开机以来**,零新增代码。新套件 `test/host/boot_stats` 21/21,五处注入
**全部有牙**(含「漂一字节被校验和挡下而不是报 256 倍错账」)。
· **adc_cal 可诊断化**(道E task-43):三个 volatile 计数 + `adc_cal_get_stats()`
/ `adc_cal_note_persisted()`
(水位**盖写非自增**,因为一次 save 覆盖整档,数 save 会留假未落盘);「差额 × 脏位」三态语义唯一落在
`adc_cal.h`,其中「差额 > 0 且脏位恒 0」= 绕过语义 setter 的静默丢失;TC-ADCCAL-019~023。
三条**必须留档的自纠**(都是执行道自己报的,我不替他们润色):
① stdint 那条断链是**宿主套件抓到、通讯道先修**,采集道承认自己是重复添加者并删掉自己那份;
② 「exit 2 不是证据,断言变红才是」——采集道第一版反证注入了未声明标识符导致编译错,差点当成功;
③ 套件汇总行原写 `s_total/s_total`,失败时会打印「21/21 PASSED (failed=1)」这种自相矛盾的行,已改。
另修:`check_registration.py` 的 `SIM_EXEMPT` 加一行豁免 `App/util/boot_stats.c
`(依赖 I2C 与 RCC 位掩码,
MCU 专属;核过 `sys_clock.c`/`sha256.c` 同形态先例),注册反向校验 exit 1 → 0。发号 TC-IEC1
04-034、
TC-UIDATA-029 已实抬游标(`TC-IEC104-033→034`、`TC-UIDATA-026→029`)。
门禁:id-check --strict 与 plain 均 rc=0、doc-links --all rc=0、注册校验 0、cppche
ck / coding-standard /
bom-drift 0;iec104 179/179、ui_data 295/295、boot_stats 21/21、adc_cal 11
7/117、run_par 67/67;菜单 8 状态
池 5368 不变、内容页 53/53。**已知遗留**:内容页数 47 → 53 的全仓文本同步尚未做(另卡跟踪),本笔只保
证代码与黄金一致;面板注键真机那一腿缺 CLI,交台架道补。
272 lines
27 KiB
Markdown
272 lines
27 KiB
Markdown
# IEC 60870-5-104 上行设计说明(B4)
|
||
|
||
> **定位**:DTU 上行规约 IEC 60870-5-104(DL/T 634.5104-2009)的设计基线——
|
||
> 范围、点表、链路流程、板端接入、预算与测试。规格来源
|
||
> `docs/算法/继电保护功能复现规划.md` §1.5(B0 产品定义,验收 = 省电科院点表);
|
||
> 代码落点 `App/protocol/iec104/`;未闭环的送检验收挂 `docs/任务规划/登记簿.md` §7。
|
||
> **角色**:本 DTU = **被控站(受控端)**,104 **TCP 服务器,端口 `[comm]` 段 `port`(工厂默认 2404)**;主站
|
||
> (控制端,点表参考 `192.168.1.199`)主动连入。
|
||
|
||
## 1. 范围(V0.1 子集)
|
||
|
||
| 面 | 本期做 | 本期不做(登记 §8) |
|
||
|---|---|---|
|
||
| 链路 | APCI U/S/I、STARTDT/STOPDT/TESTFR、k/w 窗、t1/t2/t3 | 多主站并发(单连接语义,见 §5) |
|
||
| 遥测 YC | 短浮点 M_ME_NC_1(系数 1):背景/周期/死区上送 | 归一化/标度、谐波轨(「遥测谐波轨(可选)」) |
|
||
| 遥信 YX | 单点 M_SP + 双点 M_DP:背景 + 突发(COT=3);**突发单点带 CP56 时标 = M_SP_TB_1(B9,随「SOE 记录」 SOE 落地)** | 双点带时标(V0.1 双点恒 IV,无意义) |
|
||
| 遥控 YK | 双点 C_DC 两段式(选择 82H/执行 02H) | 带时标、升降/步位 |
|
||
| 定值 | C_RD 读 + C_SE_NC 两段写(地址 = prot_set `comm_addr`) | 定值区切换/下装文件 |
|
||
| 其他 | C_CS 对时(→ `sys_clock`)、C_TS、C_RP | 固有参数 8001H~800AH(字符串类)、C_CI 电度、文件传输(录波) |
|
||
|
||
## 2. 分层与模块(采集链路测试可验证性约束:协议解析与硬件 I/O 分离)
|
||
|
||
| 模块 | 文件 | 职责 | I/O |
|
||
|---|---|---|---|
|
||
| ASDU 编解码 | `App/protocol/iec104/iec104_asdu.c/h` | 类型/COT 常量、ASDU 头、IOA 3B 小端、短浮点、CP56Time2a↔epoch | 零 |
|
||
| 点表/数据源 | `App/protocol/iec104/iec104_pts.c/h` | YC/YX/YK/定值表、COV(变位+死区)、**数据源 vtable**(板端绑 phasor/prot_*,单测绑假源) | 零(源注入) |
|
||
| 链路状态机 | `App/protocol/iec104/iec104_link.c/h` | TCP 流重组、U/S/I、k/w/t1/t2/t3、总召/突发/遥控/定值/对时编排 | 零(收=on_rx 喂流,发=回调,时基注入) |
|
||
| 板端胶水 | `App/task/iec104_serv.c/h`(随实现定名) | `[comm]` port 监听(工厂默认 2404)、数据通道收发、断链重听、netTask 驱动 | 全部(net_* API) |
|
||
| 通讯参数段 | `App/protocol/iec104/iec104_comm.c/h`(道G task-8) | `[comm]` 段注册 + ca/端口 getter 合法带自愈 / setter 守卫 | cfg_file 引擎(只注册不属主) |
|
||
|
||
> 三个纯逻辑模块 + 真实数据源(`App/algo/` 全纯逻辑)可整体在主机侧编译 →
|
||
> L0.5 单测覆盖**全协议栈**(`test/host/iec104/`),与 `test/host/prot_elm/` 同模式。
|
||
|
||
## 3. 点表(V0.1)
|
||
|
||
### 3.1 遥测 YC(IOA 0x4011+,短浮点,系数 1)
|
||
|
||
| IOA | 点 | 来源 | V0.1 状态 |
|
||
|---|---|---|---|
|
||
| 0x4011 | 1Ua | L2 遥测快照槽 `ADC_SEM_UA`(卡 9) | ✅ 有效 |
|
||
| 0x4012/0x4013 | 1Ub/1Uc | 同表槽位;STM32 侧削顶(`docs/算法/继电保护功能复现规划.md` §1.6) | ❌ 发 IV——**品质驱动**(快照 CLIPPED 位映射,非点表绑死;V0.2 消除双转换器无共同采样触发后零改动自动启用) |
|
||
| 0x4014 | 1U0 | 快照槽 `ADC_SEM_UN`(外部零序专用通道) | ✅ 有效 |
|
||
| 0x4015 | 1Ia | 快照槽 `ADC_SEM_IA` | ✅ 有效 |
|
||
| 0x4016~0x4018 | 1Ib/1Ic/1I0 | 同 Ub/Uc:绑槽 + 品质驱动 | ❌ 发 IV |
|
||
| 0x401D | 1f 频率 | 快照 `freq_hz`(卡 11 绑源;B8 自适应窗测频 `freq_get()` 同源) | ✅ 随测频收敛生效;`freq_valid()==0` → IV(卡 11 DoD) |
|
||
|
||
- **数据源 = L2 遥测快照**(`App/algo/meas.h`,「数据可信」卡 8/9):200 ms 基波有效值
|
||
+ 每点品质,104 与 UI 共用同一份上游;读数单位 = ADC 引脚电压(eng=0,`App/algo/adc_cal`
|
||
折算层 2026-10-25 落地;二次值等卡 12 标定置 VALID)。槽位值/品质整体透传,本层
|
||
**不再自行判新旧**(快照 `seq` 仅供 COV 去重)。
|
||
- 品质映射:快照 `MEAS_QDS_*` 低字节与线上 QDS 同值直传;**CLIPPED → IV**(「削顶通道
|
||
恒 IV」口径不变、改由品质驱动,docs/任务规划/数据可信.md §8 风险表末行的单测要求);
|
||
快照从未发布(开机 <200 ms)→ IV|NT;判定顺序 IV 优先于 NT。
|
||
- 死区(卡 9):从「越死区即报」改为**连续 2 个新测量点越限才确认**——板端测量点 =
|
||
快照换帧(100 ms 轮询 vs 200 ms 快照按 `seq` 去重,防同一帧把单点噪声重复计满 2 点;
|
||
基准恒为**上次上送值**,非上次读值——防慢漂移把基准吃掉,参考系统同款);品质翻转
|
||
当拍直报、不计数。死区数值 = 运行时副本(`iec104_pts_yc_set_deadband`,ROM 默认沿
|
||
卡 6 额定 0.5% 档:0.5 V / 0.005 A / 0.5 Hz;卡 10 接 8020H 段后主站可读写);
|
||
标准源注入复核(卡 12)待台架。
|
||
|
||
### 3.2 遥信 YX(IOA 1~33)
|
||
|
||
| 段 | 点 | 来源 | V0.1 状态 |
|
||
|---|---|---|---|
|
||
| 1~4 | 开关位置(双点) | 无出口/位置硬件 | ❌ IV |
|
||
| 5~14 | 预留 | — | ❌ IV |
|
||
| 15 | 故障总 | OC1∨OC2∨OC3∨3U0(`prot_elm`) | ✅ |
|
||
| 16~18 | 过流 Ⅰ/Ⅱ/Ⅲ 段 | `PE_OC1/2/3` asserted | ✅ |
|
||
| 19~20 | 零序过流 Ⅰ/Ⅱ | 「三段式零序过流」未实现 | ❌ IV |
|
||
| 21~22 | 接地故障/重载 | 未实现 | ❌ IV |
|
||
| 23 | 过载 | `PE_OL` asserted | ✅ |
|
||
| 24~30 | 外部遥信(RS-485) | B2 暂缓(`docs/任务规划/暂缓-RS485.md`) | ❌ IV |
|
||
| 31 | 保护闭锁 | `prot_set_locked()` | ✅ |
|
||
| 32~33 | 预留 | — | ❌ IV |
|
||
|
||
> **点存在性优先**:无效点照常入总召/周期表并置 IV——点表是验收口径,缺行比
|
||
> 置 IV 更糟(主站侧无法区分"没做"与"接线错")。
|
||
>
|
||
> **保护类 YX(15/16~18/23/31)自 B5(2026-10-12)起为活数据**:protectTask
|
||
> 20 ms 判据节拍驱动 `prot_elm` 状态 → pts COV 变位上送(≤120 ms 端到端)。
|
||
>
|
||
> **突发单点遥信自 B9(2026-10-12)起带时标 = M_SP_TB_1(30)**:仅自发
|
||
> (COT=3)单点组(idx≥4)换型,信息体 = SIQ + CP56Time2a(8B);**总召/
|
||
> 周期扫描保持 M_SP_NA_1/M_DP_NA_1**(时标只用于变位事件,标准语义,防
|
||
> "全量换型")。时标源 = `sys_clock`(link cfg `epoch_ms` 回调):秒域时基
|
||
> → ms 域 = 秒×1000(亚秒恒 0,不造假);墙钟未建 → CP56 IV 位如实置位。
|
||
> 与 `/log/soe.log` 落盘记录同源同时基(`App/log/soe_store.c`,见
|
||
> `App/log/README.md`)——104 时标 = 事件上送时刻,SOE 记录 = 事件发生
|
||
> 时刻(20 ms 判据拍),两者差 ≤ 一拍 + 排空延迟(≤50 ms)。
|
||
|
||
### 3.3 遥控 YK(IOA 0x6000+,双点两段式)
|
||
|
||
| IOA | 点 | V0.1 行为 |
|
||
|---|---|---|
|
||
| 0x6000~0x6003 | YK1~4 开关 | **否定确认**(无出口硬件,`docs/算法/继电保护功能复现规划.md` R7) |
|
||
| 0x600A | YK11 信号复归 | ✅ 执行段 → `prot_elm_request_reset()`(B5 起跨上下文安全:请求由 protectTask 下一拍 eval 头部消费,不当拍直接复位) |
|
||
| 0x600B | YK12 遥控软压板 | ✅ 两段式转真(B7):选择段校验 DPC(ON/OFF,非法即 PN);执行段 → `prot_set_set_sealed(PS_GLOBAL_EN)` 原子写+封存;protectTask 下一拍读到退出态即复位元件并停判据(`App/task/protect_task.c`) |
|
||
| 0x600C | YK13 电池活化 | 否定确认(无对应硬件) |
|
||
| 0x600D | YK14 解除闭锁 | 否定确认(闭锁源于定值校验和,只能重写定值解除) |
|
||
|
||
### 3.4 定值(IOA = 通讯地址)
|
||
|
||
- 地址 = `App/algo/prot_set.h` 元数据 `comm_addr`(0x8820 基址 + 告警段 0x8027~0x802A,
|
||
逐项对照参考项目 `Const_CommSetPara.c`,见 `docs/算法/继电保护功能复现规划.md` §5.4)——
|
||
**点表不另立地址表**,prot_set 即单一事实源。`comm_addr = 0` 的本地项(投退/返回系数/
|
||
全局软压板)不可经 C_RD/C_SE 寻址(B7 起显式排除,防 IOA=0 误命中首个本地项)。
|
||
- 写两段式:选择 = 范围校验;执行 = `prot_set_set_sealed`(**原子写+封存**:影子区
|
||
写好后单字交换活跃区,protectTask 的「定值校验和」巡检任何时刻都看到自洽快照,
|
||
B5 登记的 µs 级竞态窗口就此收口)。
|
||
- 持久化(B7):执行段置 prot_set 脏标志 → iec104Task 每轮 poll `dirty_peek` 投递
|
||
`SYS_EVT_PROT_SET_SAVE` → **defaultTask(配置引擎属主)** 经 `App/cfg/prot_set_store.c`
|
||
原子写 `/prot_set.bin`(blob = magic+版本+计数+值区+sum32 正/反码对);
|
||
开机在 STORAGE_READY 屏障前装载,损坏/越界/版本换代 = 整表拒绝保持出厂默认
|
||
(all-or-nothing)+ 自检留痕 `prot set corrupt`;写盘失败脏标志保留 = 下轮重试。
|
||
|
||
**运行参数段 `0x8020H~0x8058H`(「数据可信」卡 10,2026-10-25 落实)**:
|
||
|
||
> ⚠ 逐项地址为**本仓自定**(`docs/算法/继电保护功能复现规划.md` §5.4 的权威表不在仓——
|
||
参考项目 `CommPara_ConfigTable` 拿不到,送检点表到位后**以送检为准替换常量表**,
|
||
映射表只落在 `App/algo/run_par.c` 顶部常量段一处)。
|
||
|
||
| 地址 | 项 | 域(C_SE/C_RD 浮点工程量) | 工厂默认 | 真源与守卫 |
|
||
|---|---|---|---|---|
|
||
| 0x8030~0x8038 | 遥测死区 UA/UB/UC/UN/IA/IB/IC/IN/FREQ | V / A / Hz,分档上限 50/1/5 | 卡 6 额定 0.5 % 档(0.5 V ×4 / 0.005 A ×4 / 0.5 Hz) | `run_par` [run_par] 段 9 键 int32 毫单位;落盘键表 → `docs/子系统设计/网络配置说明.md` §3.5 |
|
||
| 0x8040~0x8047 | 通道 k 覆盖(µV/码) | 正浮点;adc_cal 合法带 ROM×[0.5,2.0] 执行段裁决 | 回显生效值(ROM = 152.587890625 / 805.6640625) | **写 = `adc_cal_set` 代理,系数唯一真源在 [adc_cal] 段,run_par 不存系数**(防后人拿 run_par 表当真源表) |
|
||
| 0x8048~0x804F | 通道 b 覆盖(码值,可负) | ±8192(adc_cal 带) | 0(回显) | 同上;单侧写 RMW 用另一侧**当前生效值** |
|
||
| 其余 | 留白(PT/CT 变比等未启用类别) | — | — | C_RD → COT14+EVI / C_SE → actcon+PN |
|
||
|
||
- `0x8027~0x802A` 是 prot_set 告警段(过压/欠压),**run_par 命中集精确匹配、永不覆盖**;
|
||
两表共存的路由顺序 = **run_par 表先、未命中落 prot_set**(`iec104_pts.c` set 路由,
|
||
证据钉在 TC-IEC104-029)。
|
||
- 现行门控 = 两段式 + 范围/合法带校验(与保护定值同款),**无「仅暂停/测试态可写」
|
||
门控**——文档现行如此,不造新语义;若送检点表要求该类门控,接线点在
|
||
`run_par_104_write` 执行段入口,加一处即可。
|
||
- 持久化(卡 10):任一写成功置 `run_par` 脏 → iec104Task 同款 peek 投递
|
||
`SYS_EVT_RUN_PAR_SAVE`(1<<8) → defaultTask `run_par_store_save()` 调 `cfg_file_save()`
|
||
整档外科保存(一趟覆盖 [run_par] 9 键 + 被代理改写的 [adc_cal]/[adc_cal_ofs],
|
||
lead 裁②一条事件位一趟够用);失败脏保留 = 下轮重试。消费侧(COV 判定)**实时读
|
||
引擎副本**,无缓存无投递(卡 9 的 pts 层 s_yc_db 副本已收编进 run_par)。
|
||
|
||
## 4. 链路与流程
|
||
|
||
- 参数:k=12 / w=8 / t1=15s / t2=10s / t3=20s(标准默认);序号 15bit 回绕,
|
||
超时判定一律差值法(tick 回绕安全,同 `App/algo/` 惯例)。
|
||
- 状态机:IDLE→(TCP 建立)OPEN→(STARTDT act/con)RUN⇄STOPPED;t1 超时或坏帧
|
||
→ 实例回 IDLE,**由胶水层负责断 socket**(纯逻辑层不感知 I/O)。
|
||
- 总召(C_IC 组 1):actcon → 分片背景扫描(YX 双点组 SQ=1 → YX 单点组 SQ=1 →
|
||
YC 组 SQ=1 → 频率单点)→ actterm;首召/ RBT 位 → COT=4(初始化),否则 COT=2。
|
||
单次 poll 发送预算 4 个 ASDU(防大扫描饿死宿主任务)。
|
||
- 突发:COV = 遥信变位 + 遥测**死区 2 点确认 + 品质翻转直报**(`iec104_pts_cov_check`,
|
||
卡 9 语义见 §3.1 注),COT=3 逐点 SQ=0。
|
||
- 周期:RUN 态 60 s 全 YC 上送 COT=1。
|
||
- 遥控/定值写:两段式,失配/越界 → COT|PN 否定确认;未知 IOA → COT=14+EVI、
|
||
错公共地址 → COT=13+EVI、未知类型 → COT=12+EVI。
|
||
- 对时 C_CS:CP56 → epoch ms → 胶水层 `sys_clock` 设置(IV 位置起即 PN)。
|
||
|
||
## 5. 板端接入(iec104Task 胶水,2026-10-12 实现回填)
|
||
|
||
- **承载任务 = 专用 iec104Task(640 words / Normal)**,非 netTask:netTask 是
|
||
socket RPC 执行者,`net_recv/net_send` 在 netTask 内调用 = 自己等自己回执(死锁)。
|
||
手写于 `Src/freertos.c` USER CODE 区(timeSyncTask/adcTask 同款先例),文件
|
||
`App/task/iec104_serv.c`(纯编排,协议语义全在 `App/protocol/iec104/`)。
|
||
- **看门狗**:`TASK_WD_IEC104 = 7` 纳入 `wd_required_mask()` 两分支(产品 0x1F7 /
|
||
HW 测试层 0x1F5,含 B5 protect 位 bit8);主循环 100ms 节拍喂位,屏障等待按
|
||
100ms 分片喂位(timeSyncTask 2026-10-02 台架先例)。
|
||
- **就绪屏障**:等 `SYS_EVT_NET_READY`(`osFlagsNoClear` + 分片)后才建监听。
|
||
- **单连接语义**(`AGENTS.md` 模块约定,抄 `ui_net_sink.c` 模板):2404 监听与
|
||
数据通道复用同一 socket(accept 返回即 listen fd);EOF 时 net 层 auto_relisten,
|
||
应用层**不得**关 fd(`client == listen` 分支);仅模拟器多连接后端(fd 不同)显式关。
|
||
- **门控 + 兜底**:`net_listener_armed`/`net_can_read`(纯 RAM 读)省无谓 RPC 往返
|
||
(门控不用只认 ESTABLISHED 的 `net_can_accept`——那会把监听
|
||
服役窗口全挡掉,CONNECT 事件补 accept 探针从不运行);
|
||
每 32 轮无条件 recv 一次防 RECV_OK 事件未收到(沿用 UI 推流侧「周期 recv 兜事件丢失」的先例)。
|
||
- **网络代次自愈**:`net_get_generation()` 变化 → 关旧 fd 重建监听(netTask
|
||
NET_RECONFIG 重建路径的既有约定)。
|
||
- **主动拆链**(与 EOF 路径相对):协议故障(坏帧/N(R) 倒退/t1 超时)或发送连续
|
||
3 次失败(短写先例)→ 本端 `net_close` + 重建监听,促主站重连——违例时
|
||
主站不会自行断开,必须本端断(time_sync 会话收尾先例,非芯片 auto_relisten 风暴路径)。
|
||
- **抢占策略修正(V0.1 如实登记)**:建档时定"后连优先",实现后确认单连接
|
||
socket 在连接态无法 accept(监听即数据通道),**V0.1 实为首到优先**——旧会话
|
||
经 EOF/t1/拆链结束后新主站才能接入;后连优先需 net 层支持,见 §8 第 7 条。
|
||
- **k/w 与 RPC 时延**:`net_send` 经 netTask 串行 RPC(最坏往返无界 ≈4 s);
|
||
t1/t2/t3 全部用注入 tick 判定,单次 RPC 停顿不会误触 t1(15 s),连续停顿由
|
||
"发送 3 连败拆链"兜底。COV 突发延迟 ≤100ms(服务周期),远小于 SOE 5000ms 线。
|
||
- **对时**:C_CS → `sys_clock_set_unix()`(含 SD2506 RTC 写回);epoch 秒 >2^32
|
||
(2106-02-07 后)显式拒绝回 PN。
|
||
- **通讯参数可配置化(道G task-8,2026-10-26 落地)**:公共地址与监听端口真源 =
|
||
`/config.ini` `[comm]` 段(键表 → `docs/子系统设计/网络配置说明.md` §3.6)。消费方式 =
|
||
`iec104Task` 启动读一次 `iec104_comm_ca()` 填链路 cfg(**ca 生效 = 改后重启**),
|
||
`s_bind_listen()` 每次现取 `iec104_comm_port()`(端口另在下次重 bind 自然生效);
|
||
getter 合法带 ca∈1..65535 / port∈1024..65535,带外自愈回工厂默认 1/2404
|
||
(adc_cal 合法带哨兵同款;getter 不打日志,省 iec104Task 深链栈)。不挂段回调、
|
||
不新增事件位、不走 SYS_EVT_NET_RECONFIG(热切换代价见 §8,原「V0.1 固定 1」口径作废)。
|
||
- **面板编辑(道G task-9,2026-10-27)**:「通讯参数 → 通讯设置」页(`#page=comm`,
|
||
`Drivers/BSP/UI/ui_page_comm.c`)经**通道六注入**(`ui_data_comm_ops_t`,理由与
|
||
通道五同构:分层 / 模拟器 / 「写值+置脏」原子性)编辑 ca/port;合法带由执行侧
|
||
现给(面板粗守与 setter 守卫同一出口,抄数即第二真源)。保存行 ENTER →
|
||
WAIT/OK 锁存判定 = `iec104_comm_dirty_peek()`,落盘 = defaultTask 每轮无条件
|
||
`iec104_comm_store_save()`(run_par/prot_set 同款 B7 脏位形态,**无事件位**,
|
||
延续上条 D5 口径)。屏上 OK 只证明**落盘完成**,不证明"已在新值上运行"——
|
||
生效时刻仍按上条(ca 重启 / port 重 bind)。容量核对:生产占 **6/8 段、
|
||
[comm] 2/16 键**,超限现象 = 注册返 -1 → `comm init: FAIL` 启动锚 + getter
|
||
回 ROM 默认,语义由 cfg_file 宿主套 TC-CONFIG-056/057 钉住,不抬宏。
|
||
|
||
- **观测计数(只读 getter,2026-10-27 道G task-12)**:`App/task/iec104_serv.c` 另有四枚
|
||
**只增不清**的计数,经 `iec104_serv_get_stats()`(声明在 `App/task/iec104_serv.h`)对外只读:
|
||
`conn_up`(主站接入次数)/ `apdu_tx`(成功发出的 APDU 帧数)/ `tx_fail`(发送短写或失败次数)/
|
||
`rx_bytes`(收到的**字节**数,不是帧数——帧边界在 link 层重组,serv 层看不见)。口径是
|
||
**上电以来、跨重连不清零**,给页面用时那一栏要写「本次开机以来」,与运行时长同一类。
|
||
⚠ 与本节三枚**控制量**(`s_liveness_ctr` / `s_send_fail_run` / `s_conn_dead`,为"要不要拆链"
|
||
服务、会被复位、只有 8 位)无关,拿它们当统计数字必错。为什么留在 serv.c 而不并进通用
|
||
统计模块、也不放进 `iec104_link_t`(实例是文件级 static,喂数据侧拿不到指针,且
|
||
`link_open/link_close` 会把"上电以来"洗成"本次连接"):104 的账本归 104。getter
|
||
**任意上下文可读**(不取锁、不读时刻、不碰 socket;四枚 u32 单字原子,跨字段不保证同一
|
||
瞬间,四枚之间没有"合起来才成立"的判据),到顶饱和不回绕。**「总召次数 / 上送 I 帧数」
|
||
不在这里**:那是 link 层事件,serv 照不到,需要它得去
|
||
`App/protocol/iec104/iec104_link.c` 加——本卡未做,别在页面上摆一个数却没有产生它的地方。
|
||
|
||
## 6. RAM / 栈预算(2026-10-12 实测)
|
||
|
||
| 项 | 实测 | 依据 |
|
||
|---|---|---|
|
||
| 静态(新增) | link 实例 ~560 B(含 512 B 流重组缓冲)+ pts 快照 ~120 B + 胶水 rx 128 B | `iec104_link_t` 字段和 |
|
||
| iec104Task 栈 | 640 words(2560 B):静态最坏链 1456 B(拆链→重建监听→net_bind→SPI 故障→日志尾),余 1104 B / 43% **PASS** | `stack_report.py` 2026-10-12;512 words 时余 592 B < ISR 底线 → 抬栈 |
|
||
| CCM 堆 | 任务栈 2.5 KB + TCB,min_ever 6,640 → ≈6,100 B(> 3,072 告警线) | adcTask 抬栈同口径台账 |
|
||
| 总量门禁 | RW_IRAM1 73.1% / RW_CCM 75.3%(<92%) | `ram_baseline.py --update` 2026-10-12 |
|
||
|
||
## 7. 测试方案
|
||
|
||
| 层 | 内容 |
|
||
|---|---|
|
||
| L0.5 | `test/host/iec104/`:APCI 重组/坏帧、STARTDT 握手、总召全流程(含 RBT/分片/预算)、COV、k/w 窗、t1/t2/t3(假时基)、遥控两段式与 PN、YK12 软压板两段转真 + 置脏(B7)、定值两段写 + set_sealed 后 selfcheck、C_RD(含本地项不可寻址)、C_CS(含闰年)、错地址/错类型 EVI;**板端默认源真实链**(ring→phasor→freq→meas 快照,非桩):值/品质透传、CLIPPED→IV、0x401D 绑频(收敛 ±0.02 Hz / 未新鲜 IV)、死区运行时化 + 2 点确认/回摆撤销、seq 去重(卡 9/11,TC-IEC104-025~028)+ 运行参数段路由/两段式/RMW(卡 10,TC-IEC104-029)+ `[comm]` 段真链(道G task-8,TC-IEC104-031~033:注册/出厂模板/沉降重载/带外自愈/setter 守卫/ca 端到端 = C_RD 正答与旧写死 ca=1 转 COT13+EVI);`test/host/iec104_serv/` 钉端口与 ca 取值来源(TC-I104SRV-001b/c);`test/host/cfg_file/` 钉段/键容量上限(TC-CONFIG-056/057);`test/host/run_par/`:[run_par] 注册/落盘往返/守卫/系数直通合法带(TC-RUNPAR-001~008);`test/host/prot_set/`:blob 往返 + 损坏整表拒绝(all-or-nothing)|
|
||
| L0 | `iec104-unit-test` 钩子 + cppcheck/coding-standard |
|
||
| 台架 | `@test` 锚点(104 服务启动/监听行);**PC 主站客户端 `test/host/iec104_master.py`(纯标准库,B6 2026-10-12 就绪)**:STARTDT/总召四组+actterm/C_SE 定值两段写→YX15·16 变位(COT=3)/恢复复归/YK11 两段正答/C_RD 读回,台架往返 **18/18 PASS**(证据 `../测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt`);**B7 持久化模式 `--b7-pre/--b7-post/--b7-mark/--b7-check`**(中间 ST-LINK 复位):YK12 两段投退→保护退出/联动、**定值与压板态跨复位保持**(含非默认 7.5 往返),**21/21 + 13/13 + 4/4+4/4 PASS**(证据 `../测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt`);**B9 SOE 腿**(同工具同轮回归):自发 YX 断言 **M_SP_TB_1 带 ts**(工具解析 type 30/1 双型)+ FTP 下载 `/log/soe.log` 经 `test/host/soe/decode_soe.py` 解码断言(校验和/seq 单调/CP56↔epoch UTC 交叉),pre 21/21 + post 13/13 不回归;lib60870 级第三方全流程归 B10 |
|
||
|
||
## 8. V0.1 限制与待办(如实登记)
|
||
|
||
1. 固有参数 8001H~800AH 未实现(字符串类无法短浮点上送)→ 未知 IOA 应答;随送检需求再设计。
|
||
2. ~~SOE 带时标~~ **突发单点已带 CP56 时标 = M_SP_TB_1(B9 落地,见 §3.2)**;
|
||
双点带时标不做(V0.1 双点恒 IV,无意义)。
|
||
3. YK1~4/13/14 否定确认——出口硬件确认后(R7)转真执行(YK12 已于 B7 转真)。
|
||
4. ~~遥测死区 10.0 码值为拟定值~~——工程量死区已于 2026-10-25 卡 6 落地(额定 0.5%);
|
||
卡 9 已加 2 点确认;卡 10(2026-10-25)已落地 **0x8020~0x8058 读写映射 + [run_par]
|
||
持久化 + 系数覆盖直通 adc_cal**——死区系数唯一真源 = cfg 引擎副本(run_par 存死区、
|
||
**不存系数**,系数真源在 [adc_cal] 段,见 §3.4 表注),`iec104_pts_yc_set_deadband`
|
||
降级为转发壳。
|
||
5. 多主站/双链路冗余不做(单连接语义)。
|
||
6. 主站侧验证工具 = `test/host/iec104_master.py`(B6 2026-10-12 就绪,台架往返 18/18,覆盖总召/变位/遥控/定值);**第三方送检环境仍未就绪**——lib60870 级第三方全流程归 B10。
|
||
7. **后连优先未实现**(V0.1 = 首到优先):单连接 socket 连接态无法 accept,
|
||
旧会话结束前新主站接入被拒;后连优先需 net 层(CH395F 单连接模型)支持,
|
||
真需要冗余切换时随 net 扩展立项。
|
||
8. ~~公共地址固定 1、监听端口固定 2404~~——**可配置化已落地**(道G task-8,
|
||
2026-10-26,`[comm]` 段,见 §5 与 `docs/子系统设计/网络配置说明.md` §3.6)。
|
||
**主站地址(accept 侧 IP 白名单)仍不做**:现无既有消费点;单连接 socket 上
|
||
「拒绝非白名单」= close + re-listen,端口扫描可打成 SPI/看门狗风暴,且配错
|
||
即锁死真主站(FTP 口令那套失败锁的代价在 104 侧没有等价护栏可低成本复刻)
|
||
→ 待送检/现场需求明确后另行立项,`[comm]` 段当前**没有**该键。
|
||
|
||
## 变更记录
|
||
|
||
| 日期 | 变更 |
|
||
|---|---|
|
||
| 2026-10-12 | 建档(B4):范围/分层/点表/链路流程/接入决策/预算/测试方案;§5 接线细节随实现回填 |
|
||
| 2026-10-12 | B4 落地回填:承载改**专用 iec104Task**(netTask 承载会 RPC 自死锁);§5 全量回填(门控/代次/拆链/对时/看门狗位 7);抢占策略修正为**首到优先**(§8 第 7 条);§6 实测(640 words,链 1456 B,余 43% PASS) |
|
||
| 2026-10-12 | **B7 定值持久化 + 软压板**:YK12 转真(§3.3,两段式 → `PS_GLOBAL_EN`);定值执行段改 `prot_set_set_sealed` 原子写+封存(§3.4,收口 B5 竞态窗口);本地项 `comm_addr=0` 不可寻址;持久化 = 脏标志 → `SYS_EVT_PROT_SET_SAVE` → defaultTask 原子写 `/prot_set.bin`,开机屏障前整表原子装载(损坏拒绝保默认 + 自检留痕);单测 +7(iec104 94 断言)+ prot_set blob 往返/损坏 33 断言 |
|
||
| 2026-10-12 | **B7 台架腿闭环**(§7 台架行回填):主站工具加 `--b7-pre/--b7-post/--b7-mark/--b7-check` 四模式(中间 ST-LINK 复位);pre 21/21(YK12 OFF→低定值不动作 / ON→YX15·16 即动作)、post 13/13(**压板退出态跨复位保持** + 重启后联动在位)、mark/check 4/4+4/4(**非默认定值 7.5 跨复位保持**);开机日志 `[CFG] prot set loaded (/prot_set.bin)`;证据 `../测试说明/boot_log_data/20261012_B7_*` |
|
||
| 2026-10-25 | **标定折算落地联动(卡 6)**:遥测读数由原始码值改工程量(§3.1 注已重写);死区按额定 0.5% 逐点重定(0.5 V / 0.005 A / 0.5 Hz),§8 第 4 条改「已落地,8020H 段仍归卡 10」 |
|
||
| 2026-10-25 | **卡 10(道D,「数据可信」M6-①)**:新增 `App/algo/run_par.c/h`——遥测死区 9 点真源收编([run_par] 段 9 键 int32 毫单位落盘,工厂默认 = 卡 6 档;pts 层 s_yc_db 副本删除、set/get 转转发壳并保留清确认计数语义);104 **0x8020~0x8058 读写映射**(§3.4 新表:逐项地址本仓自定、送检点表到位后替换常量段;0x8027~0x802A 永不覆盖,路由 run_par 先 prot_set 后);**k/b 系数覆盖 = adc_cal_set 代理**(合法带/越带留痕复用,run_par 不存系数);持久化走新事件位 `SYS_EVT_RUN_PAR_SAVE`(1<<8) 整档外科 save;单测 test/host/run_par 新建(TC-RUNPAR-001~008,67 断言)+ iec104 套 +TC-IEC104-029 路由钉(141 断言);台架/送检腿待排窗 |
|
||
| 2026-10-25 | **卡 9/卡 11(道D,「数据可信」M5/M6)**:YC 板端源改读 L2 遥测快照(削顶五路从点表绑死 -1 改为**槽位绑定 + 快照品质 CLIPPED→IV**,V0.2/N-18 零改动启用);`0x401D` 绑频率源(`freq_valid()==0` → IV);死区改运行时副本 + `iec104_pts_yc_set_deadband()`(卡 10 接线点);COV 遥测腿 = 死区连续 2 点确认(快照 `seq` 去重)+ 品质翻转直报;`iec104_pts_src_t` 表尾追加 `yc_read_ex`(旧源退路语义不变);单测 97→127(TC-IEC104-025~028 走真实 L2 链);台架腿(总召读回一致 / 频率 ±0.01 Hz)待排窗——主站工具已记 val+qds,无需改工具 |
|
||
| 2026-10-12 | **B9 时标 SOE**:自发单点 YX 换 **M_SP_TB_1(30)**(SIQ+CP56,§3.2 注;总召/周期保持 NA 型);link cfg 增 `epoch_ms` 时标源(NULL/无效 → IV 如实);serv 绑 `sys_clock`(秒域 → ms 域=秒×1000);主站工具解析 type 30/1 双型;单测 iec104 94→97(TB 时标 + IV 路径,两种类型都断言);台架腿见 §7 B9 行;落盘侧见 `App/log/README.md` soe 节 |
|
||
| 2026-10-26 | **道G task-8:`[comm]` 段落地(「UI 补齐」卡 5 非 UI 前置)**——ca/端口从写死改 `[comm]` 可配(getter 合法带自愈,键表 → `docs/子系统设计/网络配置说明.md` §3.6);`iec104_comm_init()` 内核前注册于 `app_main_init`(先注册后 load 契约,同 [adc_cal]/[run_par]);生效 = 改后重启(ca 任务启动读一次;port 下次重 bind 自然生效),不挂回调不新增事件位;§5/§8 同步销项,**主站地址不做**的理由登记 §8 第 8 条;死 define `IEC104_PORT` 删除(零 .c 消费);`IEC104_SERV_PORT` 降为快照兼容出口(真源 getter,task-9 切 ui_data_feed);单测 = `test/host/iec104` TC-IEC104-031~033(套件 174/174 PASS)+ `test/host/iec104_serv` TC-I104SRV-001b/c(37/37 PASS)+ `test/host/cfg_file` TC-CONFIG-056/057(207/207 PASS)|
|