diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8aceebb4..3c26255e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -352,7 +352,18 @@ repos: name: 保护元件框架单测(主机侧) entry: python test/host/prot_elm/run_unit_test.py language: system - files: ^(App/algo/prot_elm\.(c|h)|App/algo/prot_set\.(c|h)|App/algo/phasor\.(c|h)|test/host/prot_elm/.*|test/host/common/unit_test_harness\.py)$ + files: ^(App/algo/prot_elm\.(c|h)|App/algo/prot_set\.(c|h)|App/algo/phasor\.(c|h)|App/algo/freq\.(c|h)|test/host/prot_elm/.*|test/host/common/unit_test_harness\.py)$ + pass_filenames: false + + # 7j2) 频率测量层(L2.5,B8)主机侧单元测试(2026-10-12 加) + # 自适应窗测频(K_eff 对齐负序泄漏纹波周期)的 J1~J6 判据 + # (扫频/噪声/收敛/阶跃/浮空 valid=0/钳制恢复)是纯合成信号 + # 可穷举的精度契约;板端无标准源照不出来(规划 §3.3 L3-5)。 + - id: freq-unit-test + name: 频率测量单测(主机侧) + entry: python test/host/freq/run_unit_test.py + language: system + files: ^(App/algo/freq\.(c|h)|App/algo/phasor\.(c|h)|App/algo/sample_ring\.(c|h)|test/host/freq/.*|test/host/common/unit_test_harness\.py)$ pass_filenames: false # 7k) SHA-256 主机侧单元测试(2026-10-11 加,N-19 FTP 鉴权) @@ -388,7 +399,7 @@ repos: name: IEC104 协议栈单测(主机侧) entry: python test/host/iec104/run_unit_test.py language: system - files: ^(App/protocol/iec104/iec104_(asdu|pts|link)\.(c|h)|App/algo/(prot_set|prot_elm|phasor|sample_ring|adc_input)\.(c|h)|test/host/iec104/.*|test/host/common/unit_test_harness\.py)$ + files: ^(App/protocol/iec104/iec104_(asdu|pts|link)\.(c|h)|App/algo/(prot_set|prot_elm|phasor|sample_ring|adc_input|freq)\.(c|h)|test/host/iec104/.*|test/host/common/unit_test_harness\.py)$ pass_filenames: false # 8) 测试套件开关门禁(2026-10-01 加) diff --git a/AGENTS.md b/AGENTS.md index 5d264845..8b44b6b0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -46,7 +46,7 @@ - netTask:`net_stack_bring_up`(配置已由 defaultTask 在屏障前加载,本任务只读 RAM 副本)→ 置 NET_READY → 循环 `net_poll` + `net_process_messages`;消费 `SYS_EVT_NET_RECONFIG` → 按网络代次号重建监听(新 IP 免重启生效) - defaultTask:`f_mount` forced(无卷自动 `f_mkfs`;挂载后卷健康探针,FAT 区陈旧时自愈重格式化)→ 加载网络配置 → STORAGE_READY → LED 闪烁;同时是 syslog(`/log/run.log`·`selftest.log`,定长 64B 记录)的**唯一写者**与**配置引擎属主**(netTask/uiTask 不得直接触碰配置引擎) - adcTask:**纯消费者**——每拍 `adc_input_poll()`(TPAFE 原子快照 + 消费一帧 STM32 ADC1 DMA 双缓冲),只取数不做保护运算;**节拍与唤醒同源**(TIM3 ISR 内触发 CONVST + 同一更新事件经 TRGO 触发 ADC1,并调 `adc_tick_irq_notify()` 置位,任务 `osThreadFlagsWait` 等唤醒)。⚠ ISR 侧**只能**走 `adc_tick_irq_notify()`(内含"消费者就绪"门,TIM3 比调度器早 ≈100 ms 启动);手写于 `Src/freertos.c` 的 `USER CODE` 区,纳入 IWDG `required_mask`(`TASK_WD_ADC`) -- **采集与算法层(L1/L2/L3)落在 `App/algo/`**:`adc_input`/`adc_health` = L1,`sample_ring`/`phasor` = L2,`prot_set`/`prot_elm` = L3。板端消费者 = **protectTask**(B5,2026-10-12):20 ms 节拍 `prot_elm_run()` + L5-4 采样故障闭锁 + L5-1 定值校验和巡检;跨上下文复归(104 YK11)经 `prot_elm_request_reset()` 落请求。纳入 IWDG `required_mask`(`TASK_WD_PROTECT`,产品 `0x1F7`)。→ `App/algo/README.md` +- **采集与算法层(L1/L2/L3)落在 `App/algo/`**:`adc_input`/`adc_health` = L1,`sample_ring`/`phasor` = L2,`freq` = L2.5 测频(B8,自适应窗),`prot_set`/`prot_elm` = L3。板端消费者 = **protectTask**(B5,2026-10-12):20 ms 节拍 `prot_elm_run()` + L5-4 采样故障闭锁 + L5-1 定值校验和巡检;跨上下文复归(104 YK11)经 `prot_elm_request_reset()` 落请求。纳入 IWDG `required_mask`(`TASK_WD_PROTECT`,产品 `0x1F7`)。→ `App/algo/README.md` - 全景 → `docs/架构设计/项目架构总览.md`;启动时序与内核前模式 → `docs/架构设计/项目启动顺序管理.md` @@ -89,7 +89,7 @@ ## 提交门禁(pre-commit) -- 任一失败即拦截,共 **31 个钩子**(逐个详解 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 13 个(`-unit-test` 后缀)+ `test-suite-switch` + `registration-check`(双端注册反向校验,N-23)+ `mem-budget`(RAM 92% 预算门禁,N-27) +- 任一失败即拦截,共 **32 个钩子**(逐个详解 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 14 个(`-unit-test` 后缀)+ `test-suite-switch` + `registration-check`(双端注册反向校验,N-23)+ `mem-budget`(RAM 92% 预算门禁,N-27) - **范围 = 项目代码**:第三方(`Lib/`、`Middlewares/`、CMSIS、HAL、`lftpd`、`dhara`、`MDK-ARM`)排除;`cppcheck`/`coding-standard` 另排除 `test/`,规范检查再排除 CubeMX 生成的 `Src/`/`Inc/`。**`simulator/` 已纳入全部钩子**(2026-10-11)——生成物只靠 `.gitignore` 挡,**不在 `exclude` 里写目录名**(教训见 `docs/代码规范/pre-commit使用说明.md` §5.5) - ⚠ **pre-commit 4.x 已移除 `always: true`**(实测对 `local` 钩子只告警 `Unexpected key(s)` 并跳过)→ 想"总是跑"的钩子**必须让 `files:` 覆盖到所有会触发它的文件**,没有兜底开关 - **改写型钩子(`trailing-whitespace` + `end-of-file-fixer`)豁免 CubeMX/Keil 生成文件**(配置里 YAML 锚点 `&cubemx-generated`);⚠ **只读检查不受影响**:`cppcheck` / 乱码 / `cubemx-survival` / `task-table` / `mem-numbers` 仍覆盖 `Src/`、`Inc/` @@ -172,7 +172,7 @@ | ADC 采样节拍 / 通道映射 / V0.1 硬件缺陷 | `docs/子系统设计/ADC采样节拍设计说明.md`、`docs/硬件平台/ADC通道映射说明.md` | | 存储栈(FatFs / dhara / lftpd / 两条 FatFs 陷阱) | `docs/架构设计/STM32F4-Base存储架构说明.md` | | RAM / 栈预算 / 容量台账 | `docs/内存管理/RAM使用分析与优化方案.md`、`内存内容分配策略.md` | -| pre-commit 31 个钩子逐个详解 | `docs/代码规范/pre-commit使用说明.md` | +| pre-commit 32 个钩子逐个详解 | `docs/代码规范/pre-commit使用说明.md` | | 代码规范 V1.0 / cppcheck 口径 | `docs/代码规范/嵌入式C语言代码规范_V1.0.md`、`cppcheck使用说明.md` | | 自动化测试 / 实机测试 / 板级套件 | `docs/测试说明/自动化测试流程.md`、`实机测试实施指南.md`、`board-test-suite` skill | | 烧录与复位语义 | `docs/测试说明/ST-LINK_CLI_复位使用说明.md` | diff --git a/docs/代码规范/pre-commit使用说明.md b/docs/代码规范/pre-commit使用说明.md index af3a4732..be17c617 100644 --- a/docs/代码规范/pre-commit使用说明.md +++ b/docs/代码规范/pre-commit使用说明.md @@ -396,6 +396,17 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法 | **为什么需要** | 板端复现这些分支要真主站 + 真等待(t1=15 s、k 窗满要发满 12 帧);link 层 tick 注入 + pts vtable 抽象就是为 L0.5 毫秒级穷举设计;数据源依赖进触发面——测试直接 `#include` 这些生产源,签名变了立刻暴露 | | **运行器** | `test/host/iec104/run_unit_test.py`(MSVC `cl.exe`,L0.5) | +### 2.21 freq-unit-test — 频率测量层主机侧单测(2026-10-12 加,B8) + +| 项 | 说明 | +|---|---| +| **触发条件** | `App/algo/freq.*`、`App/algo/phasor.*`、`App/algo/sample_ring.*`、`test/host/freq/**` 或 `test/host/common/unit_test_harness.py` 变动 | +| **处理方式** | **阻止提交**(单测失败即拦截) | +| **被测对象** | `App/algo/freq.c/h`(L2.5 测频:共轭乘积相位增量 + 解缠绕 + 自适应窗长 K_eff 对齐负序泄漏纹波周期 + 假值钳制带 35~65 Hz + 幅值门 valid=0)——纯合成信号、零 I/O | +| **用例** | 46 断言:J1 扫频 45~55 Hz ≤0.02 Hz(实测 0.0101)/ J2 噪声 1% ≤0.10 Hz / J3 启动收敛 ≤40 ms / J4 阶跃 50→51 ≤120 ms(精度优先于响应,见 `App/algo/README.md` §3.7)/ J5 浮空 valid=0 不发散 / J6 双跳变钳制恢复 | +| **为什么需要** | 测频精度是 OF/UF 判据的地基;板端无标准源照不出来(规划 §3.3 L3-5 注入验收归 B10);定长窗负序泄漏纹波(0.317 Hz)这类坑只有扫频合成信号才能暴露 | +| **运行器** | `test/host/freq/run_unit_test.py`(MSVC `cl.exe`,L0.5) | + --- ## 3. 日常工作流 @@ -523,7 +534,7 @@ $env:PATH = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Env | 文件 | 位置 | 说明 | |---|---|---| -| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(**31 个钩子**,2026-10-12 清点;本文 §2 详解非单测类——N-19 新增的两个单测钩子见 §2.16/§2.17,N-23 双端注册反向校验见 §2.18,N-27 RAM 预算门禁见 §2.19,B4 IEC104 协议栈单测见 §2.20,其余主机侧单测见 AGENTS.md 门禁条;主机侧单测共 13 个) | +| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(**32 个钩子**,2026-10-12 清点;本文 §2 详解非单测类——N-19 新增的两个单测钩子见 §2.16/§2.17,N-23 双端注册反向校验见 §2.18,N-27 RAM 预算门禁见 §2.19,B4 IEC104 协议栈单测见 §2.20,B8 频率测量单测见 §2.21,其余主机侧单测见 AGENTS.md 门禁条;主机侧单测共 14 个) | | `.gitlint` | 仓库根 | gitlint 规则(宽松,兼容中文) | | `.cubemx_survival_baseline.json` | 仓库根 | CubeMX 易失定制基线(哈希;`--write` 重建) | | `scripts/check_mojibake.py` | scripts/ | U+FFFD 检测脚本 | diff --git a/docs/任务规划/README.md b/docs/任务规划/README.md index 9ec9719b..1d7e004f 100644 --- a/docs/任务规划/README.md +++ b/docs/任务规划/README.md @@ -103,8 +103,8 @@ ### 2.1 顺序一图 ``` -W1 收尾 台架道: B6✅→N-33✅(M1 ✅ 2026-10-12) ∥ 代码道: B7✅→{B8∥B9}(M2) → B10 送检(M3, Fixed Date) 详表 W1-采集保护收尾.md - (B4 IEC104 ✅ / B5 protectTask ✅ / B6 台架复测 ✅ / B7 定值持久化+软压板 ✅ / N-33 栈收口 ✅ 2026-10-12 已销项;台账三件套 ✅) +W1 收尾 台架道: B6✅→N-33✅(M1 ✅ 2026-10-12) ∥ 代码道: B7✅→B8✅→B9(M2) → B10 送检(M3, Fixed Date) 详表 W1-采集保护收尾.md + (B4 IEC104 ✅ / B5 protectTask ✅ / B6 台架复测 ✅ / B7 定值持久化+软压板 ✅ / N-33 栈收口 ✅ / B8 频率保护 ✅ 2026-10-12 已销项;台账三件套 ✅) ↓ W2 数据 N-21 dhara is_free/copy(配主机侧移植层测试) ↓ diff --git a/docs/任务规划/W1-采集保护收尾.md b/docs/任务规划/W1-采集保护收尾.md index fc75d42b..d6468b36 100644 --- a/docs/任务规划/W1-采集保护收尾.md +++ b/docs/任务规划/W1-采集保护收尾.md @@ -19,7 +19,10 @@ B7 证据 = `../子系统设计/IEC104上行设计说明.md` §3.4 + boot_log_da (定值/压板跨复位保持 + YK12→YX 联动,主站 42+8 判据 + 主机 63+94 断言); **N-33 已销项(2026-10-12)**——证据 = `../内存管理/RAM预算台账.md` §6 + `../内存管理/RAM使用分析与优化方案.md` §2.3(抬栈 +1536 B,`stack_report` 9 任务 0 FAIL, -`@test` 复测 PASS,min_ever 实测 8464 与预算吻合)。 +`@test` 复测 PASS,min_ever 实测 8464 与预算吻合); +**B8 已销项(2026-10-12,merge `37f74f0`)**——证据 = `../算法/继电保护功能复现规划.md` +变更记录 B8 行 + `App/algo/README.md` §3.7(自适应窗测频 J1~J6 判据,扫频最坏 0.0101 Hz; +定值 32→40、blob VER 1→2、prot_elm 7→9;freq 46 + prot_set 90 + prot_elm 47 断言)。 **本波目标(用户决定 2026-10-12)**:把"采集→相量→保护→上送"链路从"代码落地"收口到 **"台架闭环 + 功能面完整 + 可送检"**。规划方式 = **里程碑(时间驱动、判据退出)× @@ -30,7 +33,7 @@ B7 证据 = `../子系统设计/IEC104上行设计说明.md` §3.4 + boot_log_da | 里程碑 | 退出判据(全部满足才算完成,随后销项) | 服务分类 | |---|---|---| | **M1 台架闭环 ✅ 达成(2026-10-12)** | B6 `@test` PASS ✅ + N-33 `stack_report` 9 任务 0 FAIL ✅ + `@test` 复测腿 PASS ✅——判据全满足 | Standard | -| **M2 功能面完整** | B8/B9 全部合入 + `ci_local` 全绿 + PC 客户端往返含"SOE 时标"("定值掉电保持" ✅ B7 台架 2026-10-12) | Standard | +| **M2 功能面完整** | B8 ✅ 已合入(2026-10-12)+ B9 合入(台架腿进行中)+ `ci_local` 全绿 + PC 客户端往返含"SOE 时标"("定值掉电保持" ✅ B7 台架 2026-10-12) | Standard | | **M3 可送检** | B10 注入判据 + 第三方主站全流程通过,证据归档 | **Fixed Date**(送检窗口一到全道让路;窗口前 2 日特性冻结,只修稳定——Zephyr RC 语义) | ## 3. 并行道(台架 = 约束资源永不空转;代码道 = worktree 并行、绿即合) @@ -38,12 +41,10 @@ B7 证据 = `../子系统设计/IEC104上行设计说明.md` §3.4 + boot_log_da ```mermaid graph LR subgraph CL[代码道 🟢 worktree 并行 绿即合] - B8[B8 频率保护] B9[B9 动作记录/SOE 🔴含台架腿] end M1((M1 ✅)) --> B10[B10 送检窗口 🟡 Fixed Date] - B8 --> M2((M2)) - B9 --> M2 + B9 --> M2((M2)) M2 --> B10 ``` @@ -51,18 +52,17 @@ graph LR > 资源图例:🔴 台架(COM6/ST-LINK,`bench.lock` 独占)· 🟡 外部(标准源/第三方主站)· 🟢 纯软件(可并行)。 > 状态:⬜ 未开始 · 🟦 进行中(销项行直接删除,见 `docs/任务规划/README.md` §3 维护约定)。 -> ⚠ **写范围相交**:B7 已先合入(2026-10-12,`App/algo/prot_set.*` 与 `App/protocol/iec104/iec104_pts.c` 定值段已释放);B8∥B9 写范围互不相交,可直接并行。 +> ⚠ **写范围**:B7/B8 已先合入(2026-10-12,`App/algo/` 全部与 `App/cfg/prot_set_store.*` 已释放);B9 生产码写范围与主干无冲突面,但 `test/host/iec104/iec104_test.c` 与 B8 有交集 → B9 sync 时两边叠加手工合并(B8 的 freq include + 断言 与 B9 的 M_SP_TB_1 用例共存)。 | 序 | 任务 | DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 | 出处 | |---|---|---|---|---|---|---|---| -| **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.*`(定值行) | 🟦(worktree `B8-freq-protection`,方案已审:相位解缠绕微分 + 8 定值行 + OF/UF 实例) | 保护规划 §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` | 🟦(worktree `B9-soe-record`,方案已审:/log/soe.log 64 B 定长 + 队列异步 + 自发 M_SP_TB_1) | 保护规划 §3.4 L4、保护规划 §7 P4;`../子系统设计/IEC104上行设计说明.md` §3.2 注 | +| **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` | 🟦(worktree `B9-soe-record`,代码+首轮台架腿已完成;待 sync 追平 B8/N33 后重跑台架腿再合并) | 保护规划 §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 | ## 5. 并行规则(执行层映射 → `../环境与部署/并行任务工作树方案.md` §7.3) > ① **WIP ≤ 2**:每道最多 1 个进行中(台架道 + 代码道各一),先完再开(Kanban); -> ② worktree 分支**存活 ≤2 天、绿即合**(`done` 预演合并;31 钩子强门禁是并行安全底座); +> ② worktree 分支**存活 ≤2 天、绿即合**(`done` 预演合并;32 钩子强门禁是并行安全底座); > ③ 写范围相交必须声明合并次序(见 §4 表注); > ④ **里程碑不拖延、功能顺延下一轮**(时间驱动,Zephyr 发布语义); > ⑤ 台架道永不空转:代码道在跑时,为下一个台架任务备料(约束优先,TOC)。 diff --git a/docs/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index f8095a5e..1a0263a3 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -36,10 +36,10 @@ | 区域 | 用量 | 容量 | 占比 | |---|---|---|---| -| ER_IROM1 | 223,724 B (218.48 KB) | 1,048,576 B (1024 KB) | 21.3% | -| RW_IRAM1 | 96,144 B (93.89 KB) | 131,072 B (128 KB) | 73.4% | +| ER_IROM1 | 225,936 B (220.64 KB) | 1,048,576 B (1024 KB) | 21.5% | +| RW_IRAM1 | 96,776 B (94.51 KB) | 131,072 B (128 KB) | 73.8% | | RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% | -| **Flash (ROM 合计)** | **224,772 B (219.5 KB)** | 1,048,576 B (1024 KB) | **21.4%** | +| **Flash (ROM 合计)** | **227,016 B (221.7 KB)** | 1,048,576 B (1024 KB) | **21.6%** | 各区的容量与常量来源: diff --git a/docs/内存管理/RAM预算台账.md b/docs/内存管理/RAM预算台账.md index a7841c3b..27c57cf0 100644 --- a/docs/内存管理/RAM预算台账.md +++ b/docs/内存管理/RAM预算台账.md @@ -15,10 +15,10 @@ | 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) | |---|---|---|---|---| -| ER_IROM1 (Flash) | 223,724 B | 1,048,576 B | 21.3% | 参考 | +| ER_IROM1 (Flash) | 225,936 B | 1,048,576 B | 21.5% | 参考 | | RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS | | UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 | -| RW_IRAM1 | 96,144 B | 131,072 B | 73.4% | PASS | +| RW_IRAM1 | 96,776 B | 131,072 B | 73.8% | PASS | | 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 | |---|---|---|---| @@ -26,8 +26,8 @@ | 存储 | 7,056 B | 12 KB | OK | | UI | 54,988 B | 16 KB | ⚠ 超 37.7 KB | | RTOS 堆 | 57,376 B | 56 KB | 堆=配额 | -| 应用 | 13,119 B | 8 KB | ⚠ 超 4.8 KB | -| 其它 | 7,596 B | — | 参考 | +| 应用 | 13,247 B | 8 KB | ⚠ 超 4.9 KB | +| 其它 | 8,100 B | — | 参考 | - **门禁**:pre-commit `mem-budget` 钩子(`scripts/ram_baseline.py --gate`)—— diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index c71b6763..3e531c54 100644 --- a/docs/算法/继电保护功能复现规划.md +++ b/docs/算法/继电保护功能复现规划.md @@ -281,7 +281,7 @@ | L3-2 | 三段式零序过流 | 零序电流 > 定值,经延时出口 | Ⅰ/Ⅱ/Ⅲ 段零序电流 + 延时 | ⬜(N-18:`IN` 走 STM32,V0.2 使能;框架已就绪,加实例表一行即可) | | L3-3 | 过负荷 | 相电流 > 定值,告警/跳闸可整定 | 过负荷电流 + 延时 | 🔶 同 L3-1(`OL-IA` 实例,默认告警不跳闸;板端接线随 B5 落地,YX23 上送) | | L3-4 | 过压 / 欠压 | 相/线电压越限,经延时出口 | 过压定值、失压定值 + 延时 | 🔶 同 L3-1(`OV-UA`/`UV-UA`,欠量方向单测覆盖;沿用参考告警段 0x8027/0x8029) | -| L3-5 | 过频 / 低频 | 频率越限,经延时出口 | 过频、低频定值 + 延时 | ⬜(随频率测量算法 P2;框架已就绪) | +| L3-5 | 过频 / 低频 | 频率越限,经延时出口 | 过频、低频定值 + 延时 | ✅ 软件侧完成(B8,2026-10-12):`freq` 层测频(自适应窗,45~55 Hz 扫频最坏 **0.0101 Hz** / 1% 噪声 0.0160 Hz)+ `OF/UF` 实例(51.0/49.0 Hz、dly 1000 ms、返回系数 0.99/1.01,本地定值 8 项);OF/UF 暂无独立遥信点,动作仅经 YX15 总聚合可见(独立分点 + 注入验收 = B10) | | L3-6 | 零序过压 | 零序电压 > 定值 | 零序过压定值 + 延时 | 🔶 同 L3-1(`3U0-UN` 实例,外部零序电压通道,不受 N-18 限制) | **扩展集(P2/P3)** @@ -467,7 +467,7 @@ | --- | --- | --- | --- | --- | | **P0** | 采样与相量底座 | B1(周期 CONVST + `adcTask` 消费 + 建任务 + 栈预算)+ L1 + L2 | B0 + B1 ✅ | 每 1 ms 产出正确的基波相量 —— **✅ 2026-10-11 台架闭环**(L1-6 同日落地 ✅;L1-5 标定 / L1-7 等周波为 P0 遗留项,精度复核依赖标准源) | | **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 同批主机完成(同框架实例);**过频/低频待频率测量算法** | +| **P2** | 电压/频率类保护 | 过压/欠压(`UA`)、过频/低频、零序过压(`UN`) | P0 | 电压/频率越限正确动作 —— 🔶 过压/欠压/零序过压随 P1 同批主机完成(同框架实例);过频/低频 ✅ **B8 已落地(2026-10-12)**:freq 层(自适应窗,扫频最坏 0.0101 Hz)+ OF/UF 实例;出口独立遥信点与注入验收归 B10 | | **P3** | 异常检测与闭锁 | L5 自检闭锁、采样通道自检;三相类(涌流/PT·CT 断线/母线接地)**建接口不使能** | P1/P2 | 自检失败闭锁;未使能元件不误动 | | **P4** | 出口、记录与定值集成 | L4 出口与记录、§5 定值模型落 cfg_file、UI 显示、上送 | P1 | 动作出口 + SOE 记录 + UI 显示闭环(**定值持久化 + 软压板 + 竞态收口 = B7 完成 2026-10-12,台架腿已验 ✅**) | | **P5** | 方向/功率类(延后) | L3-13 方向元件等 | V0.2 硬件 / 子板计量 | 跨转换器相位一致后实现 | @@ -608,3 +608,4 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5) | 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` 已刷)。**台架腿完成(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 仍待窗) | +| 2026-10-12 | **B8 频率测量层 + 过频/低频保护(L3-5,W1 任务卡)** | 新增 `App/algo/freq.c/h`(L2.5 测频:共轭乘积相位增量 + 解缠绕 + **自适应窗长** K_eff=round(8·Fs/(2·f̂))——定长窗受 20 点矩形窗**负序泄漏纹波**限制(实测最坏 0.317 Hz)、60 拍 Kay 复数和 0.197 Hz(交叉项和角不按 1/K² 衰减),自适应窗把窗长对齐纹波周期 fs/(2f) 整数倍 → **0.0101 Hz**;假值钳制带 35~65 Hz 与系统合理带分离(贴边钳制会非对称丢纹波半周 → 45 Hz 点 +0.16 Hz 偏置);幅值门 <50 码 → valid=0 保持;UA→IA 优先级;`freq_run()` 挂 adcTask `phasor_run()` 后,心跳 `freq(hb)` 行)。**定值 32→40**:尾追加 OF/UF 8 项(51.0/49.0 Hz、dly 1000 ms、返回系数 0.99/1.01;全部本地项 `comm_addr=0`,参考逐项地址不在本仓库待对照);`bad_mask`→`uint64_t`(TC-PS-011 断言 bit39 可指认);**blob VER 1→2**(144→176 B;升级语义换代/损坏分流:旧档 → `prot_set_store_load()` **rc=2 换代** INFO ≠ **rc<0 真损坏** ERROR+自检,defaultTask 不误报)。**prot_elm 7→9**:`PE_OF`/`PE_UF` + `pe_cfg_t.src`(0=相量有效值 / 1=freq 测频;freq 无读数按方向填"必不启动"值,不整拍跳过);OF/UF 暂无独立 YX 点,动作仅经 YX15 总聚合可见(独立分点 = B10 送检点表);YC `0x401D` 频率点仍 QDS=IV(接真值 + 独立分点归 B10)。单测:`test/host/freq/` **46 断言**(J1 扫频 45~55 Hz ≤0.02 实测 0.0101 / J2 噪声 1% ≤0.10 实测 0.0160 / J3 启动收敛 ≤40 ms 实测 20 / J4 阶跃 50→51 ≤120 ms 实测 98——**精度优先于响应**显式取舍:98 ms ≪ OF/UF 动作延时定值默认 1000 ms / J5 浮空 valid=0 漂移 0.13 / J6 双跳变 60 ms 回 ±0.05;三代弯路推导写 `freq.c` 文件头防重蹈)+ prot_set **90**(+27:40 项/VER 2/64 位 bad_mask/旧档拒绝)+ prot_elm **47**(+OF/UF 滞回·方向隔离·测频接线);回归 phasor 57 / iec104 94 无退化。`@build` 0 错 0 警(Code=207468);RW_IRAM1 +632 B(73.3%→73.8%)、CCM 不变、Flash +2,244 B(21.6%);**adcTask/protectTask 栈链不变**(freq_run 帧未进最坏链,无需抬栈)。§3.3 L3-5 置 ✅(软件侧)、§7 P2 更新;`freq-unit-test` 钩子登记(31→32) | diff --git a/scripts/ram_baseline.tsv b/scripts/ram_baseline.tsv index 3a6276e7..9a1e1990 100644 --- a/scripts/ram_baseline.tsv +++ b/scripts/ram_baseline.tsv @@ -1,2 +1,2 @@ date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi -2026-10-12 205516 18044 1036 152484 223560 21.3 96096 73.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=40960;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;console_log.o=4120;ch395f.o=4106;default_task.o=2736;sys_log_mcu.o=1924 +2026-10-12 207636 18300 1080 153120 225936 21.5 96776 73.8 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=40960;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;console_log.o=4120;ch395f.o=4106;default_task.o=2736;sys_log_mcu.o=1924