From 6215bb6f532a649af8593953e6ca7887b1194923 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 12 Oct 2026 16:54:23 +0800 Subject: [PATCH] =?UTF-8?q?test(b7):=20=E5=AE=9A=E5=80=BC=E6=8C=81?= =?UTF-8?q?=E4=B9=85=E5=8C=96+=E8=BD=AF=E5=8E=8B=E6=9D=BF=E5=8F=B0?= =?UTF-8?q?=E6=9E=B6=E8=85=BF=E9=97=AD=E7=8E=AF=EF=BC=88=E8=B7=A8=E5=A4=8D?= =?UTF-8?q?=E4=BD=8D=E4=BF=9D=E6=8C=81=2042+8=20=E5=88=A4=E6=8D=AE?= =?UTF-8?q?=EF=BC=89+=20B6/B7=20=E9=94=80=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - @test PASS(B6 门控修复生效,protect 锚点行完好) - 主站工具 iec104_master.py 增 --b7-pre/--b7-post/--b7-mark/--b7-check 四模式(纯标准库、ASCII 输出可归档,中间 ST-LINK 复位) - pre 21/21:YK12 两段 OFF → 0.05 A 低定值不动作(保护退出); ON → YX15/16 立即动作(COT=3);C_SE→C_RD 回读 - post 13/13:压板退出态跨复位保持(开机日志 global plate OUT + 低定值仍不动作)、重启后 YK12 ON 联动在位 - mark/check 4/4+4/4:非默认定值 7.5 跨复位保持(C_RD=7.500, 排除"回落出厂默认"假阳性);台架留干净态(定值/压板回默认) - 开机日志两次 [CFG] prot set loaded (/prot_set.bin) - 证据:boot_log_data 20261012_B7_* 两份 + 清单行 - 文档:IEC104 §7 台架行/变更记录、保护规划状态行/§7 P4/B7 行尾巴、 W1 卡 B6+B7 销项(删行 + §1 指针/§2 判据/§3 图/写范围注)、 任务规划 README §2.0/§2.1、test/host/README - 验证:doc-links 全绿(141 文档)、9 个文件字节卫生干净 --- docs/任务规划/README.md | 6 +- docs/任务规划/W1-采集保护收尾.md | 18 +- docs/子系统设计/IEC104上行设计说明.md | 3 +- .../20261012_B7_iec104_persist_log.txt | 214 ++++++++++++++++++ .../20261012_B7_persist_boot_log.txt | 60 +++++ docs/测试说明/boot_log_data/README.md | 1 + docs/算法/继电保护功能复现规划.md | 6 +- test/host/README.md | 2 +- test/host/iec104_master.py | 184 ++++++++++++++- 9 files changed, 476 insertions(+), 18 deletions(-) create mode 100644 docs/测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt create mode 100644 docs/测试说明/boot_log_data/20261012_B7_persist_boot_log.txt diff --git a/docs/任务规划/README.md b/docs/任务规划/README.md index 4535a3bd..5191e452 100644 --- a/docs/任务规划/README.md +++ b/docs/任务规划/README.md @@ -90,7 +90,7 @@ | 波次 | 内容 | 为什么在这 | |---|---|---| -| **W1 采集+保护收尾** | **里程碑制 + 并行道**:M1 台架闭环(台架道 B6→N-33)∥ M2 功能面(代码道 B7→{B8∥B9})→ M3 送检(B10,Fixed Date)——任务卡/判据/写范围见 `W1-采集保护收尾.md` | **用户决定(2026-10-12):先把 ADC 采集、保护等相关功能完成**。B4/B5 代码已落地但未台架闭环、功能面不完整(定值不落盘 / 无频率保护 / 无动作记录 / 栈两处 FAIL)——本波收口到"可用 + 可验收";真约束只有**台架**与**送检窗口**两个稀缺资源,其余任务按写范围切分并行 | +| **W1 采集+保护收尾** | **里程碑制 + 并行道**:M1 台架闭环(台架道 B6 ✅→N-33)∥ M2 功能面(代码道 B7 ✅→{B8∥B9})→ M3 送检(B10,Fixed Date)——任务卡/判据/写范围见 `W1-采集保护收尾.md` | **用户决定(2026-10-12):先把 ADC 采集、保护等相关功能完成**。B4/B5 代码已落地但未台架闭环、功能面不完整(定值不落盘 / 无频率保护 / 无动作记录 / 栈两处 FAIL)——本波收口到"可用 + 可验收";真约束只有**台架**与**送检窗口**两个稀缺资源,其余任务按写范围切分并行 | | **W2 数据正确性** | **N-21** dhara `is_free`/`copy`(报告 N-12/13) | 低概率、后果重(数据丢失);修复须配主机侧移植层测试,一并补报告"覆盖率"缺口 | | **W3 预算与内存** | **N-27 后半**:R-9 池 40→16 KB → R-2 后半(54 KB→CCM)→ R-3~R-6 逐项评估 | 依赖 W1 三件套产出的台账数据;**B5 堆扩容后 CCM 只剩 ≈8 KB**(56 KB 堆),R-2 后半更被堵死(解锁链见 `docs/内存管理/RAM预算台账.md` §3) | | **W4 结构债** | **N-20 → C6(S-3)→ C3(N-2+N-24)→ C1 pending 二期 → C5(含 N-23 残余)→ N-22/N-25/N-26/N-28**(详表 `排期详述.md` §1) | 无紧急,按性价比排:C6 灭 IWDG 误复位机制根源;C1 体量大、验证重,放后(N-23 钩子已落地 2026-10-12,残余并入 C5) | @@ -103,8 +103,8 @@ ### 2.1 顺序一图 ``` -W1 收尾 台架道: B6→N-33(M1) ∥ 代码道: B7→{B8∥B9}(M2) → B10 送检(M3, Fixed Date) 详表 W1-采集保护收尾.md - (B4 IEC104 ✅ / B5 protectTask ✅ 2026-10-12 已销项;台账三件套 ✅) +W1 收尾 台架道: B6✅→N-33(M1) ∥ 代码道: B7✅→{B8∥B9}(M2) → B10 送检(M3, Fixed Date) 详表 W1-采集保护收尾.md + (B4 IEC104 ✅ / B5 protectTask ✅ / B6 台架复测 ✅ / B7 定值持久化+软压板 ✅ 2026-10-12 已销项;台账三件套 ✅) ↓ W2 数据 N-21 dhara is_free/copy(配主机侧移植层测试) ↓ diff --git a/docs/任务规划/W1-采集保护收尾.md b/docs/任务规划/W1-采集保护收尾.md index 45fa8ff5..3978c6f9 100644 --- a/docs/任务规划/W1-采集保护收尾.md +++ b/docs/任务规划/W1-采集保护收尾.md @@ -12,7 +12,11 @@ B0 产品定义 2026-10-10 确认——上行 **IEC 60870-5-104**(以太网 TC B1 ADC 采集链路已 `@test` 实机闭环;B3 纪律门禁已固化进 `AGENTS.md`; **B4/B5 已销项(2026-10-12)**——证据见 `../子系统设计/IEC104上行设计说明.md`(82 断言 + 钩子)与 `../算法/继电保护功能复现规划.md` §7 变更记录(protectTask 20 ms 判据节拍 + L5-4 采样闭锁 + -IWDG bit8 + 堆 48→56 KB + prot_elm 28 用例)。 +IWDG bit8 + 堆 48→56 KB + prot_elm 28 用例); +**B6/B7 已销项(2026-10-12)**——B6 证据 = `../测试说明/boot_log_data/README.md` §3 +(@test PASS + 门控缺陷 MISS→FIX 快照 + PC 主站 18/18,工具 `test/host/iec104_master.py`); +B7 证据 = `../子系统设计/IEC104上行设计说明.md` §3.4 + boot_log_data B7 行 +(定值/压板跨复位保持 + YK12→YX 联动,主站 42+8 判据 + 主机 63+94 断言)。 **本波目标(用户决定 2026-10-12)**:把"采集→相量→保护→上送"链路从"代码落地"收口到 **"台架闭环 + 功能面完整 + 可送检"**。规划方式 = **里程碑(时间驱动、判据退出)× @@ -22,8 +26,8 @@ IWDG bit8 + 堆 48→56 KB + prot_elm 28 用例)。 | 里程碑 | 退出判据(全部满足才算完成,随后销项) | 服务分类 | |---|---|---| -| **M1 台架闭环** | B6 `@test` PASS + N-33 `stack_report` 0 FAIL(含 `@test` 复测腿) | Standard | -| **M2 功能面完整** | B7/B8/B9 全部合入 + `ci_local` 全绿 + PC 客户端往返含"定值掉电保持"与"SOE 时标" | Standard | +| **M1 台架闭环** | N-33 `stack_report` 0 FAIL(含 `@test` 复测腿);B6 `@test` PASS ✅ 2026-10-12(min_ever 背书就绪) | Standard | +| **M2 功能面完整** | B8/B9 全部合入 + `ci_local` 全绿 + PC 客户端往返含"SOE 时标"("定值掉电保持" ✅ B7 台架 2026-10-12) | Standard | | **M3 可送检** | B10 注入判据 + 第三方主站全流程通过,证据归档 | **Fixed Date**(送检窗口一到全道让路;窗口前 2 日特性冻结,只修稳定——Zephyr RC 语义) | ## 3. 并行道(台架 = 约束资源永不空转;代码道 = worktree 并行、绿即合) @@ -34,8 +38,8 @@ graph LR B6[B6 @test 复测] --> N33[N-33 栈收口+复测] end subgraph CL[代码道 🟢 worktree 并行 绿即合] - B7[B7 定值持久化] -->|合并次序| B8[B8 频率保护] - B7 -->|合并次序| B9[B9 动作记录/SOE] + B8[B8 频率保护] + B9[B9 动作记录/SOE] end N33 --> M1((M1)) B8 --> M2((M2)) @@ -48,13 +52,11 @@ graph LR > 资源图例:🔴 台架(COM6/ST-LINK,`bench.lock` 独占)· 🟡 外部(标准源/第三方主站)· 🟢 纯软件(可并行)。 > 状态:⬜ 未开始 · 🟦 进行中(销项行直接删除,见 `docs/任务规划/README.md` §3 维护约定)。 -> ⚠ **写范围相交**:B7×B8(`App/algo/prot_set.*`)、B7×B9(`App/protocol/iec104/iec104_pts.c`)→ **B7 先合**,其后 B8∥B9(互不相交)。 +> ⚠ **写范围相交**:B7 已先合入(2026-10-12,`App/algo/prot_set.*` 与 `App/protocol/iec104/iec104_pts.c` 定值段已释放);B8∥B9 写范围互不相交,可直接并行。 | 序 | 任务 | DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 | 出处 | |---|---|---|---|---|---|---|---| -| **B6** | **台架 `@test` 闭环复测(B4/B5 验收窗口)** | `@test` PASS:`protect task start` 锚点 ×1;`[STACK] protect`/`iec104` 水位行在且 free 达标;新堆 min_ever 记录、无 `HEAP_LOW_WATER_B` 告警;PC 客户端 2404 总召/变位往返日志;采样闭锁不误报 | — | 🔴 | `.serialtest/config.json`(无新固件代码) | ✅ 完成(2026-10-12,**待销项删行**):首跑 FAIL 暴露 protectTask 启动行违反写者门控纪律(B5 台架腿缺口实锤,缺陷快照留档)→ 启动行 writer-ready 首拍补打修复(+16 B 固件代码,经用户认可随修)→ 复测 PASS 全判据;104 往返 18/18(两版固件);证据 `../测试说明/boot_log_data/`(20261012_B6_* 四份快照) | 保护规划 §7 变更记录"遗留";`../测试说明/自动化测试流程.md` | | **N-33** | **栈余量收口**(defaultTask 余 1080 B < 30% 线 / timeSyncTask 余 784 B < ISR 底线,2026-10-12 实测;**既有债非 B4/B5 引入**;链 = dhara GC→控制台回显尾→`(Cycle)`) | `stack_report.py` 9 任务 0 FAIL + `@build` 0/0;若抬栈:台账 §6 登记 + `@test` 复测 PASS | B6 ✅(min_ever=10000 已背书 2026-10-12,AGENTS 抬栈门禁) | 🟢(瘦链调研)+ 🔴(复测腿) | `Src/freertos.c`(USER CODE)/ 瘦链目标文件 | ⬜ | 2026-10-12 `stack_report.py` 实测 | -| **B7** | **定值持久化 + 遥控软压板(P4)** | 主机单测:定值存/取往返、损坏→all-or-nothing 拒绝、YK12 两段式转真执行;`@build` 0/0;**台架腿**:104 C_SE 写 → 断电重启 → 定值保持;写+seal 原子化(B5 竞态窗口关闭,回填保护规划 §3.5) | —(代码);验证腿 🔴 | 🟢 + 🔴 | `App/algo/prot_set.*`、`App/cfg/`、`App/protocol/iec104/iec104_pts.c`(定值段)、`App/task/iec104_serv.c` | 🟦 代码腿完成(2026-10-12:prot_set 63 + iec104 94 断言全绿、`@build` 0/0;`/prot_set.bin` 原子持久化 + YK12 转真 + 竞态收口已落地);**台架腿待窗口 🔴**(C_SE 两段写路径已随 B6 窗 2026-10-12 验证:104 往返 18/18;剩余 = 断电重启→定值保持 + YK12→YX 联动) | 保护规划 §3.5 L5-1、§5;`../子系统设计/IEC104上行设计说明.md` §3.3 | | **B8** | **频率测量算法 + 过频/低频保护(P2 剩余)** | 频率测量主机单测(45~55 Hz 扫描,精度判据写入文档)+ OF/UF 实例单测;`@build` 0/0;心跳行显示频率值。OV/UV/3U0 实例 B5 起已在跑,注入判据归 B10 | — | 🟢 | `App/algo/phasor.*`(或新 `freq.*`)、`App/algo/prot_elm.*`、`App/algo/prot_set.*`(定值行) | ⬜ | 保护规划 §3.3 L3-5、保护规划 §7 P2 | | **B9** | **动作记录 + 时标 SOE(L4)** | SOE 记录编解码主机单测 + iec104 单测(M_SP_TB_1);`@build` 0/0;protectTask 静态链不变(动作路径无 NAND I/O,记录走队列异步);**台架腿**:动作边沿 → `/log` 记录可见。出口跳闸仍否定确认(R7 口径不变) | —(代码);验证腿 🔴 | 🟢 + 🔴 | `App/log/`、`App/protocol/iec104/iec104_asdu.*` + `iec104_pts.c`(YX 时标段)、`App/task/protect_task.c` | ⬜ | 保护规划 §3.4 L4、保护规划 §7 P4;`../子系统设计/IEC104上行设计说明.md` §3.2 注 | | **B10** | **标准源注入 + 第三方 104 主站往返(送检窗口)** | 标准源注入:L1-5 标定复核 / L1-7 等周波 / P1 过流·过负荷 / P2 电压 + 频率类判据全通过;第三方主站总召/周期/变位/遥控全流程(`../子系统设计/IEC104上行设计说明.md` §7/§8 核对单);证据归档 | M1 + M2 | 🟡 | —(窗口内缺陷修复走 Expedite 类) | ⬜ | 保护规划 §7 P1/P2 验收;`../子系统设计/IEC104上行设计说明.md` §7/§8 | diff --git a/docs/子系统设计/IEC104上行设计说明.md b/docs/子系统设计/IEC104上行设计说明.md index 7d6af784..bc0bf441 100644 --- a/docs/子系统设计/IEC104上行设计说明.md +++ b/docs/子系统设计/IEC104上行设计说明.md @@ -152,7 +152,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;`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`);lib60870 级第三方全流程归 B10 | +| 台架 | `@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`);lib60870 级第三方全流程归 B10 | ## 8. V0.1 限制与待办(如实登记) @@ -174,3 +174,4 @@ | 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_*` | diff --git a/docs/测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt b/docs/测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt new file mode 100644 index 00000000..54c23368 --- /dev/null +++ b/docs/测试说明/boot_log_data/20261012_B7_iec104_persist_log.txt @@ -0,0 +1,214 @@ +B7 bench leg: IEC104 setpoint persistence + global soft plate (YK12) round-trip +fw: HEAD dafcf80 (B7 1fe163b + B6 gating fix), device 192.168.1.100:2404 +tool: test/host/iec104_master.py --b7-pre / --b7-post / --b7-mark / --b7-check +sequence: pre(reset 前) -> ST-LINK reset -> post; mark(7.5) -> reset -> check +date: 2026-10-12 16:42~16:45 +08:00 + +==== phase 1: --b7-pre (21/21 PASS) ==== +[ 0.006s] iec104 master client -> 192.168.1.100:2404 mode=pre +[ 0.010s] TX U STARTDT act 68 04 07 00 00 00 +[ 0.179s] RX U STARTDT con +[ 1.190s] CHECK startdt_con PASS +[ 1.190s] TX I C_IC act (pre) 68 0E 00 00 00 00 64 01 06 00 01 00 00 00 00 14 +[ 1.281s] RX I type=100 cot=7 body=00 00 00 14 +[ 1.281s] TX S N(R)=1 68 04 01 00 02 00 +[ 1.282s] TX S N(R)=2 68 04 01 00 04 00 +[ 1.283s] RX I M_SP ioa=15 val=0 iv=0 cot=4 [N(R)=1] +[ 1.283s] RX I M_SP ioa=16 val=0 iv=0 cot=4 [N(R)=1] +[ 1.283s] RX I M_SP ioa=17 val=0 iv=0 cot=4 [N(R)=1] +[ 1.283s] RX I M_SP ioa=18 val=0 iv=0 cot=4 [N(R)=1] +[ 1.283s] RX I M_SP ioa=23 val=0 iv=0 cot=4 [N(R)=1] +[ 1.283s] RX I M_SP ioa=31 val=0 iv=0 cot=4 [N(R)=1] +[ 1.283s] TX S N(R)=3 68 04 01 00 06 00 +[ 1.285s] TX S N(R)=5 68 04 01 00 0A 00 +[ 1.385s] RX I type=100 cot=8 body=00 00 00 14 +[ 1.385s] TX S N(R)=6 68 04 01 00 0C 00 +[ 2.400s] CHECK gi_actterm_pre PASS +[ 2.400s] CHECK baseline_yx16_off PASS yx16=(0, False) +[ 2.400s] TX I C_SE select 0x8858 = 7.500 (mark) 68 12 02 00 0C 00 32 01 06 00 01 00 58 88 00 00 00 F0 40 80 +[ 2.487s] RX I type=50 cot=7 body=58 88 00 00 00 F0 40 80 +[ 2.487s] TX S N(R)=7 68 04 01 00 0E 00 +[ 3.497s] CHECK se_sel_mark PASS +[ 3.497s] TX I C_SE exec 0x8858 = 7.500 (mark) 68 12 04 00 0E 00 32 01 06 00 01 00 58 88 00 00 00 F0 40 00 +[ 3.497s] CHECK se_exe_mark PASS +[ 3.497s] TX I C_RD 0x8858 68 0D 06 00 0E 00 66 01 05 00 01 00 58 88 00 +[ 3.588s] RX I type=50 cot=7 body=58 88 00 00 00 F0 40 00 +[ 3.588s] TX S N(R)=8 68 04 01 00 10 00 +[ 3.689s] RX I M_ME_NC ioa=0x8858 val=7.500 qds=0x00 cot=5 +[ 3.689s] TX S N(R)=9 68 04 01 00 12 00 +[ 4.702s] CHECK rd_mark_7.5 PASS read=7.500 want=7.500 +[ 4.702s] TX I C_DC 0x600B select QDC=81 68 0E 08 00 12 00 34 01 06 00 01 00 0B 60 00 81 +[ 4.790s] RX I type=52 cot=7 body=0B 60 00 81 +[ 4.790s] TX S N(R)=10 68 04 01 00 14 00 +[ 5.805s] CHECK yk12_off_sel PASS +[ 5.805s] TX I C_DC 0x600B execute QDC=01 68 0E 0A 00 14 00 34 01 06 00 01 00 0B 60 00 01 +[ 5.805s] CHECK yk12_off_exe PASS +[ 5.805s] TX I C_SE select 0x8858 = 0.050 (low) 68 12 0C 00 14 00 32 01 06 00 01 00 58 88 00 CD CC 4C 3D 80 +[ 5.805s] CHECK se_sel_low PASS +[ 5.805s] TX I C_SE exec 0x8858 = 0.050 (low) 68 12 0E 00 14 00 32 01 06 00 01 00 58 88 00 CD CC 4C 3D 00 +[ 5.805s] CHECK se_exe_low PASS +[ 5.891s] RX I type=52 cot=7 body=0B 60 00 01 +[ 5.891s] TX S N(R)=11 68 04 01 00 16 00 +[ 5.993s] RX I type=50 cot=7 body=58 88 00 CD CC 4C 3D 80 +[ 5.993s] TX S N(R)=12 68 04 01 00 18 00 +[ 6.036s] RX I type=50 cot=7 body=58 88 00 CD CC 4C 3D 00 +[ 6.036s] RX S N(R)=8 +[ 6.036s] TX S N(R)=13 68 04 01 00 1A 00 +[ 9.071s] CHECK plate_out_no_trip PASS YX16 must stay OFF while plate OUT (protection disabled) +[ 9.071s] TX I C_RD 0x8858 68 0D 10 00 1A 00 66 01 05 00 01 00 58 88 00 +[ 9.101s] RX I M_ME_NC ioa=0x8858 val=0.050 qds=0x00 cot=5 +[ 9.101s] TX S N(R)=14 68 04 01 00 1C 00 +[ 10.113s] CHECK rd_low_0.05 PASS read=0.050 want=0.050 +[ 10.113s] TX I C_DC 0x600B select QDC=82 68 0E 12 00 1C 00 34 01 06 00 01 00 0B 60 00 82 +[ 10.113s] CHECK yk12_on_sel PASS +[ 10.113s] TX I C_DC 0x600B execute QDC=02 68 0E 14 00 1C 00 34 01 06 00 01 00 0B 60 00 02 +[ 10.113s] CHECK yk12_on_exe PASS +[ 10.201s] RX I type=52 cot=7 body=0B 60 00 82 +[ 10.201s] TX S N(R)=15 68 04 01 00 1E 00 +[ 10.303s] RX I type=52 cot=7 body=0B 60 00 02 +[ 10.303s] TX S N(R)=16 68 04 01 00 20 00 +[ 10.504s] RX I M_SP ioa=15 val=1 iv=0 cot=3 [N(R)=11] +[ 10.504s] TX S N(R)=17 68 04 01 00 22 00 +[ 10.505s] RX I M_SP ioa=16 val=1 iv=0 cot=3 [N(R)=11] +[ 10.505s] TX S N(R)=18 68 04 01 00 24 00 +[ 11.512s] CHECK spont_yx16_ON PASS +[ 11.512s] CHECK spont_yx15_ON PASS +[ 11.512s] TX I C_SE select 0x8858 = 10.000 (restore) 68 12 16 00 24 00 32 01 06 00 01 00 58 88 00 00 00 20 41 80 +[ 11.607s] RX I type=50 cot=7 body=58 88 00 00 00 20 41 80 +[ 11.607s] TX S N(R)=19 68 04 01 00 26 00 +[ 12.614s] CHECK se_sel_restore PASS +[ 12.614s] TX I C_SE exec 0x8858 = 10.000 (restore) 68 12 18 00 26 00 32 01 06 00 01 00 58 88 00 00 00 20 41 00 +[ 12.614s] CHECK se_exe_restore PASS +[ 12.707s] RX I type=50 cot=7 body=58 88 00 00 00 20 41 00 +[ 12.707s] TX S N(R)=20 68 04 01 00 28 00 +[ 12.708s] RX I M_SP ioa=15 val=0 iv=0 cot=3 [N(R)=13] +[ 12.709s] TX S N(R)=21 68 04 01 00 2A 00 +[ 12.710s] RX I M_SP ioa=16 val=0 iv=0 cot=3 [N(R)=13] +[ 12.710s] TX S N(R)=22 68 04 01 00 2C 00 +[ 13.720s] CHECK yx16_off_after_restore PASS via spontaneous COT=3 +[ 13.720s] TX I C_DC 0x600B select QDC=81 68 0E 1A 00 2C 00 34 01 06 00 01 00 0B 60 00 81 +[ 13.811s] RX I type=52 cot=7 body=0B 60 00 81 +[ 13.811s] TX S N(R)=23 68 04 01 00 2E 00 +[ 14.813s] CHECK yk12_off_final_sel PASS +[ 14.813s] TX I C_DC 0x600B execute QDC=01 68 0E 1C 00 2E 00 34 01 06 00 01 00 0B 60 00 01 +[ 14.813s] CHECK yk12_off_final_exe PASS +[ 14.813s] wait 2s: dirty -> SYS_EVT_PROT_SET_SAVE -> /prot_set.bin +[ 16.813s] SUMMARY: 21/21 checks PASS -> PASS + +==== phase 2: --b7-post (13/13 PASS) ==== +[ 0.007s] iec104 master client -> 192.168.1.100:2404 mode=post +[ 0.024s] TX U STARTDT act 68 04 07 00 00 00 +[ 0.120s] RX U STARTDT con +[ 1.126s] CHECK startdt_con PASS +[ 1.126s] TX I C_IC act (post) 68 0E 00 00 00 00 64 01 06 00 01 00 00 00 00 14 +[ 1.221s] RX I type=100 cot=7 body=00 00 00 14 +[ 1.221s] TX S N(R)=1 68 04 01 00 02 00 +[ 1.223s] TX S N(R)=2 68 04 01 00 04 00 +[ 1.224s] RX I M_SP ioa=15 val=0 iv=0 cot=4 [N(R)=1] +[ 1.224s] RX I M_SP ioa=16 val=0 iv=0 cot=4 [N(R)=1] +[ 1.224s] RX I M_SP ioa=17 val=0 iv=0 cot=4 [N(R)=1] +[ 1.224s] RX I M_SP ioa=18 val=0 iv=0 cot=4 [N(R)=1] +[ 1.224s] RX I M_SP ioa=23 val=0 iv=0 cot=4 [N(R)=1] +[ 1.224s] RX I M_SP ioa=31 val=0 iv=0 cot=4 [N(R)=1] +[ 1.224s] TX S N(R)=4 68 04 01 00 08 00 +[ 1.225s] TX S N(R)=5 68 04 01 00 0A 00 +[ 1.325s] RX I type=100 cot=8 body=00 00 00 14 +[ 1.327s] TX S N(R)=6 68 04 01 00 0C 00 +[ 2.337s] CHECK gi_actterm_post PASS +[ 2.337s] CHECK baseline_yx16_off PASS yx16=(0, False) (plate OUT after reboot -> protection disabled) +[ 2.337s] TX I C_RD 0x8858 68 0D 02 00 0C 00 66 01 05 00 01 00 58 88 00 +[ 2.428s] RX I M_ME_NC ioa=0x8858 val=10.000 qds=0x00 cot=5 +[ 2.428s] TX S N(R)=7 68 04 01 00 0E 00 +[ 3.429s] CHECK persist_rd_10.0 PASS read=10.000 want=10.000 +[ 3.429s] TX I C_SE select 0x8858 = 0.050 (low) 68 12 04 00 0E 00 32 01 06 00 01 00 58 88 00 CD CC 4C 3D 80 +[ 3.528s] RX I type=50 cot=7 body=58 88 00 CD CC 4C 3D 80 +[ 3.528s] TX S N(R)=8 68 04 01 00 10 00 +[ 4.539s] CHECK se_sel_low PASS +[ 4.539s] TX I C_SE exec 0x8858 = 0.050 (low) 68 12 06 00 10 00 32 01 06 00 01 00 58 88 00 CD CC 4C 3D 00 +[ 4.539s] CHECK se_exe_low PASS +[ 4.628s] RX I type=50 cot=7 body=58 88 00 CD CC 4C 3D 00 +[ 4.628s] TX S N(R)=9 68 04 01 00 12 00 +[ 7.649s] CHECK plate_out_persisted_no_trip PASS plate OUT state survived the reset +[ 7.649s] TX I C_DC 0x600B select QDC=82 68 0E 08 00 12 00 34 01 06 00 01 00 0B 60 00 82 +[ 7.731s] RX I type=52 cot=7 body=0B 60 00 82 +[ 7.731s] TX S N(R)=10 68 04 01 00 14 00 +[ 8.734s] CHECK yk12_on_sel PASS +[ 8.734s] TX I C_DC 0x600B execute QDC=02 68 0E 0A 00 14 00 34 01 06 00 01 00 0B 60 00 02 +[ 8.734s] CHECK yk12_on_exe PASS +[ 8.831s] RX I type=52 cot=7 body=0B 60 00 02 +[ 8.831s] TX S N(R)=11 68 04 01 00 16 00 +[ 8.934s] RX I M_SP ioa=15 val=1 iv=0 cot=3 [N(R)=6] +[ 8.934s] TX S N(R)=12 68 04 01 00 18 00 +[ 8.936s] RX I M_SP ioa=16 val=1 iv=0 cot=3 [N(R)=6] +[ 8.936s] TX S N(R)=13 68 04 01 00 1A 00 +[ 9.946s] CHECK spont_yx16_ON_after_reboot PASS +[ 9.946s] TX I C_SE select 0x8858 = 10.000 (restore) 68 12 0C 00 1A 00 32 01 06 00 01 00 58 88 00 00 00 20 41 80 +[ 10.039s] RX I type=50 cot=7 body=58 88 00 00 00 20 41 80 +[ 10.040s] TX S N(R)=14 68 04 01 00 1C 00 +[ 10.539s] RX I M_SP ioa=15 val=0 iv=0 cot=3 [N(R)=7] +[ 10.539s] TX S N(R)=15 68 04 01 00 1E 00 +[ 10.541s] RX I M_SP ioa=16 val=0 iv=0 cot=3 [N(R)=7] +[ 10.541s] TX S N(R)=16 68 04 01 00 20 00 +[ 10.643s] RX I M_SP ioa=15 val=1 iv=0 cot=3 [N(R)=7] +[ 10.643s] TX S N(R)=17 68 04 01 00 22 00 +[ 10.644s] RX I M_SP ioa=16 val=1 iv=0 cot=3 [N(R)=7] +[ 10.644s] TX S N(R)=18 68 04 01 00 24 00 +[ 10.745s] RX I M_SP ioa=15 val=0 iv=0 cot=3 [N(R)=7] +[ 10.745s] TX S N(R)=19 68 04 01 00 26 00 +[ 10.746s] RX I M_SP ioa=16 val=0 iv=0 cot=3 [N(R)=7] +[ 10.746s] TX S N(R)=20 68 04 01 00 28 00 +[ 10.848s] RX I M_SP ioa=15 val=1 iv=0 cot=3 [N(R)=7] +[ 10.848s] TX S N(R)=21 68 04 01 00 2A 00 +[ 10.849s] RX I M_SP ioa=16 val=1 iv=0 cot=3 [N(R)=7] +[ 10.849s] TX S N(R)=22 68 04 01 00 2C 00 +[ 11.250s] RX S N(R)=7 +[ 11.251s] CHECK se_sel_restore PASS +[ 11.251s] TX I C_SE exec 0x8858 = 10.000 (restore) 68 12 0E 00 2C 00 32 01 06 00 01 00 58 88 00 00 00 20 41 00 +[ 11.251s] CHECK se_exe_restore PASS +[ 11.351s] RX I type=50 cot=7 body=58 88 00 00 00 20 41 00 +[ 11.351s] TX S N(R)=23 68 04 01 00 2E 00 +[ 11.351s] RX I M_SP ioa=15 val=0 iv=0 cot=3 [N(R)=8] +[ 11.352s] TX S N(R)=24 68 04 01 00 30 00 +[ 11.352s] RX I M_SP ioa=16 val=0 iv=0 cot=3 [N(R)=8] +[ 11.352s] TX S N(R)=25 68 04 01 00 32 00 +[ 12.360s] CHECK yx16_off_final PASS via spontaneous COT=3 +[ 12.360s] wait 1s: final dirty -> save, leave plate IN +[ 13.360s] SUMMARY: 13/13 checks PASS -> PASS + +==== phase 3: --b7-mark (4/4 PASS) ==== +[ 0.007s] iec104 master client -> 192.168.1.100:2404 mode=mark +[ 0.036s] TX U STARTDT act 68 04 07 00 00 00 +[ 0.166s] RX U STARTDT con +[ 1.172s] CHECK startdt_con PASS +[ 1.172s] TX I C_SE select 0x8858 = 7.500 (distinct) 68 12 00 00 00 00 32 01 06 00 01 00 58 88 00 00 00 F0 40 80 +[ 1.268s] RX I type=50 cot=7 body=58 88 00 00 00 F0 40 80 +[ 1.268s] TX S N(R)=1 68 04 01 00 02 00 +[ 2.273s] CHECK se_sel_distinct PASS +[ 2.273s] TX I C_SE exec 0x8858 = 7.500 (distinct) 68 12 02 00 02 00 32 01 06 00 01 00 58 88 00 00 00 F0 40 00 +[ 2.273s] CHECK se_exe_distinct PASS +[ 2.273s] TX I C_RD 0x8858 68 0D 04 00 02 00 66 01 05 00 01 00 58 88 00 +[ 2.368s] RX I type=50 cot=7 body=58 88 00 00 00 F0 40 00 +[ 2.368s] TX S N(R)=2 68 04 01 00 04 00 +[ 2.469s] RX I M_ME_NC ioa=0x8858 val=7.500 qds=0x00 cot=5 +[ 2.469s] TX S N(R)=3 68 04 01 00 06 00 +[ 3.473s] CHECK rd_distinct PASS read=7.500 want=7.500 +[ 3.473s] wait 1.5s: dirty -> save (/prot_set.bin) +[ 4.973s] SUMMARY: 4/4 checks PASS -> PASS + +==== phase 4: --b7-check (4/4 PASS, non-default 7.5 survived reset) ==== +[ 0.006s] iec104 master client -> 192.168.1.100:2404 mode=check +[ 0.029s] TX U STARTDT act 68 04 07 00 00 00 +[ 0.186s] RX U STARTDT con +[ 1.198s] CHECK startdt_con PASS +[ 1.198s] TX I C_RD 0x8858 68 0D 00 00 00 00 66 01 05 00 01 00 58 88 00 +[ 1.293s] RX I M_ME_NC ioa=0x8858 val=7.500 qds=0x00 cot=5 +[ 1.293s] TX S N(R)=1 68 04 01 00 02 00 +[ 2.297s] CHECK persist_distinct_after_reset PASS read=7.500 want=7.500 +[ 2.297s] TX I C_SE select 0x8858 = 10.000 (restore) 68 12 02 00 02 00 32 01 06 00 01 00 58 88 00 00 00 20 41 80 +[ 2.387s] RX I type=50 cot=7 body=58 88 00 00 00 20 41 80 +[ 2.387s] TX S N(R)=2 68 04 01 00 04 00 +[ 3.391s] CHECK se_sel_restore PASS +[ 3.391s] TX I C_SE exec 0x8858 = 10.000 (restore) 68 12 04 00 04 00 32 01 06 00 01 00 58 88 00 00 00 20 41 00 +[ 3.391s] CHECK se_exe_restore PASS +[ 3.391s] wait 1s: restore saved, bench left at defaults +[ 4.392s] SUMMARY: 4/4 checks PASS -> PASS diff --git a/docs/测试说明/boot_log_data/20261012_B7_persist_boot_log.txt b/docs/测试说明/boot_log_data/20261012_B7_persist_boot_log.txt new file mode 100644 index 00000000..7ca3ca26 --- /dev/null +++ b/docs/测试说明/boot_log_data/20261012_B7_persist_boot_log.txt @@ -0,0 +1,60 @@ +[SYS] 2026-10-12T16:44:51.032+08:00 log cleared (gen=144) +[RX] 2026-10-12T16:44:51.475+08:00 [----/--/-- --:--:--][APP] boot: syslog init OK +[RX] 2026-10-12T16:44:51.475+08:00 [----/--/-- --:--:--][APP] fw build: Oct 12 2026 14:02:47 suite=NONE dstr=off +[RX] 2026-10-12T16:44:51.489+08:00 [----/--/-- --:--:--][APP] reset cause: software (NVIC_SystemReset) (CSR=0x14000000) +[RX] 2026-10-12T16:44:51.489+08:00 PREVRUN seg=2 seq=1933923012 t=123484 +[RX] 2026-10-12T16:44:51.500+08:00 TICKRUN uw=123508 n=123508 duw=24 +[RX] 2026-10-12T16:44:51.500+08:00 [----/--/-- --:--:--][RTC] sd2506_init: OK +[RX] 2026-10-12T16:44:51.511+08:00 [----/--/-- --:--:--][APP] SD2506 init: OK (ret=0) +[RX] 2026-10-12T16:44:51.511+08:00 [2026-10-12 08:44:49][CLK] sys_clock_init: RTC initial time 2026-10-12 08:44:49 +[RX] 2026-10-12T16:44:51.521+08:00 [2026-10-12 08:44:49][CLK] sys_clock_init: wall clock base = unix 1791794689, base_tick=139 +[RX] 2026-10-12T16:44:51.532+08:00 [2026-10-12 08:44:49][APP] RS485 init: OK (UART4, DE=PA15) +[RX] 2026-10-12T16:44:51.543+08:00 [2026-10-12 08:44:49][NAND] Resetting NAND... +[RX] 2026-10-12T16:44:51.564+08:00 [2026-10-12 08:44:49][NAND] Reading NAND ID... +[RX] 2026-10-12T16:44:51.564+08:00 [2026-10-12 08:44:49][NAND] NAND ID: MID=0xC8, DID=0x52 +[RX] 2026-10-12T16:44:51.574+08:00 [2026-10-12 08:44:49][NAND] Scanning bad blocks... +[RX] 2026-10-12T16:44:51.700+08:00 [2026-10-12 08:44:49][NAND] BBT scan: 0 bad blocks found +[RX] 2026-10-12T16:44:51.711+08:00 [2026-10-12 08:44:49][NAND] Enabling ECC... +[RX] 2026-10-12T16:44:51.711+08:00 [2026-10-12 08:44:49][NAND] Unlocking block protection... +[RX] 2026-10-12T16:44:51.721+08:00 [2026-10-12 08:44:49][NAND] Locating BBT pool... +[RX] 2026-10-12T16:44:51.721+08:00 [2026-10-12 08:44:49][NAND] Loading persisted BBT... +[RX] 2026-10-12T16:44:51.732+08:00 [2026-10-12 08:44:49][NAND] NAND init OK +[RX] 2026-10-12T16:44:51.732+08:00 [2026-10-12 08:44:49][APP] NAND init: OK +[RX] 2026-10-12T16:44:51.732+08:00 [2026-10-12 08:44:49][ADC] Init OK +[RX] 2026-10-12T16:44:51.743+08:00 [2026-10-12 08:44:49][APP] ADC init: OK +[RX] 2026-10-12T16:44:51.743+08:00 [2026-10-12 08:44:49][APP] ADC input layer init: OK +[RX] 2026-10-12T16:44:51.753+08:00 [2026-10-12 08:44:49][APP] phasor layer init: OK (inst=5) +[RX] 2026-10-12T16:44:51.753+08:00 [2026-10-12 08:44:49][APP] protection init: OK (set=32 elm=7) +[RX] 2026-10-12T16:44:51.764+08:00 [2026-10-12 08:44:49][APP] SD2506 ID: 2512153425482405 +[RX] 2026-10-12T16:44:51.764+08:00 [2026-10-12 08:44:49][APP] SD2506 time: 2026-10-12 08:44:50 (week 4) +[RX] 2026-10-12T16:44:51.774+08:00 [2026-10-12 08:44:49][APP] SD2506 temp: 28 C +[RX] 2026-10-12T16:44:51.774+08:00 [2026-10-12 08:44:49][APP] SD2506 battery: 3.11 V +[RX] 2026-10-12T16:44:51.785+08:00 [2026-10-12 08:44:49][APP] App init OK +[RX] 2026-10-12T16:44:51.785+08:00 [2026-10-12 08:44:49][NAND_FTL] Initializing NAND FTL... +[RX] 2026-10-12T16:44:51.816+08:00 [2026-10-12 08:44:49][NAND_FTL] Map resumed: 14094/97504 sectors used +[RX] 2026-10-12T16:44:51.816+08:00 [2026-10-12 08:44:49][NAND_FTL] Map head=18496 tail=290 epoch=2 +[RX] 2026-10-12T16:44:51.827+08:00 [2026-10-12 08:44:49][NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB) +[RX] 2026-10-12T16:44:51.899+08:00 [2026-10-12 08:44:49] [FS] FATFS mounted +[RX] 2026-10-12T16:44:51.952+08:00 [2026-10-12 08:44:49][SYSLOG] runlog boot entry: reboot +[RX] 2026-10-12T16:44:51.962+08:00 [2026-10-12 08:44:49][CFG] register: section 'network' (4 keys) +[RX] 2026-10-12T16:44:51.962+08:00 [2026-10-12 08:44:49][CFG] register: section 'ftp' (3 keys) +[RX] 2026-10-12T16:44:51.973+08:00 [2026-10-12 08:44:49][CFG] load: OK (523B, heap free 18088B) +[RX] 2026-10-12T16:44:51.973+08:00 [2026-10-12 08:44:49][NET_CFG] load: OK ip=192.168.1.100 +[RX] 2026-10-12T16:44:51.983+08:00 [2026-10-12 08:44:49] [CFG] prot set loaded (/prot_set.bin) +[RX] 2026-10-12T16:44:52.015+08:00 [2026-10-12 08:44:49][ADC_TASK] first: UA=11428 UB=957 UC=821 UN=11454 IA=11453 IB=938 IC=983 IN=878 T=915 +[RX] 2026-10-12T16:44:52.015+08:00 [2026-10-12 08:44:49][ADC_TASK] phasor(first) C01-IA-F1: Re=-4 Im=1 rms=4 (x0.1) +[RX] 2026-10-12T16:44:52.025+08:00 [2026-10-12 08:44:49][ADC_TASK] phasor(first) C02-UA-F1: Re=-2 Im=0 rms=3 (x0.1) +[RX] 2026-10-12T16:44:52.035+08:00 [2026-10-12 08:44:49][ADC_TASK] phasor(first) C03-UN-F1: Re=-4 Im=-2 rms=5 (x0.1) +[RX] 2026-10-12T16:44:52.046+08:00 [2026-10-12 08:44:49][ADC_TASK] phasor(first) C04-IA-F2: Re=0 Im=0 rms=0 (x0.1) +[RX] 2026-10-12T16:44:52.046+08:00 [2026-10-12 08:44:49][ADC_TASK] phasor(first) C05-IA-F5: Re=0 Im=-1 rms=1 (x0.1) +[RX] 2026-10-12T16:44:52.056+08:00 [2026-10-12 08:44:49][NET_TASK] === Network Init === +[RX] 2026-10-12T16:44:52.056+08:00 [2026-10-12 08:44:49][PROT] protect task start: cycle=20ms elm=7 +[RX] 2026-10-12T16:44:52.067+08:00 [2026-10-12 08:44:49][NET] ch395f ver=0x4A fun_para=0x08 +[RX] 2026-10-12T16:44:52.067+08:00 [2026-10-12 08:44:49][NET_TASK] net init: OK +[RX] 2026-10-12T16:44:52.077+08:00 [2026-10-12 08:44:49][NET_TASK] MAC: 3C:AB:72:53:2B:12 +[RX] 2026-10-12T16:44:52.077+08:00 [2026-10-12 08:44:49][NET_TASK] IP_INF: IP=192.168.1.100 GW=192.168.1.1 MASK=255.255.255.0 +[RX] 2026-10-12T16:44:52.087+08:00 MISS start snap=0x000001E7 req=0x000001F7 t=716 +[RX] 2026-10-12T16:44:52.098+08:00 [2026-10-12 08:44:49][WD] [WD] armed: timeout ~2498ms (worst ~1701ms), miss_tol=800ms +[RX] 2026-10-12T16:44:52.108+08:00 [2026-10-12 08:44:49][UI_TASK] UI task: started, wait net ready +[RX] 2026-10-12T16:44:53.611+08:00 [2026-10-12 08:44:51][PROT] elm OC1-IA asserted=1 picked=1 +[RX] 2026-10-12T16:44:53.673+08:00 [2026-10-12 08:44:51][PROT] elm OC1-IA asserted=0 picked=0 diff --git a/docs/测试说明/boot_log_data/README.md b/docs/测试说明/boot_log_data/README.md index d9c27727..72df60a2 100644 --- a/docs/测试说明/boot_log_data/README.md +++ b/docs/测试说明/boot_log_data/README.md @@ -33,6 +33,7 @@ | 2026-10-12 | `prod`(B7 `1fe163b` + B6 门控修复)/ 开机 + 30 s 空载(**B6 复测 PASS**) | `protect` 828/2048(59%,free_min 1220);`iec104` 424/2560(83%);heap free=17936 **min_ever=10000**(**N-33 抬栈 min_ever 背书就绪**);锚点行完好 `cycle=20ms elm=7`(+577 ms,写者 attach 后首拍);零 `[ERR]`、采样闭锁不误报 | `20261012_B6_prod_boot_log.txt` | | 2026-10-12 | 同 MISS 固件(d3107f3)/ **PC 主站 2404 往返**(`test/host/iec104_master.py`) | STARTDT/总召四组+actterm/C_SE 两段写触发 YX15·16 变位(COT=3)/恢复复归/YK11 两段正答/C_RD 读回 10.000 → **18/18 PASS**(104 链与锚点缺陷无关,验收窗口固件本身上先行闭环) | `20261012_B6_iec104_roundtrip_pre-fix_log.txt` | | 2026-10-12 | 同 PASS 固件(B7+fix)/ **PC 主站 2404 往返**(复测) | 同上全链 18/18 PASS——B7 `set_sealed`+持久化写路径下 C_SE→YX 联动仍成立(B5 遗留"104 YX 联动"腿闭环) | `20261012_B6_iec104_roundtrip_log.txt` | +| 2026-10-12 | 同 PASS 固件 / **B7 定值持久化 + 软压板 YK12 台架腿**(`test/host/iec104_master.py --b7-pre/--b7-post/--b7-mark/--b7-check`,中间 ST-LINK 复位) | pre **21/21**:C_SE 写 7.5+C_RD 回读、YK12 两段 OFF → 0.05 A 低定值**不动作**(保护退出)、YK12 ON → YX15/16 立即动作(COT=3)、收尾留压板退出;post **13/13**:**压板退出态跨复位保持**(开机日志 `global plate OUT -> protection disabled` + 低定值仍不动作)、重启后 YK12 ON 即动作(联动在位);mark/check **4/4+4/4**:**非默认定值 7.5 跨复位保持**(C_RD=7.500,与出厂默认可区分);开机日志两次 `[CFG] prot set loaded (/prot_set.bin)` | `20261012_B7_iec104_persist_log.txt` / `20261012_B7_persist_boot_log.txt` | ## 4. 关联 diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index e91a102a..c71b6763 100644 --- a/docs/算法/继电保护功能复现规划.md +++ b/docs/算法/继电保护功能复现规划.md @@ -4,7 +4,7 @@ > **参考来源**:`D:\Code\DTU\参考资料\huaiyuan\huaiyuan\Scatter_P_HV03.01_SV01.01\项目分析文档\04-算法与采样专题\ADC采集至数据使用全流程详解`(同专题另有《项目详细分析-交流采样与有效值计算》《傅氏算法详解》《项目详细分析-阶段6-继电器保护单元分析》)。 > **阅读前提**:先读 `docs/算法/傅氏算法详解.md`(算法原理)与 `docs/硬件平台/ADC通道映射说明.md`(采样通道权威口径)。 > **相关文档**:`docs/产品需求/产品需求设计文档.md`、`docs/任务规划/README.md`、`docs/内存管理/RAM使用分析与优化方案.md`。 -> **状态**:**P0 采样与相量底座已台架闭环(2026-10-11)**——L1 采集链路(B1,2026-10-10)、L1-6 采样有效性校验与 L2 相量层(`sample_ring` + `phasor`,57 项主机单测 + 台架 `@test` 含 `phasor(first)/phasor(hb)` 标记闭环)均已落地;**P1/P2 保护元件与定值模型软件侧完成(2026-10-11,`prot_set` + `prot_elm`,57 项主机单测)**;**B5 板端接线完成(2026-10-12)**——`protectTask`(20 ms 判据节拍 + L5-4 采样故障闭锁 + L5-1 定值校验和巡检,IWDG `TASK_WD_PROTECT` bit8,栈 512 words 静态链 872 B / 余 57%),判据结果经 B4 IEC104 遥信(YX15~23/31)上送;**B7 定值持久化 + 全局软压板 + 竞态收口完成(2026-10-12,代码腿;台架腿待窗口)**;**出口记录(L4)与标准源注入验收为下一步**(见 §7)。 +> **状态**:**P0 采样与相量底座已台架闭环(2026-10-11)**——L1 采集链路(B1,2026-10-10)、L1-6 采样有效性校验与 L2 相量层(`sample_ring` + `phasor`,57 项主机单测 + 台架 `@test` 含 `phasor(first)/phasor(hb)` 标记闭环)均已落地;**P1/P2 保护元件与定值模型软件侧完成(2026-10-11,`prot_set` + `prot_elm`,57 项主机单测)**;**B5 板端接线完成(2026-10-12)**——`protectTask`(20 ms 判据节拍 + L5-4 采样故障闭锁 + L5-1 定值校验和巡检,IWDG `TASK_WD_PROTECT` bit8,栈 512 words 静态链 872 B / 余 57%),判据结果经 B4 IEC104 遥信(YX15~23/31)上送;**B7 定值持久化 + 全局软压板 + 竞态收口完成(2026-10-12,含台架腿验证)**;**出口记录(L4)与标准源注入验收为下一步**(见 §7)。 --- @@ -469,7 +469,7 @@ | **P1** | 基础保护元件 | **V0.1 有效子集**:过流(A 相,`IA`)、过负荷(A 相)+ 定值模型;B/C 相过流**建接口不使能** | P0 | 标准源注入 A 相可正确动作 —— 🔶 **软件侧 2026-10-11 完成**(`prot_set` 定值模型 30 用例 + `prot_elm` 元件框架/过流三段/过负荷 27 用例,主机全绿);**板端接线已落地(B5,2026-10-12:protectTask + IWDG bit8 + 栈核算 + 104 YX 上送)**;标准源注入验收待做 | | **P2** | 电压/频率类保护 | 过压/欠压(`UA`)、过频/低频、零序过压(`UN`) | P0 | 电压/频率越限正确动作 —— 🔶 过压/欠压/零序过压随 P1 同批主机完成(同框架实例);**过频/低频待频率测量算法** | | **P3** | 异常检测与闭锁 | L5 自检闭锁、采样通道自检;三相类(涌流/PT·CT 断线/母线接地)**建接口不使能** | P1/P2 | 自检失败闭锁;未使能元件不误动 | -| **P4** | 出口、记录与定值集成 | L4 出口与记录、§5 定值模型落 cfg_file、UI 显示、上送 | P1 | 动作出口 + SOE 记录 + UI 显示闭环(**定值持久化 + 软压板 + 竞态收口 = B7 已完成 2026-10-12**,台架腿待窗口 🔴) | +| **P4** | 出口、记录与定值集成 | L4 出口与记录、§5 定值模型落 cfg_file、UI 显示、上送 | P1 | 动作出口 + SOE 记录 + UI 显示闭环(**定值持久化 + 软压板 + 竞态收口 = B7 完成 2026-10-12,台架腿已验 ✅**) | | **P5** | 方向/功率类(延后) | L3-13 方向元件等 | V0.2 硬件 / 子板计量 | 跨转换器相位一致后实现 | > ⚠️ **V0.1 硬件裁剪**(2026-10-10,详见 §1.6):V0.1 上只有 TPAFE 三路(`UA`/`UN`/`IA`)测量有效。故 **P0 骨架全做**(与通道无关),**P1/P2 只做有效通道子集**——A 相过流、A 相过负荷、过压/欠压、零序过压、过频/低频;**三相过流(B/C 相)、零序过流、方向/功率类、PT/CT 断线**依赖 V0.2 硬件(N-18 修复 + 中点偏置),本期**建接口不使能**。 @@ -606,5 +606,5 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5) | 2026-10-11 | **L1-6 采样有效性校验落地** | 新增 `App/algo/adc_health.c/h`(**纯逻辑判定层**,零平台依赖免桩单测):① 静默——两侧帧序号连续 ≥100 ms 无前进(电平位,可自愈;`adc_health_flags()` 为 L5-4 闭锁预留);② 丢帧——TPAFE 序号一次前进 >1 计 `tgap`(与 STM32 侧 `adc1_gap` 对称,边沿事件不告警——消费者超拍是已知现象,告警会淹没真故障);③ 单调性——序号倒退锁存位;④ 错误增量——FRSTDATA / HAL 错误回调 / STM32 停摆计数增量(事件位与锁存位**编号对齐**,消费者按位图"每类每次开机留痕一次")。`adc_task.c` 只做告警编排:严重事件/上升沿 `DBG_ERROR` + `SYSLOG_SELFTEST`("adc sampling fault"),下降沿 `DBG_INFO`,心跳行增 `tgap`。主机单测 `test/host/adc_health/` **31 用例全绿**(100 ms 门限两侧、tick 回绕、边沿语义、NULL 守卫、init 幂等;`adc-health-unit-test` 钩子登记)。台架 `@test` PASS:零 `[ERR]`(健康不误报)、`tgap=1→2` 与 `adc1_gap` 同步可见、`frames` 1000.0 Hz;证据 `boot_log_data/20261011_prod_adc_health_boot_log.txt`。⚠ **抬栈**:`adc_health_report`→`syslog_post` 控制台回显尾使 adcTask 静态最坏链 832→**1080 B**(512 words 余 968 B < 1024 B 底线)→ **512→640 words**,复测余 **1480 B / 57%**、堆 min_ever 7152→6640 B(AGENTS 任务表 / `docs/内存管理/RAM使用分析与优化方案.md` §2.3 已同步)。§3.1 L1-6 置 ✅ | | 2026-10-11 | **P1/P2 软件侧:定值模型 + 保护元件框架** | 新增 `App/algo/prot_set.c/h`(**定值模型**:Q10 定点与参考 2^10 口径一致;31 项元数据表**通讯地址逐项对照参考 `Comm/Pub/Const_CommSetPara.c`**——过流 Ⅰ/Ⅱ/Ⅲ = 0x8856~0x8861、过负荷 = 0x8871~0x8874、零序过压 = 0x888E~0x8890、过压/欠压沿用告警段 0x8027~0x802A;范围校验 + 整表装载 all-or-nothing + **sum32 正/反码封存自检闭锁**(参考 `dwTagSum/dwTagSumN` 模式,L5-1);⚠ 默认值/范围为**拟定**,参考 EEPROM 出厂表不在本仓库,待对照修订)+ `App/algo/prot_elm.c/h`(**元件框架**:通用"越限 + 返回系数滞回 + 定时限"核,数据驱动实例表 7 行 = OC1/OC2/OC3/OL(IA)+ OV/UV(UA)+ 3U0(UN);`prot_elm_eval()` 纯判据可主机单测,`prot_elm_run()` 为 phasor→测量薄适配(相量未就绪整拍跳过);定值闭锁 → 全元件复位)。主机单测 `test/host/prot_set/`(30 用例)+ `test/host/prot_elm/`(27 用例:1.01× 启动 / 100 ms 到点 / 滞回保持与释放 / 欠量方向 / 投退 / 闭锁联动 / 时基回绕)全绿,钩子 `prot-set-unit-test` / `prot-elm-unit-test` 登记。`@build` 0 错 0 警(**未接线 → 链接器整对象移除,零 Flash/RAM 足迹**);板端接线随 protectTask 立项(栈预算 + IWDG 门禁),标准源注入验收随其后。§3.3 L3-1/3/4/6 置 🔶、L3-2/5 注明框架就绪待通道/频率算法;§3.5 L5-1/2/4 置 🔶;§5.4 落实进度注 | | 2026-10-12 | **B5 板端接线:protectTask 立项落地** | 新增 `App/task/protect_task.c/h`(**纯编排**,判据仍在 `App/algo/`):20 ms 节拍三件事——① **L5-4 采样故障闭锁**:`adc_health_flags()` 电平位(TPAFE/STM32 stall + 序号倒退)命中 → `prot_elm_init()` 复位 + 本拍不 eval(stall 自愈自动恢复;锁存类事件位不闭锁——非"当前测量不可信");② **L5-1 定值校验和巡检**(每拍 `prot_set_selfcheck()`,31 项 sum32 开销可忽略;⚠ 与 104 定值写的竞态窗口 µs 级、同次写 seal 即清锁,如实登记,P4 定值持久化收口);③ `prot_elm_run()` + 动作位图边沿日志(`[PROT]`,V0.1 无出口 → 动作 = 遥信 + 日志)。**线程契约收口**:`prot_elm_request_reset()`(单字标志,任意上下文)——104 YK11 在 iec104Task 落请求、下一拍 eval 头部消费,杜绝与 protectTask eval 竞态(`iec104_pts.c` 改走此口);定值/元件初始化移入 `app_main_init`(内核前,phasor_init 之后)。**门禁(E-59 同款)**:`TASK_WD_PROTECT = 8` 入 `wd_required_mask()` 两分支(产品 `0xF7`→`0x1F7`、HW 层 `0xF5`→`0x1F5`,看门狗单测 39 断言同步);栈 **512 words**,`stack_report.py` 实测静态最坏链 **872 B / 余 1176 B / 57%**;**FreeRTOS 堆 48→56 KB**(`.ioc` L1 参数 + `FreeRTOSConfig.h` 同步,CCM 75.3%→87.9% < 92% 门禁,`RAM预算台账.md` §6 登记配额 48→56 KB)。任务手写于 `Src/freertos.c` USER CODE 区(Normal,V0.1 无出口不需 AboveNormal;§2.2 表已注"1 ms/高"为 P2 瞬时值口径)。单测 +1(TC-PE-010 复归请求:不当拍生效、下一拍消费,滞回保持区可区分复位与否)→ prot_elm 28 用例全绿。`@build` 0 错 0 警(Code=204348,ZI +8,196 = 堆 +8 KB);台架 `@test`(PROT 锚点 + `[STACK] protect` 水位 + 104 YX 联动)待做。§3.3 L3-1/3 注板端落地、§3.5 L5-4 置 ✅、§7 P1 里程碑更新 | -| 2026-10-12 | **B7 定值持久化 + 全局软压板 + 竞态收口(W1 任务卡)** | **定值模型增项** `PS_GLOBAL_EN`(全局软压板,枚举尾追加,编号不回收);**原子写**:`prot_set_set_sealed()` 影子区拷贝→改→重封→**单字交换活跃区**(双缓冲 +124 B 静态),`prot_set_selfcheck()` 改 seqlock 式复核(封存和两读不一致 = 提交撞见 → 本轮跳过)——B5 登记的"104 写 vs 巡检"µs 级误锁窗口就此消除(§3.5 L5-1 注收口)。**持久化**:新增 `App/cfg/prot_set_store.c/h`(双端注册 + 模拟器豁免点名)——blob = magic`PSET`+版本+计数+值区+sum32 正/反码对(144 B),`/prot_set.bin` 走 `cfg_store_write_atomic`(临时文件+rename,掉电安全);**写路径** = C_SE/YK12 执行段置脏 → iec104Task `dirty_peek` 投递 `SYS_EVT_PROT_SET_SAVE`(事件位 bit7)→ defaultTask(配置引擎属主)落盘,写失败脏回置 = 下轮重试;**装载** = storage_bring_up 在 STORAGE_READY 前整表原子 parse(损坏/越界/版本换代 → 拒绝保出厂默认 + 自检留痕 `prot set corrupt`;文件缺失 = 首启正常静默)。**YK12 转真**:`iec104_pts.c` 两段式(选择段校验 DPC、执行段 set_sealed),protectTask 下一拍读退出态 → 复位元件 + 停判据(`global plate OUT/IN` 边沿日志);本地定值项 `comm_addr=0` 显式不可寻址(防 IOA=0 误命中)。单测:prot_set 63 断言(+33:软压板/原子写/脏握手/blob 往返/坏 magic/截断/坏版本/**伪造自洽越界**对抗样本)、iec104 94 断言(+7:YK12 两段转真/置脏/本地项 C_RD EVI)。`@build` 0 错 0 警(Code=205500 +1152 B,ZI +280 = 双缓冲+blob 缓冲,`ram_baseline` 已刷)。台架腿(104 C_SE 写→断电重启→定值保持 + YK12 联动 YX)待窗口 🔴 | +| 2026-10-12 | **B7 定值持久化 + 全局软压板 + 竞态收口(W1 任务卡)** | **定值模型增项** `PS_GLOBAL_EN`(全局软压板,枚举尾追加,编号不回收);**原子写**:`prot_set_set_sealed()` 影子区拷贝→改→重封→**单字交换活跃区**(双缓冲 +124 B 静态),`prot_set_selfcheck()` 改 seqlock 式复核(封存和两读不一致 = 提交撞见 → 本轮跳过)——B5 登记的"104 写 vs 巡检"µs 级误锁窗口就此消除(§3.5 L5-1 注收口)。**持久化**:新增 `App/cfg/prot_set_store.c/h`(双端注册 + 模拟器豁免点名)——blob = magic`PSET`+版本+计数+值区+sum32 正/反码对(144 B),`/prot_set.bin` 走 `cfg_store_write_atomic`(临时文件+rename,掉电安全);**写路径** = C_SE/YK12 执行段置脏 → iec104Task `dirty_peek` 投递 `SYS_EVT_PROT_SET_SAVE`(事件位 bit7)→ defaultTask(配置引擎属主)落盘,写失败脏回置 = 下轮重试;**装载** = storage_bring_up 在 STORAGE_READY 前整表原子 parse(损坏/越界/版本换代 → 拒绝保出厂默认 + 自检留痕 `prot set corrupt`;文件缺失 = 首启正常静默)。**YK12 转真**:`iec104_pts.c` 两段式(选择段校验 DPC、执行段 set_sealed),protectTask 下一拍读退出态 → 复位元件 + 停判据(`global plate OUT/IN` 边沿日志);本地定值项 `comm_addr=0` 显式不可寻址(防 IOA=0 误命中)。单测:prot_set 63 断言(+33:软压板/原子写/脏握手/blob 往返/坏 magic/截断/坏版本/**伪造自洽越界**对抗样本)、iec104 94 断言(+7:YK12 两段转真/置脏/本地项 C_RD EVI)。`@build` 0 错 0 警(Code=205500 +1152 B,ZI +280 = 双缓冲+blob 缓冲,`ram_baseline` 已刷)。**台架腿完成(2026-10-12)**:`@test` PASS + PC 主站 `test/host/iec104_master.py --b7-pre` **21/21**(YK12 两段 OFF→0.05 A 低定值不动作 / ON→YX15·16 即动作,C_SE→C_RD 回读)、`--b7-post` **13/13**(**压板退出态跨复位保持**:开机日志 `global plate OUT -> protection disabled` + 低定值仍不动作、重启后 YK12 ON 联动在位)、`--b7-mark/--b7-check` **4/4+4/4**(**非默认定值 7.5 跨复位保持**,C_RD=7.500,与出厂默认可区分);开机日志两次 `[CFG] prot set loaded (/prot_set.bin)`;证据 `docs/测试说明/boot_log_data/`(20261012_B7_* 两份) | | 2026-10-12 | **B6 台架 `@test` 闭环复测(B4/B5 验收窗口,W1 任务卡)** | 首跑(HEAD `d3107f3`)**FAIL**:`protect task start` 锚点行字节级交错损坏(`st[art: cycle=220ms elm=70`,两次开机同形复现)= protectTask 启动行违反控制台写者注册前门控纪律(B5 台架腿未跑故未暴露,机理与实证见 `docs/子系统设计/控制台单写者日志设计说明.md` §11 2026-10-12 行);其余 8 Required / 零 `[ERR]` / 锚点×1 / 回读一致全过。**修复** = 启动锚点行改 `dbg_console_writer_ready()` 首拍补打(adcTask 首帧门控同款,+16 B)。**复测 PASS**(B7 `1fe163b`+fix):锚点行完好(+577 ms,attach 后);**首采水位** `protect` 828/2048(free_min 1220,59%)、`iec104` 424/2560(83%)、新 56 KB 堆 free=17936 **min_ever=10000**(>3072 告警线零告警,**N-33 抬栈 min_ever 背书就绪**);采样闭锁不误报。**PC 主站往返**:新增 `test/host/iec104_master.py`(纯标准库主站客户端)STARTDT→总召四组+actterm→C_SE 两段写临时压低 OC1 定值**确定性**触发 YX15·16 变位(COT=3)→恢复复归→YK11 两段正答→C_RD 读回 10.000,**18/18 PASS**(`d3107f3` 与 B7+fix 两版固件各一轮),串口侧 `[I104] accepted`/`[PROT] elm OC1-IA` 边沿/YK11 复位→UV-UA +10 s 重返联一致。证据 `docs/测试说明/boot_log_data/20261012_B6_*`(含缺陷复现 MISS 快照)。B5 行"台架 `@test` 待做"遗留**闭环**;B7 台架腿的 C_SE 写路径已随本窗验证(断电重启保持 + YK12→YX 仍待窗) | diff --git a/test/host/README.md b/test/host/README.md index 871eb4e9..f9929512 100644 --- a/test/host/README.md +++ b/test/host/README.md @@ -22,7 +22,7 @@ | `ftp_speed_test.py` | FTP 传输速度测试 | | `ftp_capture.py` | FTP 流量抓取 | | `ftp_regression.py` | FTP 回归套件 | -| `iec104_master.py` | **IEC 60870-5-104 主站客户端(B6)**:连设备 :2404 跑 STARTDT → 总召(actcon/四组背景扫描/actterm)→ 经 C_SE 两段写临时压低 OC1 定值确定性触发 YX16 变位(COT=3)→ 恢复 → YK11 两段式 → C_RD 读回;纯标准库,输出纯 ASCII 可直接重定向归档为台架证据(判据 exit 0/1/2) | +| `iec104_master.py` | **IEC 60870-5-104 主站客户端(B6/B7)**:连设备 :2404 跑 STARTDT → 总召(actcon/四组背景扫描/actterm)→ 经 C_SE 两段写临时压低 OC1 定值确定性触发 YX16 变位(COT=3)→ 恢复 → YK11 两段式 → C_RD 读回;**B7 持久化模式 `--b7-pre/--b7-post/--b7-mark/--b7-check`**(中间 ST-LINK 复位):YK12 两段投退→保护退出/联动、定值与压板态跨复位保持(含非默认 7.5 往返);纯标准库,输出纯 ASCII 可直接重定向归档为台架证据(判据 exit 0/1/2) | ### 时间 / 时延 diff --git a/test/host/iec104_master.py b/test/host/iec104_master.py index f236fdbb..168a0d14 100644 --- a/test/host/iec104_master.py +++ b/test/host/iec104_master.py @@ -29,6 +29,19 @@ round-trip log as bench evidence). Usage: python iec104_master.py [--ip 192.168.1.100] [--port 2404] [--addr 0x8858] [--low 0.05] [--restore 10.0] + +B7 bench leg modes (setpoint persistence + global soft plate, task card +docs/任务规划/W1-采集保护收尾.md B7; firmware side App/cfg/prot_set_store.c): + --b7-pre : before reset: mark setpoint 7.5 (C_SE+C_RD), YK12 OFF (two-step) + -> low setpoint 0.05 must NOT trip YX16 (plate OUT disables + protection); YK12 ON -> YX16 trips (linkage); restore 10.0; + leave plate OUT (persistence proof), wait for dirty->save. + --b7-post: after reset: C_RD 10.0 (setpoint persisted); low setpoint 0.05 + still must NOT trip (plate OUT persisted); YK12 ON -> YX16 + trips (linkage after reboot); restore 10.0, leave plate IN. + --b7-mark / --b7-check [--mark 7.5]: write a distinctive NON-default + setpoint (save), reset, read it back (literal "setpoint + hold" proof, distinguishable from factory default), restore. """ import argparse import collections @@ -263,6 +276,145 @@ def actcon_of(type_id, want_pn=None): and (want_pn is None or e[1][2] == want_pn)) +def spont(ioa, val): + return lambda e: (e[0] == "yx" and e[1][0] == ioa + and e[1][1] == val and e[1][3] == COT_SPONT) + + +def gi_baseline(m, ck, tag): + """General interrogation; wait for actterm (baseline YX state loaded).""" + m.send_i(asdu(T_C_IC_NA_1, 1, COT_ACT, 0, ioa=0, payload=bytes([RQT_GROUP1])), + "I C_IC act (%s)" % tag) + ck.add("gi_actterm_%s" % tag, m.wait_event( + lambda e: (e[0] == "asdu" and e[1][0] == T_C_IC_NA_1 + and e[1][1] == COT_ACTTERM), 15.0) is not None) + + +def se_write(m, ck, addr, val, tag): + """Two-step C_SE_NC_1 write (select then execute), both must actcon.""" + pl = struct.pack(" second GI background scan") + gi_baseline(m, ck, "off-scan") + ck.add(name, m.yx.get(16) == (0, False), "via GI scan, yx16=%r" + % (m.yx.get(16),)) + + +def b7_pre(m, ck, args): + """B7 phase 1 (before reset): plate linkage + mark setpoint for save.""" + addr = int(args.addr, 0) + gi_baseline(m, ck, "pre") + v16 = m.yx.get(16) + ck.add("baseline_yx16_off", v16 is not None and v16 == (0, False), + "yx16=%r" % (v16,)) + + se_write(m, ck, addr, 7.5, "mark") + rd_set(m, ck, addr, 7.5, "rd_mark_7.5") + + yk_two_step(m, ck, 0x600B, 0x81, 0x01, "yk12_off") # plate OUT + se_write(m, ck, addr, args.low, "low") # 0.05 A + m.events.clear() + ck.add("plate_out_no_trip", m.wait_event(spont(16, 1), 3.0) is None, + "YX16 must stay OFF while plate OUT (protection disabled)") + rd_set(m, ck, addr, args.low, "rd_low_0.05") # setpoint still writable + + yk_two_step(m, ck, 0x600B, 0x82, 0x02, "yk12_on") # plate IN -> linkage + m.events.clear() + ck.add("spont_yx16_ON", m.wait_event(spont(16, 1), 5.0) is not None) + ck.add("spont_yx15_ON", m.wait_event(spont(15, 1), 3.0) is not None) + + se_write(m, ck, addr, args.restore, "restore") # back to 10.0 + yx16_off_confirmed(m, ck, "yx16_off_after_restore") + + yk_two_step(m, ck, 0x600B, 0x81, 0x01, "yk12_off_final") # leave OUT + log("wait 2s: dirty -> SYS_EVT_PROT_SET_SAVE -> /prot_set.bin") + time.sleep(2.0) + + +def b7_post(m, ck, args): + """B7 phase 2 (after reset): persistence + linkage after reboot.""" + addr = int(args.addr, 0) + gi_baseline(m, ck, "post") + v16 = m.yx.get(16) + ck.add("baseline_yx16_off", v16 is not None and v16 == (0, False), + "yx16=%r (plate OUT after reboot -> protection disabled)" % (v16,)) + + rd_set(m, ck, addr, args.restore, "persist_rd_10.0") # setpoint persisted + + se_write(m, ck, addr, args.low, "low") + m.events.clear() + ck.add("plate_out_persisted_no_trip", + m.wait_event(spont(16, 1), 3.0) is None, + "plate OUT state survived the reset") + + yk_two_step(m, ck, 0x600B, 0x82, 0x02, "yk12_on") # linkage after reboot + m.events.clear() + ck.add("spont_yx16_ON_after_reboot", + m.wait_event(spont(16, 1), 5.0) is not None) + + se_write(m, ck, addr, args.restore, "restore") + yx16_off_confirmed(m, ck, "yx16_off_final") + log("wait 1s: final dirty -> save, leave plate IN") + time.sleep(1.0) + + +def b7_mark(m, ck, args): + """B7 distinctive-value mark: write non-default setpoint, let it save.""" + addr = int(args.addr, 0) + se_write(m, ck, addr, args.mark, "distinct") + rd_set(m, ck, addr, args.mark, "rd_distinct") + log("wait 1.5s: dirty -> save (/prot_set.bin)") + time.sleep(1.5) + + +def b7_check(m, ck, args): + """B7 distinctive-value check after reset: must read back non-default, + then restore default so the bench is left in a clean state.""" + addr = int(args.addr, 0) + rd_set(m, ck, addr, args.mark, "persist_distinct_after_reset") + se_write(m, ck, addr, args.restore, "restore") + log("wait 1s: restore saved, bench left at defaults") + time.sleep(1.0) + + def main(): ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) ap.add_argument("--ip", default="192.168.1.100") @@ -273,12 +425,24 @@ def main(): help="temporary low OC1 setting (A) to force pickup") ap.add_argument("--restore", type=float, default=10.0, help="OC1 default setting to restore (A)") + ap.add_argument("--b7-pre", action="store_true", + help="B7 phase 1 (before reset) instead of B6 flow") + ap.add_argument("--b7-post", action="store_true", + help="B7 phase 2 (after reset) instead of B6 flow") + ap.add_argument("--b7-mark", action="store_true", + help="B7 write distinctive non-default setpoint (pre-reset)") + ap.add_argument("--b7-check", action="store_true", + help="B7 verify distinctive setpoint survived reset, restore") + ap.add_argument("--mark", type=float, default=7.5, + help="distinctive setpoint value (A), must be non-default") args = ap.parse_args() addr = int(args.addr, 0) + b7_mode = ("pre" if args.b7_pre else "post" if args.b7_post else + "mark" if args.b7_mark else "check" if args.b7_check else None) ck = Checks() - log("iec104 master client -> %s:%d (COV trigger: write 0x%X %.2f then " - "restore %.2f)" % (args.ip, args.port, addr, args.low, args.restore)) + log("iec104 master client -> %s:%d mode=%s" + % (args.ip, args.port, b7_mode or "b6")) try: m = Master(args.ip, args.port) @@ -293,6 +457,22 @@ def main(): ck.add("startdt_con", m.wait_event( lambda e: e[0] == "startdt_con", 5.0) is not None) + if b7_mode is not None: + if b7_mode == "pre": + b7_pre(m, ck, args) + elif b7_mode == "post": + b7_post(m, ck, args) + elif b7_mode == "mark": + b7_mark(m, ck, args) + else: + b7_check(m, ck, args) + m.close() + rc = 0 if all(ok for _, ok, _ in ck.items) else 1 + n_ok = sum(1 for _, ok, _ in ck.items) + log("SUMMARY: %d/%d checks PASS -> %s" + % (n_ok, len(ck.items), "PASS" if rc == 0 else "FAIL")) + return rc + # 2. first general interrogation m.send_i(asdu(T_C_IC_NA_1, 1, COT_ACT, 0, ioa=0, payload=bytes([RQT_GROUP1])),