From 90db5280327e9fee55451aaae423f1dfb71dc4a5 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 12 Oct 2026 12:36:23 +0800 Subject: [PATCH 1/6] =?UTF-8?q?W1=20=E5=8A=9F=E8=83=BD=E4=B8=BB=E7=BA=BF?= =?UTF-8?q?=E5=AE=8C=E6=88=90=EF=BC=9A=E5=86=85=E5=AD=98=E5=8F=B0=E8=B4=A6?= =?UTF-8?q?=E4=B8=89=E4=BB=B6=E5=A5=97(W1-0)=20+=20IEC104=20=E4=B8=8A?= =?UTF-8?q?=E8=A1=8C(B4)=20+=20protectTask=20=E6=9D=BF=E7=AB=AF=E6=8E=A5?= =?UTF-8?q?=E7=BA=BF(B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit W1-0 台账三件套:scripts/ram_baseline.py(四模式)+ ram_baseline.tsv 趋势 + docs/内存管理/RAM预算台账.md + pre-commit mem-budget 钩子(RW_IRAM1/RW_CCM >92% 即 FAIL + Top-10 附表);审查报告 §5.5 三条闭环。 B4 IEC 60870-5-104 上行(被控站,TCP 2404):App/protocol/iec104/ 三模块 (asdu 编解码 / pts 点表+数据源 vtable / link APCI+FSM,纯逻辑零 I/O)+ App/task/iec104_serv.c(iec104Task,NET_READY 屏障 100ms 分片喂位)。 82 断言 L0.5 全绿 + iec104-unit-test 钩子(第 31 钩子); 设计说明 docs/子系统设计/IEC104上行设计说明.md 全量回填。 B5 protectTask(L3 板端接线):App/task/protect_task.c——20ms 判据节拍 prot_elm_run + L5-4 采样故障闭锁(adc_health 电平位→元件复位)+ L5-1 定值 校验和巡检;新增 prot_elm_request_reset() 收口跨上下文复归(104 YK11 落请求、 eval 头部消费);定值/元件初始化移入 app_main_init(内核前)。TC-PE-010 (prot_elm 28 用例)。 门禁与内存:TASK_WD_PROTECT=8 入 required_mask(产品 0x77→0x1F7、HW 层 0x1F5,看门狗单测 39 断言同步);FreeRTOS 堆 48→56KB(.ioc L1 参数 + FreeRTOSConfig.h 同步,RAM预算台账 §6 登记配额 48→56KB)。 ZI 144,008→152,204(+8,196 B = 堆 +8KB,B5 扩容);Code=204,348。 stack_report:protectTask 512 words 静态链 872 B/余 57%、iec104Task 640 words 1456 B/余 43% 均 PASS;RW_IRAM1 73.1% / RW_CCM 87.9%(<92%)。 验证:@build 0 错 0 警;ci_local 全绿(31 钩子 + 13 主机侧单测); doc-links 135 文档 PASS。登记簿 B4/B5 销项、W1 波次完成;保护规划/看门狗 说明/AGENTS(9 任务)/RAM 三文档全部同步。 遗留(验收窗口,非代码空洞):台架第三方 104 主站往返(送检窗口)、 标准源注入动作判据、@test PROT 锚点 + protect 栈水位 + 新堆 min_ever 复测。 --- .cubemx_survival_baseline.json | 2 +- .pre-commit-config.yaml | 27 + AGENTS.md | 18 +- App/algo/README.md | 6 +- App/algo/prot_elm.c | 20 + App/algo/prot_elm.h | 15 +- App/app/app_main.c | 10 + App/protocol/README.md | 15 +- App/protocol/iec104/iec104_asdu.c | 208 ++++++ App/protocol/iec104/iec104_asdu.h | 130 ++++ App/protocol/iec104/iec104_link.c | 777 +++++++++++++++++++++ App/protocol/iec104/iec104_link.h | 136 ++++ App/protocol/iec104/iec104_pts.c | 426 ++++++++++++ App/protocol/iec104/iec104_pts.h | 94 +++ App/task/default_task.c | 12 +- App/task/iec104_serv.c | 295 ++++++++ App/task/iec104_serv.h | 20 + App/task/protect_task.c | 105 +++ App/task/protect_task.h | 25 + App/util/task_watchdog.c | 8 +- App/util/task_watchdog.h | 2 + Inc/FreeRTOSConfig.h | 2 +- MDK-ARM/STM32F407-Demo.uvprojx | 27 +- README.md | 2 + STM32F407-Demo.ioc | 2 +- Src/freertos.c | 37 + docs/README.md | 4 +- docs/产品需求/产品需求设计文档.md | 4 +- docs/代码规范/pre-commit使用说明.md | 29 +- docs/内存管理/RAM使用分析与优化方案.md | 18 +- docs/内存管理/RAM预算台账.md | 96 +++ docs/内存管理/内存内容分配策略.md | 8 +- docs/子系统设计/IEC104上行设计说明.md | 168 +++++ docs/子系统设计/看门狗设计说明.md | 3 +- docs/待处理内容.md | 195 +++--- docs/测试说明/测试开发标准流程.md | 2 +- docs/环境与部署/并行任务工作树方案.md | 163 +++-- docs/算法/继电保护功能复现规划.md | 18 +- docs/问题记录/项目审查与优化建议报告.md | 9 +- scripts/check_registration.py | 5 + scripts/ci_local.py | 17 +- scripts/ram_baseline.py | 407 +++++++++++ scripts/ram_baseline.tsv | 2 + scripts/stack_report.py | 4 + test/host/README.md | 1 + test/host/iec104/iec104_test.c | 868 ++++++++++++++++++++++++ test/host/iec104/run_unit_test.py | 40 ++ test/host/prot_elm/prot_elm_test.c | 27 + test/host/watchdog/watchdog_test.c | 14 +- 49 files changed, 4300 insertions(+), 223 deletions(-) create mode 100644 App/protocol/iec104/iec104_asdu.c create mode 100644 App/protocol/iec104/iec104_asdu.h create mode 100644 App/protocol/iec104/iec104_link.c create mode 100644 App/protocol/iec104/iec104_link.h create mode 100644 App/protocol/iec104/iec104_pts.c create mode 100644 App/protocol/iec104/iec104_pts.h create mode 100644 App/task/iec104_serv.c create mode 100644 App/task/iec104_serv.h create mode 100644 App/task/protect_task.c create mode 100644 App/task/protect_task.h create mode 100644 docs/内存管理/RAM预算台账.md create mode 100644 docs/子系统设计/IEC104上行设计说明.md create mode 100644 scripts/ram_baseline.py create mode 100644 scripts/ram_baseline.tsv create mode 100644 test/host/iec104/iec104_test.c create mode 100644 test/host/iec104/run_unit_test.py diff --git a/.cubemx_survival_baseline.json b/.cubemx_survival_baseline.json index 993e1839..fa05f149 100644 --- a/.cubemx_survival_baseline.json +++ b/.cubemx_survival_baseline.json @@ -13,7 +13,7 @@ "stack-overflow-hook-impl": "a006edbd30d2c4d7", "malloc-failed-hook-impl": "fcd7250e5cd6403b", "stack-overflow-hook-helper": "cacd9fd028be9b5b", - "watchdog-module": "3d908285b092c402", + "watchdog-module": "663f05caf22cf7d0", "reset-cause-latch": "52fc71acbb0f1aed", "iwdg-hal-driver": "4b902875a84554e9", "hal-iwdg-enabled": "1a8ed6cff34f7ba6", diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index eb050c72..6e7a90e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -378,6 +378,19 @@ repos: files: ^(Drivers/BSP/NET/lftpd/lftpd_auth\.(c|h)|App/util/sha256\.(c|h)|test/host/ftp_auth/.*|test/host/common/unit_test_harness\.py)$ pass_filenames: false + # 7m) IEC 60870-5-104 被控站协议栈主机侧单元测试(2026-10-12 加,B4) + # APCI 重组/STARTDT/总召分片/COV/k-w-t1~t3/遥控定值两段式/C_CS/错误 + # 应答——link 层 tick 注入 + pts 数据源 vtable 抽象就是为 L0.5 全离线 + # 穷举设计(A-4 约束 1);板端复现这些分支要真主站+真等待。 + # 触发面含数据源依赖(prot_set/prot_elm/phasor/sample_ring)——测试 + # 直接 #include 这些生产源,签名变了要立刻在这里暴露。 + - id: iec104-unit-test + 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)$ + pass_filenames: false + # 8) 测试套件开关门禁(2026-10-01 加) # 背景:test_config.h 的 TEST_SUITE_* 决定固件里编入哪个测试套件, # 全部注释 = 产品构建。但此前**无任何门禁检查**——实测已提交的 HEAD 里 @@ -409,3 +422,17 @@ repos: language: system files: (\.c$|\.uvprojx$|CMakeLists\.txt$|^scripts/check_registration\.py$) pass_filenames: false + # 10) RAM 预算 92% 阈值门禁(2026-10-12 加,登记簿 N-27 前半 / 审查报告 §5.5 三件套) + # 背景:报告 §5.5 第 1 条要求"超阈值即失败 + Top-10 附表"——此前 mem-numbers 只防 + # "文档数字漂移",**没有任何机械检查拦"占用超阈值"**;台账三件套(ram_baseline.py + + # ram_baseline.tsv + docs/内存管理/RAM预算台账.md)落地后,本钩子把 92% 红线机械化。 + # 逻辑:RW_IRAM1/RW_CCM 任一 >92% → FAIL + Top-10 RW+ZI 对象表;台账受管区漂移 → FAIL + # (提示 --write);无 .map → 自适应跳过(同 mem-numbers 在 CI 的行为,盲区登记 A-5 残余)。 + # ⚠ pre-commit 4.x 无 `always: true` → files 覆盖所有能改变 RAM 的触发面: + # 全部自研代码目录 + lv_conf.h + 测试板配置 + 脚本/tsv/台账自身 + 本配置文件。 + - id: mem-budget + name: RAM 预算 92% 阈值门禁 (N-27) + entry: python scripts/ram_baseline.py --gate + language: system + files: ^(App/|Drivers/BSP/|Src/|Inc/|Lib/lv_conf\.h|test/board/|scripts/ram_baseline\.|docs/内存管理/|\.pre-commit-config\.yaml$) + pass_filenames: false diff --git a/AGENTS.md b/AGENTS.md index c9e916e2..df7607b2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,13 +10,13 @@ ## 项目概况 -**现状一句话**:平台能力(网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置)**已实现并台架验收**;**ADC / RS-485 这两个 DTU 核心采集职责尚未接线到业务消费者**——当前最大功能缺口,接线节奏受 E-59 门禁约束(见「平台约束」)。 +**现状一句话**:平台能力(网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置)**已实现并台架验收**;采集主线已闭环到业务消费者(L1→L2 相量→L3 保护判据 protectTask→104 遥信,B5);**RS-485 采集尚未接线**(B2 按用户决策冻结,见登记簿 §2.4)——当前最大功能缺口,接线节奏受 E-59 门禁约束(见「平台约束」)。 **数据主线**(能力视角;分层图与跨层依赖表 → `docs/架构设计/项目架构总览.md`): -- **采集**:TPAFE5160(计量级 8 路,并行总线)+ 片内 ADC1(9 路,DMA)→ TIM3 1 kHz 节拍 + 原子快照 → adcTask → L1 有效性校验 → L2 相量 → L3 保护(软件侧已落地,待接任务) +- **采集**:TPAFE5160(计量级 8 路,并行总线)+ 片内 ADC1(9 路,DMA)→ TIM3 1 kHz 节拍 + 原子快照 → adcTask → L1 有效性校验 → L2 相量 → L3 保护(protectTask 20 ms 判据节拍,B5)→ 104 遥信上送 - **存储**:GD5F SPI NAND → dhara FTL → FatFs → `/log` 运行与自检记录、`/config.ini` 配置、FTP 根目录 -- **网络**:CH395F → netTask 串行 socket 栈 → FTP(21) / 对时(8888) / RemoDispBus 远程显示(7003) +- **网络**:CH395F → netTask 串行 socket 栈 → FTP(21) / 对时(8888) / RemoDispBus 远程显示(7003) / IEC 60870-5-104 上行(2404) - **人机**:LVGL 160×160 单色菜单(uiTask),**与 PC 模拟器同一份 UI 源码**,远端可看图 + 注键 **目录地图**(只列顶层——稳定边界;细结构自己 `ls`,别背路径): @@ -39,14 +39,14 @@ ## 架构要点 -`Src/main.c`(CubeMX 初始化)→ `app_main_init` → `osKernelStart` → 7 任务(`osKernelStart` 之前全是内核启动前代码:禁调任何内核 API,见「平台约束」) +`Src/main.c`(CubeMX 初始化)→ `app_main_init` → `osKernelStart` → 9 任务(`osKernelStart` 之前全是内核启动前代码:禁调任何内核 API,见「平台约束」) - `app_main_init`(时间子系统优先,使后续日志带时间戳):`sd2506_init` → `sys_clock_init` → `rs485_init` → `gd5f2gq5ue_init` → `tpafe5160_init` → `adc_input_init`(L1 采集层)→ SD2506 诊断 → **启动 TIM3 1 kHz 采样节拍** - **就绪屏障**(`App/app/sys_events.h` Event Flags,取代魔法延时):`SYS_EVT_NET_READY` / `STORAGE_READY` / `FTP_READY` / `TIMESYNC_READY`;消费者用 `osEventFlagsWait` 阻塞等待(就绪位 `osFlagsNoClear`) - 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 软件侧(**尚无任务调用 `prot_elm_run()`**——链接器移除、零足迹,板端接线随 protectTask 立项走 E-59 同款门禁)。→ `App/algo/README.md` +- **采集与算法层(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` - 全景 → `docs/架构设计/项目架构总览.md`;启动时序与内核前模式 → `docs/架构设计/项目启动顺序管理.md` @@ -59,6 +59,8 @@ | uiTask | 4096 | BelowNormal | | timeSyncTask | 512 | Normal | | adcTask | 640 | AboveNormal | +| iec104Task | 640 | Normal | +| protectTask | 512 | Normal | (实际值以 `Src/freertos.c` 为准,本表由 `scripts/gen_task_table.py` 生成、`task-table` 钩子校验;testTask 仅在启用测试套件时创建。FreeRTOS 堆已迁 CCM,任务栈不占 SRAM;**每次抬栈的实测最坏链与余量台账** → `docs/内存管理/RAM使用分析与优化方案.md` §1.4 与 `docs/内存管理/内存内容分配策略.md` §6) @@ -87,7 +89,7 @@ ## 提交门禁(pre-commit) -- 任一失败即拦截,共 **29 个钩子**(逐个详解 → `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` + 主机侧单测 12 个(`-unit-test` 后缀)+ `test-suite-switch` + `registration-check`(双端注册反向校验,N-23) +- 任一失败即拦截,共 **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) - **范围 = 项目代码**:第三方(`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/` @@ -108,7 +110,7 @@ - **`osKernelStart` 之前禁止任何 FreeRTOS/CMSIS-RTOS 创建类 API**(`osMessageQueueNew` 等会杀死启动,2026-09-20 实证根因)→ 内核前标准模式(纯寄存器/HAL 轮询 + **无锁静态缓冲** + 内核启动后**惰性创建**真队列)见 `docs/架构设计/项目启动顺序管理.md` - **就绪屏障位必须 `osFlagsNoClear`**:`osEventFlagsWait` **默认消费**所等位,就绪位被先消费掉 → `ftpTask` 的 `WaitAll` 永不成立 → **FTP 21 端口静默不监听**(无日志无报错)。命令位(`SYS_EVT_CFG_SAVE`/`NET_RECONFIG`)保持消费型 - **自研代码禁用 C 库堆分配**(`malloc/calloc/realloc/strdup/free`):MicroLIB 的 C 堆由 `startup_stm32f407xx.s` 的 `Heap_Size EQU 0x200` 限定为 **512 B**,KB 级分配必然返回 NULL,而**模拟器(宿主 CRT 堆)完全正常、照不出来** → 只用 `pvPortMalloc/vPortFree`,或把分配收进平台后端 → `docs/内存管理/RAM使用分析与优化方案.md` -- **内存预算紧张**:新增任何任务/缓冲/栈前先核算 RAM 余量;改栈或加大局部变量**前后各跑一次** `scripts/stack_report.py`(静态最坏链 + 串口 `[STACK]` 水位)与 `scripts/ram_report.py`(.map 静态占用)→ `docs/内存管理/` +- **内存预算紧张**:新增任何任务/缓冲/栈前先核算 RAM 余量;改栈或加大局部变量**前后各跑一次** `scripts/stack_report.py`(静态最坏链 + 串口 `[STACK]` 水位)与 `scripts/ram_report.py`(.map 静态占用);**总量红线已机械化**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势见 `docs/内存管理/RAM预算台账.md`(**每次 `@build` 后跑 `scripts/ram_baseline.py --update`**)→ `docs/内存管理/` - FreeRTOS V10.3.1(CMSIS-RTOS V2);HAL 时基 = **TIM7**(非 SysTick),tick = 1ms;NVIC 4 位优先级分组,**外设中断优先级 ≥ 5** **采集链(ADC / RS-485)** @@ -170,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 29 个钩子逐个详解 | `docs/代码规范/pre-commit使用说明.md` | +| pre-commit 31 个钩子逐个详解 | `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/App/algo/README.md b/App/algo/README.md index 3b88233d..32432413 100644 --- a/App/algo/README.md +++ b/App/algo/README.md @@ -196,8 +196,10 @@ flowchart TD - **闭锁联动**:`prot_set_locked()`(L5-1)或投退=0 → 该元件状态整体复位、不判据。 - **V0.1 实例**(N-18):`OC1/OC2/OC3/OL`(IA)、`OV/UV`(UA)、`3U0`(UN 外部通道)。 零序过流(IN 走 STM32)与过频/低频(待频率算法)**故意不在表中**。 -- **尚未接线**:无任务调用 `prot_elm_run()`(链接器整对象移除,零足迹); - 板端接线随 protectTask 立项(栈预算 + IWDG 心跳门禁,AGENTS E-59 同款流程)。 +- **板端接线已落地(B5,2026-10-12)**:`App/task/protect_task.c`(protectTask, + 20 ms 节拍)消费 `prot_elm_run()` + L5-4 采样故障闭锁 + L5-1 校验和巡检; + 跨上下文复归走 `prot_elm_request_reset()`(104 YK11 落请求、eval 头部消费)。 + 判据结果经 104 遥信上送(`iec104_pts` YX15~23/31)。→ `docs/算法/继电保护功能复现规划.md` §7 ## 4. 关键约定 diff --git a/App/algo/prot_elm.c b/App/algo/prot_elm.c index 4bd4b882..77e5f62c 100644 --- a/App/algo/prot_elm.c +++ b/App/algo/prot_elm.c @@ -43,6 +43,9 @@ typedef struct { static pe_rt_t s_rt[PE_COUNT]; +/* 跨上下文复归请求(单字标志,volatile;B5:104 YK11 在 iec104Task 落请求) */ +static volatile uint8_t s_reset_req; + /* * 函数功能:按名前缀在 phasor 实例表里找索引(开机解析一次) * 入口参数:prefix - 相量实例名前缀(如 "C01") @@ -90,6 +93,16 @@ void prot_elm_init(void) { } } +/* + * 函数功能:登记"复归元件状态"请求(任意上下文安全,见 prot_elm.h) + * 入口参数:无 + * 返 回 值:无 + * 函数说明:只置单字标志;真正的状态复位在下一拍 eval 头部(消费者上下文)执行。 + */ +void prot_elm_request_reset(void) { + s_reset_req = 1u; +} + /* * 函数功能:纯判据步进——按当前定值 + 给定测量值推进所有元件 * 入口参数:now_ms - 单调时基(tick ms,差值法回绕安全) @@ -103,6 +116,13 @@ void prot_elm_eval(uint32_t now_ms, const float meas[PE_COUNT]) { uint8_t locked = prot_set_locked(); uint32_t i; + /* 跨上下文复归请求在此消费(YK11 经 request_reset,见 prot_elm.h) */ + if (s_reset_req != 0u) { + s_reset_req = 0u; + prot_elm_init(); + locked = prot_set_locked(); + } + for (i = 0u; i < (uint32_t)PE_COUNT; i++) { const pe_cfg_t *cfg = &k_pe[i]; uint8_t cond; diff --git a/App/algo/prot_elm.h b/App/algo/prot_elm.h index 636a2bff..d23a39c3 100644 --- a/App/algo/prot_elm.h +++ b/App/algo/prot_elm.h @@ -18,8 +18,10 @@ * - 复压/方向/无压无流闭锁(dwSetFyCtrl 类)随 P2/P3 元件扩展; * - 工程量↔码值换算系数暂为 1(L1-5 标定未实现,同 phasor 层口径)。 * - * 线程约定:init 内核启动前;eval/run 仅保护消费者任务上下文(P1 阶段 = 单测; - * 板端接线随 protectTask 立项,走栈预算 + IWDG 心跳门禁)。 + * 线程约定:init 内核启动前或保护消费者任务上下文;eval/run 仅保护消费者任务 + * 上下文(B5 起 = protectTask);request_reset 任意上下文(跨上下文复归请求, + * 如 104 遥控 YK11 在 iec104Task 落请求、下一拍 eval 头部消费)。板端接线 + * 走栈预算 + IWDG 心跳门禁。 * * 创建日期:2026-10-11 */ @@ -50,9 +52,18 @@ typedef struct { /* * 函数功能:复位全部元件状态(定值不动;幂等,内核启动前可调) + * 限定条件:内核启动前,或保护消费者任务上下文(跨上下文请用 request_reset) */ void prot_elm_init(void); +/* + * 函数功能:登记"复归元件状态"请求(任意上下文安全,单字标志) + * 函数说明:下一拍 prot_elm_eval() 头部消费并执行 prot_elm_init()。 + * 104 遥控 YK11(iec104Task 上下文)必须走本接口,不得直接调 + * prot_elm_init()(会与 protectTask 的 eval 竞态)。 + */ +void prot_elm_request_reset(void); + /* * 函数功能:纯判据步进——按当前定值(prot_set RAM)+ 给定测量值推进所有元件 * 入口参数:now_ms - 单调时基(tick ms,回绕安全:差值法) diff --git a/App/app/app_main.c b/App/app/app_main.c index a3d9a17e..416a6d46 100644 --- a/App/app/app_main.c +++ b/App/app/app_main.c @@ -25,6 +25,8 @@ #include "tpafe5160.h" #include "adc_input.h" /* L1 采集层:adc_input_init()(语义映射 + STM32 ADC1 扫描) */ #include "phasor.h" /* L2 相量层:phasor_init()(系数表 + 实例 + 双区交换) */ +#include "prot_set.h" /* L3 定值模型:prot_set_init()(B5,内核前封存) */ +#include "prot_elm.h" /* L3 元件框架:prot_elm_init()(B5,解析相量索引) */ #include "sys_log.h" #include "task_watchdog.h" /* task_wd_seg_report():round 8 复位不丢"进段打点"上报 */ #include "test_config.h" /* 套件开关:身份戳的构建变体串(FW_BUILD_VARIANT)依赖本头, @@ -240,6 +242,14 @@ int app_main_init(void) { (void)phasor_init(); DBG_INFO("phasor layer init: OK (inst=%u)", (unsigned)phasor_inst_count()); + /* 4d) 保护定值 + 元件层初始化(B5):出厂默认定值封存校验和 + 元件状态 + * 复位并解析相量索引(须在 phasor_init 之后)。内核前完成 → iec104 + * 定值读/protectTask 首拍前定值必已装载。判据消费在 protectTask。 */ + prot_set_init(); + prot_elm_init(); + DBG_INFO("protection init: OK (set=%u elm=%u)", + (unsigned)PS_ID_COUNT, (unsigned)PE_COUNT); + /* 5) SD2506 RTC 诊断信息 */ { /* 读取 ID */ diff --git a/App/protocol/README.md b/App/protocol/README.md index 9871a636..4ee6b5c2 100644 --- a/App/protocol/README.md +++ b/App/protocol/README.md @@ -1,11 +1,18 @@ -# App/protocol/ — 通信协议(预留) +# App/protocol/ — 通信协议(纯逻辑层) -> **占位目录**:规划用于存放自定义通信协议实现(解析 / 组帧 / 状态机)。 -> 当前为空(仅 `.gitkeep`),协议相关实现暂分散在: -> - RS-485 侧:`App/task/rs485_task.c` + `App/util/crc.c` + `App/util/ringbuf.c` +> 存放**跨接口复用的协议逻辑**(解析 / 组帧 / 状态机),零 I/O、依赖注入, +> 可被任意任务/接口承载;板端 I/O 胶水在对应 task(如 `App/task/iec104_serv.c`)。 +> 其余协议实现暂分散在: +> - RS-485 侧:`App/task/rs485_task.c`(CRC 在驱动内) > - 网络侧:`Drivers/BSP/NET/` > - 远端显示:`docs/UI设计/RemoDispBus协议与接收设计说明.md` +## 已落地协议 + +| 子目录 | 协议 | 说明 | +|---|---|---| +| `iec104/` | IEC 60870-5-104 被控站(TCP 2404 上行) | **纯逻辑**三件套(asdu/pts/link,零 I/O,数据源 vtable 注入)→ 全栈 L0.5 主机单测;板端胶水与点表决策 → `docs/子系统设计/IEC104上行设计说明.md` | + ## 何时使用本目录 当出现**跨接口复用的协议逻辑**(如统一的帧编解码器、协议状态机)时,落到此处, diff --git a/App/protocol/iec104/iec104_asdu.c b/App/protocol/iec104/iec104_asdu.c new file mode 100644 index 00000000..fc543aab --- /dev/null +++ b/App/protocol/iec104/iec104_asdu.c @@ -0,0 +1,208 @@ +/* + * 模块名称:IEC 60870-5-104 ASDU 编解码(应用层,纯逻辑) + * 模块功能:实现 iec104_asdu.h——ASDU 头解析/组装、IOA 3B 小端、IEEE754 + * 短浮点小端、CP56Time2a ↔ epoch 毫秒(UTC 分解,Hinnant civil + * 日历算法,不依赖 time.h → ARMCC/MSVC 双端可移植)。 + * 线程约定:全部纯函数,无状态 → 任意上下文可调。 + * 创建日期:2026-10-12(B4) + */ +#include "iec104_asdu.h" + +#include + +/* COT 首字节:bit0..5 = 值,bit6 = PN,bit7 = T;RBT 复用 bit4(C_IC 语义) */ +#define COT_VAL_MASK 0x3FU +#define COT_FLAG_MASK 0xC0U + +/* + * 函数功能:解析 ASDU 头(6B),信息体起点经 obj/obj_len 指出 + * 入口参数:buf/len = ASDU 首字节与总长;hdr = 输出 + * 返 回 值:0 成功 / -1 空指针或长度不足 6B + */ +int iec104_asdu_parse_hdr(const uint8_t *buf, uint16_t len, iec104_asdu_hdr_t *hdr) { + if ((buf == NULL) || (hdr == NULL) || (len < 6u)) { + return -1; + } + hdr->type = buf[0]; + hdr->vsq = buf[1]; + hdr->cot = (uint8_t)(buf[2] & COT_VAL_MASK); + hdr->cot_hi = (uint8_t)(buf[2] & 0xC0u); + hdr->oa = buf[3]; + hdr->ca = (uint16_t)(buf[4] | ((uint16_t)buf[5] << 8)); + hdr->obj = &buf[6]; + hdr->obj_len = (uint16_t)(len - 6u); + return 0; +} + +/* + * 函数功能:组装 ASDU 头(OA 恒 0,EVI 由调用方置 buf[3];RBT 位透传) + * 入口参数:cot = 6bit 原因值;cot_hi = 标志位(T/PN/RBT);ca = 公共地址 + * 返 回 值:固定 6(头字节数) + */ +uint16_t iec104_asdu_put_hdr(uint8_t *buf, uint8_t type, uint8_t vsq, + uint8_t cot, uint8_t cot_hi, uint16_t ca) { + buf[0] = type; + buf[1] = vsq; + buf[2] = (uint8_t)(((uint8_t)(cot & COT_VAL_MASK)) + | (uint8_t)(cot_hi & COT_FLAG_MASK) + | (uint8_t)(cot_hi & 0x10u)); /* RBT 位透传 */ + buf[3] = 0u; /* OA = 0(EVI 由调用方按需置位) */ + buf[4] = (uint8_t)(ca & 0xFFu); + buf[5] = (uint8_t)(ca >> 8); + return 6u; +} + +/* + * 函数功能:IOA 3 字节小端写入 + */ +void iec104_put_ioa(uint8_t *buf, uint32_t ioa) { + buf[0] = (uint8_t)(ioa & 0xFFu); + buf[1] = (uint8_t)((ioa >> 8) & 0xFFu); + buf[2] = (uint8_t)((ioa >> 16) & 0xFFu); +} + +/* + * 函数功能:IOA 3 字节小端读取 + */ +uint32_t iec104_get_ioa(const uint8_t *buf) { + return (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16); +} + +/* + * 函数功能:IEEE754 短浮点 → 小端字节序(104 恒小端,宿主字节序无关) + */ +void iec104_put_float(uint8_t *buf, float v) { + /* 位模式小端:memcpy 不假设宿主字节序,逐字节拆给目标(104 恒小端) */ + uint8_t tmp[sizeof(float)]; + uint32_t i; + + (void)memcpy(tmp, &v, sizeof(tmp)); + for (i = 0u; i < sizeof(tmp); i++) { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + buf[i] = tmp[sizeof(tmp) - 1u - i]; +#else + buf[i] = tmp[i]; +#endif + } +} + +/* + * 函数功能:小端字节序 → IEEE754 短浮点 + */ +float iec104_get_float(const uint8_t *buf) { + uint8_t tmp[sizeof(float)]; + uint32_t i; + float v; + + for (i = 0u; i < sizeof(tmp); i++) { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + tmp[i] = buf[sizeof(tmp) - 1u - i]; +#else + tmp[i] = buf[i]; +#endif + } + (void)memcpy(&v, tmp, sizeof(v)); + return v; +} + +/* ---------------- CP56Time2a ↔ epoch ---------------- */ + +/* 2000-01-01 00:00:00 UTC 的 epoch 毫秒(钳位下限) */ +#define EPOCH_2000_MS 946684800000ULL + +/* + * 函数功能:公历(y>=1)→ 距 1970-01-01 天数(Hinnant civil_from_days 正向) + * 说明:纯整数算法;m 取 1..12。 + */ +static uint32_t s_days_from_civil(uint32_t y, uint32_t m, uint32_t d) { + uint32_t yy = y - ((m <= 2u) ? 1u : 0u); + uint32_t era = yy / 400u; + uint32_t yoe = yy - (era * 400u); + uint32_t mp = (m > 2u) ? (m - 3u) : (m + 9u); /* 3 月 = 月序 0 */ + uint32_t doy = ((153u * mp) + 2u) / 5u + d - 1u; + uint32_t doe = (yoe * 365u) + (yoe / 4u) - (yoe / 100u) + doy; + + return (era * 146097u) + doe - 719468u; +} + +/* + * 函数功能:距 1970-01-01 天数 → 公历(Hinnant 反向) + * 入口参数:z_in = 天数;y/m/d = 输出 + */ +static void s_civil_from_days(uint32_t z_in, uint32_t *y, uint32_t *m, uint32_t *d) { + uint32_t z = z_in + 719468u; + uint32_t era = z / 146097u; + uint32_t doe = z - (era * 146097u); + uint32_t yoe = (doe - (doe / 1460u) + (doe / 36524u) - (doe / 146096u)) / 365u; + uint32_t yy = yoe + (era * 400u); + uint32_t doy = doe - ((365u * yoe) + (yoe / 4u) - (yoe / 100u)); + uint32_t mp = ((5u * doy) + 2u) / 153u; + uint32_t mon = mp + ((mp < 10u) ? 3u : 0u); + + *d = doy - (((153u * mp) + 2u) / 5u) + 1u; + if (mp >= 10u) { + mon = mp - 9u; + } + *m = mon; + *y = yy + ((mon <= 2u) ? 1u : 0u); +} + +/* + * 函数功能:CP56Time2a → epoch 毫秒(UTC 分解) + * 入口参数:buf = 7B;epoch_ms = 输出 + * 返 回 值:0 成功 / -2 IV(时间无效,调用方应拒绝)/ -1 字段越界 + */ +int iec104_cp56_to_epoch_ms(const uint8_t *buf, uint64_t *epoch_ms) { + uint32_t ms_min, minute, hour, day, mon, year; + + if ((buf == NULL) || (epoch_ms == NULL)) { + return -1; + } + if ((buf[2] & 0x80u) != 0u) { + return -2; /* IV:时间无效,调用方应拒绝 */ + } + ms_min = (uint32_t)buf[0] | ((uint32_t)buf[1] << 8); /* 0..59999 */ + minute = (uint32_t)buf[2] & 0x3Fu; + hour = (uint32_t)buf[3] & 0x1Fu; + day = (uint32_t)buf[4] & 0x1Fu; + mon = (uint32_t)buf[5] & 0x0Fu; + year = 2000u + ((uint32_t)buf[6] & 0x7Fu); + if ((day == 0u) || (day > 31u) || (mon == 0u) || (mon > 12u) + || (hour > 23u) || (minute > 59u) || (ms_min > 59999u)) { + return -1; + } + *epoch_ms = ((uint64_t)s_days_from_civil(year, mon, day) * 86400000ULL) + + ((uint64_t)hour * 3600000ULL) + + ((uint64_t)minute * 60000ULL) + + (uint64_t)ms_min; + return 0; +} + +/* + * 函数功能:epoch 毫秒 → CP56Time2a(钳位 [2000-01-01, 2127-12-31],IV 恒 0) + * 返 回 值:固定 7(字节数) + */ +uint16_t iec104_epoch_ms_to_cp56(uint64_t epoch_ms, uint8_t *buf) { + uint64_t days, rem, clamped; + uint32_t y, m, d, ms_min; + + clamped = (epoch_ms < EPOCH_2000_MS) ? EPOCH_2000_MS : epoch_ms; + days = clamped / 86400000ULL; + rem = clamped % 86400000ULL; + s_civil_from_days((uint32_t)days, &y, &m, &d); + if (y > 2127u) { /* 年字段 7bit 上限(2000+127) */ + y = 2127u; + m = 12u; + d = 31u; + rem = 86399999ULL; + } + ms_min = (uint32_t)(rem % 60000ULL); + buf[0] = (uint8_t)(ms_min & 0xFFu); + buf[1] = (uint8_t)(ms_min >> 8); + buf[2] = (uint8_t)((rem / 60000ULL) % 60ULL); /* min,IV=0 */ + buf[3] = (uint8_t)((rem / 3600000ULL) % 24ULL); /* hour */ + buf[4] = (uint8_t)(d & 0x1Fu); /* day */ + buf[5] = (uint8_t)(m & 0x0Fu); /* month */ + buf[6] = (uint8_t)((y - 2000u) & 0x7Fu); /* year */ + return 7u; +} diff --git a/App/protocol/iec104/iec104_asdu.h b/App/protocol/iec104/iec104_asdu.h new file mode 100644 index 00000000..492b9c2d --- /dev/null +++ b/App/protocol/iec104/iec104_asdu.h @@ -0,0 +1,130 @@ +/* + * 模块名称:IEC 60870-5-104 ASDU 编解码(应用层,纯逻辑) + * 模块功能:104 规约应用服务数据单元(ASDU)的类型/传送原因常量、组帧与解析。 + * **零 I/O、零平台依赖**(仅 stdint.h)→ 主机侧 L0.5 可离线单测 + * (登记簿 A-4 约束 1"协议解析与硬件 I/O 分离")。 + * 口径来源:docs/算法/继电保护功能复现规划.md §1.5(B0 产品定义)—— + * 公共地址 2 字节、传送原因 2 字节、信息体地址 IOA **3 字节**(101 为 2 字节); + * 遥测上送**短浮点** M_ME_NC_1(系数 = 1);遥信双点上双点、其余单点; + * 遥控**双点命令**(选择 82H / 执行 02H,即 QDC 的 S 位 + 值 2)。 + * 帧结构(本层只管 ASDU,APCI 6 字节头归 iec104_link): + * [type 1B][vsq 1B][cot 2B][ca 2B]( [ioa 3B][元素...] )*n + * 多信息体地址对象(SQ=0)每对象带独立 IOA;顺序对象(SQ=1)单 IOA + n 元素。 + * 创建日期:2026-10-12(B4,登记簿 §2.1 W1) + */ +#ifndef IEC104_ASDU_H +#define IEC104_ASDU_H + +#include + +/* ---------------- 类型标识(DL/T 634.5104,仅定义本期子集) ---------------- */ +#define IEC104_T_M_SP_NA_1 1U /* 单点遥信 SIQ */ +#define IEC104_T_M_DP_NA_1 3U /* 双点遥信 DIQ */ +#define IEC104_T_M_ME_NC_1 13U /* 遥测短浮点 float+QDS(§1.5 口径) */ +#define IEC104_T_C_SE_NC_1 50U /* 定值写(短浮点)float+QDS */ +#define IEC104_T_C_DC_NA_1 52U /* 双点遥控 QDC(82H 选 / 02H 执行) */ +#define IEC104_T_C_IC_NA_1 100U /* 总召 RQT */ +#define IEC104_T_C_RD_NA_1 102U /* 读单个测量值 IOA only */ +#define IEC104_T_C_CS_NA_1 103U /* 时钟同步 CP56Time2a */ +#define IEC104_T_C_TS_NA_1 104U /* 试验 FBP 2B */ +#define IEC104_T_C_RP_NA_1 105U /* 进程复位 RPA 1B */ + +/* ---------------- 传送原因 COT(低字节 6bit;高字节 T|PN|RBT/…) ---------- */ +#define IEC104_COT_PERIODIC 1U /* 周期/循环 */ +#define IEC104_COT_BG_SCAN 2U /* 背景扫描(总召响应) */ +#define IEC104_COT_SPONT 3U /* 突发(cos) */ +#define IEC104_COT_INIT 4U /* 初始化(总召 + RBT=1 时用) */ +#define IEC104_COT_REQ 5U /* 请求(C_RD 响应) */ +#define IEC104_COT_ACT 6U /* 激活 */ +#define IEC104_COT_ACTCON 7U /* 激活确认 */ +#define IEC104_COT_ACTTERM 8U /* 激活终止 */ +#define IEC104_COT_DEACT 9U /* deactivate */ +#define IEC104_COT_DEACTCON 10U /* 停止激活确认 */ +#define IEC104_COT_UNK_COT 12U /* 未知传送原因 */ +#define IEC104_COT_UNK_CA 13U /* 未知公共地址 */ +#define IEC104_COT_UNK_IOA 14U /* 未知信息体地址(+EVI) */ +#define IEC104_COT_BIT_T 0x80U /* COT 高字节 bit7:试验 */ +#define IEC104_COT_BIT_PN 0x40U /* COT 高字节 bit6:否定确认 */ +#define IEC104_COT_BIT_RBT 0x10U /* COT 高字节 bit4:请求链路仿真(总召初始化) */ + +/* ---------------- VSQ ---------------- */ +#define IEC104_VSQ_SQ 0x80U /* 1 = 顺序地址(单 IOA + n 元素) */ +#define IEC104_VSQ_N(n) ((uint8_t)((n) & 0x7FU)) + +/* ---------------- 遥信/遥测品质描述位(本期只用溢出/异常/非当前) --------- */ +#define IEC104_QDS_OV 0x01U +#define IEC104_QDS_BL 0x10U /* blocked(闭锁) */ +#define IEC104_QDS_NT 0x20U /* not top(暂态品质,遥测未就绪用) */ +#define IEC104_QDS_IV 0x80U /* invalid(无效,通道不可用用) */ +#define IEC104_DIQ_IV 0x80U +#define IEC104_SIQ_IV 0x80U + +/* ---------------- 双点值(DIQ/QDC 低 2bit) ---------------- */ +#define IEC104_DPC_DONTCARE 0U +#define IEC104_DPC_OFF 1U +#define IEC104_DPC_ON 2U +#define IEC104_QDC_S 0x80U /* 1 = 选择,0 = 执行(§1.5:82H/02H) */ + +/* ---------------- 总召 RQT ---------------- */ +#define IEC104_RQT_GROUP1 20U /* 总查询(组 1) */ + +/* ---------------- ASDU 头(解析产物) ---------------- */ +typedef struct { + uint8_t type; /* 类型标识 */ + uint8_t vsq; /* 可变结构限定词 */ + uint8_t cot; /* 传送原因低 6bit */ + uint8_t cot_hi; /* COT 首字节的高位标志(T=0x80 / PN=0x40 / RBT=0x10 原样保留) */ + uint8_t oa; /* 源发站地址(第 2 COT 字节;bit7 = EVI) */ + uint16_t ca; /* 公共地址(链路地址 = ASDU 公共地址,2B) */ + const uint8_t *obj; /* 信息体区首址(指向调用方缓冲,生命周期同 on_rx) */ + uint16_t obj_len; /* 信息体区长度 */ +} iec104_asdu_hdr_t; + +/* + * 函数功能:解析 ASDU 头(不解析信息体——各命令的体解析在 iec104_link 内做) + * 入口参数:buf - ASDU 首址(不含 APCI);len - ASDU 长度 + * hdr - 输出头 + * 返 回 值:0 成功 / -1 参数或长度错(len < 6) + * 函数说明:纯只读,不改动 buf。 + */ +int iec104_asdu_parse_hdr(const uint8_t *buf, uint16_t len, iec104_asdu_hdr_t *hdr); + +/* + * 函数功能:写 ASDU 头 + * 入口参数:buf - 目标缓冲(容量须 ≥ 6);type/vsq/cot/cot_hi/ca 见常量 + * 返 回 值:固定 6(已写字节数) + */ +uint16_t iec104_asdu_put_hdr(uint8_t *buf, uint8_t type, uint8_t vsq, + uint8_t cot, uint8_t cot_hi, uint16_t ca); + +/* ---------------- 小工具(IOA 3B 小端 / IEEE 短浮点小端) ---------------- */ + +/* IOA(3 字节小端)写入 */ +void iec104_put_ioa(uint8_t *buf, uint32_t ioa); +/* IOA(3 字节小端)读取 */ +uint32_t iec104_get_ioa(const uint8_t *buf); +/* IEEE754 float 按 104 小端写入(memcpy 位模式,不做字节序假设) */ +void iec104_put_float(uint8_t *buf, float v); +/* IEEE754 float 按 104 小端读取 */ +float iec104_get_float(const uint8_t *buf); + +/* ---------------- CP56Time2a(C_CS 时钟同步用) ---------------- */ + +/* + * 函数功能:解析 CP56Time2a(7 字节)为 epoch 毫秒 + * 入口参数:buf - 7B 首址;epoch_ms - 输出(UTC 毫秒) + * 返 回 值:0 成功 / -1 参数错 / -2 IV 位置起(时间无效,调用方应拒绝) + * 函数说明:年字段仅 7bit(0..127,基准 2000);月/日/时/分按 1.. 语义; + * 不处理 SU(夏令时)位——忽略。 + */ +int iec104_cp56_to_epoch_ms(const uint8_t *buf, uint64_t *epoch_ms); + +/* + * 函数功能:epoch 毫秒 → CP56Time2a(7 字节,UTC 分解) + * 入口参数:epoch_ms - UTC 毫秒;buf - 目标 7B + * 返 回 值:固定 7 + * 函数说明:epoch_ms < 2000-01-01 时钳到 2000(年字段下限);IV 清 0。 + */ +uint16_t iec104_epoch_ms_to_cp56(uint64_t epoch_ms, uint8_t *buf); + +#endif /* IEC104_ASDU_H */ diff --git a/App/protocol/iec104/iec104_link.c b/App/protocol/iec104/iec104_link.c new file mode 100644 index 00000000..df881608 --- /dev/null +++ b/App/protocol/iec104/iec104_link.c @@ -0,0 +1,777 @@ +/* + * 模块名称:IEC 60870-5-104 链路层(实现) + * 模块功能:实现 iec104_link.h——APCI 流重组与 U/S/I 编解码、STARTDT/STOPDT/ + * TESTFR、k/w 窗与 t1/t2/t3(差值法,tick 回绕安全)、总召分片、 + * COV 突发(k 窗满暂存不丢)、周期上送、遥控/定值两段式、C_RD、 + * C_CS 对时、错误应答(COT 12/13/14 + EVI)。 + * 失败语义:坏帧/序号错/N(R) 越窗/缓冲溢出 → 实例置 IDLE(链路故障), + * 由胶水层检测 IDLE 跳变断开 socket;本层不感知 I/O。 + * 创建日期:2026-10-12(B4) + */ +#include "iec104_link.h" + +#include "iec104_asdu.h" + +#include + +/* ---------------- APCI 常量 ---------------- */ +#define APCI_START 0x68u +#define APCI_CTRL_LEN 4u /* len 字段最小值(纯控制域) */ +#define APCI_LEN_MIN 4u +#define APCI_LEN_MAX 252u +#define SEQ_MOD 32768u /* 序号 15bit */ + +/* U 帧控制字节(DL/T 634.5104 表:低 2 位恒 11) */ +#define U_STARTDT_ACT 0x07u +#define U_STARTDT_CON 0x0Bu +#define U_STOPDT_ACT 0x13u +#define U_STOPDT_CON 0x23u +#define U_TESTFR_ACT 0x43u +#define U_TESTFR_CON 0x83u + +/* 本实现单 ASDU 信息体区上限(背景 YC 组 8×5=40 B 最大) */ +#define BODY_MAX 64u +/* 周期上送周期(COT=1) */ +#define PERIOD_MS 60000UL + +/* + * 函数功能:超时判定(now 到达/越过 deadline,tick 回绕安全) + * 返 回 值:1 已到期 / 0 未到期 + */ +static int s_expired(uint32_t now, uint32_t deadline) { + return (((int32_t)(now - deadline)) >= 0) ? 1 : 0; +} + +/* ---------------- 发送原语 ---------------- */ + +/* + * 函数功能:发 U 帧(STARTDT/STOPDT/TESTFR act|con) + * 说明:t1 只约束"需确认的发送"(标准语义)——TESTFR act 置挂起并起 t1; + * STARTDT/STOPDT con 不启动 t1(主站可合法静默,靠 t3 探活)。 + */ +static void s_send_u(iec104_link_t *lk, uint8_t q) { + uint8_t buf[6]; + + if (lk->cfg->send_apdu == NULL) { + return; + } + buf[0] = APCI_START; + buf[1] = APCI_CTRL_LEN; + buf[2] = q; + buf[3] = 0u; + buf[4] = 0u; + buf[5] = 0u; + lk->cfg->send_apdu(lk->ctx, buf, 6u); + /* t1 只约束"需确认的发送"(标准语义):TESTFR act 等 con; + * STARTDT/STOPDT con 不启动 t1——主站可合法静默,靠 t3 探活 */ + if (q == U_TESTFR_ACT) { + lk->testfr_pending = 1u; + lk->t1_deadline = lk->now_ms + IEC104_T1_MS; + } + lk->t3_deadline = lk->now_ms + IEC104_T3_MS; +} + +/* + * 函数功能:发 S 帧(确认已收序号,rx_unacked 清零) + * 说明:S 不需对端确认 → 不起 t1,只刷 t3。 + */ +static void s_send_s(iec104_link_t *lk) { + uint8_t buf[6]; + uint16_t r = (uint16_t)(lk->rx_seq << 1); + + if (lk->cfg->send_apdu == NULL) { + return; + } + buf[0] = APCI_START; + buf[1] = APCI_CTRL_LEN; + buf[2] = 0x01u; + buf[3] = 0u; + buf[4] = (uint8_t)(r & 0xFFu); + buf[5] = (uint8_t)(r >> 8); + lk->cfg->send_apdu(lk->ctx, buf, 6u); + lk->rx_unacked = 0u; + lk->t3_deadline = lk->now_ms + IEC104_T3_MS; /* S 不需确认 → 不起 t1 */ +} + +/* + * 函数功能:发一个 I 帧(asdu 由调用方组好,N(S)/N(R) 由本层填) + * 返 回 值:0 已发出 / -1 k 窗满或超长(调用方保留数据下次重试) + */ +static int s_send_i(iec104_link_t *lk, const uint8_t *asdu, uint16_t len) { + uint8_t buf[6u + BODY_MAX]; + uint16_t s16; + uint16_t r16; + + if ((lk->cfg->send_apdu == NULL) || (len > BODY_MAX)) { + return -1; + } + if (lk->tx_unacked >= IEC104_K_MAX) { + return -1; + } + buf[0] = APCI_START; + buf[1] = (uint8_t)(APCI_CTRL_LEN + len); + s16 = (uint16_t)(lk->tx_seq << 1); + r16 = (uint16_t)(lk->rx_seq << 1); + buf[2] = (uint8_t)(s16 & 0xFFu); + buf[3] = (uint8_t)(s16 >> 8); + buf[4] = (uint8_t)(r16 & 0xFFu); + buf[5] = (uint8_t)(r16 >> 8); + (void)memcpy(&buf[6], asdu, len); + lk->tx_seq = (uint16_t)((lk->tx_seq + 1u) % SEQ_MOD); + lk->tx_unacked++; + lk->cfg->send_apdu(lk->ctx, buf, (uint16_t)(6u + len)); + lk->t1_deadline = lk->now_ms + IEC104_T1_MS; + lk->t3_deadline = lk->now_ms + IEC104_T3_MS; + return 0; +} + +/* + * 函数功能:组 ASDU(hdr [+ ioa] + body)并发 I 帧 + * 说明:evi=1 → OA bit7(EVI,未知 IOA/类型/地址类应答) + * 返 回 值:同 s_send_i + */ +static int s_send_asdu(iec104_link_t *lk, uint8_t type, uint8_t vsq, + uint8_t cot, uint8_t cot_hi, + uint8_t with_ioa, uint32_t ioa, + const uint8_t *body, uint16_t body_len, uint8_t evi) { + uint8_t buf[6u + BODY_MAX]; + uint16_t n; + + n = iec104_asdu_put_hdr(buf, type, vsq, cot, cot_hi, lk->cfg->ca); + if (evi != 0u) { + buf[3] |= 0x80u; /* OA bit7 = EVI */ + } + if (with_ioa != 0u) { + iec104_put_ioa(&buf[n], ioa); + n += 3u; + } + if (body_len > 0u) { + if ((uint32_t)n + (uint32_t)body_len > (uint32_t)sizeof(buf)) { + return -1; + } + (void)memcpy(&buf[n], body, body_len); + n += body_len; + } + return s_send_i(lk, buf, n); +} + +/* + * 函数功能:命令应答(actcon/deactcon 等)——原样回显信息体(ioa+限定词) + * 入口参数:pn = 1 置否定确认位 + */ +static void s_cmd_con(iec104_link_t *lk, uint8_t type, const uint8_t *obj, + uint16_t obj_len, uint8_t cot, uint8_t pn) { + uint8_t body[BODY_MAX]; + uint16_t n = obj_len; + + if (n > BODY_MAX) { + n = 0u; + } + if (n > 0u) { + (void)memcpy(body, obj, n); + } + (void)s_send_asdu(lk, type, 1u, cot, + (pn != 0u) ? IEC104_COT_BIT_PN : 0u, + 0u, 0u, body, n, 0u); +} + +/* ---------------- 数据上送 ---------------- */ + +/* + * 函数功能:单点上送遥测(M_ME_NC_1 SQ=0,值+QDS) + * 返 回 值:同 s_send_i + */ +static int s_send_yc_single(iec104_link_t *lk, uint8_t idx, uint8_t cot) { + uint8_t body[5]; + float v; + uint8_t qds; + + (void)iec104_pts_yc_read(idx, &v, &qds); + iec104_put_float(body, v); + body[4] = qds; + return s_send_asdu(lk, IEC104_T_M_ME_NC_1, 1u, cot, 0u, 1u, + iec104_pts_yc_ioa(idx), body, 5u, 0u); +} + +/* + * 函数功能:总召/周期扫描一步(phase 游标 = interp_yx_idx: + * 0 双点组→1 单点组→2 YC 组→3 频率→4 actterm) + * 入口参数:budget = 本 poll 发送预算(成功一步减一);periodic = 周期扫描 + * 返 回 值:0 本步已发出 / -1 k 窗满原地保留(poll 循环必须就此停步, + * 否则死循环——2026-10-12 单测抓到) + */ +static int s_scan_step(iec104_link_t *lk, uint8_t *budget, uint8_t periodic) { + uint8_t body[BODY_MAX]; + uint8_t n = 0u; + uint8_t i; + uint8_t d; + uint8_t qds; + float v; + int rc = -1; + + switch (lk->interp_yx_idx) { + case 0u: /* YX 双点组 SQ=1,IOA 1..4 */ + for (i = 0u; i < 4u; i++) { + iec104_pts_yx_read(i, &d); + body[n++] = d; + } + rc = s_send_asdu(lk, IEC104_T_M_DP_NA_1, (uint8_t)(IEC104_VSQ_SQ | 4u), + lk->interp_cot, 0u, 1u, 1u, body, n, 0u); + break; + case 1u: /* YX 单点组 SQ=1,IOA 5..33 */ + for (i = 4u; i < 33u; i++) { + iec104_pts_yx_read(i, &d); + body[n++] = d; + } + rc = s_send_asdu(lk, IEC104_T_M_SP_NA_1, (uint8_t)(IEC104_VSQ_SQ | 29u), + lk->interp_cot, 0u, 1u, 5u, body, n, 0u); + break; + case 2u: /* YC 组 SQ=1,IOA 0x4011..0x4018 */ + for (i = 0u; i < 8u; i++) { + (void)iec104_pts_yc_read(i, &v, &qds); + iec104_put_float(&body[n], v); + n += 4u; + body[n++] = qds; + } + rc = s_send_asdu(lk, IEC104_T_M_ME_NC_1, (uint8_t)(IEC104_VSQ_SQ | 8u), + lk->interp_cot, 0u, 1u, 0x4011u, body, n, 0u); + break; + case 3u: /* 频率单点 SQ=0,IOA 0x401D */ + (void)iec104_pts_yc_read(8u, &v, &qds); + iec104_put_float(&body[n], v); + n += 4u; + body[n++] = qds; + rc = s_send_asdu(lk, IEC104_T_M_ME_NC_1, 1u, lk->interp_cot, 0u, + 1u, 0x401Du, body, n, 0u); + break; + default: /* actterm(仅总召;周期扫描不走这步) */ + iec104_put_ioa(&body[n], 0u); + n += 3u; + body[n++] = IEC104_RQT_GROUP1; + rc = s_send_asdu(lk, IEC104_T_C_IC_NA_1, 1u, IEC104_COT_ACTTERM, 0u, + 0u, 0u, body, n, 0u); + break; + } + if (rc != 0) { + return -1; /* k 窗满:下次 poll 重试本 phase */ + } + (*budget)--; + lk->interp_yx_idx++; + if (periodic != 0u) { + if (lk->interp_yx_idx >= 4u) { + lk->interp_step = 0u; /* 周期只发 YC(phase 2..3),无 actterm */ + } + } else if (lk->interp_yx_idx >= 5u) { + lk->interp_step = 0u; + lk->init_pending = 0u; + } + return 0; +} + +/* + * 函数功能:突发(COV)上送——pend 暂存逐点 SQ=0 COT=3,发成功才清位 + */ +static void s_spont_step(iec104_link_t *lk, uint8_t *budget) { + uint8_t body[5]; + uint8_t i; + uint8_t d; + int rc; + + while ((*budget > 0u) && ((lk->pend_yx != 0u) || (lk->pend_yc != 0u))) { + if (lk->pend_yx != 0u) { + i = 0u; + while (i < 33u) { + if ((lk->pend_yx & (1uLL << i)) != 0u) { + break; + } + i++; + } + iec104_pts_yx_read(i, &d); + body[0] = d; + rc = s_send_asdu(lk, + (i < 4u) ? IEC104_T_M_DP_NA_1 + : IEC104_T_M_SP_NA_1, + 1u, IEC104_COT_SPONT, 0u, 1u, + (uint32_t)i + 1u, body, 1u, 0u); + if (rc != 0) { + return; /* k 窗满:pend 位保留,下次续发 */ + } + lk->pend_yx &= ~(1uLL << i); + } else { + i = 0u; + while (i < 16u) { + if ((lk->pend_yc & (uint16_t)(1u << i)) != 0u) { + break; + } + i++; + } + rc = s_send_yc_single(lk, i, IEC104_COT_SPONT); + if (rc != 0) { + return; + } + lk->pend_yc &= (uint16_t)~(1u << i); + } + (*budget)--; + } +} + +/* ---------------- 命令处理 ---------------- */ + +/* + * 函数功能:C_IC_NA_1 总召处理(ACT → actcon + 启动扫描;DEACT → deactcon) + * 说明:RBT(bit4)落在 COT 6bit 值域内,ACT+RBT 上收为 22——先剥再判; + * 首召/RBT → COT=4(init),后续 COT=2(bg) + */ +static void s_h_ic(iec104_link_t *lk, const iec104_asdu_hdr_t *h) { + /* RBT(bit4)落在 COT 6bit 值域内:ACT+RBT 上收为 22——先剥 RBT 再判值 */ + uint8_t cot_val = (uint8_t)(h->cot & 0xEFu); + + if (cot_val == IEC104_COT_DEACT) { + lk->interp_step = 0u; + s_cmd_con(lk, IEC104_T_C_IC_NA_1, h->obj, h->obj_len, + IEC104_COT_DEACTCON, 0u); + return; + } + if (cot_val != IEC104_COT_ACT) { + return; + } + if ((h->obj_len < 4u) || (h->obj[3] != IEC104_RQT_GROUP1)) { + s_cmd_con(lk, IEC104_T_C_IC_NA_1, h->obj, h->obj_len, + IEC104_COT_ACTCON, 1u); + return; + } + s_cmd_con(lk, IEC104_T_C_IC_NA_1, h->obj, h->obj_len, IEC104_COT_ACTCON, 0u); + lk->interp_step = 1u; + lk->interp_yx_idx = 0u; + lk->interp_cot = ((lk->init_pending != 0u) + || ((h->cot & IEC104_COT_BIT_RBT) != 0u)) + ? (uint8_t)IEC104_COT_INIT : (uint8_t)IEC104_COT_BG_SCAN; +} + +/* + * 函数功能:C_CS_NA_1 对时(CP56 → epoch → cfg->clock_sync) + * 说明:IV/字段坏/系统侧拒绝 → actcon + PN + */ +static void s_h_cs(iec104_link_t *lk, const iec104_asdu_hdr_t *h) { + uint64_t epoch = 0u; + int rc = -1; + + if (h->obj_len >= 10u) { + rc = iec104_cp56_to_epoch_ms(&h->obj[3], &epoch); + if ((rc == 0) && (lk->cfg->clock_sync != NULL)) { + rc = lk->cfg->clock_sync(lk->ctx, epoch); + } + } + s_cmd_con(lk, IEC104_T_C_CS_NA_1, h->obj, h->obj_len, IEC104_COT_ACTCON, + (rc == 0) ? 0u : 1u); +} + +/* + * 函数功能:C_DC_NA_1 遥控两段式(选择记 ioa+dpc;执行须匹配,否则 PN) + */ +static void s_h_dc(iec104_link_t *lk, const iec104_asdu_hdr_t *h) { + uint32_t ioa; + uint8_t qdc; + uint8_t sel; + uint8_t dpc; + int rc; + + if (h->obj_len < 4u) { + return; + } + ioa = iec104_get_ioa(h->obj); + qdc = h->obj[3]; + sel = (uint8_t)(((qdc & IEC104_QDC_S) != 0u) ? 1u : 0u); + dpc = (uint8_t)(qdc & 0x03u); + if (sel != 0u) { + rc = iec104_pts_yk_exec(ioa, dpc, 1u); + if (rc == 0) { + lk->yk_sel_ioa = ioa; + lk->yk_sel_dpc = dpc; + } + } else { + if ((lk->yk_sel_ioa == ioa) && (lk->yk_sel_dpc == dpc)) { + rc = iec104_pts_yk_exec(ioa, dpc, 0u); + } else { + rc = -1; /* 无选择/失配 → 否定确认 */ + } + lk->yk_sel_ioa = 0u; + lk->yk_sel_dpc = 0u; + } + s_cmd_con(lk, IEC104_T_C_DC_NA_1, h->obj, h->obj_len, IEC104_COT_ACTCON, + (rc == 0) ? 0u : 1u); +} + +/* + * 函数功能:C_SE_NC_1 定值两段式写(选择段只校验;执行段落盘) + * 说明:越界/未知地址 → actcon + PN + */ +static void s_h_se(iec104_link_t *lk, const iec104_asdu_hdr_t *h) { + uint32_t addr; + float v; + uint8_t sel; + int rc; + + if (h->obj_len < 8u) { + return; + } + addr = iec104_get_ioa(h->obj); + v = iec104_get_float(&h->obj[3]); + sel = (uint8_t)(((h->obj[7] & IEC104_QDC_S) != 0u) ? 1u : 0u); + rc = iec104_pts_set_write(addr, v, sel); + s_cmd_con(lk, IEC104_T_C_SE_NC_1, h->obj, h->obj_len, IEC104_COT_ACTCON, + (rc == 0) ? 0u : 1u); +} + +/* + * 函数功能:C_RD_NA_1 读单个信息体(YC 命中 → M_ME COT5;定值命中 → 同; + * 未知 IOA → 原样回 C_RD + COT14 + EVI) + */ +static void s_h_rd(iec104_link_t *lk, const iec104_asdu_hdr_t *h) { + uint32_t ioa; + uint8_t i; + float v; + + if (h->obj_len < 3u) { + return; + } + ioa = iec104_get_ioa(h->obj); + for (i = 0u; i < iec104_pts_yc_count(); i++) { + if (iec104_pts_yc_ioa(i) == ioa) { + s_send_yc_single(lk, i, IEC104_COT_REQ); + return; + } + } + if (iec104_pts_set_read(ioa, &v) == 0) { + uint8_t body[5]; + + iec104_put_float(body, v); + body[4] = 0u; + (void)s_send_asdu(lk, IEC104_T_M_ME_NC_1, 1u, IEC104_COT_REQ, 0u, + 1u, ioa, body, 5u, 0u); + return; + } + (void)s_send_asdu(lk, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_UNK_IOA, 0u, + 1u, ioa, NULL, 0u, 1u); +} + +/* + * 函数功能:ASDU 分派(公共地址校验 → 类型路由) + * 说明:错 ca → COT13+EVI;未知类型 → COT12+EVI(原类型回) + */ +static void s_h_asdu(iec104_link_t *lk, const uint8_t *asdu, uint16_t len) { + iec104_asdu_hdr_t h; + + if (iec104_asdu_parse_hdr(asdu, len, &h) != 0) { + return; + } + if (h.ca != lk->cfg->ca) { + (void)s_send_asdu(lk, h.type, 1u, IEC104_COT_UNK_CA, 0u, + 0u, 0u, NULL, 0u, 1u); + return; + } + switch (h.type) { + case IEC104_T_C_IC_NA_1: + s_h_ic(lk, &h); + break; + case IEC104_T_C_CS_NA_1: + s_h_cs(lk, &h); + break; + case IEC104_T_C_DC_NA_1: + s_h_dc(lk, &h); + break; + case IEC104_T_C_SE_NC_1: + s_h_se(lk, &h); + break; + case IEC104_T_C_RD_NA_1: + s_h_rd(lk, &h); + break; + case IEC104_T_C_TS_NA_1: + s_cmd_con(lk, IEC104_T_C_TS_NA_1, h.obj, h.obj_len, + IEC104_COT_ACTCON, 0u); + break; + case IEC104_T_C_RP_NA_1: + iec104_pts_cov_check(NULL); /* 进程复位:重建快照(清历史) */ + s_cmd_con(lk, IEC104_T_C_RP_NA_1, h.obj, h.obj_len, + IEC104_COT_ACTCON, 0u); + break; + default: + (void)s_send_asdu(lk, h.type, 1u, IEC104_COT_UNK_COT, 0u, + 0u, 0u, NULL, 0u, 1u); + break; + } +} + +/* ---------------- APDU 分派 ---------------- */ + +/* + * 函数功能:U 帧处理(STARTDT/STOPDT act → con + 态迁移;TESTFR act → con; + * TESTFR con → 清挂起) + */ +static void s_h_u(iec104_link_t *lk, uint8_t q) { + switch (q) { + case U_STARTDT_ACT: + s_send_u(lk, U_STARTDT_CON); + lk->state = IEC104_ST_RUN; + lk->interp_step = 0u; + lk->yk_sel_ioa = 0u; + break; + case U_STOPDT_ACT: + s_send_u(lk, U_STOPDT_CON); + lk->state = IEC104_ST_STOPPED; + lk->interp_step = 0u; + break; + case U_TESTFR_ACT: + s_send_u(lk, U_TESTFR_CON); + break; + case U_TESTFR_CON: + lk->testfr_pending = 0u; + break; + default: + break; /* con/未知 U:t1/t3 已由外层刷新 */ + } +} + +/* + * 函数功能:N(R) 校验并更新 tx_unacked(V(A) ≤ V(A)' ≤ V(S),即 0 ≤ d ≤ 窗内) + * 说明:N(R) 倒退(早于上次确认)= 协议违例 → 链路故障(标准语义); + * tx_unacked 恒 ≤ k(发送侧门控),故 d ≤ tx_unacked 已蕴含窗校验 + * 返 回 值:0 / -1 违例 + */ +static int s_apply_nr(iec104_link_t *lk, uint16_t nr) { + uint16_t d = (uint16_t)(((uint32_t)lk->tx_seq + SEQ_MOD - (uint32_t)nr) + % SEQ_MOD); + + if ((uint32_t)d > (uint32_t)lk->tx_unacked) { + return -1; + } + lk->tx_unacked = d; + return 0; +} + +/* + * 函数功能:单个完整 APDU 分派(U/S/I);任何接收只刷 t3(不刷 t1) + * 说明:OPEN 态只认 U;I 帧 N(S) 不连续 → IDLE;RUN 态才处理 ASDU; + * 收满 w 个未确认 → 回 S + */ +static void s_h_apdu(iec104_link_t *lk, const uint8_t *p, uint16_t total) { + const uint8_t *c = &p[2]; /* 控制域 4B */ + uint16_t ns; + uint16_t nr; + + lk->t3_deadline = lk->now_ms + IEC104_T3_MS; + if ((c[0] & 0x03u) == 0x03u) { + s_h_u(lk, c[0]); + return; + } + if (lk->state == IEC104_ST_OPEN) { + return; /* OPEN 态只认 U 帧 */ + } + if ((c[0] & 0x01u) != 0u) { /* S 格式 */ + nr = (uint16_t)(((uint16_t)c[2] | ((uint16_t)c[3] << 8)) >> 1); + if (s_apply_nr(lk, nr) != 0) { + lk->state = IEC104_ST_IDLE; + } + return; + } + /* I 格式 */ + ns = (uint16_t)(((uint16_t)c[0] | ((uint16_t)c[1] << 8)) >> 1); + nr = (uint16_t)(((uint16_t)c[2] | ((uint16_t)c[3] << 8)) >> 1); + if (ns != lk->rx_seq) { + lk->state = IEC104_ST_IDLE; /* 序号错 → 链路故障 */ + return; + } + if (s_apply_nr(lk, nr) != 0) { + lk->state = IEC104_ST_IDLE; + return; + } + lk->rx_seq = (uint16_t)((ns + 1u) % SEQ_MOD); + lk->rx_unacked++; + if (lk->rx_unacked == 1u) { + lk->t2_deadline = lk->now_ms + IEC104_T2_MS; + } + if (lk->state == IEC104_ST_RUN) { + s_h_asdu(lk, &p[6], (uint16_t)(total - 6u)); + } + if (lk->rx_unacked >= IEC104_W_MAX) { + s_send_s(lk); + } +} + +/* ---------------- 公开接口 ---------------- */ + +/* + * 函数功能:链路实例初始化(全清零 + 绑配置与上下文,态 = IDLE) + */ +void iec104_link_init(iec104_link_t *lk, const iec104_link_cfg_t *cfg, + void *ctx) { + (void)memset(lk, 0, sizeof(*lk)); + lk->cfg = cfg; + lk->ctx = ctx; + lk->state = IEC104_ST_IDLE; +} + +/* + * 函数功能:TCP 连接建立 → OPEN(序号/窗口/定时/暂存全部复位,init_pending=1) + */ +void iec104_link_open(iec104_link_t *lk, uint32_t now_ms) { + lk->state = IEC104_ST_OPEN; + lk->tx_seq = 0u; + lk->rx_seq = 0u; + lk->tx_unacked = 0u; + lk->rx_unacked = 0u; + lk->testfr_pending = 0u; + lk->init_pending = 1u; + lk->rx_len = 0u; + lk->yk_sel_ioa = 0u; + lk->yk_sel_dpc = 0u; + lk->interp_step = 0u; + lk->interp_yx_idx = 0u; + lk->pend_yx = 0u; + lk->pend_yc = 0u; + lk->now_ms = now_ms; + lk->t1_deadline = now_ms + IEC104_T1_MS; + lk->t2_deadline = now_ms + IEC104_T2_MS; + lk->t3_deadline = now_ms + IEC104_T3_MS; + lk->period_next = now_ms + PERIOD_MS; +} + +/* + * 函数功能:链路断开/故障 → IDLE(清重组缓冲与所有暂存) + */ +void iec104_link_close(iec104_link_t *lk) { + lk->state = IEC104_ST_IDLE; + lk->rx_len = 0u; + lk->interp_step = 0u; + lk->pend_yx = 0u; + lk->pend_yc = 0u; + lk->yk_sel_ioa = 0u; + lk->yk_sel_dpc = 0u; +} + +/* + * 函数功能:喂入收到的原始字节(APCI 流重组:半帧/粘帧逐处) + * 说明:坏起始符/坏长度/缓冲溢出 → IDLE(胶水层检测后断开 socket) + */ +void iec104_link_on_rx(iec104_link_t *lk, const uint8_t *data, uint16_t len, + uint32_t now_ms) { + lk->now_ms = now_ms; + if ((lk->state == IEC104_ST_IDLE) || (data == NULL)) { + return; + } + if ((uint32_t)len > (uint32_t)(IEC104_RXBUF_SZ - lk->rx_len)) { + lk->state = IEC104_ST_IDLE; /* 重组缓冲溢出 = 坏流 */ + lk->rx_len = 0u; + return; + } + (void)memcpy(&lk->rx_buf[lk->rx_len], data, len); + lk->rx_len = (uint16_t)(lk->rx_len + len); + + while (lk->rx_len >= 2u) { + uint16_t lf; + uint16_t need; + + if (lk->rx_buf[0] != APCI_START) { + lk->state = IEC104_ST_IDLE; + break; + } + lf = lk->rx_buf[1]; + if ((lf < APCI_LEN_MIN) || (lf > APCI_LEN_MAX)) { + lk->state = IEC104_ST_IDLE; + break; + } + need = (uint16_t)(lf + 2u); + if (lk->rx_len < need) { + break; /* 半帧:等下次 on_rx */ + } + s_h_apdu(lk, lk->rx_buf, need); + if (lk->state == IEC104_ST_IDLE) { + break; + } + if (need < lk->rx_len) { + (void)memmove(lk->rx_buf, &lk->rx_buf[need], + (uint16_t)(lk->rx_len - need)); + } + lk->rx_len = (uint16_t)(lk->rx_len - need); + } + if (lk->state == IEC104_ST_IDLE) { + lk->rx_len = 0u; + } +} + +/* + * 函数功能:周期节拍(胶水层每次服务循环调用一次,时基由调用方注入) + * 说明:t1 超时 → close;t3 到期 → TESTFR act;t2 到期 → S; + * RUN 态按优先级:总召续扫 > 周期续扫 > COV 突发 > 周期触发 + */ +void iec104_link_poll(iec104_link_t *lk, uint32_t now_ms) { + uint8_t budget = IEC104_POLL_BUDGET; + + lk->now_ms = now_ms; + if ((lk->state != IEC104_ST_RUN) && (lk->state != IEC104_ST_STOPPED)) { + return; + } + if (((lk->tx_unacked > 0u) || (lk->testfr_pending != 0u)) + && (s_expired(now_ms, lk->t1_deadline) != 0)) { + iec104_link_close(lk); /* t1:未确认 I/未答 TESTFR 超时 = 故障 */ + return; + } + if (s_expired(now_ms, lk->t3_deadline) != 0) { + s_send_u(lk, U_TESTFR_ACT); + } + if ((lk->rx_unacked > 0u) && (s_expired(now_ms, lk->t2_deadline) != 0)) { + s_send_s(lk); + } + if (lk->state != IEC104_ST_RUN) { + return; + } + if (lk->interp_step == 1u) { + while ((budget > 0u) && (lk->interp_step == 1u)) { + if (s_scan_step(lk, &budget, 0u) != 0) { + break; /* k 窗满:本 poll 停步(防死循环) */ + } + } + return; + } + if (lk->interp_step == 3u) { + while ((budget > 0u) && (lk->interp_step == 3u)) { + if (s_scan_step(lk, &budget, 1u) != 0) { + break; + } + } + return; + } + if ((lk->pend_yx != 0u) || (lk->pend_yc != 0u)) { + s_spont_step(lk, &budget); + if (budget == 0u) { + return; + } + } + if (s_expired(now_ms, lk->period_next) != 0) { + lk->interp_step = 3u; + lk->interp_yx_idx = 2u; /* 周期只扫 YC(phase 2..3) */ + lk->interp_cot = IEC104_COT_PERIODIC; + lk->period_next = now_ms + PERIOD_MS; + while ((budget > 0u) && (lk->interp_step == 3u)) { + if (s_scan_step(lk, &budget, 1u) != 0) { + break; + } + } + return; + } + { + iec104_pts_cov_t cov; + + iec104_pts_cov_check(&cov); + lk->pend_yx |= cov.yx_changed; + lk->pend_yc |= cov.yc_changed; + s_spont_step(lk, &budget); + } +} + +/* + * 函数功能:查询链路状态(胶水层检测 IDLE 跳变以断开/重建 socket) + */ +iec104_state_t iec104_link_state(const iec104_link_t *lk) { + return lk->state; +} diff --git a/App/protocol/iec104/iec104_link.h b/App/protocol/iec104/iec104_link.h new file mode 100644 index 00000000..0405a998 --- /dev/null +++ b/App/protocol/iec104/iec104_link.h @@ -0,0 +1,136 @@ +/* + * 模块名称:IEC 60870-5-104 链路层(APCI + 状态机,纯逻辑) + * 模块功能:TCP 流 → APDU 重组、U/S/I 帧编解码、STARTDT/STOPDT/TESTFR、 + * k/w 流量窗与 t1/t2/t3 超时、发送序号 N(S)/N(R) 管理,以及应用层 + * 流程编排:总召(act→背景扫描→actterm,首召 RBT 用 COT=4)、 + * 突发上送(COV,COT=3)、周期上送(COT=1)、读单个(C_RD→COT=5)、 + * 双点遥控两段式(选择/执行,失配否定确认 PN)、定值读(C_RD)/ + * 定值写(C_SE_NC 选择=范围校验 / 执行=写入+封存)、时钟同步(C_CS + * → clock_sync 回调)、试验(C_TS)与进程复位(C_RP,清快照)。 + * **零 I/O**:收 = on_rx 喂 TCP 流片段,发 = send_apdu 回调, + * 时基 = 调用方注入 now_ms(tick ms,回绕安全:差值法) + * → 全栈(asdu+pts+link)主机侧 L0.5 可离线跑(登记簿 A-4 约束 1)。 + * 参数(DL/T 634.5104 标准默认,§1.5 未另定):k=12 w=8 t1=15s t2=10s t3=20s。 + * 端口:TCP **2404**(§1.5 B0 定义;本 DTU = 被控站/服务器,主站连入)。 + * 线程约定:单实例单任务上下文(板端 = 104 服务在 netTask 消息循环内驱动, + * 见 iec104_serv 胶水层);非线程安全,禁止多任务共享一实例。 + * 失败语义:send_apdu 内**不得阻塞**;发送失败由胶水层断链(主站会重连), + * 本层不感知发送失败。 + * 创建日期:2026-10-12(B4) + */ +#ifndef IEC104_LINK_H +#define IEC104_LINK_H + +#include + +#include "iec104_pts.h" + +/* 服务端口(§1.5:以太网 TCP 2404) */ +#define IEC104_PORT 2404U + +/* 链路参数(标准默认值) */ +#define IEC104_K_MAX 12U /* 未确认 I 帧上限 */ +#define IEC104_W_MAX 8U /* 收到 I 帧未发确认的强制 S 阈值 */ +#define IEC104_T1_MS 15000UL /* 发送/确认超时(超时 = 链路故障) */ +#define IEC104_T2_MS 10000UL /* 无 I 发送时强制 S 确认超时(< t1) */ +#define IEC104_T3_MS 20000UL /* 空闲发 TESTFR 周期(< t1) */ + +/* TCP 流重组缓冲:APDU 上限 253 + 半帧余量 */ +#define IEC104_RXBUF_SZ 512U + +/* 单次 poll 发送预算(ASDU 数)——防总召大扫描饿死宿主任务 */ +#define IEC104_POLL_BUDGET 4U + +/* 链路状态 */ +typedef enum { + IEC104_ST_IDLE = 0, /* TCP 未建立(或已断开) */ + IEC104_ST_OPEN, /* TCP 已建立,等 STARTDT act */ + IEC104_ST_RUN, /* STARTDT 已确认,数据服务开 */ + IEC104_ST_STOPPED /* STOPDT 已确认:停数据,保 S/TESTFR */ +} iec104_state_t; + +/* 配置与回调(ctx 原样回传给回调) */ +typedef struct { + uint16_t ca; /* 公共地址 = 链路地址(2B,§1.5) */ + /* 发一个完整 APDU(含 6B APCI 头)。不得阻塞;生命周期仅回调内有效 */ + void (*send_apdu)(void *ctx, const uint8_t *apdu, uint16_t len); + /* C_CS 时钟同步:epoch 毫秒;NULL 或返回 -1 → 否定确认 */ + int (*clock_sync)(void *ctx, uint64_t epoch_ms); +} iec104_link_cfg_t; + +/* 链路实例(胶水层静态持有,零堆) */ +typedef struct { + const iec104_link_cfg_t *cfg; + void *ctx; + iec104_state_t state; + uint8_t init_pending; /* 1 = 下次总召按初始化(COT=4 + RBT) */ + /* 序号(0..32767,帧内 ×2) */ + uint16_t tx_seq; + uint16_t rx_seq; + uint16_t tx_unacked; /* 已发 I 未获认(k 窗) */ + uint16_t rx_unacked; /* 已收 I 未确认(w 阈) */ + uint8_t testfr_pending; /* 1 = TESTFR act 未获 con(t1 同样约束它) */ + /* 定时器到期时刻(now_ms 域;差值法判超时,回绕安全) */ + uint32_t t1_deadline; + uint32_t t2_deadline; + uint32_t t3_deadline; + uint32_t now_ms; + /* TCP 流重组 */ + uint8_t rx_buf[IEC104_RXBUF_SZ]; + uint16_t rx_len; + /* 总召进度:0 无 / 1 背景扫描中 / 2 待发 actterm */ + uint8_t interp_step; + uint8_t interp_yc_idx; /* 背景扫描 YC 游标 */ + uint8_t interp_yx_idx; /* 背景扫描 YX 游标 */ + uint8_t interp_cot; /* 本次总召用的 COT(BG_SCAN 或 INIT) */ + /* 遥控选择暂存(执行段比对) */ + uint32_t yk_sel_ioa; /* 0 = 无选择 */ + uint8_t yk_sel_dpc; + /* 周期上送(COT=1)下次触发时刻 */ + uint32_t period_next; + /* COV 待发暂存(k 窗满时保留到下次 poll,变化不许丢) */ + uint64_t pend_yx; + uint16_t pend_yc; +} iec104_link_t; + +/* + * 函数功能:初始化实例(置 IDLE、清序号;不发送任何帧) + * 入口参数:lk - 实例;cfg/ctx - 配置与回调上下文 + */ +void iec104_link_init(iec104_link_t *lk, const iec104_link_cfg_t *cfg, void *ctx); + +/* + * 函数功能:TCP 连接建立(新连接或重连后调用) + * 入口参数:now_ms - 当前时基 + * 函数说明:序号清零、init_pending 置位(首召 = 初始化总召)、进 OPEN。 + */ +void iec104_link_open(iec104_link_t *lk, uint32_t now_ms); + +/* + * 函数功能:TCP 断开(对端断开或胶水层发送失败主动断链时调用) + * 函数说明:回 IDLE、清重组缓冲与选择暂存;不发送任何帧。 + */ +void iec104_link_close(iec104_link_t *lk); + +/* + * 函数功能:喂入 TCP 收到的流片段(任意切分/粘帧) + * 入口参数:data/len - 流片段;now_ms - 当前时基 + * 函数说明:内部重组,凑齐 APDU 即处理;坏帧(起始符/长度非法)→ 视同链路 + * 故障,实例回 IDLE(胶水层检测到 IDLE 跳变应断开 socket)。 + * 返回后实例仍为 RUN 不代表对端合法——仅表示未触发断链条件。 + */ +void iec104_link_on_rx(iec104_link_t *lk, const uint8_t *data, uint16_t len, + uint32_t now_ms); + +/* + * 函数功能:周期驱动(定时器 + COV + 总召分片 + 周期上送) + * 入口参数:now_ms - 当前时基(建议 ≤100 ms 调一次) + * 函数说明:仅 RUN 态产生数据帧;STOPPED 态只处理 t2/t3(S/TESTFR)。 + * 单次调用发送量 ≤ IEC104_POLL_BUDGET 个 ASDU。 + */ +void iec104_link_poll(iec104_link_t *lk, uint32_t now_ms); + +/* 当前状态(日志/看门狗用) */ +iec104_state_t iec104_link_state(const iec104_link_t *lk); + +#endif /* IEC104_LINK_H */ diff --git a/App/protocol/iec104/iec104_pts.c b/App/protocol/iec104/iec104_pts.c new file mode 100644 index 00000000..49560e6c --- /dev/null +++ b/App/protocol/iec104/iec104_pts.c @@ -0,0 +1,426 @@ +/* + * 模块名称:IEC 60870-5-104 点表与数据源适配(实现) + * 模块功能:实现 iec104_pts.h——YC/YX/YK/定值点表(ROM)、板端默认源 + * (phasor / prot_elm / prot_set)、COV 快照比对(遥信变位 + + * 遥测死区)。点表口径见 iec104_pts.h 文件头与设计文档 §3。 + * 线程约定:init/bind 建服务前;其余仅 104 服务任务上下文(快照非原子)。 + * 创建日期:2026-10-12(B4) + */ +#include "iec104_pts.h" + +#include + +#include "iec104_asdu.h" /* QDS/DIQ 品质位常量 */ +#include "phasor.h" /* 板端源:遥测 = 基波有效值 */ +#include "prot_elm.h" /* 板端源:遥信 = 元件状态 */ +#include "prot_set.h" /* 板端源:定值 + 闭锁 */ +#include "adc_input.h" /* adc_semantic_t(phasor 实例按语义绑定) */ + +/* ---------------- YC 表(§1.5 点号 4011+;死区 = 拟定码值,L1-5 后复核) -- */ +typedef struct { + uint32_t ioa; + int8_t sem; /* 绑定的 phasor 语义通道(-1 = 无 phasor 源,恒无效) */ + float deadband; /* 死区(工程量绝对值) */ +} pts_yc_def_t; + +static const pts_yc_def_t k_yc[] = { + { 0x4011u, (int8_t)ADC_SEM_UA, 10.0f }, /* 1Ua */ + { 0x4012u, -1, 10.0f }, /* 1Ub:V0.1 削顶 → IV */ + { 0x4013u, -1, 10.0f }, /* 1Uc:同上 */ + { 0x4014u, (int8_t)ADC_SEM_UN, 10.0f }, /* 1U0(外部零序专用通道) */ + { 0x4015u, (int8_t)ADC_SEM_IA, 10.0f }, /* 1Ia */ + { 0x4016u, -1, 10.0f }, /* 1Ib */ + { 0x4017u, -1, 10.0f }, /* 1Ic */ + { 0x4018u, -1, 10.0f }, /* 1I0 */ + { 0x401Du, -1, 0.5f }, /* 1f:L1-7 未实现 → IV */ +}; +#define YC_N ((uint8_t)(sizeof(k_yc) / sizeof(k_yc[0]))) + +/* phasor 实例下标缓存(init 时按 sem+harm==1 查表;-1 = 未找到) */ +static int8_t s_yc_phasor_idx[YC_N]; + +/* ---------------- YX 表(IOA = 1..33;双点 = 开关位置类) ------------------ */ +#define YX_N 33u +#define YX_DP_N 4u /* idx 0..3 = 双点(开关位置,V0.1 无硬件 → IV) */ + +/* 有效位图:YX15~18(idx14~17)+ YX23(idx22)+ YX31(idx30) */ +#define YX_VALID_MASK (((1uLL << 14u) | (1uLL << 15u) | (1uLL << 16u) \ + | (1uLL << 17u) | (1uLL << 22u) | (1uLL << 30u))) + +/* ---------------- 数据源(默认 = 板端;bind_src 可整体替换) -------------- */ +static int s_src_yc_read(uint8_t idx, float *out); +static uint64_t s_src_yx_bits(void); +static uint64_t s_src_yx_valid(void); +static int s_src_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select); +static int s_src_set_read(uint32_t addr, float *out); +static int s_src_set_write(uint32_t addr, float v, uint8_t select); + +static const iec104_pts_src_t k_default_src = { + s_src_yc_read, s_src_yx_bits, s_src_yx_valid, + s_src_yk_exec, s_src_set_read, s_src_set_write +}; +static const iec104_pts_src_t *s_src; + +/* ---------------- COV 快照 ---------------- */ +static float s_yc_last[YC_N]; +static uint16_t s_yc_have; /* bit i = 已有上次快照 */ +static uint64_t s_yx_last; +static uint8_t s_yx_snap_ok; + +/* ============================ 公开接口 ================================== */ + +/* + * 函数功能:初始化点表模块(扫 phasor 基波实例映射、恢复默认源、清快照) + */ +void iec104_pts_init(void) { + uint8_t i; + uint8_t n; + + (void)memset(s_yc_phasor_idx, -1, sizeof(s_yc_phasor_idx)); + n = phasor_inst_count(); + for (i = 0u; i < YC_N; i++) { + uint8_t j; + + if (k_yc[i].sem < 0) { + continue; + } + for (j = 0u; j < n; j++) { + const phasor_inst_t *inst = phasor_inst(j); + + if ((inst != NULL) && ((uint8_t)inst->sem == (uint8_t)k_yc[i].sem) + && (inst->harm == 1u)) { + s_yc_phasor_idx[i] = (int8_t)j; + break; + } + } + } + s_src = &k_default_src; + s_yc_have = 0u; + s_yx_snap_ok = 0u; + s_yx_last = 0u; +} + +/* + * 函数功能:替换数据源(NULL = 恢复板端默认源;单测注入假源) + */ +void iec104_pts_bind_src(const iec104_pts_src_t *src) { + s_src = (src != NULL) ? src : &k_default_src; +} + +/* + * 函数功能:遥测点数 + */ +uint8_t iec104_pts_yc_count(void) { + return YC_N; +} + +/* + * 函数功能:遥测点 IOA(按下标;越界 → 0) + */ +uint32_t iec104_pts_yc_ioa(uint8_t idx) { + return (idx < YC_N) ? k_yc[idx].ioa : 0u; +} + +/* + * 函数功能:读遥测(值 + 品质 descriptor;源 -2 → NT,其余失败 → IV) + * 返 回 值:0 有效 / -1 无效 + */ +int iec104_pts_yc_read(uint8_t idx, float *v, uint8_t *qds) { + int rc; + + if (v != NULL) { + *v = 0.0f; + } + if ((idx >= YC_N) || (s_src == NULL) || (s_src->yc_read == NULL)) { + if (qds != NULL) { + *qds = IEC104_QDS_IV; + } + return -1; + } + rc = s_src->yc_read(idx, v); + if (rc == 0) { + if (qds != NULL) { + *qds = 0u; + } + return 0; + } + if (v != NULL) { + *v = 0.0f; + } + if (qds != NULL) { + *qds = (rc == -2) ? IEC104_QDS_NT : IEC104_QDS_IV; + } + return -1; +} + +/* + * 函数功能:遥信点数 + */ +uint8_t iec104_pts_yx_count(void) { + return (uint8_t)YX_N; +} + +/* + * 函数功能:遥信点 IOA(idx + 1;越界 → 0) + */ +uint32_t iec104_pts_yx_ioa(uint8_t idx) { + return ((uint8_t)idx < YX_N) ? ((uint32_t)idx + 1u) : 0u; +} + +/* + * 函数功能:该遥信是否双点型(idx < 4 = 开关位置类) + */ +uint8_t iec104_pts_yx_is_dp(uint8_t idx) { + return ((uint8_t)idx < YX_DP_N) ? 1u : 0u; +} + +/* + * 函数功能:读遥信(无效通道 → DIQ_IV;双点 → DPC 编码) + */ +void iec104_pts_yx_read(uint8_t idx, uint8_t *out) { + uint64_t bits; + uint64_t valid; + uint8_t on; + + if (out == NULL) { + return; + } + if ((idx >= YX_N) || (s_src == NULL) || (s_src->yx_bits == NULL) + || (s_src->yx_valid == NULL)) { + *out = IEC104_DIQ_IV; + return; + } + valid = s_src->yx_valid(); + if (((valid >> idx) & 1u) == 0u) { + *out = IEC104_DIQ_IV; + return; + } + bits = s_src->yx_bits(); + on = (uint8_t)((bits >> idx) & 1u); + if (iec104_pts_yx_is_dp(idx) != 0u) { + *out = (on != 0u) ? (uint8_t)IEC104_DPC_ON : (uint8_t)IEC104_DPC_OFF; + } else { + *out = on; + } +} + +/* + * 函数功能:COV 快照比对(遥信 = 有效位翻转;遥测 = 死区) + * 入口参数:cov = 输出变位位图(NULL = 只刷快照) + */ +void iec104_pts_cov_check(iec104_pts_cov_t *cov) { + iec104_pts_cov_t local; + + (void)memset(&local, 0, sizeof(local)); + + /* YX:变位 = 有效位上的位翻转(无效位不参与,避免 IV 通道抖动成"变位") */ + if ((s_src != NULL) && (s_src->yx_bits != NULL) + && (s_src->yx_valid != NULL)) { + uint64_t bits = s_src->yx_bits() & s_src->yx_valid(); + + if (s_yx_snap_ok != 0u) { + local.yx_changed = bits ^ s_yx_last; + } + s_yx_last = bits; + s_yx_snap_ok = 1u; + } + + /* YC:死区比对(仅对"本次有效 且 上次有快照"的点判定) */ + if ((s_src != NULL) && (s_src->yc_read != NULL)) { + uint8_t i; + + for (i = 0u; i < YC_N; i++) { + float v; + + if (s_src->yc_read(i, &v) != 0) { + continue; + } + if (((s_yc_have >> i) & 1u) != 0u) { + float d = v - s_yc_last[i]; + + if (d < 0.0f) { + d = -d; + } + if (d > k_yc[i].deadband) { + local.yc_changed |= (uint16_t)(1u << i); + } + } + s_yc_last[i] = v; + s_yc_have |= (uint16_t)(1u << i); + } + } + + if (cov != NULL) { + *cov = local; + } +} + +/* + * 函数功能:遥控两段式(转发数据源;select=1 选择段 / 0 执行段) + * 返 回 值:0 接受 / -1 拒绝(调用方回 PN) + */ +int iec104_pts_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select) { + if ((s_src == NULL) || (s_src->yk_exec == NULL)) { + return -1; + } + return s_src->yk_exec(ioa, dpc, select); +} + +/* + * 函数功能:按通讯地址读定值(工程量浮点) + * 返 回 值:0 / -1 未知地址 + */ +int iec104_pts_set_read(uint32_t addr, float *out) { + if ((s_src == NULL) || (s_src->set_read == NULL)) { + return -1; + } + return s_src->set_read(addr, out); +} + +/* + * 函数功能:按通讯地址写定值(select=1 只校验;0 执行写入) + * 返 回 值:0 / -1 越界或未知地址 + */ +int iec104_pts_set_write(uint32_t addr, float v, uint8_t select) { + if ((s_src == NULL) || (s_src->set_write == NULL)) { + return -1; + } + return s_src->set_write(addr, v, select); +} + +/* ============================ 板端默认源 ================================= */ + +/* + * 函数功能:板端默认源 - 遥测 = 基波相量有效值(fAmSQ) + * 返 回 值:0 / -1 无 phasor 源(削顶通道/频率未实现)/ -2 未满一周波(NT) + */ +static int s_src_yc_read(uint8_t idx, float *out) { + phasor_t p; + int8_t pi; + + if ((idx >= YC_N) || (out == NULL)) { + return -1; + } + pi = s_yc_phasor_idx[idx]; + if (pi < 0) { + return -1; /* 无 phasor 源(削顶通道/频率未实现) */ + } + if (phasor_get((uint8_t)pi, &p) != 0) { + return -2; /* 未满一周波:未就绪(NT) */ + } + *out = p.fAmSQ; /* 有效值口径(系数已折算) */ + return 0; +} + +/* + * 函数功能:板端默认源 - 遥信位图(保护元件动作态 + 定值闭锁) + */ +static uint64_t s_src_yx_bits(void) { + prot_elm_state_t oc1; + prot_elm_state_t oc2; + prot_elm_state_t oc3; + prot_elm_state_t ol; + prot_elm_state_t u0; + uint64_t bits = 0u; + + prot_elm_state(PE_OC1, &oc1); + prot_elm_state(PE_OC2, &oc2); + prot_elm_state(PE_OC3, &oc3); + prot_elm_state(PE_OL, &ol); + prot_elm_state(PE_3U0, &u0); + if ((oc1.asserted != 0u) || (oc2.asserted != 0u) || (oc3.asserted != 0u) + || (u0.asserted != 0u)) { + bits |= (1uLL << 14u); /* YX15 故障总 */ + } + if (oc1.asserted != 0u) { + bits |= (1uLL << 15u); /* YX16 过流 I 段 */ + } + if (oc2.asserted != 0u) { + bits |= (1uLL << 16u); /* YX17 过流 II 段 */ + } + if (oc3.asserted != 0u) { + bits |= (1uLL << 17u); /* YX18 过流 III 段 */ + } + if (ol.asserted != 0u) { + bits |= (1uLL << 22u); /* YX23 过载 */ + } + if (prot_set_locked() != 0u) { + bits |= (1uLL << 30u); /* YX31 保护闭锁 */ + } + return bits; +} + +/* + * 函数功能:板端默认源 - 遥信有效位图(V0.1 = YX15~18/23/31) + */ +static uint64_t s_src_yx_valid(void) { + return YX_VALID_MASK; +} + +/* + * 函数功能:板端默认源 - 遥控(V0.1 仅 YK11 复归 → prot_elm_request_reset) + * 返 回 值:0 / -1 无出口硬件或未知 IOA(YK1~4/12~14 负向确认) + * 函数说明:本回调跑在 iec104Task 上下文,**不得**直接 prot_elm_init() + * (与 protectTask 的 eval 竞态)→ 落请求,下一拍 eval 头部消费(B5)。 + */ +static int s_src_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select) { + (void)dpc; /* 本期仅 YK11 与双点值无关(复归) */ + switch (ioa) { + case 0x600Au: /* YK11 信号复归 → 元件状态复位(异步一拍) */ + if (select == 0u) { + prot_elm_request_reset(); + } + return 0; + default: + return -1; /* 其余 YK:无出口硬件/无对应能力 → 拒绝 */ + } +} + +/* + * 函数功能:板端默认源 - 定值读(扫 g_prot_set_meta 通讯地址映射) + * 返 回 值:0 / -1 未知地址 + */ +static int s_src_set_read(uint32_t addr, float *out) { + uint32_t i; + + if (out == NULL) { + return -1; + } + for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { + if (g_prot_set_meta[i].comm_addr == (uint16_t)addr) { + *out = prot_set_get_f((prot_set_id_t)i); + return 0; + } + } + return -1; +} + +/* + * 函数功能:板端默认源 - 定值写(Q10 范围校验;执行段 prot_set_set + seal) + * 返 回 值:0 / -1 越界或未知地址 + */ +static int s_src_set_write(uint32_t addr, float v, uint8_t select) { + uint32_t i; + int32_t q10; + + for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { + const prot_set_meta_t *meta = &g_prot_set_meta[i]; + + if (meta->comm_addr != (uint16_t)addr) { + continue; + } + q10 = PROT_SET_Q10(v); + if ((q10 < meta->min) || (q10 > meta->max)) { + return -1; /* 越界:选择段即拒(执行段同样拒) */ + } + if (select != 0u) { + return 0; /* 选择段 = 只做范围校验 */ + } + if (prot_set_set((prot_set_id_t)i, q10) != 0) { + return -1; + } + prot_set_seal(); /* 执行段:写入 + 封存校验和(L5-1) */ + return 0; + } + return -1; /* 未知地址 */ +} diff --git a/App/protocol/iec104/iec104_pts.h b/App/protocol/iec104/iec104_pts.h new file mode 100644 index 00000000..d488a41e --- /dev/null +++ b/App/protocol/iec104/iec104_pts.h @@ -0,0 +1,94 @@ +/* + * 模块名称:IEC 60870-5-104 点表与数据源适配(纯逻辑 + 源注入) + * 模块功能:104 点表(遥测 YC / 遥信 YX / 遥控 YK / 定值)的定义、读取与变化检测 + * (COV:遥信变位 + 遥测死区)。**数据源经 vtable 注入**:板端绑 + * phasor/prot_elm/prot_set 真实源;主机单测绑假源 → 协议栈全链 + * (asdu+pts+link)可离线跑(登记簿 A-4 约束 1)。 + * 点表口径(docs/算法/继电保护功能复现规划.md §1.5,验收 = 省电科院点表): + * - YC:IOA 0x4011~0x4018 + 0x401d(频率),短浮点、系数 1; + * ⚠ V0.1 有效通道仅 UA/UN/IA(TPAFE 三路,§1.6)——其余点**存在但置 IV** + * (无效位),频率随 L1-7 落地前同样置 IV; + * - YX:IOA 1~33(§1.5 表(3));双点 = 开关位置类(YX1~4,本期无硬件 → IV), + * 保护动作类 YX15~23 映射 prot_elm 状态,闭锁类 YX31~33 映射 prot_set; + * - YK:IOA 0x6000+(§1.5 表(3));V0.1 无出口硬件(规划 R7)——除 + * YK11 信号复归(→ prot_elm_init)外一律否定确认(COT|PN),如实回; + * - 定值:IOA = prot_set 元数据 comm_addr(0x8820 基址 + 告警段 0x8027~0x802A), + * 读经 C_RD、写经 C_SE_NC(选择/执行两段,执行完成统一 seal 校验和); + * - 固有参数 8001H~800AH:本期**不实现**(字符串类无法用短浮点上送), + * 按未知 IOA(COT 14 + EVI)应答,登记为待办(设计文档)。 + * 线程约定:init/bind 内核启动前或建服务前;cov_check/read 仅 104 服务任务上下文。 + * 创建日期:2026-10-12(B4) + */ +#ifndef IEC104_PTS_H +#define IEC104_PTS_H + +#include + +/* ---------------- 数据源 vtable(NULL 项 = 该能力不可用 → 按无效/拒绝处理) -- */ +typedef struct { + /* 遥测读:idx = YC 表下标;out = 工程量浮点。 + * 返回 0 有效 / -1 无效(发 IV)/ -2 数据未就绪(发 NT,如相量未满一周波) */ + int (*yc_read)(uint8_t idx, float *out); + /* 遥信位图:bit i = YX 表下标 i 的"合/动作"态(双点按 ON 计) */ + uint64_t (*yx_bits)(void); + /* 遥信有效位图:bit i = 1 该点有效;0 → 发 IV(无硬件/未实现) */ + uint64_t (*yx_valid)(void); + /* 遥控:select=1 选择段 / 0 执行段(dpc 已剥 S 位)。返回 0 接受 / -1 拒绝 */ + int (*yk_exec)(uint32_t ioa, uint8_t dpc, uint8_t select); + /* 定值读:addr = 通讯地址;返回 0 存在 / -1 未知地址 */ + int (*set_read)(uint32_t addr, float *out); + /* 定值写:select=1 预置校验(范围)/ 0 执行写入。返回 0 / -1 越界或未知 */ + int (*set_write)(uint32_t addr, float v, uint8_t select); +} iec104_pts_src_t; + +/* ---------------- 变化检测结果(cov_check 输出) ---------------- */ +typedef struct { + uint64_t yx_changed; /* bit i = YX 下标 i 变位(相对上次快照) */ + uint16_t yc_changed; /* bit i = YC 下标 i 越过死区(相对上次快照) */ +} iec104_pts_cov_t; + +/* + * 函数功能:点表层初始化(清快照、绑板端默认源) + * 限定条件:内核启动前或 104 服务启动前,调一次 + */ +void iec104_pts_init(void); + +/* + * 函数功能:覆盖数据源(主机单测注假源) + * 入口参数:src - vtable(浅拷贝,调用方保生命周期);NULL = 恢复板端默认源 + */ +void iec104_pts_bind_src(const iec104_pts_src_t *src); + +/* ---------------- YC ---------------- */ +uint8_t iec104_pts_yc_count(void); +uint32_t iec104_pts_yc_ioa(uint8_t idx); +/* 读 YC:v 有效值(无效时为 0);qds 输出品质位(IV/NT 等)。返回 0/无效-1 */ +int iec104_pts_yc_read(uint8_t idx, float *v, uint8_t *qds); + +/* ---------------- YX ---------------- */ +uint8_t iec104_pts_yx_count(void); +uint32_t iec104_pts_yx_ioa(uint8_t idx); +uint8_t iec104_pts_yx_is_dp(uint8_t idx); /* 1 = 双点(M_DP) */ +/* 读 YX:out = DIQ/SIQ 值(含 IV)。 */ +void iec104_pts_yx_read(uint8_t idx, uint8_t *out); + +/* ---------------- COV(每 poll 一次) ---------------- */ +/* + * 函数功能:读全表快照并与上次比对(变位 + 死区),输出变化集 + * 入口参数:cov - 输出(可为 NULL = 只刷快照不取变化) + * 函数说明:首次调用只建快照、变化集全 0(突发由初始化/总召覆盖)。 + * 死区 = 点表内置绝对值(§1.5 运行参数 8020H 段本期取内置默认)。 + */ +void iec104_pts_cov_check(iec104_pts_cov_t *cov); + +/* ---------------- 遥控 ---------------- */ +/* 遥控两段式(转发 src->yk_exec;无源 = 一律拒绝)。返回 0 接受 / -1 拒绝 */ +int iec104_pts_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select); + +/* ---------------- 定值 ---------------- */ +/* 按通讯地址读定值(转发 src->set_read)。返回 0 / -1 未知地址 */ +int iec104_pts_set_read(uint32_t addr, float *out); +/* 按通讯地址写定值(两段)。返回 0 / -1 */ +int iec104_pts_set_write(uint32_t addr, float v, uint8_t select); + +#endif /* IEC104_PTS_H */ diff --git a/App/task/default_task.c b/App/task/default_task.c index bd5b7fb6..4439702d 100644 --- a/App/task/default_task.c +++ b/App/task/default_task.c @@ -62,6 +62,10 @@ extern osThreadId_t timeSyncTaskHandle; extern const osThreadAttr_t timeSyncTask_attributes; extern osThreadId_t adcTaskHandle; extern const osThreadAttr_t adcTask_attributes; +extern osThreadId_t iec104TaskHandle; +extern const osThreadAttr_t iec104Task_attributes; +extern osThreadId_t protectTaskHandle; +extern const osThreadAttr_t protectTask_attributes; /* Private defines -----------------------------------------------------------*/ /* 栈水位观测节奏:首次报告须晚于 bring-up 深链(mount/mkfs/探针/cfg/syslog), @@ -69,9 +73,11 @@ extern const osThreadAttr_t adcTask_attributes; #define STACK_PROBE_FIRST_MS 5000u #define STACK_PROBE_PERIOD_MS 2000u /* S11(2026-10-03):堆低水位告警阈值(B)。 - * 依据:2026-10-03 上板两次开机的 min_ever 实测下限 3,712 B(configTOTAL_HEAP_SIZE + * 依据:2026-10-03 上板两次开机的 min_ever 实测下限 3,712 B(当时 configTOTAL_HEAP_SIZE * = 48KB)——低于此值说明堆余量 <8%,新增任务/缓冲随时可能分配失败(隐性风险)。 - * 阈值取 3,072 B 留出运行间 ~600B 波动余量,避免把正常波动误报为故障。 */ + * 阈值取 3,072 B 留出运行间 ~600B 波动余量,避免把正常波动误报为故障。 + * 2026-10-12(B5):堆扩至 56KB(.ioc configTOTAL_HEAP_SIZE=57344,CCM 腾给 + * protectTask/iec104Task 栈),阈值**不随堆缩放**——它是绝对字节安全线。 */ #define HEAP_LOW_WATER_B 3072u /* E-31 自愈策略(2026-09-21 审计 P0 修复):启动期存储挂载失败后, * 主循环按 2s 周期重跑完整 bring-up 的次数上限;耗尽则维持无存储降级 @@ -93,6 +99,8 @@ static const stack_probe_task_t s_stack_probe[] = { { "ui", &uiTaskHandle, &uiTask_attributes }, { "timesync", &timeSyncTaskHandle, &timeSyncTask_attributes }, { "adc", &adcTaskHandle, &adcTask_attributes }, + { "iec104", &iec104TaskHandle, &iec104Task_attributes }, + { "protect", &protectTaskHandle, &protectTask_attributes }, }; #define STACK_PROBE_COUNT (sizeof(s_stack_probe) / sizeof(s_stack_probe[0])) diff --git a/App/task/iec104_serv.c b/App/task/iec104_serv.c new file mode 100644 index 00000000..35b18417 --- /dev/null +++ b/App/task/iec104_serv.c @@ -0,0 +1,295 @@ +/* + * 模块名称:IEC 60870-5-104 被控站服务(板端胶水任务) + * 模块功能:2404 监听 + 单连接 socket 收发 + 把字节流喂给 iec104_link 纯逻辑 + * 层;对时经 sys_clock_set_unix 落墙钟;数据源走 iec104_pts 默认源 + * (phasor / prot_elm / prot_set)。协议语义全部在 App/protocol/iec104, + * 本文件只做 I/O 编排(A-4 约束 1)。 + * 线程约定:iec104Task 独占(NET_READY 屏障后循环,100ms 节拍 + 看门狗心跳)。 + * 创建日期:2026-10-12(B4) + */ +#include "iec104_serv.h" + +#define DBG_LINE_BUF_MAX 128U /* 深链模块日志缓冲收紧(time_sync 先例) */ +#define DBG_TAG "[I104]" + +#include "iec104_link.h" +#include "iec104_pts.h" +#include "net_socket.h" +#include "sys_clock.h" +#include "sys_events.h" +#include "task_watchdog.h" +#include "dbg_log.h" + +#include "cmsis_os2.h" + +#include + +/* 服务周期:COV 延迟 ≤100ms(远小于 SOE 5000ms 验收线);心跳间隔同值 */ +#define IEC104_POLL_MS 100u +/* 接收搬运缓冲(静态,不入栈;link 层内部另有 512B 重组缓冲) */ +#define IEC104_RX_SZ 128u +/* 兜底节拍:门控判"无数据"时每 32 轮无条件收一次(ui_net_sink RM 先例, + * 防 RECV_OK 中断丢失把数据永久藏住);须为 2 的幂 */ +#define IEC104_LIVENESS_DIV 32u +/* 连续发送失败阈值:同 ui_net_sink E-04(短写=对端收坏帧) */ +#define IEC104_SEND_FAIL_MAX 3u + +/* ---------------- 服务状态(iec104Task 独占) ---------------- */ +static iec104_link_t s_link; +static int s_listen = -1; +static int s_client = -1; /* 单连接模型:MCU 上即 s_listen */ +static uint32_t s_gen; /* 网络代次(重建自愈,ui_net_sink 先例) */ +static uint8_t s_rx[IEC104_RX_SZ]; +static uint8_t s_liveness_ctr; +static uint8_t s_send_fail_run; +static uint8_t s_conn_dead; /* 发送连败 → 本轮 link 调用返回后拆链 */ + +/* 前向声明(cfg 初始化引用) */ +static void s_send_apdu(void *ctx, const uint8_t *apdu, uint16_t len); +static int s_clock_sync(void *ctx, uint64_t epoch_ms); + +/* V0.1 公共地址固定 1(点表口径;可配置项挂二期) */ +static const iec104_link_cfg_t s_cfg = { 1u, s_send_apdu, s_clock_sync }; + +/* + * 函数功能:link 层发送回调——经 net_send 串行 RPC 发出一个 APDU + * 入口参数:ctx 未用;apdu/len = 完整 APCI 帧 + * 返回值:无 + * 限定条件:s_client >= 0(在 link 调用栈内执行,即本任务上下文) + * 函数说明:短写/失败累计(E-04 先例);连续 3 次 → 置 s_conn_dead, + * 由 s_service_link 在 link 调用返回后统一拆链(严禁在回调里拆) + */ +static void s_send_apdu(void *ctx, const uint8_t *apdu, uint16_t len) { + int ret; + + (void)ctx; + if (s_client < 0) { + return; + } + ret = net_send(s_client, apdu, (int)len, 0); + if (ret == (int)len) { + s_send_fail_run = 0u; + return; + } + if (s_send_fail_run < 255u) { + s_send_fail_run++; + } + DBG_ERROR("i104 send short: ret=%d/%u run=%u", ret, (unsigned)len, + (unsigned)s_send_fail_run); + if (s_send_fail_run >= IEC104_SEND_FAIL_MAX) { + s_conn_dead = 1u; + } +} + +/* + * 函数功能:link 层对时回调——epoch 毫秒落系统墙钟(含 SD2506 RTC 写回) + * 入口参数:ctx 未用;epoch_ms = C_CS 解析出的 UTC 时刻 + * 返回值:0 成功 / -1 失败(link 层回 actcon+PN) + * 函数说明:uint32 秒域上限 2106-02-07,越界显式拒绝(CP56 域到 2127) + */ +static int s_clock_sync(void *ctx, uint64_t epoch_ms) { + uint64_t secs = epoch_ms / 1000ULL; + + (void)ctx; + if (secs > 0xFFFFFFFFULL) { + return -1; + } + return sys_clock_set_unix((uint32_t)secs); +} + +/* + * 函数功能:创建并监听 2404(socket+bind+listen,抄 ui_net_sink bind_listen) + * 返回值:0 成功(s_listen 写回)/ -1 失败 + * 限定条件:net 子系统可用(NET_READY 屏障后) + */ +static int s_bind_listen(void) { + int ls; + struct net_sockaddr_in addr; + + ls = net_socket(NET_AF_INET, NET_SOCK_STREAM); + if (ls < 0) { + return -1; + } + (void)memset(&addr, 0, sizeof(addr)); + addr.sin_family = NET_AF_INET; + addr.sin_port = net_htons(IEC104_SERV_PORT); + addr.sin_addr.s_addr = NET_INADDR_ANY; + if (net_bind(ls, (struct net_sockaddr *)&addr, (int)sizeof(addr)) < 0) { + net_close(ls); + return -1; + } + if (net_listen(ls) < 0) { + net_close(ls); + return -1; + } + s_listen = ls; + return 0; +} + +/* + * 函数功能:主动断开当前 104 连接并重建监听(协议故障/t1 超时/发送连败) + * 入口参数:why = 日志原因串(ASCII) + * 返回值:无 + * 函数说明:与 EOF 路径不同——协议违例时主站不会自行断开,必须本端 close + * 促其重连;单连接模型下 client 即 listen,close 后统一重建 + * (time_sync 会话收尾先例,非芯片侧 auto_relisten 风暴路径) + */ +static void s_drop_conn(const char *why) { + DBG_ERROR("i104 drop: %s", why); + if (s_client >= 0) { + net_close(s_client); + } + s_client = -1; + s_listen = -1; + iec104_link_close(&s_link); + s_send_fail_run = 0u; + s_conn_dead = 0u; + s_liveness_ctr = 0u; + if (s_bind_listen() < 0) { + s_listen = -1; /* 主循环下轮重试 */ + } +} + +/* + * 函数功能:link 层节拍服务 + 故障检测(poll 后查 IDLE 跳变/发送连败) + * 入口参数:now = 注入时基(tick ms) + * 返回值:无 + */ +static void s_service_link(uint32_t now) { + iec104_link_poll(&s_link, now); + if (s_conn_dead != 0u) { + s_drop_conn("send fail"); + return; + } + if (iec104_link_state(&s_link) == IEC104_ST_IDLE) { + s_drop_conn("protocol fault"); + } +} + +/* + * 函数功能:单次服务循环(代次自愈 → accept → 门控收 → 喂 link → 节拍) + * 返回值:无 + * 限定条件:NET_READY 已置位;s_cfg/s_link 已 init + * 函数说明:门控(net_can_accept/net_can_read 纯 RAM 读)+ 兜底节拍照 + * ui_net_sink I-1/I-2;EOF 时 client==listen 严禁 close(net 层 + * 已 auto_relisten,close 会连监听一起毁) + */ +static void s_serv_poll(void) { + uint32_t now = osKernelGetTickCount(); + int n; + + /* 网络重建(代次变化):旧监听/客户端随芯片复位失效 → 重建 */ + if (net_get_generation() != s_gen) { + if ((s_client >= 0) && (s_client != s_listen)) { + net_close(s_client); + } + if (s_listen >= 0) { + net_close(s_listen); + s_listen = -1; + } + s_client = -1; + iec104_link_close(&s_link); + s_send_fail_run = 0u; + s_conn_dead = 0u; + s_liveness_ctr = 0u; + s_gen = net_get_generation(); + (void)s_bind_listen(); + return; + } + + if (s_listen < 0) { + (void)s_bind_listen(); /* 启动失败/被毁:重试 */ + return; + } + + if (s_client < 0) { + int c; + + if (net_can_accept(s_listen) == 0) { + if (net_get_sock(s_listen) == NULL) { + s_listen = -1; /* 控制块消失:交回上方重建 */ + } + return; + } + c = net_accept(s_listen, NULL, NULL); + if (c >= 0) { + s_client = c; + s_send_fail_run = 0u; + s_conn_dead = 0u; + s_liveness_ctr = 0u; + iec104_link_open(&s_link, now); + DBG_INFO("i104: accepted fd=%d", c); + } + return; + } + + /* 门控 + 兜底:无数据多数轮直接走 link 节拍;每 32 轮无条件收一次 */ + if (net_can_read(s_client) == 0) { + if (((++s_liveness_ctr) & (IEC104_LIVENESS_DIV - 1u)) != 0u) { + s_service_link(now); + return; + } + } else { + s_liveness_ctr = 0u; + } + + n = net_recv(s_client, s_rx, (int)sizeof(s_rx), NET_MSG_DONTWAIT); + if (n > 0) { + iec104_link_on_rx(&s_link, s_rx, (uint16_t)n, now); + } else if (n == 0) { + /* 对端关闭:net 层已 auto_relisten;client==listen 时严禁 close */ + if (s_client != s_listen) { + net_close(s_client); /* 模拟器多连接后端:数据通道独立 */ + } + s_client = -1; + s_liveness_ctr = 0u; + iec104_link_close(&s_link); + if ((net_get_sock(s_listen) == NULL) && (s_bind_listen() < 0)) { + s_listen = -1; + } + return; + } else if (net_get_errno() != NET_ERR_WOULDBLOCK) { + s_drop_conn("recv err"); + return; + } + + s_service_link(now); +} + +/* + * 函数功能:iec104Task 任务体(freertos.c USER CODE 区创建) + * 入口参数:argument 未用 + * 返回值:无(不返回) + * 函数说明:NET_READY 屏障(100ms 分片 + 每片喂心跳,timeSyncTask 先例)→ + * 点表/链路 init + 建监听 → 100ms 服务循环(每轮喂看门狗) + */ +void iec104_serv_task(void *argument) { + (void)argument; + + if (sys_evtHandle != NULL) { + for (;;) { + uint32_t r = osEventFlagsWait(sys_evtHandle, SYS_EVT_NET_READY, + osFlagsWaitAny | osFlagsNoClear, 100u); + if ((r & osFlagsError) == 0u) { + break; /* 就绪位是状态位(NoClear),不消费 */ + } + task_wd_beat(TASK_WD_IEC104); + } + } + + iec104_pts_init(); + iec104_link_init(&s_link, &s_cfg, NULL); + s_gen = net_get_generation(); + if (s_bind_listen() < 0) { + DBG_ERROR("i104: bind port %u FAIL, retry in loop", + (unsigned)IEC104_SERV_PORT); + } else { + DBG_INFO("i104: listening on %u", (unsigned)IEC104_SERV_PORT); + } + + for (;;) { + task_wd_beat(TASK_WD_IEC104); + s_serv_poll(); + osDelay(IEC104_POLL_MS); + } +} diff --git a/App/task/iec104_serv.h b/App/task/iec104_serv.h new file mode 100644 index 00000000..1dff9ea6 --- /dev/null +++ b/App/task/iec104_serv.h @@ -0,0 +1,20 @@ +/* + * 模块名称:IEC 60870-5-104 被控站服务(对外接口) + * 模块功能:声明 iec104Task 任务体与监听端口;协议实现在 App/protocol/iec104/, + * 本接口仅供 Src/freertos.c 创建任务使用。 + * 创建日期:2026-10-12(B4) + */ +#ifndef IEC104_SERV_H +#define IEC104_SERV_H + +/* IEC 60870-5-104 被控站监听端口(DL/T 634.5104 标准端口) */ +#define IEC104_SERV_PORT 2404u + +/* + * 函数功能:iec104Task 任务体(在 Src/freertos.c USER CODE 区 osThreadNew 创建) + * 入口参数:argument - 未用 + * 返回值:无(任务不返回) + */ +void iec104_serv_task(void *argument); + +#endif /* IEC104_SERV_H */ diff --git a/App/task/protect_task.c b/App/task/protect_task.c new file mode 100644 index 00000000..b29b9dc6 --- /dev/null +++ b/App/task/protect_task.c @@ -0,0 +1,105 @@ +/* + * 模块名称:保护任务(L3 板端接线,B5)——实现 + * 模块功能:见 protect_task.h。每拍三件事: + * ① L5-4 采样故障闭锁:adc_health_flags() 电平位命中 → 元件状态 + * 复位(防陈旧判据)+ 本拍不 eval; + * ② prot_set_selfcheck()(L5-1 定值完整性巡检,31 项 sum32,开销 + * 可忽略;失配 → prot_set 内部闭锁,eval 自动复位全元件); + * ③ prot_elm_run()(phasor rms → 判据步进)+ 动作位图边沿日志。 + * 定值/元件初始化在 app_main_init(内核前,B5);本任务只消费。 + * 线程约定:prot_elm_run / prot_set_selfcheck 仅本任务上下文(prot_elm.h); + * 跨上下文复归(104 YK11)经 prot_elm_request_reset 落请求。 + * 创建日期:2026-10-12(B5) + */ +#include "protect_task.h" + +#include "cmsis_os2.h" + +#define DBG_TAG "[PROT]" +#define DBG_LINE_BUF_MAX 128U +#include "dbg_log.h" + +#include "adc_health.h" +#include "prot_elm.h" +#include "prot_set.h" +#include "task_watchdog.h" + +/* L5-4 采样故障电平闭锁位:stall(可自愈)+ backward(锁存)都须停判据。 + * 锁存类(FRSTDATA/HW_ERR 等)不在此列——它们是一次性事件痕迹,不构成 + * "当前测量不可信";持续 stall/backward 才是。 */ +#define PROT_HF_LOCK_MASK (ADC_HF_TPAFE_STALL | ADC_HF_STM32_STALL | ADC_HF_SEQ_BACKWARD) + +static uint32_t s_prev_active; /* 上拍动作位图(边沿日志用) */ +static uint8_t s_prev_hf_lock; /* 上拍采样闭锁态(边沿日志用) */ + +/* + * 函数功能:动作位图变化沿日志(逐变化元件打名字与状态) + * 入口参数:active - 本拍 prot_elm_active_mask() + * 函数说明:V0.1 无出口硬件(规划 R7),动作 = 遥信 + 日志;SOE 落盘随 L4。 + */ +static void s_log_active_edge(uint32_t active) { + uint32_t chg = active ^ s_prev_active; + uint32_t i; + + for (i = 0u; (i < (uint32_t)PE_COUNT) && (chg != 0u); i++) { + const uint32_t bit = 1u << i; + + if ((chg & bit) != 0u) { + prot_elm_state_t st; + + chg &= ~bit; + prot_elm_state((prot_elm_id_t)i, &st); + DBG_INFO("elm %s asserted=%u picked=%u", + prot_elm_name((prot_elm_id_t)i), + (unsigned)st.asserted, (unsigned)st.picked); + } + } + s_prev_active = active; +} + +/* + * 函数功能:protectTask 线程入口 + * 入口参数:argument - 未用 + * 返 回 值:无(不返回) + * 函数说明:无就绪屏障(判据只依赖 phasor 使用区,未就绪时 prot_elm_run + * 整拍自跳;采样闭锁另有 adc_health 电平位兜底)→ 上电即跑。 + * 每拍喂看门狗(TASK_WD_PROTECT,产品 required_mask 0x1F7)。 + */ +void protect_task(void *argument) { + (void)argument; + + DBG_INFO("protect task start: cycle=%ums elm=%u", + (unsigned)PROTECT_TASK_CYCLE_MS, (unsigned)PE_COUNT); + + for (;;) { + uint32_t now = osKernelGetTickCount(); + uint32_t hf = adc_health_flags(); + + if ((hf & PROT_HF_LOCK_MASK) != 0u) { + /* L5-4:测量链不可信 → 复位元件(本任务上下文,直接 init 合法) + * 并跳过判据;stall 自愈后下一拍自动恢复 */ + if (s_prev_hf_lock == 0u) { + DBG_ERROR("sampling FAULT -> protection blocked (hf=0x%08lX)", + (unsigned long)(hf & PROT_HF_LOCK_MASK)); + } + s_prev_hf_lock = 1u; + prot_elm_init(); + } else { + if (s_prev_hf_lock != 0u) { + DBG_INFO("sampling recovered -> protection resumed"); + s_prev_hf_lock = 0u; + } + /* L5-1 巡检:定值区与封存校验和不符 → prot_set 闭锁(下一拍起 + * eval 自动复位全元件)。⚠ 与 104 定值写(iec104Task set+seal) + * 的竞态窗口为 µs 级:selfcheck 误锁后同一次写的 seal 即清锁 + * (prot_set.c),V0.1 如实登记,P4 定值持久化时收口。 */ + (void)prot_set_selfcheck(); + prot_elm_run(now); + } + + s_log_active_edge(prot_elm_active_mask()); + + task_wd_beat(TASK_WD_PROTECT); + osDelay(PROTECT_TASK_CYCLE_MS); + } +} diff --git a/App/task/protect_task.h b/App/task/protect_task.h new file mode 100644 index 00000000..8d2aeed6 --- /dev/null +++ b/App/task/protect_task.h @@ -0,0 +1,25 @@ +/* + * 模块名称:保护任务(L3 板端接线,B5) + * 模块功能:protectTask 线程入口——以固定节拍驱动保护判据 + * (`prot_elm_run()`:phasor rms → 元件步进),并落实 L5-4 采样 + * 故障闭锁(`adc_health_flags()` 电平位 → 元件状态复位 + 本拍不判据)。 + * 判据本体在 `App/algo/prot_elm.c`(纯逻辑,L0.5 已覆盖),本文件 + * 只做消费/编排(AGENTS 目录地图:task 不装算法)。 + * 线程约定:仅本任务调 prot_elm_run / prot_set_selfcheck(prot_elm.h 线程约定); + * prot_set 写在 P4 前无第二写者(104 定值写经 pts→prot_set,见注)。 + * 创建日期:2026-10-12(B5) + */ +#ifndef PROTECT_TASK_H +#define PROTECT_TASK_H + +/* 判据节拍(ms):V0.1 元件吃 50 Hz 基波 rms(phasor 每工频周更新)→ 20 ms + * = 一个工频周;延时精度由 prot_elm 的 now_ms 差值法保证,与节拍无关。 + * 规划 §4 的"1 ms 高优先级"是参考系统瞬时值元件口径,随 P2 瞬时值元件再评。 */ +#define PROTECT_TASK_CYCLE_MS 20u + +/* + * 函数功能:protectTask 线程入口(freertos.c USER CODE 区创建) + */ +void protect_task(void *argument); + +#endif /* PROTECT_TASK_H */ diff --git a/App/util/task_watchdog.c b/App/util/task_watchdog.c index e0078381..28c5739c 100644 --- a/App/util/task_watchdog.c +++ b/App/util/task_watchdog.c @@ -191,7 +191,9 @@ static uint32_t wd_required_mask(void) { | (1u << (uint32_t)TASK_WD_FTP) | (1u << (uint32_t)TASK_WD_UI) | (1u << (uint32_t)TASK_WD_TIMESYNC) - | (1u << (uint32_t)TASK_WD_ADC); /* adcTask 不依赖任何屏障,任何构建都置位 */ + | (1u << (uint32_t)TASK_WD_ADC) /* adcTask 不依赖任何屏障,任何构建都置位 */ + | (1u << (uint32_t)TASK_WD_IEC104) /* iec104Task 同 adcTask:任何构建都创建 */ + | (1u << (uint32_t)TASK_WD_PROTECT);/* protectTask 同:判据节拍必须心跳 */ #if defined(ENABLE_HW_LAYER_TESTS) /* 见函数说明:CH395F 硬件层测试构建 = default + 屏障等待者(等待分片喂位) @@ -200,7 +202,9 @@ static uint32_t wd_required_mask(void) { | (1u << (uint32_t)TASK_WD_FTP) | (1u << (uint32_t)TASK_WD_UI) | (1u << (uint32_t)TASK_WD_TIMESYNC) - | (1u << (uint32_t)TASK_WD_ADC); + | (1u << (uint32_t)TASK_WD_ADC) + | (1u << (uint32_t)TASK_WD_IEC104) + | (1u << (uint32_t)TASK_WD_PROTECT); #endif return m; diff --git a/App/util/task_watchdog.h b/App/util/task_watchdog.h index 72a2eac5..0acab18e 100644 --- a/App/util/task_watchdog.h +++ b/App/util/task_watchdog.h @@ -31,6 +31,8 @@ typedef enum { TASK_WD_UI = 4, TASK_WD_TIMESYNC = 5, TASK_WD_ADC = 6, /* adcTask:1ms 采样节拍消费者(B1,2026-10-10) */ + TASK_WD_IEC104 = 7, /* iec104Task:104 上行服务(B4,2026-10-12) */ + TASK_WD_PROTECT = 8, /* protectTask:保护判据节拍(B5,2026-10-12) */ TASK_WD_ID_MAX } task_wd_id_t; diff --git a/Inc/FreeRTOSConfig.h b/Inc/FreeRTOSConfig.h index c07a15d4..3f3de2ca 100644 --- a/Inc/FreeRTOSConfig.h +++ b/Inc/FreeRTOSConfig.h @@ -68,7 +68,7 @@ #define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES ( 56 ) #define configMINIMAL_STACK_SIZE ((uint16_t)128) -#define configTOTAL_HEAP_SIZE ((size_t)49152) +#define configTOTAL_HEAP_SIZE ((size_t)57344) #define configMAX_TASK_NAME_LEN ( 16 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 diff --git a/MDK-ARM/STM32F407-Demo.uvprojx b/MDK-ARM/STM32F407-Demo.uvprojx index 8982afef..7b575f6f 100644 --- a/MDK-ARM/STM32F407-Demo.uvprojx +++ b/MDK-ARM/STM32F407-Demo.uvprojx @@ -337,7 +337,7 @@ --diag_suppress=1,68,111,188,191,546,1293 USE_HAL_DRIVER,STM32F407xx,NDEBUG - ../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../Drivers/BSP/NET/lftpd;../Drivers/BSP/NETCFG;../App;../App/app;../App/algo;../App/cfg;../App/fs;../App/log;../App/sync;../App/task;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs;../test/board;../Lib/lvgl;../Drivers/BSP/UI;../Lib + ../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../Drivers/BSP/NET/lftpd;../Drivers/BSP/NETCFG;../App;../App/app;../App/algo;../App/cfg;../App/fs;../App/log;../App/sync;../App/task;../App/protocol/iec104;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs;../test/board;../Lib/lvgl;../Drivers/BSP/UI;../Lib @@ -947,6 +947,31 @@ 1 ..\App\task\adc_task.c + + iec104_serv.c + 1 + ..\App\task\iec104_serv.c + + + protect_task.c + 1 + ..\App\task\protect_task.c + + + iec104_asdu.c + 1 + ..\App\protocol\iec104\iec104_asdu.c + + + iec104_pts.c + 1 + ..\App\protocol\iec104\iec104_pts.c + + + iec104_link.c + 1 + ..\App\protocol\iec104\iec104_link.c + adc_input.c 1 diff --git a/README.md b/README.md index 1bd71484..86bf7dd5 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,8 @@ main.c | uiTask | 4096 words | BelowNormal | LVGL UI 界面 | | timeSyncTask | 512 words | Normal | 墙钟时间同步 | | adcTask | 640 words | AboveNormal | TPAFE5160 采样(TIM3 1kHz 事件驱动 + 原子快照 + STM32 ADC DMA) | +| iec104Task | 640 words | Normal | | +| protectTask | 512 words | Normal | | > 上表与 `Src/freertos.c` 的 `osThreadAttr_t` 一致(2026-09-25 校准);改动栈大小前先读 diff --git a/STM32F407-Demo.ioc b/STM32F407-Demo.ioc index cd1ccfc6..54b08b4c 100644 --- a/STM32F407-Demo.ioc +++ b/STM32F407-Demo.ioc @@ -122,7 +122,7 @@ FREERTOS.Queues01=netMsgQueue,8,net_msg_t,0,Dynamic,NULL,NULL FREERTOS.Tasks01=defaultTask,24,1024,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;netTask,24,960,StartNetTask,Default,NULL,Dynamic,NULL,NULL;ftpTask,24,1024,StartFtpTask,As weak,NULL,Dynamic,NULL,NULL;testTask,16,2048,start_test_task,As weak,NULL,Dynamic,NULL,NULL;uiTask,16,4096,StartUiTask,Default,NULL,Dynamic,NULL,NULL FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2 FREERTOS.configENABLE_FPU=1 -FREERTOS.configTOTAL_HEAP_SIZE=49152 +FREERTOS.configTOTAL_HEAP_SIZE=57344 FREERTOS.configUSE_MALLOC_FAILED_HOOK=1 File.Version=6 GPIO.groupedBy=Group By Peripherals diff --git a/Src/freertos.c b/Src/freertos.c index 37f0f4ca..31d2fbe1 100644 --- a/Src/freertos.c +++ b/Src/freertos.c @@ -39,6 +39,8 @@ #include "sys_events.h" #include "default_task.h" #include "adc_task.h" /* B1(2026-10-10):ADC 采集消费者(手写任务,见 Variables 区) */ +#include "iec104_serv.h" /* B4(2026-10-12):IEC 104 上行服务(手写任务,见 Variables 区) */ +#include "protect_task.h" /* B5(2026-10-12):保护判据节拍任务(手写任务,同上) */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -119,6 +121,13 @@ static int hook_ptr_ok(const void *p) * syslog_post 回显尾)。静态最坏链 1080 B,512 words 时余 968 B < 1024 B * ISR 底线 → 抬至 640 words(2.5 KB,堆余量 min_ever 7152→≈6640 B,可承受)。 * 栈值以 `scripts/stack_report.py` 实测最坏链为准,改动前后各跑一次。 + * iec104Task 640 words:B4(2026-10-12)104 上行服务(2404 监听 + link 状态 + * 机)。link/pts 缓冲全静态;stack_report 实测静态最坏链 1456 B(拆链 + * 重建监听 → net_bind → SPI 故障 → 日志尾,日志主导)。512 words 时余 + * 592 B < 1024 B ISR 底线 → 抬至 640(2.5 KB)。 + * protectTask 512 words:B5(2026-10-12)保护判据节拍(prot_elm_run 消费者 + * + L5-4 采样闭锁)。stack_report 实测静态最坏链 872 B(float 判据 + + * phasor 快照 + 日志尾),余 1176 B / 57% ≥ ISR 底线 → 512 保持。 */ /* 存储测试变量(g_storage_stats / s_perf_buf)已迁至 test/board/storage_test_task.c */ osThreadId_t timeSyncTaskHandle; @@ -140,6 +149,28 @@ const osThreadAttr_t adcTask_attributes = { .stack_size = 640 * 4, .priority = (osPriority_t) osPriorityAboveNormal, }; +/* B4(2026-10-12):IEC 60870-5-104 被控站服务(2404 监听 + 链路状态机消费)。 + * 手写于此而非 .ioc(同 timeSyncTask/adcTask:不在 Tasks01 里 → 重生成会丢, + * 靠审计 WARN 提示)。640 words:stack_report 实测静态最坏链 1456 B(拆链→ + * 重建监听→net_bind→SPI 故障→日志尾,日志主导);512 words 时余 592 B + * < 1024 B ISR 底线 → 抬至 640(2.5 KB,CCM 堆 min_ever 再降 512 B,可承受)。 */ +osThreadId_t iec104TaskHandle; +const osThreadAttr_t iec104Task_attributes = { + .name = "iec104Task", + .stack_size = 640 * 4, + .priority = (osPriority_t) osPriorityNormal, +}; +/* B5(2026-10-12):保护判据节拍(prot_elm_run 消费者 + L5-4 采样闭锁)。 + * 手写于此而非 .ioc(同上)。512 words:stack_report 实测静态最坏链 872 B + * (float 判据 + phasor 快照 + 日志尾),余 1176 B / 57% ≥ ISR 底线 → 保持。 + * 优先级 Normal:V0.1 无出口硬件(规划 R7),判据是 20ms 软实时,不需要 + * adcTask 的 AboveNormal;规划 §4 的"1ms/高"随 P2 瞬时值元件再评。 */ +osThreadId_t protectTaskHandle; +const osThreadAttr_t protectTask_attributes = { + .name = "protectTask", + .stack_size = 512 * 4, + .priority = (osPriority_t) osPriorityNormal, +}; /* USER CODE END Variables */ /* Definitions for defaultTask */ osThreadId_t defaultTaskHandle; @@ -320,6 +351,12 @@ void MX_FREERTOS_Init(void) { * (内核启动前)完成;本任务只做运行期采样。 */ adcTaskHandle = osThreadNew(adc_task_func, NULL, &adcTask_attributes); + /* B4(2026-10-12):IEC 60870-5-104 上行服务任务。任务体内先等 NET_READY + * 屏障(100ms 分片 + 每片喂心跳,timeSyncTask 先例),再建 2404 监听并 + * 100ms 循环服务;纳入 IWDG required_mask(TASK_WD_IEC104,任何构建都创建)。 */ + iec104TaskHandle = osThreadNew(iec104_serv_task, NULL, &iec104Task_attributes); + protectTaskHandle = osThreadNew(protect_task, NULL, &protectTask_attributes); + /* P2-13(2026-10-04):产品构建(未选任何 TEST_SUITE_*)不需要 testTask。 * 上方生成区按 .ioc FREERTOS.Tasks01 无条件创建它,其 2048 words(8KB) 栈 + TCB * 取自 CCM 堆;而产品构建下 start_test_task() 仅打印一行后 osDelay(1000) 永久空转, diff --git a/docs/README.md b/docs/README.md index 7a83c4c2..659cecbd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -90,6 +90,7 @@ docs/ | [`运行与自检记录设计说明.md`](子系统设计/运行与自检记录设计说明.md) | `/log/run.log`·`selftest.log` 定长记录与待机显示 | | [`看门狗设计说明.md`](子系统设计/看门狗设计说明.md) | IWDG(CubeMX 配置)+ 任务心跳位图:选型与超时推导、掩码与埋点、取证机制、验证记录;已台架闭环(V2/V4/V5)。**§11 = 任务级饥饿的诊断方法与 `[PROF]` 实测基线**(Task #32 沉淀:判读口径、量化归因、三条脆弱点、明确不做的四条) | | [`ADC采样节拍设计说明.md`](子系统设计/ADC采样节拍设计说明.md) | **ADC 采集链路采样节拍**:TIM3 1 kHz 更新事件同时触发 TPAFE CONVST 与(经 TRGO)STM32 ADC1 + DMA 乒乓缓冲;方案选型、CubeMX 配置规格、代码改造清单、时序/优先级分析、验收判据与实测剖面;**已落地并上板闭环** | +| [`IEC104上行设计说明.md`](子系统设计/IEC104上行设计说明.md) | **B4 上行规约**:IEC 60870-5-104 被控站(TCP 2404)范围/点表(V0.1 有效子集)/链路流程(k/w/t1~t3、总召、COV、遥控两段式、定值)/netTask 接入决策/预算与测试方案;协议核心纯逻辑 + L0.5 全栈单测 | | [`网络/BSD_Socket_API_使用指南.md`](网络/BSD_Socket_API_使用指南.md) | **上层视图**:BSD Socket API 公开语义、示例、常见问题 | | [`网络/BSD_Socket_API_函数调用关系.md`](网络/BSD_Socket_API_函数调用关系.md) | **内部视图**:netTask / 消息队列 / L3 挂起 / 重试对账的调用关系与设计意图 | | [`网络/Net层阻塞模型架构设计.md`](网络/Net层阻塞模型架构设计.md) | **等待模型**:pending 请求架构、五路完成语义、设计边界与性能特征 | @@ -176,6 +177,7 @@ docs/ | [`RAM使用分析与优化方案.md`](内存管理/RAM使用分析与优化方案.md) | **内存主文档**:占用分析、优化方案、定栈规则 | | [`内存内容分配策略.md`](内存管理/内存内容分配策略.md) | 各内存区(SRAM/CCM)的分配策略 | | [`存储栈RAM优化调研.md`](内存管理/存储栈RAM优化调研.md) | 存储栈 RAM 优化调研与结论 | +| [`RAM预算台账.md`](内存管理/RAM预算台账.md) | **预算台账**:子系统配额、CCM 分配、趋势基线与 92% 门禁(N-27 三件套,2026-10-12) | | `data/` | `ram_report_*.md` / `stack_report_*.md` 快照数据(由 `scripts/` 生成) | ### 7.3 问题记录(**改驱动前必读**) @@ -254,7 +256,7 @@ docs/ | 问题 | 位置 | 说明 | |---|---|---| | 指向未实现工具 | `UI_界面制作流程.md`、`UI_自动化测试流程.md` → `tools/ui_mock/` | 该目录**始终不存在**;golden 回归实际落在 `simulator/tests/`(四脚本)。引用待改指,见 `docs/问题记录/项目审查与优化建议报告.md` §6.1 | -| 产物缺失 | `内存管理/RAM使用分析与优化方案.md` → `scripts/ram_baseline.tsv` | 方案写了、工具未建(引用已加 `[计划]` 标记) | +| ~~产物缺失~~ | ~~`内存管理/RAM使用分析与优化方案.md` → `scripts/ram_baseline.tsv`~~ | ✅ 已建(2026-10-12,N-27 前半):`ram_baseline.py` + `ram_baseline.tsv` + [`RAM预算台账.md`](内存管理/RAM预算台账.md) + `mem-budget` 钩子 | | ~~目录名含空格~~ | ~~`UI 设计/`~~ | ✅ 已修复(2026-09-25,D-6):改名为 `UI设计/`,全仓库 67 处引用同步;命名约定见 [`文档规范.md`](文档规范.md) §1 | | ~~缺一致性门禁~~ | — | ✅ 已落地(2026-09-25/26,D-7 三档齐):`scripts/check_doc_links.py`(存在性)+ `scripts/gen_task_table.py`(数值)+ `scripts/check_mem_numbers.py`(体积),接入 pre-commit `doc-links` / `task-table` / `mem-numbers` 钩子 | | ~~`docs/文档规范.md` 未创建~~ | — | ✅ 已创建(2026-09-25):[`文档规范.md`](文档规范.md) | diff --git a/docs/产品需求/产品需求设计文档.md b/docs/产品需求/产品需求设计文档.md index bb97b3ec..2a663a60 100644 --- a/docs/产品需求/产品需求设计文档.md +++ b/docs/产品需求/产品需求设计文档.md @@ -468,6 +468,7 @@ sequenceDiagram | FTP | TCP **21** | 文件上传/下载(根目录 `/`,NAND 存储) | 登录后任意 FTP 客户端列目录/读写(鉴权见 §7.6) | | 墙钟对时 | TCP **8888** | PC 主动推送时间到设备 | 对时后核对设备时间 / 日志时间戳 | | 远程显示(RemoDispBus) | TCP **7003** | 远端看图(160×160 1bpp)+ 远端导航按键 | DTU-RemoteLCD 或任意 TCP 客户端连 7003 收帧 | +| IEC 60870-5-104 上行 | TCP **2404** | 被控站接入:遥测/遥信上送、总召、遥控/定值下发(B4) | 任意 104 主站连 2404,STARTDT+总召往返(→ `docs/子系统设计/IEC104上行设计说明.md`) | > **现场组网要求**:设备与客户端**同网段**(默认 .100/24、网关 .1);跨网段先改 IP 再上线。 @@ -779,7 +780,8 @@ cfg-file-unit-test、test-suite-switch、gitlint。 ### 9.2 阶段路线图 -> **顺序唯一权威 → [`../待处理内容.md`](../待处理内容.md) §2(统一推进顺序,波次 W1~W8)**。 +> **顺序唯一权威 → [`../待处理内容.md`](../待处理内容.md) §2(统一推进顺序,波次 W1~W7; +> RS-485/B2 整簇暂缓见其 §2.4,2026-10-12 用户决定)**。 > 本节自 2026-10-11 起不再维护路线图(原阶段图删除,避免与登记簿漂移;原 C4"defaultTask 栈余量 10%" > 已于 2026-10-10 削链闭环销项,见 `../内存管理/RAM使用分析与优化方案.md`)。 > 功能缺口口径见 §9.1;B0 产品定义结论见 `../算法/继电保护功能复现规划.md` §1.5。 diff --git a/docs/代码规范/pre-commit使用说明.md b/docs/代码规范/pre-commit使用说明.md index bdb274b5..5ef112e5 100644 --- a/docs/代码规范/pre-commit使用说明.md +++ b/docs/代码规范/pre-commit使用说明.md @@ -25,7 +25,8 @@ git commit ├─ cubemx-survival CubeMX 重生成存活审计(易失定制清单 + 基线漂移) ├─ watchdog-unit-test 看门狗判定状态机主机侧单测(L0.5) ├─ test-suite-switch 测试套件开关=产品构建(防测试固件静默提交) - └─ registration-check 双端注册反向校验(uvprojx + CMakeLists,N-23) + ├─ registration-check 双端注册反向校验(uvprojx + CMakeLists,N-23) + └─ mem-budget RAM 预算 92% 阈值门禁(N-27 三件套,2026-10-12) └─ commit-msg(.git/hooks/commit-msg) └─ gitlint 校验 commit message 格式 ``` @@ -50,6 +51,7 @@ git commit | scripts/check_cubemx_survival.py | 随仓库提交 | CubeMX 重生成存活审计(纯 Python,无依赖) | | scripts/check_test_suite.py | 随仓库提交 | 测试套件开关门禁(纯 Python,无依赖) | | scripts/check_registration.py | 随仓库提交 | 双端注册反向校验(纯 Python,无依赖) | +| scripts/ram_baseline.py | 随仓库提交 | RAM 预算 92% 门禁 + 趋势台账(纯 Python,无依赖) | > **PATH 要求**:cppcheck 安装后需在 PATH 中可找到(winget 自动写入 User PATH,但当前终端不会立即生效,需**重开终端**);装在非 PATH 位置时可用 `DTU_CPPCHECK` 环境变量指向 `cppcheck.exe` 完整路径(显式设置但无效 → 硬报错,不静默回退)。 @@ -371,6 +373,29 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法 | **为什么需要** | 新 `.c` 必须手动注册两处才会被编译;历史上 `rs485_task.c`/`lftpd_log.c` **两处都没注册** = 写了却从不参与任何一端编译的**死代码**,误导读者以为功能已生效(出处审查报告 N-06 残余) | | **运行器** | `scripts/check_registration.py`(纯标准库;退出码 0=一致 / 1=有缺口 / 2=环境错误) | +### 2.19 mem-budget — RAM 预算 92% 阈值门禁(2026-10-12 加,N-27 三件套) + +| 项 | 说明 | +|---|---| +| **触发条件** | 全部自研代码目录(`App/` `Drivers/BSP/` `Src/` `Inc/`)+ `Lib/lv_conf.h` + `test/board/` + `scripts/ram_baseline.*` + `docs/内存管理/` + 本配置文件 | +| **处理方式** | **阻止提交**(RW_IRAM1 / RW_CCM 任一区占比 >92%,或台账受管区与 `.map` 漂移);无 `.map` 自适应跳过(同 `mem-numbers` 在 CI 的行为,盲区登记 `docs/待处理内容.md` A-5 残余) | +| **检查逻辑** | 解析 `.map` 执行区占比 → 超阈值即 FAIL 并附 **Top-10 RW+ZI 对象表**(定位增量元凶);同时校验 `docs/内存管理/RAM预算台账.md` 受管区与 `.map` 一致(漂移 → 提示 `--write`) | +| **软提醒**(不拦) | tsv 末行落后于 `.map`(忘跑 `--update`);`.map` 早于最新源码(忘 `@build`) | +| **配套三件套** | `scripts/ram_baseline.py`(门禁/趋势/受管区生成)+ `scripts/ram_baseline.tsv`(每次 `@build` 后 `--update` 追加的趋势基线,`--trend` 高亮 RW+ZI 增长 >1 KB 的对象)+ `docs/内存管理/RAM预算台账.md`(子系统配额 + CCM 台账 + 超配额流程) | +| **为什么需要** | `docs/问题记录/项目审查与优化建议报告.md` §5.5 第 1 条"超阈值即失败 + Top-10 附表"此前**无任何机械检查**——`mem-numbers` 只防"文档数字漂移"不防"占用超阈值";B4/B5 要新建任务与缓冲,红线必须先机械化(登记簿 N-27 前半 / W1-0) | +| **运行器** | `scripts/ram_baseline.py --gate`(纯标准库,复用 `ram_report.py` 的 `.map` 解析口径;退出码 0=通过/跳过 / 1=超阈值或漂移 / 2=解析失败) | + +### 2.20 iec104-unit-test — IEC 60870-5-104 协议栈主机侧单测(2026-10-12 加,B4) + +| 项 | 说明 | +|---|---| +| **触发条件** | `App/protocol/iec104/iec104_(asdu|pts|link).*`、数据源依赖 `App/algo/(prot_set|prot_elm|phasor|sample_ring|adc_input).*`、`test/host/iec104/**` 或 `test/host/common/unit_test_harness.py` 变动 | +| **处理方式** | **阻止提交**(单测失败即拦截) | +| **被测对象** | `App/protocol/iec104/` 三模块(ASDU 编解码 / 点表+数据源 vtable / APCI+链路 FSM)——纯逻辑、tick 注入、发送经回调注入,零 I/O(A-4 约束 1) | +| **用例** | 82 例:CP56 往返 / APCI 半帧粘帧坏帧 / STARTDT-STOPDT / 总召分片+RBT / COV 死区 / k=12 窗满 / w=8 触发 S / t1-t2-t3 / N(R) 倒退判故障 / 遥控两段式 / 定值越界 PN / C_CS 对时 / 未知类型-地址错误应答 / 周期上送 | +| **为什么需要** | 板端复现这些分支要真主站 + 真等待(t1=15 s、k 窗满要发满 12 帧);link 层 tick 注入 + pts vtable 抽象就是为 L0.5 毫秒级穷举设计;数据源依赖进触发面——测试直接 `#include` 这些生产源,签名变了立刻暴露 | +| **运行器** | `test/host/iec104/run_unit_test.py`(MSVC `cl.exe`,L0.5) | + --- ## 3. 日常工作流 @@ -498,7 +523,7 @@ $env:PATH = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Env | 文件 | 位置 | 说明 | |---|---|---| -| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(**29 个钩子**,2026-10-12 清点;本文 §2 详解非单测类——N-19 新增的两个单测钩子见 §2.16/§2.17,N-23 双端注册反向校验见 §2.18,其余主机侧单测见 AGENTS.md 门禁条;主机侧单测共 12 个) | +| `.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 个) | | `.gitlint` | 仓库根 | gitlint 规则(宽松,兼容中文) | | `.cubemx_survival_baseline.json` | 仓库根 | CubeMX 易失定制基线(哈希;`--write` 重建) | | `scripts/check_mojibake.py` | scripts/ | U+FFFD 检测脚本 | diff --git a/docs/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index 7e392177..ff904c66 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -36,10 +36,10 @@ | 区域 | 用量 | 容量 | 占比 | |---|---|---|---| -| ER_IROM1 | 214,088 B (209.07 KB) | 1,048,576 B (1024 KB) | 20.4% | -| RW_IRAM1 | 94,768 B (92.55 KB) | 131,072 B (128 KB) | 72.3% | -| RW_CCM | 49,184 B (48.03 KB) | 65,280 B (64 KB) | 75.3% | -| **Flash (ROM 合计)** | **215,056 B (210.0 KB)** | 1,048,576 B (1024 KB) | **20.5%** | +| ER_IROM1 | 222,376 B (217.16 KB) | 1,048,576 B (1024 KB) | 21.2% | +| RW_IRAM1 | 95,816 B (93.57 KB) | 131,072 B (128 KB) | 73.1% | +| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% | +| **Flash (ROM 合计)** | **223,412 B (218.2 KB)** | 1,048,576 B (1024 KB) | **21.3%** | 各区的容量与常量来源: @@ -48,7 +48,7 @@ |---|---|---| | 主 SRAM (0x20000000) | 128 KB(RW_IRAM1 Max `0x20000`) | scatter `STM32F407-Demo.sct:22` | | CCM SRAM (0x10000000) | 64 KB;FreeRTOS 堆于 2026-09-21 迁入(§1.2) | scatter `STM32F407-Demo.sct:25`;RM0090 §3.1.1 | -| FreeRTOS 堆 (heap_4) | 48 KB(49,152 B),**位于 RW_CCM**;实测 `free=8,784 / min_ever=4,848` B | `Inc/FreeRTOSConfig.h:71` `configTOTAL_HEAP_SIZE` | +| FreeRTOS 堆 (heap_4) | **56 KB(57,344 B)**,**位于 RW_CCM**;2026-10-12(B5)由 48 KB 扩容(protectTask/iec104Task 栈入堆,CCM 水位 87.9% < 92% 门禁);旧 48KB 池实测 `free=8,784 / min_ever=4,848` B(2026-10-03),新池 min_ever 待上板复测 | `Inc/FreeRTOSConfig.h:71` `configTOTAL_HEAP_SIZE`(L1:`.ioc` `FREERTOS.configTOTAL_HEAP_SIZE`) | | C 库堆/栈 (startup) | 512 B / 1 KB,启动期 main() 用 | map `startup_stm32f407xx.o` HEAP/STACK 节 | ### 2.2 静态大项排行(2026-10-10 当前,完整台账 `data/ram_report_20261010.md`) @@ -85,7 +85,7 @@ > **DMA 可达性**:第 4/6/7 项(NAND FTL、CH395F SPI2、GD5F BBT)为 DMA 缓冲,**必须留在主 SRAM**、禁止迁 CCM/SRAM3——权威清点与规则见 `内存内容分配策略.md`(本文不重复)。 > 2026-09-11 历史排行(`heap_4.o` 49,152 B 尚在 SRAM1、静态合计 122.7 KB 的旧布局)见 `data/ram_report_20260911.md`,仅供回溯。 -### 2.3 任务栈(从 48KB 堆动态分配) +### 2.3 任务栈(从 56KB 堆动态分配,2026-10-12 起;此前 48KB) ![任务栈预算](../images/任务栈预算.svg) @@ -110,6 +110,8 @@ | defaultTask | `1024*4` | 4KB | FatFS 挂载/探针 + 配置引擎 + syslog + 栈水位探针 | 2152 B(余 47%)/ 静态 2776 B | | timeSyncTask | `512*4` | 2KB | TCP 时间同步 | 616 B(余 69%)/ 静态 **1024 B**(= ISR 底线,无再加深空间) | | adcTask | `640*4` | 2.5KB | TPAFE5160 采样消费 + L2 相量 + L1-6 有效性校验(TIM3 1 kHz 节拍,B1→L2→L1-6 2026-10-11) | **952 / 2560**(余 1608 B / 62%,台架 `@test` 实测 2026-10-11);静态 1080 B | +| iec104Task | `640*4` | 2.5KB | IEC104 上行服务(2404 监听 + link 状态机,B4 2026-10-12) | 未上板 / 静态 **1456 B**(拆链→重建监听→net_bind→SPI 故障→日志尾,日志主导;512 words 时余 592 B < ISR 底线 → 抬至 640,余 1104 B / 43%) | +| protectTask | `512*4` | 2KB | 保护判据节拍(prot_elm_run 消费者 + L5-4 采样闭锁,B5 2026-10-12) | 未上板 / 静态 **872 B**(float 判据 + phasor 快照 + 日志尾,余 1176 B / 57%) | | idle(内核) | `configMINIMAL_STACK_SIZE=128` | 0.5KB | 空闲 | 未观测(未取句柄) | | timer(内核) | `configTIMER_TASK_STACK_DEPTH=256` | 1KB | 软定时器 | 未观测 | @@ -417,7 +419,7 @@ FreeRTOS 堆不变(`free=17248 / min_ever=9312`)。验证链:`@build` 0/0 依据 RM0090 §3.1.1:F407 的 64KB CCM @0x10000000 仅 CPU 可访问(DMA 不可达、无 cache)。 -**进度(2026-09-21)**:第一阶段已落地——scatter 新增 `RW_CCM` 区(`sct:25`,注释 "FreeRTOS heap only")并把 **FreeRTOS 堆整体迁入**(49,184 B,CCM 占用 75.3%)。下表缓冲迁入清单为**后续剩余项**(LVGL 池/UI 缓冲现仍在主 SRAM);`APP_CCM_ENABLE` 门禁宏**尚未实现**(scatter 无开关,见下"风险门禁")。 +**进度(2026-09-21)**:第一阶段已落地——scatter 新增 `RW_CCM` 区(`sct:25`,注释 "FreeRTOS heap only")并把 **FreeRTOS 堆整体迁入**(当时历史快照:49,184 B,CCM 占用 75.3%;现值见 §2.1——2026-10-12 B5 堆已扩至 56 KB)。下表缓冲迁入清单为**后续剩余项**(LVGL 池/UI 缓冲现仍在主 SRAM);`APP_CCM_ENABLE` 门禁宏**尚未实现**(scatter 无开关,见下"风险门禁")。 **迁入 CCM 的缓冲(全部纯 CPU 读写):** @@ -523,7 +525,7 @@ ISR 余量:该任务运行期间可能被中断打断的最深中断链(SPI/ |---|---|---| | 主 SRAM 静态占用 | 87,040 B / 128KB(66.4%) | **~27KB / 128KB**(LVGL 池 + UI 缓冲迁 CCM、`ui_net_sink` 关) | | 主 SRAM 余量 | 44,032 B(43.0KB) | **~101KB** | -| CCM 使用 | 49,184 B / 64KB(75.0%,FreeRTOS 堆) | ~56KB / 64KB(堆 32K + 池 16K + UI 缓冲 + BBT) | +| CCM 使用 | 49,184 B / 64KB(75.0%,FreeRTOS 堆,历史当时值。2026-10-12 B5 后堆 56 KB / 87.9%) | ~56KB / 64KB(堆 32K + 池 16K + UI 缓冲 + BBT) | | 任务栈合计 | 38,912 B(38.0KB) | ~21.5KB(§1.3 修正目标) | | FreeRTOS 堆 | 49,152 B(`free=8,784 / min_ever=4,848` B) | 32,768 B(余 ≥8KB,全负载验证) | | **总余量** | **~68KB**(47.9 + 16.0 + 4.8) | **~120KB** | diff --git a/docs/内存管理/RAM预算台账.md b/docs/内存管理/RAM预算台账.md new file mode 100644 index 00000000..1a395a81 --- /dev/null +++ b/docs/内存管理/RAM预算台账.md @@ -0,0 +1,96 @@ +# RAM 预算台账(配额 · 趋势 · 门禁) + +> **定位**:`docs/内存管理/RAM使用分析与优化方案.md` §8.2 模板与 +> `docs/问题记录/项目审查与优化建议报告.md` §5.5 三件套的**落地件**(2026-10-12,登记簿 N-27 前半 / W1-0)。 +> 回答三个问题:**每个子系统还能用多少 RAM**(配额)、**总量趋势往哪走**(基线 TSV)、 +> **超了怎么拦**(92% 门禁)。 +> +> **数字不手抄**:下方受管区由 `scripts/ram_baseline.py --write` 从 `.map` 生成, +> pre-commit `mem-budget` 钩子校验一致性(同 `mem-numbers` 的"事实源唯一"思路)。 +> 配额是**规划值**(`docs/问题记录/项目审查与优化建议报告.md` §5.5),改动 = 先登记本文件 §6 变更记录,再改 `ram_baseline.py` 的 `QUOTAS`。 +> 区域放置与 DMA 可达性规则 → `内存内容分配策略.md`(本文件不重复)。 + +## 1. 区域预算与门禁(受管区) + + +| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) | +|---|---|---|---|---| +| ER_IROM1 (Flash) | 222,376 B | 1,048,576 B | 21.2% | 参考 | +| RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS | +| UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 | +| RW_IRAM1 | 95,816 B | 131,072 B | 73.1% | PASS | + +| 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 | +|---|---|---|---| +| 网络 | 13,366 B | 12 KB | ⚠ 超 1.1 KB | +| 存储 | 7,056 B | 12 KB | OK | +| UI | 54,988 B | 16 KB | ⚠ 超 37.7 KB | +| RTOS 堆 | 57,376 B | 56 KB | 堆=配额 | +| 应用 | 12,843 B | 8 KB | ⚠ 超 4.5 KB | +| 其它 | 7,596 B | — | 参考 | + + +- **门禁**:pre-commit `mem-budget` 钩子(`scripts/ram_baseline.py --gate`)—— + RW_IRAM1 / RW_CCM 任一 >92% 即拦提交,并打印 Top-10 RW+ZI 对象定位增量; + 无 `.map` 时自适应跳过(CI 盲区登记在 `docs/待处理内容.md` A-5 残余)。 +- **阈值依据**:92% = `docs/问题记录/项目审查与优化建议报告.md` §5.5 第 1 条——留 ~8% 给突发缓冲与栈抬升, + 触线即触发排期,而不是静默逼近溢出。 +- **软提醒**(不拦提交):tsv 末行落后于 `.map`(忘跑 `--update`)、`.map` 早于最新源码(忘 `@build`)。 +- **子系统归集为参考值**:按对象名前缀归集(口径见 §2),合计与区域总量可差几十字节 + (链接器填充行与 `UNINIT_CCM` 等小区分段所致);区域行才是门禁事实源。 + +## 2. 子系统配额口径 + +配额值(`ram_baseline.py` 的 `QUOTAS`,与 `docs/问题记录/项目审查与优化建议报告.md` §5.5 第 3 条一致; +RTOS 堆 2026-10-12 B5 扩容 48→56 KB 见 §6):**网络 12 KB / 存储 12 KB / +UI 16 KB / RTOS 堆 56 KB / 应用 8 KB**。归集口径(按 `.map` 对象名,首匹配): + +| 子系统 | 计入对象(前缀/精确名) | 不计入 | +|---|---|---| +| 网络 | `ch395f*` `net_*` `lftpd*` `ftp_task*` | `ui_net_sink`(算 UI) | +| 存储 | `gd5f*` `nand_*` `ff*` `diskio*` `vol_lock*` + dhara 裸名(`map/journal/nand/fctl/era.o`) | `cfg_*`(算应用) | +| UI | `lv_*` `ui_*`(含 `ui_net_sink`、`ui_task`) | — | +| RTOS 堆 | `heap_4.o`(CCM)——配额 = `configTOTAL_HEAP_SIZE` 本身 | 内核对象(`tasks/queue/timers/...` 归"其它") | +| 应用 | `App/` 其余:采集 `adc_*`、保护 `prot_*`、相量 `phasor/sample_ring`、配置 `cfg_*`、日志 `sys_/dbg_/console_log`、对时 `time_sync*`、`sys_clock`、`task_watchdog`、`sha256`、`tpafe*`、`sd2506`、`default_task` 等 | — | +| 其它 | 内核对象、HAL、CMSIS、启动文件、C 库、链接器填充 | — | + +**现状判读(2026-10-12 建档)**: + +- **UI ⚠ 超配额 = W3 的既有债务,不是新增违规**:LVGL 池 40 KB(R-9 目标 16 KB)+ 帧/远显缓冲 + ≈12.8 KB(R-2 目标迁 CCM)——配额 16 KB 描述的是 **R-9/R-2 落地后的目标态**(排期见 + `docs/待处理内容.md` §2 W3)。 +- **RTOS 堆 = 配额本身**:56 KB 即 `configTOTAL_HEAP_SIZE`(2026-10-12 B5 由 48 KB 扩容,见 §6; + `heap_4.o` 另含 32 B 元数据,不计超);**改堆 = 改配额**,必须先过本文件 §6 登记。 +- **应用 ⚠ 小幅超**:8 KB 为报告规划值;2026-10-10 栈整改把 3 处 `FIL` 从栈搬进 BSS + (静态 +4,128 B,见 `docs/内存管理/RAM使用分析与优化方案.md` §4"2026-10-10 复测")—— + 属已评审的"以空间换栈安全",差额在此如实体现。 + +## 3. CCM 分配台账(谁能用 CCM) + +| 项 | 值 | 说明 | +|---|---|---| +| CCM 容量 | `RW_CCM` Max 见受管区 | scatter `RW_CCM`;**仅 CPU 可达,DMA 不可达**(RM0090 §3.1.1) | +| 现占用 | 仅 FreeRTOS 堆 `heap_4`(56 KB,2026-09-21 迁入;2026-10-12 B5 扩容 48→56 KB) | 其余候选全部仍在 SRAM1 | +| 现余量 | 受管区 RW_CCM 容量 − 占用(≈8 KB) | **不够** R-2 后半的 UI 侧待迁体量(R-9 后仍 ≈30 KB) | +| R-2 后半解锁链 | ① R-9:`LV_MEM_SIZE` 40→16 KB(待迁体量降到 ~30 KB)→ ② 堆 56→32 KB(`docs/内存管理/RAM使用分析与优化方案.md` §2.2,再腾 24 KB;⚠ 2026-10-12 B5 反向扩容至 56 KB——9 任务栈 + 队列实测需要,缩回 32 KB 前必须重跑 `stack_report.py` + 上板 min_ever 复测)→ ③ CCM 余 ~32 KB ≥ 30 KB → 迁入 | **顺序不可颠倒**;每步前后跑 `stack_report.py` / `ram_report.py`(铁律) | +| 迁入前置 | 目标缓冲必须过 DMA 可达性清单(`内存内容分配策略.md`) | 违例 = 静默传错(N-11 同类坑);克隆芯片 CCM 可靠性风险见 `docs/内存管理/RAM使用分析与优化方案.md` §7 | + +## 4. 趋势基线(`scripts/ram_baseline.tsv`) + +- **每次 `@build` 后**:`& '.venv\Scripts\python.exe' scripts/ram_baseline.py --update` + 追加一行(Code/RO/RW/ZI + 三区水位 + Top-10 RW+ZI 对象;同日重跑覆盖当日行)。 +- **看趋势 / 找增量**:`scripts/ram_baseline.py --trend`——高亮较上一行 RW+ZI 增长 >1 KB 的对象, + 即 `docs/内存管理/RAM使用分析与优化方案.md` §0.3 "ZI 增量 >1KB 必须在提交说明中解释"的机械化;提交说明直接抄 `--trend` 输出行。 + +## 5. 超配额流程 + +新增/扩大静态缓冲导致子系统越过配额:**先登记再动手**——本文件 §6 加一行 +(日期 / 子系统 / 现值→新值 / 原因 / 决定人),提交说明引用该行。 +92% 门禁拦的是**总量**,配额管的是**结构**(谁挤占了谁),两者不可互替。 + +## 6. 变更记录 + +| 日期 | 变更 | 原因 / 出处 | +|---|---|---| +| 2026-10-12 | 建档:三件套落地(本台账 + `scripts/ram_baseline.py` + `scripts/ram_baseline.tsv` + pre-commit `mem-budget` 钩子) | 登记簿 N-27 前半(W1-0);`docs/问题记录/项目审查与优化建议报告.md` §5.5 | +| 2026-10-12 | **RTOS 堆配额 48 KB → 56 KB**(`QUOTAS` 同步) | B5 protectTask 立项:iec104Task(2.5KB)+protectTask(2KB)+TCB 入堆后 48KB 池 min_ever 预估跌破 3,072 B 告警线 → `.ioc` L1 参数 `configTOTAL_HEAP_SIZE` 49152→57344(CCM 水位 75.3%→87.9%,仍 <92% 门禁;CCM 空闲降至 ≈8 KB)。连带影响见 §3 R-2 后半链注记 | diff --git a/docs/内存管理/内存内容分配策略.md b/docs/内存管理/内存内容分配策略.md index c7c3f5c1..c57bb571 100644 --- a/docs/内存管理/内存内容分配策略.md +++ b/docs/内存管理/内存内容分配策略.md @@ -38,7 +38,7 @@ ## 4. 内容分配规则 -- **R1(CCM 驻留)**:CCM 只放"**CPU-only 且损坏即致命、无自愈**"的内存。当前唯一驻留者 = **FreeRTOS 堆**(`heap_4.o`,48KB:全部任务栈/队列/定时器)。scatter 的 RW_CCM 节**不得**再列其他对象;任何新增必须经 §5 式裁决并走 §7 完整验证阶梯。 +- **R1(CCM 驻留)**:CCM 只放"**CPU-only 且损坏即致命、无自愈**"的内存。当前唯一驻留者 = **FreeRTOS 堆**(`heap_4.o`,56KB——2026-10-12 B5 由 48KB 扩容,`.ioc` L1 参数 `configTOTAL_HEAP_SIZE=57344`;全部任务栈/队列/定时器)。scatter 的 RW_CCM 节**不得**再列其他对象;任何新增必须经 §5 式裁决并走 §7 完整验证阶梯。 - **R2(DMA 缓冲)**:只允许文件作用域静态缓冲,必须落 SRAM。两条防线缺一不可: - **尺寸防线**:GD5F DMA 阈值 `GD5F_DMA_THRESHOLD=1024`(>1024B 才走 DMA;阈值以下一律 CPU 轮询)。取值须 ≥ 存储路径上可能出现在任务栈的最大缓冲(dhara meta 132B、`dhara_nand_is_free` 64B)、且 < 页大小(2048,保住页级热路径的 DMA)。 - **地址防线(2026-09-21 加固)**:`gd5f_dma_buf_ok()` 运行时校验**整段**缓冲是否落在 SRAM 区间(0x20000000~0x2001FFFF),越界者拒走 DMA、回落 CPU 轮询,并打印 `[ERR][NAND] RX/TX DMA buffer not DMA-reachable (p=… size=…) fallback poll`。 @@ -108,12 +108,12 @@ CCM 64KB 只能容纳 {FreeRTOS 堆 48KB} 与 {LVGL 集合 ~52.5KB} 之一(两 触发条件:测试构建 SRAM 余量不足,**且**已耗尽 `RAM使用分析与优化方案.md` 的 R-4 帧副本去重(−6.4~9.6KB)与 LVGL 池缩减等低代价手段。 流程:改 scatter → 走 §7 完整验证阶梯 → 同步更新本文档、`AGENTS.md`、`.sct` 头注释。在此之前,方案 A 是唯一有效布局。 -## 6. 当前容量台账(2026-09-21,最坏构建 = 存储套件) +## 6. 当前容量台账(2026-10-12,产品构建;2026-09-21 最坏构建=存储套件的历史基线见 `docs/内存管理/RAM预算台账.md` 趋势) | 区域 | 总量 | 已用 | 空闲 | 驻留内容 | |---|---|---|---|---| -| RW_IRAM1(SRAM) | 131,072B (128KB) | 78,188B (~76.4KB) | 52,884B (~51.7KB) | 全部静态(除堆),含 LVGL 集合 53,805B | -| RW_CCM | 65,536B (64KB) | 49,152B (48KB) | 16,384B (16KB) | **仅** `heap_4.o`(ucHeap 48KB) | +| RW_IRAM1(SRAM) | 131,072B (128KB) | 95,816B (~93.6KB, 73.1%) | 35,256B (~34.4KB) | 全部静态(除堆),含 LVGL 集合 53,805B | +| RW_CCM | 65,536B (64KB) | 57,376B (56KB, 87.9%) | 8,160B (~8KB) | **仅** `heap_4.o`(ucHeap 56KB,2026-10-12 B5 扩容) | LVGL 集合明细(均在 SRAM):LVGL 池 40,960B(`lv_mem_core_builtin.o`,`LV_MEM_ADR=0` 内部静态)+ `g_ui_draw_buf` 3,232B(3200+32 保护带)+ `g_ui_fbuf` 3,200B + `g_tx` 3,209B + `g_lcdmem_data` 3,204B。 diff --git a/docs/子系统设计/IEC104上行设计说明.md b/docs/子系统设计/IEC104上行设计说明.md new file mode 100644 index 00000000..346c7b12 --- /dev/null +++ b/docs/子系统设计/IEC104上行设计说明.md @@ -0,0 +1,168 @@ +# 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` §2.1(W1 / B4)。 +> **角色**:本 DTU = **被控站(受控端)**,104 **TCP 服务器,端口 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):背景/周期/死区上送 | 归一化/标度、谐波轨(L2-8) | +| 遥信 YX | 单点 M_SP + 双点 M_DP:背景 + 突发(COT=3) | SOE 带时标 CP56(M_SP_TB,随 L4-4 SOE 落地) | +| 遥控 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. 分层与模块(A-4 约束 1:协议解析与硬件 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`(随实现定名) | 2404 监听、数据通道收发、断链重听、netTask 驱动 | 全部(net_* API) | + +> 三个纯逻辑模块 + 真实数据源(`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 | phasor `C02-UA-F1` fAmSQ | ✅ 有效 | +| 0x4012/0x4013 | 1Ub/1Uc | — | ❌ 发 IV(STM32 侧削顶,`docs/算法/继电保护功能复现规划.md` §1.6) | +| 0x4014 | 1U0 | phasor `C03-UN-F1` | ✅ 有效(外部零序专用通道) | +| 0x4015 | 1Ia | phasor `C01-IA-F1` | ✅ 有效 | +| 0x4016~0x4018 | 1Ib/1Ic/1I0 | — | ❌ 发 IV(同上) | +| 0x401D | 1f 频率 | 软件测频 | ❌ 发 IV(L1-7 未实现) | + +- 现读数为**原始码值**(L1-5 标定未实现,系数=1 口径与之一致);死区本期内置 + 10.0 码值/点,标定落地后复核。 +- 相量未就绪(未满一周波)→ QDS 置 NT(0x20),与 IV(无效通道)语义区分。 + +### 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 | 零序过流 Ⅰ/Ⅱ | L3-2 未实现 | ❌ IV | +| 21~22 | 接地故障/重载 | 未实现 | ❌ IV | +| 23 | 过载 | `PE_OL` asserted | ✅ | +| 24~30 | 外部遥信(RS-485) | B2 暂缓(`docs/待处理内容.md` §2.4) | ❌ 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 端到端)。 + +### 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 遥控软压板 | 否定确认(无全局压板项,随 P4 定值集成) | +| 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 即单一事实源。 +- 写两段式:选择 = 范围校验;执行 = `prot_set_set` + `prot_set_seal`(校验和封存, + L5-1 闭环:主站改错值 → 自检闭锁链自动生效)。 + +## 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 = 遥信变位 + 遥测死区(`iec104_pts_cov_check`),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_can_accept`/`net_can_read`(纯 RAM 读)省无谓 RPC 往返; + 每 32 轮无条件 recv 一次防 RECV_OK 中断丢失(ui_net_sink I-1/I-2 先例)。 +- **网络代次自愈**:`net_get_generation()` 变化 → 关旧 fd 重建监听(netTask + NET_RECONFIG 重建路径的既有约定)。 +- **主动拆链**(与 EOF 路径相对):协议故障(坏帧/N(R) 倒退/t1 超时)或发送连续 + 3 次失败(E-04 短写先例)→ 本端 `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。公共地址 V0.1 固定 1。 + +## 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、定值两段写 + seal 后 selfcheck、C_RD、C_CS(含闰年)、错地址/错类型 EVI | +| L0 | `iec104-unit-test` 钩子 + cppcheck/coding-standard | +| 台架 | `@test` 锚点(104 服务启动/监听行);主站工具(lib60870 或等效)总召+遥测+遥控往返,随 B4 收尾 | + +## 8. V0.1 限制与待办(如实登记) + +1. 固有参数 8001H~800AH 未实现(字符串类无法短浮点上送)→ 未知 IOA 应答;随送检需求再设计。 +2. SOE 带时标(M_SP_TB_1)随 L4-4 SOE 记录落地;现突发只发 COT=3。 +3. YK1~4/12/13/14 否定确认——出口硬件确认后(R7)转真执行。 +4. 遥测死区 10.0 码值为拟定值,L1-5 标定后按工程量死区(点表 8020H 段)复核。 +5. 多主站/双链路冗余不做(单连接语义)。 +6. 主站侧验证工具与送检环境未就绪——台架只做到"第三方 104 主站可总召"级。 +7. **后连优先未实现**(V0.1 = 首到优先):单连接 socket 连接态无法 accept, + 旧会话结束前新主站接入被拒;后连优先需 net 层(CH395F 单连接模型)支持, + 真需要冗余切换时随 net 扩展立项。 +8. 公共地址固定 1、监听端口固定 2404:可配置化(config.ini)随二期。 + +## 变更记录 + +| 日期 | 变更 | +|---|---| +| 2026-10-12 | 建档(B4):范围/分层/点表/链路流程/接入决策/预算/测试方案;§5 接线细节随实现回填 | +| 2026-10-12 | B4 落地回填:承载改**专用 iec104Task**(netTask 承载会 RPC 自死锁);§5 全量回填(门控/代次/拆链/对时/看门狗位 7);抢占策略修正为**首到优先**(§8 第 7 条);§6 实测(640 words,链 1456 B,余 43% PASS) | diff --git a/docs/子系统设计/看门狗设计说明.md b/docs/子系统设计/看门狗设计说明.md index 1fe6b8c6..9f99f809 100644 --- a/docs/子系统设计/看门狗设计说明.md +++ b/docs/子系统设计/看门狗设计说明.md @@ -24,7 +24,7 @@ | 超时 | 标称 **2498 ms**,最坏(LSI 47 kHz)**≈1701 ms** | `WD_IWDG_PRESCALER=4` / `WD_IWDG_RELOAD=1249`(`task_watchdog.c`) | | 抽样周期 | **100 ms**(`WD_POLL_PERIOD_MS`) | 同上 | | 缺失容忍 | **连续 8 轮 = 800 ms** 后停喂(`WD_MISS_TOLERANCE`) | 同上 | -| 必需掩码 | 产品构建 **`0x77`**(default/net/ftp/ui/timesync/adc);`ENABLE_HW_LAYER_TESTS` 下 **`0x75`**(剔 net) | `wd_required_mask()` | +| 必需掩码 | 产品构建 **`0x1F7`**(default/net/ftp/ui/timesync/adc/iec104/protect);`ENABLE_HW_LAYER_TESTS` 下 **`0x1F5`**(剔 net) | `wd_required_mask()` | | 喂狗者 | **仅 defaultTask**(`task_wd_poll`,主循环每轮调用、内部节流) | `App/task/default_task.c` | | 启动时刻 | **defaultTask 存储 bring-up 之后**(`task_wd_start()`);`MX_IWDG_Init()` 只填参数不启动 | `default_task.c:175`、`Src/iwdg.c` 的 `USER CODE BEGIN 0` | | 复位归因 | 停喂 → IWDG 自然溢出 → `RCC_CSR.IWDGRSTF`(不用 `NVIC_SystemReset`) | `task_wd_poll()` | @@ -678,3 +678,4 @@ enter/exit 段还能读出"此刻仍在段内已多久"——**永久阻塞的 | 2026-10-10 | **B1 `@test` 实机闭环:adcTask 掩码真机验证** | 台架闭环(`.dsh/skills/serial-boot-test/scripts/run_boot_test.py`)确认 `adcTask` 纳入掩码后**无 adc 相关误复位**:`[STACK] adc peak_used=496/2048 free_min=1552 (75%)`、`frames/seq` 每 10 s 严格 +10000(=1000 Hz)、`idle=0`/`frst_err=0`、全片回读 `No difference found`。启动早期两次 `MISS start snap=0x67 req=0x77` 仅缺 bit4(`timeSync` 未启动,属正常就绪窗;adc 的 bit6 自始置位),掩码随后收敛、全程无复位。同轮另修 `dbg_console_writer_ready()` 门控(adcTask 周期日志在写者注册前抑制,见 `控制台单写者日志设计说明.md`) | | 2026-10-10 | **新增 §11:任务级饥饿的诊断方法与实测基线** | 承接 Task #32(`task stall: mask=0x67 req=0x77`,缺 `TASK_WD_UI`)结案后的沉淀——原分析文档 `docs/问题记录/UI任务看门狗停摆分析.md` 按"完成即销项"删除,可复用部分并入本文:**§11.1** 三条易误读的判读口径(启动期 `MISS start 0x67` 良性、`miss=` 是累计不是连续、`reset cause` 不能区分 IWDG 与台架);**§11.2** 诊断四步(先看掩码缺几位 → 量化占空比 → 用计数速率反证空转 → 用 `[PROF]` 指认占用者;本例否掉"CPU 饱和",实测 10%~13%);**§11.3** 三条结构性脆弱点(uiTask 唯一 BelowNormal/心跳依赖 netTask 往返/自定截止期不可恢复)与两个顺带修掉的**正确性**缺陷(无新帧仍压环 ≈3% 频率失配、失败拍静默沿用旧值);**§11.4** `[PROF]`/`[PROF2]` 全字段语义 + v2.8 基线(含 `netp=0` 是真实值、`adcm` 峰值来自心跳日志、`uip` 地板 = LVGL 帧周期)与三机理判读口诀;**§11.5** 三条教训(门控须留低频兜底、门控会消灭暴露路径、事件驱动要核对节拍源与消费者创建时刻);**§11.6** 明确不做的四条及理由。§9.1 的 R7 行改指本文 §11.3 | | 2026-10-11 | **新增 §10.4:ARMCC `__asm` 的三条语法约束** | AGENTS.md 瘦身:「ARMCC 内联汇编语法」条目的完整细节(GCC 语法报 `#18`、块内联把寄存器名当 C 标识符报 `#20`、`__asm` 取不到 C 数据符号 `A1516E`、可用写法 = 整函数 `__asm void f(void)` + `B` 到 C 入口、`#define f f_Gen` 让位机理)迁入本文,AGENTS.md 只留一行禁令与指针 | +| 2026-10-12 | **iec104Task / protectTask 纳入监视(B4/B5):必需掩码 `0x77`→`0xF7`→`0x1F7`** | 两行合并记录(B4 落地时漏补本文,B5 一并纠偏):**B4** 新增 `TASK_WD_IEC104 = 7`(iec104Task 100 ms 服务循环喂位,NET_READY 屏障等待按 100 ms 分片喂位),产品 `0x77`→`0xF7`、HW 层 `0x75`→`0xF5`;**B5** 新增 `TASK_WD_PROTECT = 8`(protectTask 20 ms 判据节拍喂位,见 `docs/算法/继电保护功能复现规划.md` §7),产品 `0xF7`→`0x1F7`、HW 层 `0xF5`→`0x1F5`。两任务均**不依赖存储/网络之外的屏障**(protectTask 无任何屏障)→ 任何构建都置位;均不做 NAND I/O → 不登记 FTL 心跳路由。主机侧单测 `beat_all()` 与 `tc_003`/`tc_005`/`tc_011` 掩码断言同步至 `0x1F7`,39 断言全绿。⚠ 注意 `0x1F7` 不含 bit3(testTask 任何构建不入掩码,口径不变) | diff --git a/docs/待处理内容.md b/docs/待处理内容.md index 88111996..3571d97d 100644 --- a/docs/待处理内容.md +++ b/docs/待处理内容.md @@ -1,58 +1,64 @@ # 待处理内容(统一待办登记簿) -> **用途**:**全项目唯一的未闭环事项登记簿**——汇总"审计发现 / 台架观察 / 测试充分性与架构 -> 专项 / 任务排序"四类待办。原 `审查记录/项目审计改进清单.md`(P-x)、`审查记录/下一步任务规划.md` -> (阶段与基线)、`审查记录/测试与架构改进建议.md`(S1x / A-x)、`docs/待处理内容.md`(N-x / S-x / T-x) -> 于 2026-10-04 合并入本文件,**编号一律沿用,不回收**。 +> **这个文件是什么**:全项目唯一的未闭环事项清单 + 全项目唯一权威的工作先后顺序。 > -> **只保留待办**:**已完成条目直接删除,不留变更记录**(历史见 `git log` 与各模块文档); +> **怎么用**:想知道"现在该做什么、按什么顺序" → 只看 **§2**;想知道"某条待办的来龙去脉" → 按编号查 **§3**; +> 想知道"还差哪些验证" → §2.3。其余章节:编号规则(§0/§8)、待确认(§4)、设计与诊断基线(§5~§7)。 +> +> **只保留待办**:已完成条目直接删除,不留变更记录(历史见 `git log` 与各模块文档); > 已闭环项的**结论与证据沉淀进对应模块文档/问题记录**,本文件不再重复。 > **消化即销项**:事项修复/关闭后,直接删除对应条目,并同步清理其它文档对本编号的引用。 > > **不在本文件范围**:`问题记录/错误码传播审计.md`(E-xx,审计报告,非待办池)、 > `问题记录/项目审查与优化建议报告.md`(体系层评审报告)、`测试说明/实机测试实施指南.md`(执行流程)。 > -> **创建**:2026-09-22(L3 pending 台架收尾);**合并重写**:2026-10-04;**统一排序 + 审查报告并轨**:2026-10-11。 +> **修订**:2026-10-04 四档合并;2026-10-11 统一排序 + 审查报告并轨; +> **2026-10-12 按用户决定 RS-485(B2)整簇暂缓(§2.4),波次重排为 W1~W7,清除已销项残留**; +> **2026-10-12 W1-0 台账三件套落地(N-27 前半闭环,`mem-budget` 钩子),N-23 钩子落地残余并入 C5**; +> **2026-10-12 B4/B5 销项——W1 功能主线代码侧全部完成**(验收窗口见 §2.1)。 --- ## 0. 编号空间与来源 -| 编号 | 含义 | 原出处 | 备注 | -|---|---|---|---| -| `P0-x` / `P1-x` / `P2-x` / `P3-x` | 审计缺陷/改进项 | `项目审计改进清单.md`(2026-09-15/09-21 审计) | P0=功能 bug、P1=疑似 bug/健壮性、P2=改进、P3=卫生 | -| `N-x` | 跨文档观察/登记项 | `待处理内容.md` 登记簿 | 台架/审计发现、暂不在修复范围;**含硬件改版项**(需下一版硬件解决,固件侧只记口径,如 N-18) | -| `S-x` | 存储/日志管线待办 | 同上 | 存储侧健壮性 | -| `T-x` | 测试/验证基础设施待办 | 同上 | 工具链、CI | -| `S1~S14` / `A-1~A-7` | 测试充分性与架构改进专项 | `测试与架构改进建议.md`(2026-10-02 复审) | **编号不随条目删除而回收** | -| `E-xx` | 错误码传播审计发现 | `错误码传播审计.md` | **不并入本文件**,交叉引用 | -| 阶段 `A/B/C/D` + `B0~B3`/`C1~C6`/`D2~D6` | 任务排序分组 | `下一步任务规划.md` | 见 §2 | -| 报告 `N-x`/`R-x`/`F-x`/`S-x`/`U-x`/`D-x` | **审查报告自有编号** | `项目审查与优化建议报告.md` | ⚠ **与本登记簿 N-x/S-x 同名不同义**(报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架;报告 S-3 = check_registration.py,登记簿 S-3 = USART1 TX-only)→ **引用一律带文档名**。2026-10-11 其未闭环项已并入本登记簿,新编 `N-19`~`N-29`(出处列保留报告编号) | +| 编号 | 含义 | 备注 | +|---|---|---| +| `P0-x`~`P3-x` | 审计缺陷/改进项(2026-09-15/09-21 审计) | P0=功能 bug、P1=疑似 bug/健壮性、P2=改进、P3=卫生 | +| `N-x` / `S-x` / `T-x` | 台架/审计观察登记项 / 存储·日志管线 / 测试与工具链 | 编号**不回收**;`N-x` 含硬件改版项(需下一版硬件,固件侧只记口径,如 N-18) | +| `S1~S14` / `A-1~A-7` | 2026-10-02 复审的测试充分性与架构专项 | 编号**不回收** | +| `E-xx` | 错误码传播审计发现 | 独立维护于 `错误码传播审计.md`,**不并入本文件**,只交叉引用 | +| `B`/`C`/`D` 前缀 | §2 排序条目编号:B=功能主线、C=结构债、D=验证窗口 | 编号不回收,见 §2 | +| 报告 `N-x`/`R-x`/`F-x`/`S-x`/`U-x`/`D-x` | `项目审查与优化建议报告.md` **自有编号** | ⚠ **与本登记簿同名不同义**(报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架)→ **引用一律带文档名**。其未闭环项 2026-10-11 并入本登记簿(新编 `N-19`~`N-29` + U 簇,出处列保留报告编号) | **严重度定义**(沿用审计口径):P0 = 确认功能 bug|P1 = 疑似 bug 或健壮性风险|P2 = 改进|P3 = 卫生。 **置信度**:high = 代码级确证|medium = 依赖外部条件(手册/硬件/产品定义)。 --- -## 1. 未闭环一览(按严重度) +## 1. 未闭环一览(按类别) -| 级别 | 数量 | 关键项 | +| 类别 | 数量 | 条目 | |---|---|---| -| **安全** | 0 | — | -| **P1** | 0 (+1 收尾) | P1-10 测试固件构建实测闭环(主体已闭环,见 §3.1);~~N-30~~ 已销项(2026-10-11 三连定案修复,回归 4 轮 11/11,见 `问题记录/CH395F_Trap_Records.md` Trap 25) | -| 登记簿 | 20 | 网络:N-2(49s 日志静默,**低风险观察项**)、N-3(L5 基线重验)、N-4(pending 二期)、N-16(A2/A4 专项负向验证)、N-17(探针窗口心跳缺口);存储/日志:**S-3(USART1 TX-only 根治)**、S-4(dhara 重试自旋)、S-5(可选全序列卷锁)、N-22(写回 flush)、N-24(日志逐条开关);数据正确性:**N-21(dhara is_free/copy,报告 N-12/13)**;结构:**N-20(Error_Handler 死循环)、N-23(注册反向校验)、N-26(NAND DMA 断言)**;预算:**N-27(内存优化簇)、N-28(Flash 死代码簇)**;仓库:**N-29(.git 149 MB,需用户决策)**;硬件:**N-18(V0.2 改版项)** | -| 测试/基础设施 | 6 | T-7(CI runner 未就绪 + 推送后两 job 闭环 + 第二机交叉验证)+ **S12**(断言宏)、**S1-c**(可选单测)、**A-4**(采集链路测试约束)、**A-5 残余**(CI 体积门禁盲区)、**D7**(串口助手 A6/A7 待 CH340) | +| P1 收尾 | 1 | P1-10 测试固件构建实测(§3.1) | +| 网络 | 5 | N-2(49s 日志静默,**低风险观察项**)· N-3(L5 基线重验)· N-4(pending 二期)· N-16(A2/A4 负向台架)· N-17(探针窗口心跳缺口) | +| 存储 / 日志 | 3 | **S-3(USART1 TX-only 根治)** · S-4(dhara 重试自旋)· S-5(可选全序列卷锁) | +| 数据正确性 | 1 | **N-21(dhara `is_free`/`copy`,全簿最高风险)** | +| 结构 / 健壮性 | 8 | N-20(Error_Handler 死循环)· N-22(写回 flush)· N-23(注册校验残余白名单)· N-24(日志逐条开关)· N-25(性能/语义簇)· N-26(NAND DMA 断言)· N-27(内存优化簇,三件套 ✅ 前半落地)· N-28(Flash 死代码簇) | +| 仓库 | 1 | N-29(`.git` 149 MB,**已决策暂不处理、登记观察**) | +| 硬件 | 1 | N-18(V0.2 改版项) | +| 测试 / 基础设施 | 6 | T-7(CI runner + 推送闭环 + 第二机交叉验证)· S12(断言宏)· S1-c(可选单测)· A-4(采集链路测试约束,RS485 侧随 B2 暂缓)· A-5 残余(CI 体积门禁盲区)· D7(串口助手 A6/A7 待 CH340) | +| UI | 1 簇 | U 簇(27 页标准化,**本轮不排期**) | +| **暂缓** | 1 簇 | **B2 RS-485 整簇(2026-10-12 用户决定,§2.4)** | > **网络侧另有 E-xx 未闭环项**(E-12/15/16/23/24/25/26/27/28/30/47/48/49/50/58/59/61,共 17 项) -> 与 1 项回归监督(E-62),详见 `问题记录/错误码传播审计.md` §3。本文件不重复登记。 -> **UI 标准化簇**(报告 U1~U5,27 页未落地)与**覆盖率缺口**(lftpd/dhara 移植层无主机测试) -> 为整簇排期项,见 §2 W7 / N-21,明细指报告 §6/§7。 +> 与 1 项回归监督(E-62),详见 `问题记录/错误码传播审计.md` §3——其中 **E-49/E-50 随 RS-485 暂缓**。 +> 本文件不重复登记。UI 标准化簇与覆盖率缺口(lftpd/dhara 移植层无主机测试)为整簇排期项,见 §2 W6 / N-21。 ### 1.1 结构性判断(排序依据) -1. **产品功能主线只剩"采集与转发"两环**:ADC 侧 ✅(B1 台架闭环);**RS-485 侧被 E-50/E-49 挡着(B2)**;**上行 IEC104(B4)与 protectTask 立项(B5)此前只写在产品需求/保护规划,未进本登记簿——2026-10-11 补登**。B4 数据源已具备,可与 B2 并行。 -2. **数据正确性最高风险 = N-21**(dhara `is_free` 只查页首 64 B / `copy` 不处理哨兵):低概率、后果重(数据丢失),且**至今只能靠人工读代码发现**——修复须配主机侧移植层测试(一并补报告"覆盖率"缺口)。 -3. **内存优化被预算卡死**:CCM 只剩 16,304 B,54 KB 的 LVGL 池+UI 缓冲迁不进去(R-2 后半段堵死)→ 必须先做 §5.5 台账三件套(`ram_baseline.tsv` + 预算台账 + 92% 门禁)再排期 R-9→R-2。 +1. **产品功能主线"转发 + 保护"两环代码已落地(2026-10-12)**:采集侧 ADC(B1)已台架闭环;上行 IEC104(B4)与保护判据 protectTask(B5)代码均已落地(`App/protocol/iec104/` + iec104Task;`App/task/protect_task.c` 20 ms 判据节拍→104 遥信),**遗留为验收窗口**(台架主站往返随送检、标准源注入、`@test` 水位)。**RS-485 对下采集(B2)按用户决定暂缓(2026-10-12,§2.4),主线不再等它**。 +2. **数据正确性最高风险 = N-21**(dhara `is_free` 只查页首 64 B / `copy` 不处理哨兵):低概率、后果重(数据丢失),且至今只能靠人工读代码发现——修复须配主机侧移植层测试(一并补报告"覆盖率"缺口)。 +3. **内存预算红线已机械化(2026-10-12,W1-0)**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势基线 → `docs/内存管理/RAM预算台账.md`;实际优化 R-9→R-2 排 W3(**B5 堆扩容 48→56 KB 后 CCM 只剩 ≈8,160 B**,解锁链见 `docs/内存管理/RAM预算台账.md` §3)。 4. **验证债仅剩窗口性事项**(D2/D5/D6/D7 + P1-10 收尾),不单独排期、逢窗口顺手做。 --- @@ -61,44 +67,49 @@ > **本节是全项目所有工作流唯一的权威顺序**:`产品需求设计文档.md` §9.2、`算法/继电保护功能复现规划.md`、 > `项目审查与优化建议报告.md` §0.3 中的路线图均为局部视图,**顺序变更只改本节,其它文档只留指针**。 -> 排序原则:**安全风险 > 产品功能主线 > 数据正确性 > 预算/结构债 > 验证常态 > UI 扩展 > 仓库决策**。 +> 排序原则:**安全风险 > 产品功能主线 > 数据正确性 > 预算/结构债 > 验证常态 > UI 扩展 > 仓库决策**(当前无未闭环安全项)。 ### 2.0 波次总览 | 波次 | 内容 | 为什么在这 | |---|---|---| -| **W2 功能主线** | **修 E-50/E-49 → B2** RS-485(ModBus RTU)∥ **B4** IEC104 上行 → **B5** protectTask 立项 | DTU 核心职责"采集与转发"仅剩两环:RS-485 侧被 E-59 挡、上行侧未动工;B4 数据源(ADC ✅)已具备,**可与 B2 并行**。**已定(2026-10-11):B2 先行(先修 E-50/E-49 驱动契约)、B4 并行开工** | -| **W3 数据正确性** | **N-21** dhara `is_free`/`copy`(报告 N-12/13) | 低概率、后果重(数据丢失);修复须配主机侧移植层测试,一并补报告"覆盖率"缺口 | -| **W4 预算与内存** | **N-27**:`docs/问题记录/项目审查与优化建议报告.md` §5.5 台账三件套 → R-9 池 40→16 KB → R-2 后半(54 KB→CCM) | CCM 只剩 16,304 B,R-2 后半被堵死;三件套是排期前提且工作量小 | -| **W5 结构债** | C1 pending 二期 · C3 日志管线(N-2 + N-24)· C5 收口 · C6 USART1(S-3)· N-20 `Error_Handler` · N-23 注册反向校验 · N-22/N-25/N-26/N-28 | 二期/健壮性/评估类,无紧急;N-23 是唯一"1 小时工作量"的一条;~~N-30~~ 已销项(Trap 25 定案修复,2026-10-11 回归 4 轮 11/11);~~N-31~~ 已销项(FUN_PARA=0x08 定案 + 0x08 下多 Socket 实测 Phase 7 34/34,见 `问题记录/CH395F_Trap_Records.md` Trap 18「定案更正」) | -| **W6 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · **D7 串口助手 A6/A7** · S12 · S1-c · A-5 | 窗口性,逢机顺带,不单独排期 | -| **W7 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5) | -| **W8 仓库决策** | **N-29** `.git` 149 MB + 图片 36.3 MB | `git filter-repo` 历史重写影响未推送提交与协作者 → **需用户决策** | +| **W1 功能主线** | **B4 IEC104 上行 ✅ 2026-10-12 → B5 protectTask ✅ 2026-10-12(W1 代码侧全部完成)**(W1-0 台账三件套 ✅ 2026-10-12 落地,见 N-27) | DTU 核心职责"转发 + 保护"两环代码均已落地:B4(`App/protocol/iec104/` 三件套 + iec104Task 2404,82 断言 L0.5 + `iec104-unit-test` 钩子);B5(`App/task/protect_task.c` 20 ms 判据节拍 + L5-4 采样闭锁 + IWDG bit8 + 栈 512 words 静态链 872 B/余 57% + 堆 48→56 KB,见 `docs/算法/继电保护功能复现规划.md` §7 变更记录)。**遗留 = 验收窗口**:台架第三方主站往返(`docs/子系统设计/IEC104上行设计说明.md` §7/§8)+ 标准源注入动作判据 + `@test` PROT 锚点/水位 | +| **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** | 无紧急,按性价比排:C6 灭 IWDG 误复位机制根源;C1 体量大、验证重,放后(N-23 钩子已落地 2026-10-12,残余并入 C5) | +| **W5 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · D7 串口助手 · S12 · S1-c · A-5 | 窗口性,逢机顺带,不单独排期 | +| **W6 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5);**本轮不排期(2026-10-11 已确认)** | +| **W7 仓库决策** | **N-29** `.git` 149 MB + 图片 36.3 MB | **已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(`git filter-repo` 历史重写影响未推送提交与协作者) | +| **暂缓** | **B2 RS-485 整簇**(§2.4) | **用户决定(2026-10-12):当前不处理 RS-485** | | **硬件改版** | N-18 8 路电气量全接 TPAFE(V0.2) | 下一版硬件;固件侧已用语义映射隔离,改版只动映射表 | -### 2.1 W2 功能主线详述 +### 2.1 W1 功能主线详述 -> **B0 产品定义已于 2026-10-10 确认并销项**:上行 **IEC 60870-5-104**(以太网 TCP 2404,遥测短浮点系数 1)/ -> 持续采集 / **1000 Hz(20 点/周波)** / RS-485 **对下 ModBus RTU 采集**;结论详见 -> `docs/算法/继电保护功能复现规划.md` §1.5,并已同步 `docs/产品需求/产品需求设计文档.md` §5.9/§5.10/§9。 -> **B3(纪律门禁)已固化进 `AGENTS.md`**;**B1(ADC 采集链路)已 `@test` 实机闭环销项**(2026-10-10)。 +> **背景(已闭环,只留指针)**:B0 产品定义 2026-10-10 确认——上行 **IEC 60870-5-104**(以太网 TCP 2404, +> 遥测短浮点系数 1)/ 持续采集 / **1000 Hz(20 点/周波)** / RS-485 对下 ModBus RTU,结论详见 +> `docs/算法/继电保护功能复现规划.md` §1.5 与 `docs/产品需求/产品需求设计文档.md` §5.9/§5.10/§9; +> B1 ADC 采集链路已 `@test` 实机闭环;B3 纪律门禁已固化进 `AGENTS.md`。 +> +> **W1 全部销项(2026-10-12)**:B4 证据见 `docs/子系统设计/IEC104上行设计说明.md`(82 断言 + 钩子 + `@build` 0/0); +> B5 证据见 `docs/算法/继电保护功能复现规划.md` §7 变更记录(protectTask 20 ms 判据节拍 + L5-4 采样闭锁 + +> IWDG `TASK_WD_PROTECT` bit8 + 栈 512 words 静态链 872 B/余 57% + 堆 48→56 KB + prot_elm 28 用例)。 +> **遗留验收窗口**(非代码空洞):台架第三方 104 主站往返(随送检窗口)、标准源注入动作判据、 +> `@test` PROT 锚点 + `[STACK] protect` 水位 + 新堆 min_ever 复测。 -| 序 | 任务 | 前置 | 说明 | -|---|---|---|---| -| **B2** | **RS-485 采集链路实现**(消化 E-50、E-49) | **E-59 门禁尚未满足**(E-50 / E-49 未修,先修驱动契约) | 双缓冲 + 序号(防包撕裂)+ DE 收尾(超时路径等 TC)+ ModBus RTU 状态机(`App/protocol/` 正是为此预留);设计约束见 A-4 | -| **B4** | **IEC 60870-5-104 上行**(TCP 2404,遥测/遥信/遥控上送) | B0 ✅ + 数据源(ADC ✅,**可与 B2 并行**) | 协议解析与 I/O 分离(A-4 约束 1)→ 天然适合 L0.5 主机单测;注意 CH395F 单连接约束(104 客户端与 FTP/远显/对时抢同一 socket 池,接入前定抢占策略,关联报告 N-09) | -| **B5** | **protectTask 立项**(L3 板端接线) | B2/B4 推进中;E-59 同款门禁 | `prot_set`/`prot_elm` 软件侧已落地(链接器移除、零足迹);建任务前后各跑 `stack_report.py`;定值/回路接线按保护规划路线图走 | +### 2.2 W4 结构债详述 -### 2.2 W5 结构债详述 +> 波内顺序 = 性价比:先可靠性根治,后大体量重构;评估簇随窗口。 | 序 | 任务 | 说明 | 出处 | |---|---|---|---| -| **C1** | **pending 二期(ACCEPT + SEND)** | 沿一期机制扩展;同期消化 E-25(net_select 语义)、E-24/E-27/E-28(跨上下文收口);基线重锁 + 探针族扩充 + 看门狗接 selftest。**设计基线见 §5.1** | 第二档 #2 / N-4 | -| **C3** | **存储侧日志管线**(消化 N-2) | 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop`+`[ERR] CONSOLE dropped`、`sys_log_mcu.c` 队列满 `DBG_ERROR`、TX 僵尸通道自愈);V5 30 min 日志**未复现 49s 静默**(运行期 >10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。剩余:与 S8(非阻塞日志)合并评估 + **S-3(USART1 TX-only 结构根治)** | N-2 / S-3 | -| **C5** | 一档剩余 | E-49(RS485 DE 收尾)、E-15(ringbuf 定去留——**已确认零调用者,倾向删除**)、E-61(SD2506 注释订正)、E-16(cfg_file 段名长度)、E-26(UDP 定案,倾向移除)、E-23、E-30 | 一档/二档 | -| **C6** | **USART1 TX-only 结构根治**(S-3) | 灭 ORE 僵尸机制根源:改 `.ioc` 令 USART1 不使能 RX / PA10 不复用为 `USART1_RX` → CubeMX 重生成 → 跑 `check_cubemx_survival.py`。属结构性改动,需单开一轮 + 复跑台架闭环 | S-3 | +| **N-20** | **`Error_Handler` 统一降级** | 一处初始化失败 = 整机挂死(只剩 IWDG 兜底)→ 记自检 + 禁用该子系统 + 其余照常。详见 §3.2 | 报告 N-03c | +| **C6** | **USART1 TX-only 结构根治(S-3)** | 灭 ORE 僵尸机制根源(2026-10-02 台架 IWDG 误复位的机制根源):改 `.ioc` 令 USART1 不使能 RX / PA10 不复用为 `USART1_RX` → CubeMX 重生成 → 跑 `check_cubemx_survival.py`。结构性改动,需单开一轮 + 复跑台架闭环 | S-3 | +| **C3** | **存储侧日志管线(N-2 + N-24)** | 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop`+`[ERR] CONSOLE dropped`、`sys_log_mcu.c` 队列满 `DBG_ERROR`、TX 僵尸通道自愈);V5 30 min 日志**未复现 49s 静默**(运行期 >10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。剩余:与 S8(非阻塞日志)合并评估 + 日志逐条 `f_open/f_write/f_close` 改造评估(N-24) | N-2 / N-24 | +| **C1** | **pending 二期(ACCEPT + SEND)** | 沿一期机制扩展;同期消化 E-25(net_select 语义)、E-24/E-27/E-28(跨上下文收口);基线重锁 + 探针族扩充 + 看门狗接 selftest。**设计基线见 §5.1** | N-4 | +| **C5** | 一档剩余 | E-15(ringbuf 定去留——**已确认零调用者,倾向删除**)、E-61(SD2506 注释订正)、E-16(cfg_file 段名长度)、E-26(UDP 定案,倾向移除)、E-23、E-30;**N-23 残余**(`KNOWN_GAPS` 白名单清理 + `app_cfg.h` 未接线开关,见 §3.2)。**E-49(RS485 DE 收尾)已移入暂缓(§2.4)** | 一档/二档 | +| **N-22/25/26/28** | 评估簇 | 写回 flush / 性能与语义一致性 / NAND DMA 断言 / Flash 死代码——逐项见 §3.2 对应行,随窗口评估 | 报告各条 | -### 2.3 W6 验证常态详述 +### 2.3 W5 验证常态详述 | 序 | 任务 | 说明 | |---|---|---| @@ -107,21 +118,34 @@ | **D6** | **N-17 探针窗口心跳缺口** | 定位 `time_sync` 监听重建为何阻塞 NET/FTP/UI(~1s 缺口,余量仅 ~0.7s);评估缩短重建重试或让掉线路径不阻塞其它任务 | | **D7** | **串口助手 A6/A7 正路径补验** | 需 CH340 硬件接入后补验(`串口助手设计说明.md` 状态行 A1–A5/A8 已过) | -### 2.4 顺序一图 +### 2.4 暂缓:RS-485 整簇(用户决定,2026-10-12) + +> **当前没有处理 RS-485 的打算**,以下条目整体冻结、不占波次;**重启 B2 时先回本节评估前置,勿直接开工**。 + +| 项 | 内容 | 重启时的前置 | +|---|---|---| +| **B2** | **RS-485 采集链路实现**(消化 E-50、E-49):双缓冲 + 序号(防包撕裂)+ DE 收尾(超时路径等 TC)+ ModBus RTU 状态机(`App/protocol/` 正是为此预留) | **E-59 门禁尚未满足**:先修 E-50(单缓冲包撕裂)、E-49(TX 超时拉 DE 未等 TC),修完驱动契约才允许接消费者 | +| E-49 | RS485 DE 收尾(原 C5 一档剩余,已移出) | 同上 | +| A-4 RS485 侧 | 采集链路测试可验证性约束(双缓冲 + 序号、DE 超时路径覆盖,§3.3.3) | 随 B2 设计文档落地 | +| §4-3 | RS-485 PD0 DE 半双工方向语义硬件实测确认 | 需硬件实测窗口 | +| N-25 中 DE 项 | `HAL_Delay(1)` 阻塞 DE | 随 B2 | + +### 2.5 顺序一图 ``` -W2 功能 E-50/E-49 → B2 RS485(ModBus) ∥ B4 IEC104 上行 → B5 protectTask +W1 功能 B4 IEC104 上行 ✅ 2026-10-12 → B5 protectTask ✅ 2026-10-12(W1 完成;台账三件套 ✅) ↓ -W3 数据 N-21 dhara is_free/copy(配主机侧移植层测试) +W2 数据 N-21 dhara is_free/copy(配主机侧移植层测试) ↓ -W4 预算 内存台账三件套 → R-9 池瘦身 → R-2 后半(54KB→CCM) +W3 预算 R-9 池瘦身 → R-2 后半(54KB→CCM)→ R-3~R-6 评估 ↓ -W5 结构 C1 pending 二期 · C3 日志(N-2/N-24) · C5 · C6(S-3) · N-20 · N-23 · N-22/25/26/28 +W4 结构 N-20 → C6(S-3) → C3(N-2/N-24) → C1 pending 二期 → C5(含 N-23 残余) → N-22/25/26/28 ↓ -W6 验证 P1-10 · T-7 CI · D2/D5/D6/D7 · S12 · S1-c · A-5 +W5 验证 P1-10 · T-7 CI · D2/D5/D6/D7 · S12 · S1-c · A-5 ↓ -W7 UI U4 残余 → U1 令牌层 → U2/U3 → 27 页(单独立项) -W8 仓库 N-29 .git 149MB(用户决策) 硬件:N-18 V0.2 +W6 UI U4 残余 → U1 令牌层 → U2/U3 → 27 页(单独立项,本轮不排期) +W7 仓库 N-29 .git 149MB(已决策暂不处理) 硬件:N-18 V0.2 +暂缓 B2 RS-485 整簇(2026-10-12 用户决定,§2.4) ``` --- @@ -143,11 +167,12 @@ W8 仓库 N-29 .git 149MB(用户决策) 硬件:N-18 V0.2 | # | 事项 | 发现 | 证据与现状 | 出处 | |---|---|---|---|---| -| N-2 | **49s 全系统日志静默(defaultTask/NAND syslog 排空停滞)**——串口日志 49s 无行,期间 net 栈照常处理外部连接 → 日志管线停滞,队列满后各任务日志行被丢;系统功能不受损 | 2026-09-22(L3 台架 F2,gen 181) | **A/B 归因:既有存储侧现象**。**2026-10-03 降级为低风险观察项**:① 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop` + `[ERR] CONSOLE dropped`;`sys_log_mcu.c` 队列满 `DBG_ERROR`;UART TX 僵尸通道自愈);② V5 30 min **未复现 49s**(>10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。**残余待办**:与 S8(非阻塞日志)合并评估 | `错误码传播审计.md` E-02 阶段二 | +| N-2 | **49s 全系统日志静默(defaultTask/NAND syslog 排空停滞)**——串口日志 49s 无行,期间 net 栈照常处理外部连接 → 日志管线停滞,队列满后各任务日志行被丢;系统功能不受损 | 2026-09-22(L3 台架 F2,gen 181) | **A/B 归因:既有存储侧现象**。**2026-10-03 降级为低风险观察项**:① 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop` + `[ERR] CONSOLE dropped`;`sys_log_mcu.c` 队列满 `DBG_ERROR`;UART TX 僵尸通道自愈);② V5 30 min **未复现 49s**(>10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。**残余待办**:与 S8(非阻塞日志)合并评估(C3) | `错误码传播审计.md` E-02 阶段二 | | N-3 | **L5 队列往返基线(1223/988µs)的 L3 后重验**——L5 测 DONTWAIT 队列全程;L3 对该路径逐位不变 → 机制上无影响,但基线数值属分片时代,严格重锁需跑一轮 Phase 13(需 PC peer) | 2026-09-22(L3 收尾留档) | 低风险:10ms/100ms 阈值余量 >8×;下次 Phase 13 窗口顺带重锁即可 | `链路延迟测试说明.md` §6.4 L5 注¹ | | N-4 | **pending 机制二期:ACCEPT + SEND 阻塞路径 pending 化**——E-06、E-20、E-21 剩余分量共用该机制扩展;届时 L3/L5 基线再重锁、探针族扩充、看门狗接 selftest 留痕、模拟器差距清单 +1 | — | 一期(RECV)已落地并入主线;架构现状见 `Net层阻塞模型架构设计.md`,二期设计基线见 §5.1 | `错误码传播审计.md` 第二档 #2 | | N-16 | **A2/A4 专项场景台架验证待办**(正常路径已实测零回归):① PHY 拔线负向测试——断链需断 **DTU 侧**线缆或关**受管交换机端口**;② A2 芯片级 `net_init` 失败分支(需 SPI 故障注入);③ A4 短写压测(需远显客户端 + UI 推流压力) | 2026-10-03(台架拓扑 = CH395↔交换机,拔线操作受限) | 待专项台架窗口 | `实机测试实施指南.md` §10 | | N-17 | **`time_sync` 30s 挂起客户端掉线 + 监听重建期间,网络任务心跳缺口达 800ms~1s(声明 stall 但未复位)。**待办**:定位监听重建为何阻塞 NET/FTP/UI;评估缩短重建重试(5×2s)或让掉线路径不阻塞其它任务 | 2026-10-03(V5 台架) | V5 长跑 44 次 `task stall: mask=0x00000001`,**100% 与 `e02_probe` 的 30s 挂起客户端触发 `time_sync: no TIME packet in 30s, drop conn` → 监听重建(约 4s)重合**;隔离实验(仅 FTP,120s)**0 次 stall** → 探针场景专属。缺口(~1s)< IWDG 最坏超时(1701ms),余量仅 ~0.7s。 | `实机测试实施指南.md` §4;`子系统设计/看门狗设计说明.md` | +| N-32 | **CH395F 监听生命周期根治(B10 残余)**——现仅靠对账④兜底(提交 `4f2cc8b`)。根治两步:**P1 把"会话已结束"从边沿改成电平**(`net_sock_t` 增 `session_dead`;`net_recv_locked` DONTWAIT 判据改 `state==CLOSED \|\| session_dead`;`ui_net_sink.c:563` 补 `g_client != g_listen` 护栏;accept 门控换 `net_listener_armed`);**P2 单一所有者**(新增 `net_listener_pump`,删 `net_accept_locked:1346`/`net_recv_locked:1884`/`net_pending_tick:2451` 散点 relisten;消灭 netTask 内 500 ms 忙等 `:2597-2616`/`:1115-1126`)。**已定案不走芯片多连接模式(A′ 出局:不支持多监听)** | 2026-10-12(B10 定案;⚠ ④ 有副作用——抢先 relisten 会把慢消费者的 EOF 永久吞掉,新客户端数据被旧会话静默吸收,待 P1 消除) | 原理 + 证据附录(实测数据 / 官方例程所有权 / 状态机 15 迁移点 / 三服务契约不一致表)+ **决策记录 D1~D7** + 可勾选执行清单 → `子系统设计/网络Socket监听生命周期设计说明.md` §7~§9;现象与回归见 `问题记录/CH395F_Trap_Records.md` B10 行 | **存储 / 日志管线** @@ -173,17 +198,17 @@ W8 仓库 N-29 .git 149MB(用户决策) 硬件:N-18 V0.2 | # | 事项 | 影响 / 现状 | 处置方向 | 波次 | 出处 | |---|---|---|---|---|---| -| N-20 | `Error_Handler` 仍 `__disable_irq(); while(1){}`(`Src/main.c:274-282`) | 一处初始化失败 = 整机挂死(只剩 IWDG 兜底),无自检日志 | 统一降级策略:记自检 + 禁用该子系统 + 其余照常 | W5 | 报告 N-03c | -| N-21 | **dhara 两处**:`dhara_nand_is_free()` 只查页首 64 B;`dhara_nand_copy()` 不处理 `DHARA_NO_PAGE` 哨兵 | 映射恢复误判 → **数据丢失风险**(低概率、后果重);哨兵页号被当真实页 → 未定义行为;至今只能靠人工读代码发现 | 整页(或首/中/尾)扫描 + 返回 `DHARA_E_UNSUPPORTED`;**必须配主机侧移植层单测**(一并补报告"覆盖率"缺口) | **W3** | 报告 N-12/N-13 + §7 | -| N-22 | 写回缓存无空闲/掉电强制 flush(整页写与换页已 flush) | 写回窗口内掉电丢最近日志/配置写 | defaultTask 空闲 N ms flush | W5 | 报告 N-14 | -| N-23 | **双端注册无反向校验**:`rs485_task.c`、`lftpd_log.c` 既不在 uvprojx 也不在 simulator | "写了不编译"= 死代码 + 误导 | `check_registration.py`(报告中唯一"1 小时工作量")+ 挂 pre-commit;`app_cfg.h` 未接线开关一并处置(C5) | W5 | 报告 N-06 残余 + 报告 S-3 | -| N-24 | 日志每条 `f_open+f_write+f_close`(`sys_log_mcu.c:123-140`) | 每条日志 2–4 次 NAND 页读写;UI 翻记录逐条 open/seek/close | 与 C3 日志管线合并评估(现仅 `FIL` static 化省 528 B 栈) | W5 | 报告 N-16(**≠ 本登记簿 N-16**) | -| N-25 | 性能/资源建议簇:PASV 每次新建监听;`NET_RECV_TIMEOUT_MS 30000`;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE | 次级性能/语义一致性 | 逐项见 `docs/问题记录/项目审查与优化建议报告.md` §4.2/§4.5/§4.7,随窗口评估 | W5 | 报告 N-09/P2-8/PHY/P3-x/rs485 | -| N-26 | NAND 直 DMA 调用方缓冲(已加运行时守卫,阈值 1024) | CCM 缓冲被 DMA = 静默传错(与 ADC DMA 不可达 CCM 同类坑) | 补编译期/启动期地址断言 + **新铁律:堆缓冲不可被 DMA 直接寻址** | W5 | 报告 N-11 | -| N-27 | **内存优化簇**:LVGL 池 + UI 两份缓冲 54,146 B 仍在 SRAM1,CCM 只剩 16,304 B;`ram_baseline.tsv` / `RAM预算台账.md` / 92% 阈值门禁**均未建** | R-2 后半段(迁 CCM)被堵死 → B2/B4/B5 的功能预算看不清 | **前置 §5.5 台账三件套** → R-9(`LV_MEM_SIZE` 40→16 KB,池水位门禁数据已具备)→ R-2 后半;R-3/R-4/R-5/R-6 逐项评估(R-6 前置已满足) | **W4** | 报告 R-2 剩余/R-3~R-6/R-9/§5.5 | -| N-28 | Flash 死代码评估簇:剩余 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个空 LVGL TU(F-1/F-2/F-3 已闭环,省的是编译时长) | 编译时长 + 文档噪音 | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制必经路径,**不可盲关** | W5 | 报告 F-4/F-5/F-6 | -| N-29 | **仓库膨胀**:`.git` 149 MB + 图片 36.3 MB | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(届时未推送提交更少、重写代价最低) | **W8** | 报告 D-1 | -| U 簇 | UI 标准化:无令牌层/组件库/页注册表(手写 `case` 仍在),**27 页**未落地;golden 未挂 pre-commit、字符集差集检查仍是约定 | 新增一页成本仍是 8 处手工改动 | 按 `docs/问题记录/项目审查与优化建议报告.md` §6.5:U4 残余(两脚本入门禁,可逢窗口顺带)→ U1 令牌层 → U2/U3 → 页面落地;U4 golden 可直接当 U1 验收工具。**已确认(2026-10-11):本轮不排期**,等功能主线出结果后按产品需求启动 | W7 | 报告 U1~U5 | +| N-20 | `Error_Handler` 仍 `__disable_irq(); while(1){}`(`Src/main.c:274-282`) | 一处初始化失败 = 整机挂死(只剩 IWDG 兜底),无自检日志 | 统一降级策略:记自检 + 禁用该子系统 + 其余照常 | W4 | 报告 N-03c | +| N-21 | **dhara 两处**:`dhara_nand_is_free()` 只查页首 64 B;`dhara_nand_copy()` 不处理 `DHARA_NO_PAGE` 哨兵 | 映射恢复误判 → **数据丢失风险**(低概率、后果重);哨兵页号被当真实页 → 未定义行为;至今只能靠人工读代码发现 | 整页(或首/中/尾)扫描 + 返回 `DHARA_E_UNSUPPORTED`;**必须配主机侧移植层单测**(一并补报告"覆盖率"缺口) | **W2** | 报告 N-12/N-13 + §7 | +| N-22 | 写回缓存无空闲/掉电强制 flush(整页写与换页已 flush) | 写回窗口内掉电丢最近日志/配置写 | defaultTask 空闲 N ms flush | W4 | 报告 N-14 | +| N-23 残余 | **钩子已落地**(2026-10-12 `registration-check` 挂 pre-commit,存量缺口走 `KNOWN_GAPS` 白名单只 WARN);**残余** = 白名单清理:`rs485_task.c`(随 B2 暂缓一并处置:删除或注册)、`lftpd_log.c`;`app_cfg.h` 未接线开关(C5) | 白名单不清 = "写了不编译"盲区仍在 | 逐项清白名单(`--strict` 供审计复跑);开关随 C5 处置 | W4(C5) | 报告 N-06 残余 + 报告 S-3 | +| N-24 | 日志每条 `f_open+f_write+f_close`(`sys_log_mcu.c:123-140`) | 每条日志 2–4 次 NAND 页读写;UI 翻记录逐条 open/seek/close | 与 C3 日志管线合并评估(现仅 `FIL` static 化省 528 B 栈) | W4 | 报告 N-16(**≠ 本登记簿 N-16**) | +| N-25 | 性能/资源建议簇:PASV 每次新建监听;`NET_RECV_TIMEOUT_MS 30000`;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(**DE 项随 B2 暂缓,§2.4**) | 次级性能/语义一致性 | 逐项见 `docs/问题记录/项目审查与优化建议报告.md` §4.2/§4.5/§4.7,随窗口评估 | W4 | 报告 N-09/P2-8/PHY/P3-x/rs485 | +| N-26 | NAND 直 DMA 调用方缓冲(已加运行时守卫,阈值 1024) | CCM 缓冲被 DMA = 静默传错(与 ADC DMA 不可达 CCM 同类坑) | 补编译期/启动期地址断言 + **新铁律:堆缓冲不可被 DMA 直接寻址** | W4 | 报告 N-11 | +| N-27 | **内存优化簇**:LVGL 池 + UI 两份缓冲 54,146 B 仍在 SRAM1,CCM 只剩 ≈8,160 B(2026-10-12 B5 堆扩容 48→56 KB 后) | R-2 后半段(迁 CCM)被堵死 → 后续功能预算看不清 | **三件套 ✅ 2026-10-12 落地**(`ram_baseline.py` 四模式 + `ram_baseline.tsv` 趋势 + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子 92% 门禁)→ **W3** 再做 R-9(`LV_MEM_SIZE` 40→16 KB,池水位门禁数据已具备)→ R-2 后半;R-3/R-4/R-5/R-6 逐项评估(R-6 前置已满足) | **W3** | 报告 R-2 剩余/R-3~R-6/R-9/§5.5 | +| N-28 | Flash 死代码评估簇:剩余 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个空 LVGL TU(F-1/F-2/F-3 已闭环,省的是编译时长) | 编译时长 + 文档噪音 | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制必经路径,**不可盲关** | W4 | 报告 F-4/F-5/F-6 | +| N-29 | **仓库膨胀**:`.git` 149 MB + 图片 36.3 MB | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(届时未推送提交更少、重写代价最低) | **W7** | 报告 D-1 | +| U 簇 | UI 标准化:无令牌层/组件库/页注册表(手写 `case` 仍在),**27 页**未落地;golden 未挂 pre-commit、字符集差集检查仍是约定 | 新增一页成本仍是 8 处手工改动 | 按 `docs/问题记录/项目审查与优化建议报告.md` §6.5:U4 残余(两脚本入门禁,可逢窗口顺带)→ U1 令牌层 → U2/U3 → 页面落地;U4 golden 可直接当 U1 验收工具。**已确认(2026-10-11):本轮不排期**,等功能主线出结果后按产品需求启动 | W6 | 报告 U1~U5 | ### 3.3 测试与架构改进专项(S1x / A-x) @@ -199,7 +224,7 @@ W8 仓库 N-29 .git 149MB(用户决策) 硬件:N-18 V0.2 |---|---|---|---| | **S12** | 模块级轻量断言宏 | ⬜ 待做(第 4 波按需) | 3.3.1 | | **S1-c** | `sys_log` / `time_sync` 主机侧单测 | ⬜ 可选(价值递减) | 3.3.2 | -| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ ADC 侧随 B1 闭环;RS485 待 B2 | 3.3.3 | +| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ ADC 侧随 B1 闭环;**RS485 侧随 B2 暂缓(§2.4)** | 3.3.3 | | **A-5 残余** | CI 体积门禁盲区(`mem-numbers` 在 CI 被跳过) | ⬜ 未消除 | 3.3.4 | #### 3.3.1 S12:模块级轻量断言宏 ⬜ @@ -242,9 +267,9 @@ W8 仓库 N-29 .git 149MB(用户决策) 硬件:N-18 V0.2 #### 3.3.3 A-4:ADC / RS485 采集链路的测试可验证性约束 ⏸ **背景**:`adc_task.c` 已实现(B1,2026-10-10),`rs485_task.c` 仍是空桩,`App/protocol/` 只有 README 与 `.gitkeep`。 -本项不是"缺陷",而是**对上游 B2(B1 已完成)的设计约束**——应在动手前明确,否则后续无法补测。 +本项不是"缺陷",而是**对上游 B2 的设计约束**(B1 已完成;**B2 暂缓中,§2.4——重启 B2 动手前必须先落实本约束**,否则后续无法补测)。 -**约束**(建议纳入 B1 / B2 设计): +**约束**(建议纳入 B2 设计): 1. **协议解析必须与硬件 I/O 分离**——`App/protocol/` 的解析函数应接受 `(const uint8_t *buf, size_t len)` 并返回解析结果,使其成为 L0.5 的**天然适格对象** @@ -267,16 +292,16 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 **完成判据**:存在**强制的**体积校验路径(CI 侧或本地侧),且文档明确其边界。 -> **注**:本项与栈预算是同一话题的两面——**具体栈风险(原 S-1)已于 2026-10-10 削链闭环销项** -> (defaultTask 静态最坏链 5312 → 2776 B、实测 3392 → 2152 B,**未抬栈**),本项仍是**门禁缺口**。 +> **注**:本项与栈预算是同一话题的两面——**具体栈风险(原 S-1)已于 2026-10-10 削链闭环** +> (核算见 `docs/内存管理/RAM使用分析与优化方案.md`),本项仍是**门禁缺口**。 --- ## 4. 待确认(需手册/硬件/产品定义,暂不直接改码) 1. TPAFE5160 是否有自动扫描模式(**已不影响**:1 kHz 硬件定时器触发已于 2026-10-10 由 **TIM3 更新中断**方案落地,不依赖自动扫描,见 `docs/子系统设计/ADC采样节拍设计说明.md`)。 -2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**;B1 取数不依赖该宏)。 -3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)。 +2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**;B1 取数不依赖该宏。**RS-485 侧门控随 B2 暂缓,§2.4**)。 +3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)——**随 B2 暂缓(§2.4)**。 --- @@ -336,9 +361,8 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 > **2026-10-10 重采(栈)/ 2026-10-04 重采(堆)**:栈 = **运行时高水位 + armlink 静态最坏链双口径** > (产品构建 `suite=NONE`,开机 + 空闲采样,串口 `[STACK]` + `stack_report.py`);静态区 = `.map` 受管快照。 -> ✅ **栈水位已回落**:2026-10-04 曾升到 defaultTask **3664 B**(登记 S-1);2026-10-10 削链 -> (删旧档迁移 + `FIL` 静态化 + 日志行缓冲按模块收紧 + 钩子脱离 HAL)后实测 **2152 B**、 -> 静态最坏链 **2776 B**,**未抬栈**即达标。完整核算见 `docs/内存管理/RAM使用分析与优化方案.md`。 +> 栈水位口径:2026-10-10 削链后 defaultTask 实测 **2152 B**、静态最坏链 **2776 B**,**未抬栈**即达标 +> (完整核算见 `docs/内存管理/RAM使用分析与优化方案.md`)。 | 项 | 当前值(栈:2026-10-10;其余:2026-10-04) | 出处 | |---|---|---| @@ -374,11 +398,12 @@ S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 - **任一项完成后直接删除对应条目**(先销本文件条目,再清理其它文档对本编号的引用); **不留变更记录**,历史见 `git log` 与各模块文档。 - 已闭环条目的**结论与证据沉淀进模块文档**,本文件不再重复。 -- 编号一律**沿用且不回收**(P-x / N-x / S-x / T-x / S1x / A-x);`错误码传播审计.md` 的 E-xx 独立维护。 +- 编号一律**沿用且不回收**(P-x / N-x / S-x / T-x / S1x / A-x / B·C·D 前缀);`错误码传播审计.md` 的 E-xx 独立维护。 - **引用审查报告编号一律带文档名**(报告 N-16 ≠ 登记簿 N-16、报告 S-3 ≠ 登记簿 S-3); 报告并轨项用本登记簿新编号(N-19~N-29 + U 簇),出处列保留报告编号。 - **§2 是全项目唯一的推进顺序权威**:`产品需求设计文档.md` §9.2 等只留指针,顺序变更只改 §2。 -- 阶段 B 完成后重写 §1(届时 ADC/RS485 应从未闭环消失)。 -- 新增发现按既有惯例分流:能立即修的进 §2(阶段 C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.2(登记簿)。 +- **暂缓块(§2.4)不是销项**:条目仍在簿,只是不占波次;重启或关闭时更新 §2.4 与 §1。 +- 功能主线(B4/B5)完成后重写 §1。 +- 新增发现按既有惯例分流:能立即修的进 §2(W4 C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.2(登记簿)。 - 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、`问题记录/错误码传播审计.md`(E-xx)、 `测试说明/实机测试实施指南.md`(执行流程)——三者均不在本文件合并范围。 diff --git a/docs/测试说明/测试开发标准流程.md b/docs/测试说明/测试开发标准流程.md index 9998c5a6..644608e8 100644 --- a/docs/测试说明/测试开发标准流程.md +++ b/docs/测试说明/测试开发标准流程.md @@ -329,7 +329,7 @@ static void phaseN_run(void) { | `App/log/sys_log_mcu.c` | — | ⬜ 候选 | 记录编解码(定长 64B) | 编解码纯逻辑;写入端依赖 FatFS + 队列,测编解码即可 | | `App/util/time_sync.c` | — | ⬜ 候选 | 协议帧编解码 | 报文组装/解析纯逻辑;网络收发不测 | | `Drivers/BSP/NETCFG/net_cfg_legacy.c` | — | ⛔ 已删除(2026-10-10) | — | 旧档 NCFG 迁移整体移除(旧档 `/cfg/netcfg.bin` 不读、不删、不迁移),测试候选随之撤销 | -| `App/net/*`(网络栈上层) | — | ⬜ 待评估 | 依赖 socket/CH395F | 纯协议状态机部分或可测,需先确认抽象质量 | +| `App/protocol/iec104/*`(104 协议栈) | — | ✅ 已覆盖(82 断言,2026-10-12 B4) | 数据源 vtable + tick 注入 + 发送回调注入 | APCI 重组/总召分片/COV/k-w-t1~t3/两段式全离线穷举;`iec104-unit-test` 钩子 | | `App/util/rs485.c` | — | ⏸ 待功能实现 | — | 上游 B2;当前为空桩 | | `Drivers/BSP/TPAFE5160/*.c` | — | ❌ 不适格 | — | 寄存器序列为主,需真机时序 | | 其余驱动(CH395F/GD5F2GQ5/SD2506) | — | ❌ 不适格 | — | 需硬件时序 / SPI / I2C 总线 | diff --git a/docs/环境与部署/并行任务工作树方案.md b/docs/环境与部署/并行任务工作树方案.md index ff6fd81a..ad97868b 100644 --- a/docs/环境与部署/并行任务工作树方案.md +++ b/docs/环境与部署/并行任务工作树方案.md @@ -25,16 +25,18 @@ Python 环境、以及 `docs/待处理内容.md` 这类**全局唯一登记簿** ## 2. 方案选型 -| 方案 | 为什么不用 | -|---|---| -| 同一目录切分支 | 构建产物 / `.venv` / 日志目录 / `.workbuddy-ai` 全共享,两任务互相踩;且本仓库明令禁止用 `git checkout` 丢弃未提交工作 | -| 每任务 `git clone` | 对象库 234 MB × N 份、Git LFS 全量重复;克隆之间无法安全共享分支,推送关系也更绕 | -| `git stash` / 打补丁倒换 | 不具备并发安全性,冲突只能靠人工记忆 | -| **`git worktree`(采用)** | 唯一同时满足「共享对象库 + 独立工作目录 + 独立 HEAD/index」的机制;git 原生,本仓库已有先例 | +| 方案 | 为什么不用 | +| ---------------------- | ----------------------------------------------------------------------------------- | +| 同一目录切分支 | 构建产物 / `.venv` / 日志目录 / `.workbuddy-ai` 全共享,两任务互相踩;且本仓库明令禁止用 `git checkout` 丢弃未提交工作 | +| 每任务 `git clone` | 对象库 234 MB × N 份、Git LFS 全量重复;克隆之间无法安全共享分支,推送关系也更绕 | +| `git stash` / 打补丁倒换 | 不具备并发安全性,冲突只能靠人工记忆 | +| **`git worktree`(采用)** | 唯一同时满足「共享对象库 + 独立工作目录 + 独立 HEAD/index」的机制;git 原生,本仓库已有先例 | -**既有先例**:`D:/Code/DTU Code/_v1pin-build`、`_v2oui-build` 就是遗留 worktree(detached HEAD, -2026-09-19 建、已过期)。本方案沿用其「仓库同级 + `_` 前缀」的命名惯例,但把散落的目录收敛到统一的 -`_wt/` 容器下,并在落地时清理这两个遗留目录。 +**命名惯例来源**:`D:/Code/DTU Code/_v1pin-build`、`_v2oui-build` 曾是遗留 worktree(detached HEAD, +2026-09-19 建、已过期),本方案沿用其「仓库同级 + `_` 前缀」命名,但把散落的目录收敛到统一的 +`_wt/` 容器下。**两者已于 2026-10-12 清理**:`_v1pin-build` 干净直接移除;`_v2oui-build` 有 2 个 +未提交改动(uvprojx / freertos.c),已按字节留档于 `_wt/.archive/2026-10-12-legacy-worktrees/` +后才移除(两提交由 `wip/trap22-fix` / `wip/v2-pending-recv` 持有,无提交丢失)。 --- @@ -65,15 +67,15 @@ D:/Code/DTU Code/ ### 3.2 共享 vs 独占 -| 资源 | 归属 | 原因 | -|---|---|---| -| `.git/` 对象库 + hooks | **共享**(git 机制自动) | 工作树共享 common dir,提交门禁无需在新空间重装 | -| `.venv/` | **共享**(junction) | 体积大、内容与任务无关;每任务重建一份纯属浪费 | -| `simulator/SDL2/` | **共享**(junction) | 下载型 SDK,与任务无关 | -| `.workbuddy-ai/` | **独占**(刻意不共享) | ① 避免并发写同一份日志丢更新;② 不给联接递归删除的机会——它是本项目最不可再生的目录。任务侧记忆由清场前归并回主工作树 | -| `MDK-ARM/` 构建产物、`simulator/build/` | **独占** | 正是需要隔离的部分:两个任务可各自构建互不干扰 | -| `.serialtest/config.json`、`.dsh/skills/`、`.pre-commit-config.yaml` | **独占但内容一致** | 受版本控制,随检出白拿,无需 bootstrap | -| `.mnemon/`、`ci-artifacts/` | **独占** | 本地运行态,gitignored | +| 资源 | 归属 | 原因 | +| ------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------- | +| `.git/` 对象库 + hooks | **共享**(git 机制自动) | 工作树共享 common dir,提交门禁无需在新空间重装 | +| `.venv/` | **共享**(junction) | 体积大、内容与任务无关;每任务重建一份纯属浪费 | +| `simulator/SDL2/` | **共享**(junction) | 下载型 SDK,与任务无关 | +| `.workbuddy-ai/` | **独占**(刻意不共享) | ① 避免并发写同一份日志丢更新;② 不给联接递归删除的机会——它是本项目最不可再生的目录。任务侧记忆由清场前归并回主工作树 | +| `MDK-ARM/` 构建产物、`simulator/build/` | **独占** | 正是需要隔离的部分:两个任务可各自构建互不干扰 | +| `.serialtest/config.json`、`.dsh/skills/`、`.pre-commit-config.yaml` | **独占但内容一致** | 受版本控制,随检出白拿,无需 bootstrap | +| `.mnemon/`、`ci-artifacts/` | **独占** | 本地运行态,gitignored | ### 3.3 junction 规则(**不能用 symlink**) @@ -98,13 +100,13 @@ D:/Code/DTU Code/ ## 4. 分支模型 -| 项 | 取值 | -|---|---| -| 集成分支(主干) | `v2-on-ui` | -| 任务分支 | `task/-`,从主干当前 HEAD 切出 | -| `` | **沿用 `docs/待处理内容.md` 的编号空间**(`P0-x`/`N-x`/`S-x`/`T-x`/`B-x`/`C-x`/`D-x`);无对应条目的临时任务用 `X-<日期>-` | -| 合并方式 | `git merge --no-ff` 合入主干 | -| 并发上限 | **同时最多 3 棵工作树** | +| 项 | 取值 | +| -------- | ---------------------------------------------------------------------------------------------------- | +| 集成分支(主干) | `v2-on-ui` | +| 任务分支 | `task/-`,从主干当前 HEAD 切出 | +| `` | **沿用 `docs/待处理内容.md` 的编号空间**(`P0-x`/`N-x`/`S-x`/`T-x`/`B-x`/`C-x`/`D-x`);无对应条目的临时任务用 `X-<日期>-` | +| 合并方式 | `git merge --no-ff` 合入主干 | +| 并发上限 | **同时最多 3 棵工作树** | **`` 复用登记簿编号**是为了可追溯:任务分支名直接对应待办条目,回收时销项有据可查。 @@ -115,17 +117,17 @@ D:/Code/DTU Code/ ## 5. 任务生命周期 -| 阶段 | 动作 | 并行性 | -|---|---|---| -| `new` | 建分支 + 工作树 + junction + 台账 | 可并行 | -| 编码 | 在新空间里改代码 | 可并行 | -| 门禁 | `scripts/ci_local.py`(L0 + L0.5,纯软件) | **可并行** | -| 构建 | `@build`(UV4 增量,需持 `build` 锁) | **必须串行** | -| 台架 | `@test` / 板级套件(需先持台架锁,见 §7) | **必须串行** | -| 提交 | 本地 `git commit`(多行正文用 `-F `) | 可并行 | -| `sync` | `rebase` 追平主干,把冲突控制在任务分支上 | 可并行 | -| `done` | 预演 → 合入主干 → 残留审计 → 重生成产物 → 门禁 → 清理工作树 | **必须串行** | -| `push` | 推送主干/任务分支 | **需用户明确许可** | +| 阶段 | 动作 | 并行性 | +| ------ | -------------------------------------------- | ----------- | +| `new` | 建分支 + 工作树 + junction + 台账 | 可并行 | +| 编码 | 在新空间里改代码 | 可并行 | +| 门禁 | `scripts/ci_local.py`(L0 + L0.5,纯软件) | **可并行** | +| 构建 | `@build`(UV4 增量,需持 `build` 锁) | **必须串行** | +| 台架 | `@test` / 板级套件(需先持台架锁,见 §7) | **必须串行** | +| 提交 | 本地 `git commit`(多行正文用 `-F `) | 可并行 | +| `sync` | `rebase` 追平主干,把冲突控制在任务分支上 | 可并行 | +| `done` | 预演 → 合入主干 → 残留审计 → 重生成产物 → 门禁 → 清理工作树 | **必须串行** | +| `push` | 推送主干/任务分支 | **需用户明确许可** | **为什么 `done` 必须串行**:合并动作会移动主干引用,两处同时合入会互相覆盖;且主干只在主工作树检出。 @@ -138,14 +140,14 @@ D:/Code/DTU Code/ 并行失败通常不是代码冲突,而是**多个任务同时改同一个「登记簿」**。以下文件在任务期间 **禁止在任务工作树里修改**,一律由 `done` 回收阶段在主工作树统一处理: -| 文件 | 冲突原因 | 回收时的处理 | -|---|---|---| -| `docs/待处理内容.md` | 全项目唯一登记簿,每个任务都要销项 | 由主工作树统一改,任务分支不碰 | -| `AGENTS.md`、`docs/README.md`(索引/登记类) | 每个任务都要在「按主题查哪份文档」表、`docs/README.md` §9.2 环境表、变更记录里**各加一行** → 两任务必冲突(2026-10-12 实测:主工作树里本任务的行与他任务的行已并排混在**同一 hunk**) | 由主工作树统一追加;提交时**只 `git add` 本任务的行**(`git apply --cached` 选择性入库),勿整文件 `git add` | -| `AGENTS.md` 的 `TASK_TABLE` 块 | 生成物,两个任务都抬栈就冲突 | 合并后重跑 `scripts/gen_task_table.py` **重新生成**,不手工并 | -| `MDK-ARM/STM32F407-Demo.uvprojx` | 新源文件注册 + UV4 自动改写 | 手工并 `` 条目 → 重跑 `registration-check` → `@build` | -| `.pre-commit-config.yaml` | 新增主机单测要加钩子 | 并集处理 | -| `docs/内存管理/RAM使用分析与优化方案.md`(及其 `mem-numbers` 快照) | `mem-numbers` 快照 | **绝不手工合数字**,合并后 `scripts/check_mem_numbers.py --write` 重生成 | +| 文件 | 冲突原因 | 回收时的处理 | +| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| `docs/待处理内容.md` | 全项目唯一登记簿,每个任务都要销项 | 由主工作树统一改,任务分支不碰 | +| `AGENTS.md`、`docs/README.md`(索引/登记类) | 每个任务都要在「按主题查哪份文档」表、`docs/README.md` §9.2 环境表、变更记录里**各加一行** → 两任务必冲突(2026-10-12 实测:主工作树里本任务的行与他任务的行已并排混在**同一 hunk**) | 由主工作树统一追加;提交时**只 `git add` 本任务的行**(`git apply --cached` 选择性入库),勿整文件 `git add` | +| `AGENTS.md` 的 `TASK_TABLE` 块 | 生成物,两个任务都抬栈就冲突 | 合并后重跑 `scripts/gen_task_table.py` **重新生成**,不手工并 | +| `MDK-ARM/STM32F407-Demo.uvprojx` | 新源文件注册 + UV4 自动改写 | 手工并 `` 条目 → 重跑 `registration-check` → `@build` | +| `.pre-commit-config.yaml` | 新增主机单测要加钩子 | 并集处理 | +| `docs/内存管理/RAM使用分析与优化方案.md`(及其 `mem-numbers` 快照) | `mem-numbers` 快照 | **绝不手工合数字**,合并后 `scripts/check_mem_numbers.py --write` 重生成 | ### 6.2 合并残留审计(**必做**) @@ -160,6 +162,7 @@ D:/Code/DTU Code/ ### 6.3 冲突时的解决位置 `done` 先做**非破坏性预演**:`git merge-tree --write-tree v2-on-ui task/-`。 + - `rc=0`(无冲突)→ 继续合并 - `rc≠0` → **在任务分支上** `git merge v2-on-ui` 解决冲突并提交,再重跑 `done` @@ -205,15 +208,15 @@ D:/Code/DTU Code/ **执行体**:`.dsh/skills/task-worktree/scripts/task_worktree.py`(纯标准库, 照 `keil_build.py` 的写法,整目录可拷到别的项目复用)。**已落地并端到端实测**(见 §11)。 -| 子命令 | 作用 | -|---|---| +| 子命令 | 作用 | +| ----------------------------------------------------- | ----------------------------------------------------------- | | `new [--base B] [--lean] [--needs-bench]` | 建分支 `task/-` + `_wt/-/` 工作树 + 共享联接 + 台账 | -| `list` | 所有任务一览:分支 / 落后领先 / 脏文件数 / 台架状态 + 两个锁的归属 | -| `status ` | 单任务详情:未提交清单、相对基线漂移、台架记录、已建联接 | -| `sync ` | `rebase` 追平主干,把冲突控制在任务分支上 | -| `lock acquire\|release\|status ` | 独占资源锁(`--task` / `--wait` / `--force` / `--bench-pass`) | -| `done [--dry-run] [--skip-build] [--skip-gates]` | 预演 → 合入主干 → 残留审计 → 重生成产物 → 门禁 → 清场 | -| `abort [--force]` | 放弃任务(有未提交/未合并内容时不加 `--force` 会拒绝) | +| `list` | 所有任务一览:分支 / 落后领先 / 脏文件数 / 台架状态 + 两个锁的归属 | +| `status ` | 单任务详情:未提交清单、相对基线漂移、台架记录、已建联接 | +| `sync ` | `rebase` 追平主干,把冲突控制在任务分支上 | +| `lock acquire\|release\|status ` | 独占资源锁(`--task` / `--wait` / `--force` / `--bench-pass`) | +| `done [--dry-run] [--skip-build] [--skip-gates]` | 预演 → 合入主干 → 残留审计 → 重生成产物 → 门禁 → 清场 | +| `abort [--force]` | 放弃任务(有未提交/未合并内容时不加 `--force` 会拒绝) | **环境变量**:`DTU_WT_ROOT`(任务容器位置)· `DTU_TASK_BASE`(默认基线)· `DTU_INTEGRATION_WORKTREE`(集成点,默认主工作树;用于隔离演练/测试)。 @@ -231,35 +234,37 @@ D:/Code/DTU Code/ ## 9. 门禁与验收 -| 层级 | 内容 | 时机 | -|---|---|---| -| 任务期 | `scripts/ci_local.py`(L0 + L0.5,可并行) | 每个任务各自跑 | -| 任务期 | `@build`(0 错 0 警,**持 `build` 锁串行**) | 每个任务各自跑 | -| 任务期(可选) | `@test` / 板级套件(持 `bench` 锁) | 需真机验证的任务 | -| 回收期 | 重生成产物 → `ci_local.py` → `@build` | `done` 内强制(`--skip-gates` 可跳过) | -| 人工 | push 许可 | 回收后 | +| 层级 | 内容 | 时机 | +| ------- | ------------------------------------ | ------------------------------ | +| 任务期 | `scripts/ci_local.py`(L0 + L0.5,可并行) | 每个任务各自跑 | +| 任务期 | `@build`(0 错 0 警,**持 `build` 锁串行**) | 每个任务各自跑 | +| 任务期(可选) | `@test` / 板级套件(持 `bench` 锁) | 需真机验证的任务 | +| 回收期 | 重生成产物 → `ci_local.py` → `@build` | `done` 内强制(`--skip-gates` 可跳过) | +| 人工 | push 许可 | 回收后 | **`done` 的完成判据**:主干上 `git merge --no-ff` 成功 + `ci_local.py` 全绿 + `@build` 0 错 0 警 -+ 残留审计无死规则/重复条目 + 工作树已移除。 + +- 残留审计无死规则/重复条目 + 工作树已移除。 --- ## 10. 已知风险与待验证项 -| 项 | 状态 | 处置 | -|---|---|---| -| UV4 能否并发构建 | **已确认不可**(2026-10-12) | `build` 与 `bench` 一并纳入串行锁 | -| 跳过 Git LFS smudge 是否影响门禁 | **已实测**(2026-10-12) | 见下表:只省磁盘、不省时间,两种方式工作区都干净 → 默认全量,`--lean` 备选 | -| 主工作树当前不干净 | 已知 | `done` 的前置检查会拦下 | -| 遗留 worktree(`_v1pin-build` / `_v2oui-build`) | 已知 | 落地时 `git worktree remove` 清理,避免新旧两套并存 | -| **「主工作树绿、干净工作树红」的隐藏依赖** | **已实证**(2026-10-12) | 见 10.2。属**原任务**漏提交,非本 skill 缺陷 | +| 项 | 状态 | 处置 | +| -------------------------------------------- | --------------------- | ------------------------------------------- | +| UV4 能否并发构建 | **已确认不可**(2026-10-12) | `build` 与 `bench` 一并纳入串行锁 | +| 跳过 Git LFS smudge 是否影响门禁 | **已实测**(2026-10-12) | 见下表:只省磁盘、不省时间,两种方式工作区都干净 → 默认全量,`--lean` 备选 | +| 主工作树当前不干净 | 已知 | `done` 的前置检查会拦下 | +| 遗留 worktree(`_v1pin-build` / `_v2oui-build`) | 已知 | 落地时 `git worktree remove` 清理,避免新旧两套并存 | +| **「主工作树绿、干净工作树红」的隐藏依赖** | **已实证**(2026-10-12) | 见 10.2。属**原任务**漏提交,非本 skill 缺陷 | +| `git worktree remove` 中途被中断 → 残留「裸目录」 | **已实证**(2026-10-12) | 见下方 10.3 | ### 10.1 LFS 实测数据(2026-10-12,2396 个受控文件 / 707 个 LFS `*.jpg`) -| 方式 | 建树耗时 | 检出体积 | `git status` | 参考图 | -|---|---|---|---|---| -| 全量 smudge(默认) | 7.25 s | 83 MB | 干净 | 真实 JPEG,可看 | -| `--lean`(`GIT_LFS_SKIP_SMUDGE=1`) | 7.05 s | 45 MB | 干净 | 指针文本 | +| 方式 | 建树耗时 | 检出体积 | `git status` | 参考图 | +| --------------------------------- | ------ | ----- | ------------ | ---------- | +| 全量 smudge(默认) | 7.25 s | 83 MB | 干净 | 真实 JPEG,可看 | +| `--lean`(`GIT_LFS_SKIP_SMUDGE=1`) | 7.05 s | 45 MB | 干净 | 指针文本 | **结论**:LFS 对象已在本地,smudge 几乎不耗时,跳过**只省约 38 MB 磁盘**。 故默认走全量(保留参考图可读性),磁盘紧张时才用 `--lean`。 @@ -286,6 +291,20 @@ docs\内存管理\RAM使用分析与优化方案.md:585 [路径引用] docs/内 **副作用提醒**:这同时说明**共享主工作树里的绿门禁不可尽信**——只要有未提交文件躺在磁盘上, 门禁就可能对着「未提交的现状」放行。多任务并行期更该用工作树 + `done` 复核。 +### 10.3 `git worktree remove` 中断会留下「裸目录」(2026-10-12 实证) + +清理遗留 worktree 时踩到:`git worktree remove --force` 被中断后,`_v2oui-build` 的 `.git` **已被删除** +(于是 `git worktree list` 显示 `prunable`),但目录里**还躺着 2774 个条目**没删完。 + +**判据**:看到 `prunable` + 目录仍存在 = git 已删掉 gitfile、删除未完成。此时那棵树**已不再是 worktree** +(git 不认它了),`git worktree remove` 无法再用,只能按普通目录删除。 + + +**处置**:`git worktree prune` 清台账 → 手工删目录。删之前必须**重新扫一遍 reparse**—— +理由它有 `.git` 时没有联接,不等于现在没有(尤其别让他人趁乱建了联接)。 +清除手段用 Python 自底向上删并顺带 `chmod +w`(MDK 产物有 2 个只读文件), +**切忌 `rm -rf`**(MSYS 会递归进联接,实测见 3.3)。 + **已知不做**:不引入第二套并行机制(如 git submodule / 多克隆), 保持「同一能力只有一个实现」的收敛原则。 @@ -300,7 +319,7 @@ docs\内存管理\RAM使用分析与优化方案.md:585 [路径引用] docs/内 | 新建 | `.dsh/skills/task-worktree/.gitignore` | ✅ | | 修改 | `AGENTS.md`「按主题查哪份文档」加一行指向本文档 | ✅ | | 修改 | `docs/README.md` §9.2 登记本文档 | ✅ | -| 清理 | 移除遗留 worktree `_v1pin-build` / `_v2oui-build` | ⏳ 待用户确认(含未提交内容则先留档) | +| 清理 | 移除遗留 worktree `_v1pin-build` / `_v2oui-build` | ✅ 2026-10-12 已清理(脏改动先留档,见 §2) | | 验证 | §10 的两个待验证项 | ✅ 见 §10 / §10.1 | ### 11.1 端到端实测记录(2026-10-12,隔离集成点演练) diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index 269bcf64..2841fda2 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/待处理内容.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 项主机单测)**,板端接线(protectTask)与出口记录(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)上送;**出口记录(L4)与标准源注入验收为下一步**(见 §7)。 --- @@ -67,7 +67,7 @@ | **B0 产品定义** | 采集是否持续 / 采样率与通道 / 转发目标 / 保护元件清单——决定 B1 与保护层的**规模** | ✅ 已确认(2026-10-10,见 §1.5) | | **B1 ADC 采集链路** | 周期 CONVST + `adc_task` 消费 `tpafe5160_snapshot()` + 建任务 + 栈预算 | ✅ 已实现并 `@test` 实机闭环(2026-10-10;`adcTask` 512 words,台架 1000 Hz) | | **N-18 硬件缺陷** | V0.1 跨转换器无同一时刻性 → 限定 V0.1 可实现的保护范围 | ⚠️ 硬件改版项(V0.2) | -| **栈预算** | 保护任务栈需入 `Src/freertos.c` 并经 `scripts/stack_report.py` 核算 | 🔶 `adcTask` 已核算(**L1-6 后:栈抬至 640 words,静态 1080 B / 台架实测峰值 952/2560 / 余 57%**);`protectTask` 为后续 | +| **栈预算** | 保护任务栈需入 `Src/freertos.c` 并经 `scripts/stack_report.py` 核算 | ✅ 两任务均已核算:`adcTask`(**L1-6 后:栈抬至 640 words,静态 1080 B / 台架实测峰值 952/2560 / 余 57%**);`protectTask`(B5,2026-10-12:**512 words,静态链 872 B / 余 1176 B / 57%**,台架水位待 `@test`) | ### 1.5 B0 产品定义(2026-10-10 确认) @@ -200,7 +200,7 @@ | 采样节拍 | 定时器中断(TIMx) | **1 ms** | 最高(ISR) | 产生 CONVST 脉冲;ISR 内只置事件/计数,不做重运算 | | 采集与预处理 | `adcTask` | 1 ms | 高 | `tpafe5160_snapshot()` 取数 → 标定 → 存入采样环 | | 相量计算 | `adcTask` 内联 或 `algoTask` | 1 ms | 高 | 全周傅氏 → 相量双区交换 | -| 保护判据 | `protectTask` | 1 ms | 高 | 各保护元件 Init/Main → 出口 | +| 保护判据 | `protectTask` | 1 ms | 高 | 各保护元件 Init/Main → 出口。**✅ B5 已落地(2026-10-12):V0.1 实为 20 ms / Normal**——元件吃 50 Hz 基波 rms(phasor 每工频周更新),延时精度由 `prot_elm` 的 now_ms 差值法保证、与节拍无关;1 ms/高是参考系统瞬时值元件口径,随 P2 瞬时值元件再评 | | 遥测与显示 | 复用 `uiTask` / 新增 `measTask` | 200 ms | 中 | 谐波方和根、死区/平滑、UI 与上送 | | 记录 | `defaultTask`(已有) | 事件驱动 | 低 | SOE/动作记录落 `sys_log` | @@ -277,9 +277,9 @@ | # | 元件 | 判据要点 | 关键定值 | 状态 | | --- | --- | --- | --- | --- | -| L3-1 | 三段式相间过流 | 相电流基波 > 定值,经延时出口;返回系数滞回 | Ⅰ/Ⅱ/Ⅲ 段电流 + 延时 | 🔶 2026-10-11 主机实现:`App/algo/prot_elm.c` 通用"滞回+定时限"核 + `prot_set.c` 定值(Ⅰ/Ⅱ/Ⅲ 段,A 相 `IA`),单测 27 用例含 1.01× 启动/100 ms 到点/滞回保持/返回释放;**板端接线与出口待 protectTask 立项** | +| L3-1 | 三段式相间过流 | 相电流基波 > 定值,经延时出口;返回系数滞回 | Ⅰ/Ⅱ/Ⅲ 段电流 + 延时 | 🔶 2026-10-11 主机实现:`App/algo/prot_elm.c` 通用"滞回+定时限"核 + `prot_set.c` 定值(Ⅰ/Ⅱ/Ⅲ 段,A 相 `IA`),单测 27 用例含 1.01× 启动/100 ms 到点/滞回保持/返回释放;**板端接线已落地(B5,2026-10-12:protectTask 20 ms 节拍,动作经 104 YX16~18 上送)**;出口(L4)待做 | | L3-2 | 三段式零序过流 | 零序电流 > 定值,经延时出口 | Ⅰ/Ⅱ/Ⅲ 段零序电流 + 延时 | ⬜(N-18:`IN` 走 STM32,V0.2 使能;框架已就绪,加实例表一行即可) | -| L3-3 | 过负荷 | 相电流 > 定值,告警/跳闸可整定 | 过负荷电流 + 延时 | 🔶 同 L3-1(`OL-IA` 实例,默认告警不跳闸) | +| L3-3 | 过负荷 | 相电流 > 定值,告警/跳闸可整定 | 过负荷电流 + 延时 | 🔶 同 L3-1(`OL-IA` 实例,默认告警不跳闸;板端接线随 B5 落地,YX23 上送) | | L3-4 | 过压 / 欠压 | 相/线电压越限,经延时出口 | 过压定值、失压定值 + 延时 | 🔶 同 L3-1(`OV-UA`/`UV-UA`,欠量方向单测覆盖;沿用参考告警段 0x8027/0x8029) | | L3-5 | 过频 / 低频 | 频率越限,经延时出口 | 过频、低频定值 + 延时 | ⬜(随频率测量算法 P2;框架已就绪) | | L3-6 | 零序过压 | 零序电压 > 定值 | 零序过压定值 + 延时 | 🔶 同 L3-1(`3U0-UN` 实例,外部零序电压通道,不受 N-18 限制) | @@ -323,7 +323,7 @@ | L5-1 | 定值校验和 | `tagPRS_XXX` 的 `dwTagSum` 自检,定值非法闭锁 | 🔶 2026-10-11:`prot_set.c` 已实现 sum32 正/反码封存 + selfcheck 失配置闭锁(参考 `dwTagSum/dwTagSumN` 模式);元件级 tagPRS 常量表校验随板端接线并入 | | L5-2 | 采样通道自检 | 通道码值越界/静默检出 | 🔶 静默/丢帧/序号倒退/错误增量已由 L1-6 `adc_health` 检出(2026-10-11);码值越界待做 | | L5-3 | 硬件自检 | 出口回路、电源、时钟 | ⬜ | -| L5-4 | 自检失败闭锁 | 任一项失败 → 闭锁相关保护并告警 | 🔶 定值闭锁 → 全元件复位已联动(`prot_elm_eval` 读 `prot_set_locked()`,单测覆盖);采样故障闭锁(`adc_health_flags` 电平位 → 元件使锁)随板端接线 | +| L5-4 | 自检失败闭锁 | 任一项失败 → 闭锁相关保护并告警 | 🔶 定值闭锁 → 全元件复位已联动(`prot_elm_eval` 读 `prot_set_locked()`,单测覆盖);**采样故障闭锁已落地(B5,2026-10-12)**:protectTask 每拍读 `adc_health_flags()` 电平位(TPAFE/STM32 stall + 序号倒退)→ 命中即 `prot_elm_init()` 复位 + 本拍不判据,自愈后自动恢复;锁存类事件位(FRSTDATA/HW_ERR)不构成"当前测量不可信"→ 不闭锁,如实登记 | --- @@ -360,7 +360,7 @@ | 相量区 RAM | `tVectorRly[2][N] × sizeof(相量)` | 双区 + **5 实例**(本项目;参考项目 4 实例) | | 采样缓冲 RAM | 40 点/通道 × 通道数 × 字宽 | 双缓冲 2 周波 | | 定值区 RAM | 元件数 × 定值项 × 字宽 | 可由 cfg_file 载入 | -| 任务栈 | `adcTask` / `protectTask` 待核算 | 建任务前后各跑 `scripts/stack_report.py` | +| 任务栈 | `adcTask` ✅ / `protectTask` ✅(B5:512 words,静态链 872 B / 余 57%) | 建任务前后各跑 `scripts/stack_report.py` | > ⚠️ **改内存相关代码后必须刷新快照**:`@build` 出 `.map` 后跑 `scripts/check_mem_numbers.py --write`,同步 `docs/内存管理/RAM使用分析与优化方案.md` §2.1(`mem-numbers` 钩子会因体积变化 FAIL)。 @@ -466,7 +466,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 用例,主机全绿);板端接线(protectTask 立项)与标准源注入待做 | +| **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 显示闭环 | @@ -585,7 +585,6 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5) 2. 出口硬件形态(继电器/回读)——依硬件(R7)。 3. 等周波调频范围与精度目标——依产品定义(R4)。 4. 是否保留遥测谐波轨(k=1~9)——依 UI/上送需求。 -5. 遥测/遥信/遥控的 104 上送实现范围与排期——依产品定义。 --- @@ -606,3 +605,4 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5) | 2026-10-11 | **L2 台架闭环:P0 收尾** | `@build` 0 错 0 警 → `@test` 闭环把 `phasor(first)`/`phasor(hb)` 列为 Required 并校验顺序 `App init OK>phasor(first)>phasor(hb)`(⚠ `net init: OK` **不在**该序内——adcTask 与 netTask 并行,`phasor(first)` ≈+500 ms 早于 `net init: OK` ≈+574 ms 属正常)→ **PASS**:5 实例相量开机即产出、心跳 5 实例持续刷新、`frames` 每 10 s +10000(1000.0 Hz)、`idle=0`、`frst_err=0`、`adc1_err=0`、`adc1_hw=0`、`fw build` 身份戳匹配、回读一致、锚点 ×1、零 `[ERR]`/HardFault;证据 `boot_log_data/20261011_prod_phasor_boot_log.txt`。栈复测:adcTask 静态 832 B / 实测峰值 **928/2048(余 54%)**,7 任务全 PASS(`docs/内存管理/RAM使用分析与优化方案.md` §2.3 已同步)。§3.1 L1-9 置 ✅(`C04-IA-F2`/`C05-IA-F5` 台架产出);§3.2 L2-1~L2-4/L2-6/L2-7 置 ✅(精度判据保留"待标准源"注),**L2-5 更正为"V0.1 不适用、随 V0.2"**(跨转换器合成被 N-18 禁止、零序走外部专用通道——原表下注"L2-1~L2-7 实现完成"对 L2-5 系误记);§7.1 P0 里程碑置 ✅(遗留 L1-5/L1-6/L1-7)。下一步 = **P1**(A 相过流/过负荷 + 定值模型)与 **L1-6 采样有效性校验** | | 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 里程碑更新 | diff --git a/docs/问题记录/项目审查与优化建议报告.md b/docs/问题记录/项目审查与优化建议报告.md index 52c8334c..35f7b0bc 100644 --- a/docs/问题记录/项目审查与优化建议报告.md +++ b/docs/问题记录/项目审查与优化建议报告.md @@ -68,7 +68,7 @@ | **内存 RAM** | **R-2 剩余** 🟡 | LVGL 池 + UI 两份缓冲 54,146 B 仍在 SRAM1;CCM 只剩 16,304 B | 先做 R-9 或 R-4 腾 CCM,再迁 | | 内存 RAM | R-3 / R-4 / R-5 / R-6 / R-9 ❌ | 页缓冲未合并 / UI 帧 4 副本 / `configMAX_PRIORITIES` 仍 56 / 栈仍动态 / `LV_MEM_SIZE` 仍 40 KB | R-9 最省力(池水位门禁数据已具备);R-6 前置条件已满足 | | 内存 RAM | N-11 🟡 | NAND 仍直 DMA 调用方缓冲(已加运行时守卫、阈值 1024) | 补编译期/启动期地址断言 + **新铁律:堆缓冲不可被 DMA 直接寻址** | -| 内存 RAM | §5.5 ❌ | `ram_baseline.tsv`、`RAM预算台账.md`、92% 阈值门禁均未建 | 三条一起补,否则 R-2 后半段无法排期 | +| 内存 RAM | §5.5 ✅ | 三件套已建(2026-10-12):`scripts/ram_baseline.tsv` + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子(92% + Top-10 附表) | 已闭环;R-9/R-2 排期解锁见登记簿 N-27(W3) | | **Flash** | **F-4 / F-5 / F-6** ❌ | 剩余可评估 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个 LVGL `.c`(F-2 后均为空 TU,省的是编译时长) | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制的必经路径,**不可盲关** | | **性能/资源** | N-09 / N-16 / P2-8 / PHY / P3-x / rs485 ❌ | PASV 每次新建监听;日志每条 open/write/close;`NET_RECV_TIMEOUT_MS 30000`;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE | 见 §4.2 / §4.5 / §4.7 各行建议 | | **结构** | S-1 / S-2 / S-3 / S-4 / N-06 残余 ❌ | `NETCFG`/`UI` 语义层错位;4 处裸 `extern`;**无注册反向校验**;`app_cfg.h` 开关未接线未删;`rs485_task.c`/`lftpd_log.c` 两边不编 | `check_registration.py` 是其中唯一"1 小时工作量"的一条 | @@ -471,10 +471,13 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap 1. **`scripts/ram_report.py` 升级为门禁**:超阈值(如 SRAM1 > 92%)即失败,并在 PR 描述里自动附 Top-10 对象表。 → **🟡 部分实现**:`scripts/check_mem_numbers.py` 已挂 pre-commit(以 `.map` 为**唯一事实源**,校验 `docs/内存管理/RAM使用分析与优化方案.md` 的 `MEM_SNAPSHOT:BEGIN/END` 受管区 + 散句陈旧数字扫描)——**防的是"文档数字漂移",不是"占用超阈值"**。⚠ 无 92% 阈值失败逻辑;且 CI 上无 `.map` 时该钩子自适应跳过(登记簿 **A-5 残余**)。 + → ✅ **2026-10-12 闭环**:新增 `mem-budget` 钩子(`scripts/ram_baseline.py --gate`)——RW_IRAM1/RW_CCM >92% 即 FAIL + Top-10 RW+ZI 附表;无 `.map` 自适应跳过(A-5 残余口径不变)。 2. **建立 `[计划] scripts/ram_baseline.tsv`**(`docs/内存管理/RAM使用分析与优化方案.md:172` 已承诺但未创建):每次构建记录 Code/RO/RW/ZI/Top 对象,形成趋势。 → **❌ 未建**;🟡 等效物已存在:`docs/内存管理/data/` 下 5 份 `ram_report`/`stack_report` 快照留档(人工触发,非 tsv 趋势表)。 + → ✅ **2026-10-12 闭环**:`scripts/ram_baseline.tsv` 已建(`--update` 每次 @build 后追加;`--trend` 高亮 RW+ZI 增长 >1 KB 对象)。 3. **RAM 预算台账**(同上,文档已承诺 `[计划] docs/内存管理/RAM预算台账.md`):按子系统配额(网络 12 KB / 存储 12 KB / UI 16 KB / RTOS 48 KB / 应用 8 KB),超配额必须先申请。 → **❌ 未建**。⚠ 复核:这条的价值在上升——堆已进 CCM 且只剩 16,304 B CCM 余量,"谁还能用 CCM"必须有台账,否则 R-2 后半段无法排期。 + → ✅ **2026-10-12 闭环**:`docs/内存管理/RAM预算台账.md` 已建——子系统配额(网络 12/存储 12/UI 16/RTOS 堆 48/应用 8 KB,现状超配 = W3 债务如实展示)+ **CCM 分配台账**(谁能用 CCM、R-2 后半解锁链)+ 超配额流程 + 受管区自动生成。 4. **DMA 可达性清单**(新增,源于 N-11):文档化"哪些缓冲必须 SRAM1",并在 CCM 迁移时对该清单加 `_Static_assert`/地址断言(`assert((addr & 0xFFF00000) == 0x20000000)`)。 → **🟡 半落地**:独立清单文档未建,但**铁律已进 AGENTS.md**("DMA 目的缓冲必须在 SRAM,DMA2 不可达 CCM 0x10000000"、"改 ADC 流后回 NVIC 核对");代码侧另有**运行时**守卫(`gd5f2gq5ue.c:110-136` 不可达回落轮询)。⚠ 仍缺**编译期/启动期断言**,且需补一条新铁律:**从 FreeRTOS 堆分配的缓冲不可被 DMA 直接寻址**(堆已在 CCM)。 5. **禁止新增 C 库 `malloc`**:写进 `docs/代码规范/`,并在 `check_coding_standard.py` 加正则检查(`App/`、`Drivers/` 内出现 `malloc(` 即告警)。 @@ -647,7 +650,7 @@ UI 剩余页面批量落地(U5)、目录级层次迁移(S-1 的物理搬 | 交付物 | 类型 | 来源条目 | **2026-10-11 状态** | |--------|------|---------|---------------------| | `[计划] scripts/check_registration.py` | 新脚本 + pre-commit hook | S-3 / N-06 | ❌ **仍未建**(`scripts/` 11 个脚本里没有它)——这是本报告里**唯一一条"1 小时工作量、至今未做"**的机械检查 | -| `[计划] scripts/ram_baseline.tsv` + `[计划] docs/内存管理/RAM预算台账.md` | 文档承诺落地 | §5.5 | ❌ **未建**;🟡 等效物 = `docs/内存管理/data/` 5 份快照 + `MEM_SNAPSHOT` 受管区(无趋势、无配额) | +| `scripts/ram_baseline.tsv` + `docs/内存管理/RAM预算台账.md` | 文档承诺落地 | §5.5 | ✅ **2026-10-12 已建**(`ram_baseline.py` 三模式:`--gate`/`--update`/`--trend`/`--write`;另有 `mem-budget` 钩子) | | `Drivers/BSP/UI/ui_tokens.h` | 令牌层 | U1 | ❌ 未建 | | `Drivers/BSP/UI/ui_w_{list,kv,records,form,msgbox,title}.{c,h}` | 组件库(需双端注册) | U2/U3 | ❌ 未建 | | `tools/menu_gen/gen_menu.py` 扩展 + `ui_page_registry.c` 生成 | 生成器 | U3 | ❌ 未建(`gen_menu.py` 未扩展,注册表不存在) | @@ -690,7 +693,7 @@ UI 剩余页面批量落地(U5)、目录级层次迁移(S-1 的物理搬 > **2026-10-11 复核收尾**: > - ⚠ **台账漏登两条**:本报告 **N-02(FTP 无鉴权)** 与 **N-12/N-13(dhara 移植缺陷)** 既未修复也未登记在 `../待处理内容.md` → 建议补登。 > - ⚠ **编号撞车**:本报告曾用 N-18 指"无 CI"(该条已销项删除),而登记簿的 N-18 = "8 路电气量分属两片转换器(V0.2 改版项)"。引用时一律带文档名。 -> - `[计划] docs/内存管理/RAM预算台账.md` 与 `scripts/ram_baseline.tsv` **仍未创建**(见 §5.5)。 +> - ✅ `docs/内存管理/RAM预算台账.md` 与 `scripts/ram_baseline.tsv` **已于 2026-10-12 创建**(见 §5.5 各条闭环标注)。 > - 本报告按 `docs/README.md` 的定位是**体系层评审报告,不是待办池**——待办一律以 `../待处理内容.md` 为准;本报告只保留**未闭环问题的发现 + 证据**,修复即销项。 --- diff --git a/scripts/check_registration.py b/scripts/check_registration.py index 4ee0342d..66717ae2 100644 --- a/scripts/check_registration.py +++ b/scripts/check_registration.py @@ -88,9 +88,14 @@ SIM_EXEMPT = [ ("App/sync/time_sync.c", "对时任务(net+RTOS),MCU 专属"), ("App/task/adc_task.c", "固件 FreeRTOS 任务,模拟器不跑固件任务"), ("App/task/default_task.c", "固件 FreeRTOS 任务,模拟器不跑固件任务"), + ("App/task/iec104_serv.c", "固件 FreeRTOS 任务(104 上行,B4),模拟器不跑固件任务"), + ("App/task/protect_task.c", "固件 FreeRTOS 任务(保护判据节拍,B5),模拟器不跑固件任务"), ("App/task/net_task.c", "固件 FreeRTOS 任务,模拟器不跑固件任务"), ("App/task/rs485_task.c", "固件 RS-485 任务,MCU 专属(另:uvprojx 缺口见 KNOWN_GAPS)"), ("App/task/ui_task.c", "固件 UI 任务,模拟器另有 main.c 驱动 UI"), + ("App/protocol/iec104/iec104_asdu.c", "104 ASDU 编解码纯逻辑,L0.5 主机单测覆盖,模拟器无消费路径"), + ("App/protocol/iec104/iec104_link.c", "104 链路状态机纯逻辑(I/O 注入),L0.5 覆盖,模拟器无消费路径"), + ("App/protocol/iec104/iec104_pts.c", "104 点表/数据源适配(phasor/prot 依赖),模拟器无消费路径"), ("App/util/sha256.c", "纯工具(FTP 鉴权在 MCU 端),模拟器无消费路径"), ("App/util/sys_clock.c", "RTC/SD2506 依赖墙钟,MCU 专属"), ("App/util/task_prof.c", "任务性能探针,MCU 专属"), diff --git a/scripts/ci_local.py b/scripts/ci_local.py index aea38aae..a641604d 100644 --- a/scripts/ci_local.py +++ b/scripts/ci_local.py @@ -13,8 +13,8 @@ 刻意**不含**(与 CI 同理由,见 workflow 文件头): - `@build`(需 Keil 授权;CI 也不跑,真编译是开发者本地红线) - - `mem-numbers` 钩子(事实源 `.map` 是 Keil 产物——**本地若存在 .map 就照常跑**, - 与 CI 的自适应逻辑一致) + - `mem-numbers` / `mem-budget` 钩子(事实源 `.map` 是 Keil 产物——**本地若存在 .map + 就照常跑**,与 CI 的自适应逻辑一致) 退出码: 0 = 全部通过(或不适用项已按规则跳过) @@ -147,17 +147,20 @@ def run_l0(): print("=" * 64) env = dict(os.environ) - # 与 CI 相同的自适应:无 .map(未做 Keil 构建)=> mem-numbers 不适用 => 跳过 + # 与 CI 相同的自适应:无 .map(未做 Keil 构建)=> mem-numbers / mem-budget + # 不适用 => 跳过(两者事实源都是 Keil 产物 .map) map_path = _find_map() if map_path: print("[INFO] 找到 .map:{}".format(map_path.relative_to(REPO_ROOT))) - print("[INFO] mem-numbers 照常运行") + print("[INFO] mem-numbers / mem-budget 照常运行") else: - print("[INFO] 未找到 .map(未做 Keil 构建)-> 跳过 mem-numbers(与 CI 一致)") + print("[INFO] 未找到 .map(未做 Keil 构建)-> 跳过 mem-numbers / " + "mem-budget(与 CI 一致)") print("[INFO] :warning: 体积门禁未执行——改代码后请本地 @build + " - "check_mem_numbers.py --scan 兜底") + "check_mem_numbers.py --scan + ram_baseline.py --gate 兜底") skip = env.get("SKIP", "") - env["SKIP"] = (skip + "," if skip else "") + "mem-numbers" + add = "mem-numbers,mem-budget" + env["SKIP"] = (skip + "," if skip else "") + add rc, text = _run_capture([PY, "-m", "pre_commit", "run", "--all-files"], env=env) # 汇总行(对齐 CI 的 ::notice::):统计钩子 Passed/Failed/Skipped diff --git a/scripts/ram_baseline.py b/scripts/ram_baseline.py new file mode 100644 index 00000000..7207a513 --- /dev/null +++ b/scripts/ram_baseline.py @@ -0,0 +1,407 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +RAM 预算门禁 + 趋势台账(登记簿 N-27 前半 / 审查报告 §5.5 三件套,2026-10-12)。 + +三件套的机械部分收在本脚本(事实源 = Keil `.map`,与 `check_mem_numbers.py` 同口径): + + 1. **92% 阈值门禁**(`--gate`,pre-commit `mem-budget` 钩子入口): + RW_IRAM1 / RW_CCM 任一区占比 > 92% → FAIL,并附 Top-10 RW+ZI 对象表; + 无 `.map`(未做 Keil 构建)→ 自适应跳过(与 `mem-numbers` 同口径, + CI 盲区登记在 `docs/待处理内容.md` A-5 残余)。 + `--gate` 同时校验台账受管区与 `.map` 一致(防漂移,同 `mem-numbers` 思路)。 + 2. **趋势基线** `scripts/ram_baseline.tsv`(`--update` 每次 @build 后追加一行; + `--trend` 看趋势并高亮 RW+ZI 较上一行增长 >1 KB 的对象——方案 §0.3 + "ZI 增量 >1KB 必须解释"的机械化)。 + 3. **台账受管区**(`--write` 同步 `docs/内存管理/RAM预算台账.md` 的 + `MEM_BUDGET:BEGIN/END` 区:区域水位 + 子系统配额对照)。 + +子系统配额(报告 §5.5 第 3 条的规划值;RTOS 堆 2026-10-12 B5 48→56 KB): + 网络 12 KB / 存储 12 KB / UI 16 KB / RTOS 堆 56 KB / 应用 8 KB + ——UI 配额是 R-9/R-2 落地后的**目标态**,现状超配 = W3 债务,台账如实展示; + 配额改动 = 先登记 `docs/内存管理/RAM预算台账.md` 变更记录,再改本脚本 `QUOTAS`。 + +用法(仓库根): + python scripts/ram_baseline.py --gate + python scripts/ram_baseline.py --write + python scripts/ram_baseline.py --update + python scripts/ram_baseline.py --trend [-n 10] + +退出码:0 通过/跳过;1 门禁失败或受管区漂移;2 事实源解析失败。 +创建日期:2026-10-12(W1-0,登记簿 N-27 前半) +""" +import argparse +import pathlib +import sys +from datetime import datetime + +sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent)) +import ram_report # noqa: E402 同目录:复用 .map 解析(regions + components,口径一致) +from check_mem_numbers import read_doc, write_doc # noqa: E402 保真读写(BOM/CRLF) + +REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent +MAP_DEFAULT = REPO_ROOT / "MDK-ARM" / "STM32F407-Demo" / "STM32F407-Demo.map" +TSV_PATH = REPO_ROOT / "scripts" / "ram_baseline.tsv" +LEDGER = REPO_ROOT / "docs" / "内存管理" / "RAM预算台账.md" + +BEGIN = "" +END = "" + +THRESHOLD_PCT = 92.0 # 报告 §5.5 第 1 条 +GATED_REGIONS = ("RW_IRAM1", "RW_CCM") # 门禁约束区;其余区仅展示 +GROWTH_ALERT_B = 1024 # 方案 §0.3:增量 >1 KB 必须解释 +TOP_N = 10 # tsv 记录 / 失败附表的对象数 + +RTOS_HEAP = "RTOS 堆" +SUBSYSTEMS = ("网络", "存储", "UI", RTOS_HEAP, "应用", "其它") +QUOTAS = {"网络": 12 * 1024, "存储": 12 * 1024, "UI": 16 * 1024, + RTOS_HEAP: 56 * 1024, "应用": 8 * 1024} # RTOS 堆 48→56 KB:2026-10-12 B5(台账 §6) + +# dhara 是裸对象名(nand.c/map.c/...),必须精确匹配,勿用前缀 +_DHARA = {"map.o", "journal.o", "nand.o", "fctl.o", "era.o"} +# RTOS 内核静态对象:归"其它"(RTOS 配额只约束 CCM 堆本体,见台账 §2 口径表) +_KERNEL = {"tasks.o", "queue.o", "timers.o", "event_groups.o", + "list.o", "port.o", "cmsis_os2.o", "freertos.o"} + + +def subsystem_of(obj): + """对象名 → 子系统(前缀首匹配;口径表见 RAM预算台账.md §2)。""" + n = obj.strip().lower() + if n.startswith(("lv_", "ui_")): + return "UI" + if n.startswith(("ch395f", "net_", "lftpd", "ftp_task")): + return "网络" + if (n.startswith(("gd5f", "nand_", "ff", "diskio", "vol_lock")) + or n in _DHARA): + return "存储" + if n == "heap_4.o": + return RTOS_HEAP + if n in _KERNEL: + return "其它" + if n.startswith(("app_", "adc_", "prot_", "phasor", "sample_ring", + "sys_", "cfg_", "dbg_", "console_log", "task_watchdog", + "sha256", "tpafe", "sd2506", "test_task", "time_sync", + "default_task")): + return "应用" + return "其它" + + +def collect(map_path): + """解析 .map → {'regions': {name: r}, 'subsys': {name: bytes}, 'top': [(obj, B)]}。""" + data = ram_report.parse_map(str(map_path)) + regions = {r["name"]: r for r in data["regions"]} + comps = [c for c in data["components"] + if not ram_report._is_aggregate(c["object"]) + and not c["object"].startswith("(incl.")] + subsys = {s: 0 for s in SUBSYSTEMS} + for c in comps: + subsys[subsystem_of(c["object"])] += c["rw_data"] + c["zi_data"] + top = sorted(((c["object"], c["rw_data"] + c["zi_data"]) for c in comps), + key=lambda t: (-t[1], t[0])) + top = [t for t in top if t[1] > 0][:TOP_N] + return {"regions": regions, "region_list": data["regions"], + "subsys": subsys, "top": top} + + +def _util(r): + return r["size"] / r["max"] * 100 if r["max"] else 0.0 + + +def _quota_status(name, used): + if name not in QUOTAS: + return "参考" + if name == RTOS_HEAP and used - QUOTAS[name] <= 64: + # heap_4.o = 堆本体 49,152 B(= 配额)+ 32 B RW 元数据,不算超 + return "堆=配额" + if used <= QUOTAS[name]: + return "OK" + return f"⚠ 超 {(used - QUOTAS[name]) / 1024:.1f} KB" + + +def render_budget(info): + """渲染台账受管区(按 .map 区出现顺序动态渲染,新增区自动入表; + 门禁列只约束 GATED_REGIONS,其余区标"参考")。""" + L = [] + L.append("| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |") + L.append("|---|---|---|---|---|") + for r in info["region_list"]: + gated = r["name"] in GATED_REGIONS + label = f"{r['name']} (Flash)" if r["name"] == "ER_IROM1" else r["name"] + u = _util(r) + mark = ("PASS" if u <= THRESHOLD_PCT else "FAIL") if gated else "参考" + L.append(f"| {label} | {r['size']:,} B | {r['max']:,} B | " + f"{u:.1f}% | {mark} |") + L.append("") + L.append("| 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 |") + L.append("|---|---|---|---|") + for s in SUBSYSTEMS: + used = info["subsys"][s] + quota = f"{QUOTAS[s] // 1024} KB" if s in QUOTAS else "—" + L.append(f"| {s} | {used:,} B | {quota} | {_quota_status(s, used)} |") + return "\n".join(L) + + +# --- 受管区读写(锚点语义同 check_mem_numbers.py) --------------------------- + +def extract_managed(text): + if BEGIN not in text or END not in text: + return None + s = text.index(BEGIN) + len(BEGIN) + e = text.index(END) + return text[s:e].strip() + + +def replace_managed(text, block): + s = text.index(BEGIN) + len(BEGIN) + e = text.index(END) + new = "\n" + block + "\n" + if text[s:e] == new: + return text, False + return text[:s] + new + text[e:], True + + +# --- 子命令 ------------------------------------------------------------------ + +def _map_or_skip(args): + map_path = pathlib.Path(args.map) + if not map_path.exists(): + return None + return map_path + + +def cmd_gate(args): + map_path = _map_or_skip(args) + if map_path is None: + print("[SKIP] 无 .map(未做 Keil 构建)→ RAM 预算门禁不适用") + print(" (CI 盲区已登记 docs/待处理内容.md A-5 残余;" + "本地改过代码请先 @build)") + return 0 + info = collect(map_path) + if not info["regions"]: + print(f"[FAIL] 未能从 {map_path.name} 解析出执行区", file=sys.stderr) + return 2 + + fails = [] + for name in ("RW_IRAM1", "RW_CCM"): + r = info["regions"].get(name) + if not r: + fails.append(f"缺执行区 {name}(scatter 变更?)") + continue + u = _util(r) + if u > THRESHOLD_PCT: + fails.append(f"{name} 占用 {u:.1f}% > {THRESHOLD_PCT:.0f}%" + f"({r['size']:,}/{r['max']:,} B)") + if fails: + print("[FAIL] RAM 预算超阈值:", file=sys.stderr) + for f in fails: + print(f" - {f}", file=sys.stderr) + print(f"\nTop-{TOP_N} 静态对象(RW+ZI,找增量元凶):", file=sys.stderr) + for obj, b in info["top"]: + print(f" {b:>7,} B {obj}", file=sys.stderr) + print("\n处置:削峰(静态化回退/缓冲复用)或按 docs/内存管理/RAM预算台账.md" + " §5 走超配额流程;勿盲目抬 scatter。", file=sys.stderr) + return 1 + + # 台账受管区一致性(防漂移;同 mem-numbers 的"事实源唯一"思路) + if not LEDGER.exists(): + print(f"[FAIL] 台账缺失:{LEDGER.relative_to(REPO_ROOT)}", file=sys.stderr) + return 1 + text, newline, bom = read_doc(LEDGER) + expected = render_budget(info) + got = extract_managed(text) + if got is None: + print(f"[FAIL] 台账缺受管锚点:{LEDGER.relative_to(REPO_ROOT)}", + file=sys.stderr) + return 1 + if got != expected: + print("[FAIL] 台账受管区与 .map 不一致(区域水位或子系统配额表漂移)", + file=sys.stderr) + print(f"事实源:{map_path.relative_to(REPO_ROOT)}", file=sys.stderr) + print("修复:python scripts/ram_baseline.py --write", file=sys.stderr) + return 1 + + # 软提醒(不拦):tsv 落后 / .map 比源码旧 + if TSV_PATH.exists(): + rows = _read_tsv() + ir = info["regions"].get("RW_IRAM1") + if rows and ir and int(rows[-1]["iram1"]) != ir["size"]: + print("[WARN] ram_baseline.tsv 末行落后于当前 .map —— " + "@build 后请跑 `python scripts/ram_baseline.py --update`") + else: + print("[WARN] ram_baseline.tsv 不存在 —— 跑 " + "`python scripts/ram_baseline.py --update` 建档") + newest = _newest_source_mtime() + if newest and newest > map_path.stat().st_mtime: + print("[WARN] .map 早于最新源码——数字来自旧构建,建议先 @build 再提交") + + ir, cc = info["regions"].get("RW_IRAM1"), info["regions"].get("RW_CCM") + print(f"RAM 预算门禁 PASS:RW_IRAM1 {_util(ir):.1f}% / RW_CCM {_util(cc):.1f}%" + f"(阈值 {THRESHOLD_PCT:.0f}%)") + return 0 + + +def cmd_write(args): + map_path = _map_or_skip(args) + if map_path is None: + print("[FAIL] 找不到 .map 事实源,先 @build", file=sys.stderr) + return 1 + info = collect(map_path) + if not LEDGER.exists(): + print(f"[FAIL] 台账不存在:{LEDGER.relative_to(REPO_ROOT)}", file=sys.stderr) + return 1 + text, newline, bom = read_doc(LEDGER) + if BEGIN not in text or END not in text: + print("[FAIL] 台账缺受管锚点", file=sys.stderr) + return 1 + new_text, did = replace_managed(text, render_budget(info)) + if did: + write_doc(LEDGER, new_text, newline, bom) + print("已同步台账受管区。") + else: + print("台账受管区已是最新。") + return 0 + + +# --- tsv 趋势基线 ------------------------------------------------------------ + +TSV_HEADER = ("date\tcode\tro\trw\tzi\ter_irom1\ter_pct\tiram1\tiram1_pct" + "\tccm\tccm_pct\ttop_rwzi") + + +def _read_tsv(): + rows = [] + lines = TSV_PATH.read_text(encoding="utf-8").splitlines() + if len(lines) < 2: + return rows + keys = lines[0].split("\t") + for ln in lines[1:]: + parts = ln.split("\t") + if len(parts) == len(keys): + rows.append(dict(zip(keys, parts))) + return rows + + +def _top_field(top): + return ";".join(f"{obj}={b}" for obj, b in top) + + +def cmd_update(args): + map_path = _map_or_skip(args) + if map_path is None: + print("[FAIL] 找不到 .map 事实源,先 @build", file=sys.stderr) + return 1 + info = collect(map_path) + gt = ram_report.parse_map(str(map_path))["grand_totals"] + if not gt: + print("[FAIL] .map 缺 Grand Totals", file=sys.stderr) + return 2 + today = datetime.now().strftime("%Y-%m-%d") + reg = info["regions"] + row = [ + today, str(gt["code"]), str(gt["ro_data"]), str(gt["rw_data"]), + str(gt["zi_data"]), + str(reg["ER_IROM1"]["size"]), f"{_util(reg['ER_IROM1']):.1f}", + str(reg["RW_IRAM1"]["size"]), f"{_util(reg['RW_IRAM1']):.1f}", + str(reg["RW_CCM"]["size"]), f"{_util(reg['RW_CCM']):.1f}", + _top_field(info["top"]), + ] + lines = (TSV_PATH.read_text(encoding="utf-8").splitlines() + if TSV_PATH.exists() else []) + if not lines: + lines = TSV_HEADER.split("\t") + lines = [TSV_HEADER] + body = [ln for ln in lines[1:] if ln.strip() + and not ln.split("\t")[0] == today] + body.append("\t".join(row)) + # newline="\n":Windows 文本模式默认 \n→\r\n,违反 .gitattributes eol=lf + TSV_PATH.write_text("\n".join([lines[0]] + body) + "\n", + encoding="utf-8", newline="\n") + print(f"已记录 {today}:RW_IRAM1 {reg['RW_IRAM1']['size']:,} B " + f"({_util(reg['RW_IRAM1']):.1f}%) / RW_CCM {reg['RW_CCM']['size']:,} B " + f"({_util(reg['RW_CCM']):.1f}%) → {TSV_PATH.relative_to(REPO_ROOT)}") + return 0 + + +def cmd_trend(args): + if not TSV_PATH.exists(): + print("[WARN] tsv 不存在——先跑 --update 建档") + return 0 + rows = _read_tsv() + if not rows: + print("[WARN] tsv 为空") + return 0 + print(f"趋势(最近 {min(args.n, len(rows))} 行,共 {len(rows)} 行):") + print(f"{'日期':<12} {'RW_IRAM1':>12} {'RW_CCM':>12} {'Flash':>12}") + for r in rows[-args.n:]: + print(f"{r['date']:<12} {int(r['iram1']):>9,} B ({r['iram1_pct']:>4}%)" + f" {int(r['ccm']):>7,} B ({r['ccm_pct']:>4}%)" + f" {int(r['er_irom1']):>7,} B ({r['er_pct']:>4}%)") + if len(rows) >= 2: + prev = dict() + for kv in rows[-2]["top_rwzi"].split(";"): + if "=" in kv: + obj, b = kv.rsplit("=", 1) + prev[obj] = int(b) + grew = [] + for kv in rows[-1]["top_rwzi"].split(";"): + if "=" not in kv: + continue + obj, b = kv.rsplit("=", 1) + delta = int(b) - prev.get(obj, 0) + if delta > GROWTH_ALERT_B: + grew.append((obj, prev.get(obj, 0), int(b), delta)) + if grew: + print(f"\n⚠ 较上一行 RW+ZI 增长 >{GROWTH_ALERT_B} B 的对象" + f"(提交说明须解释,方案 §0.3):") + for obj, old, new, d in sorted(grew, key=lambda t: -t[3]): + print(f" +{d:>6,} B {obj} ({old:,} → {new:,})") + else: + print("\nTop 对象无 >1 KB 的异常增长。") + return 0 + + +# --- 工具 -------------------------------------------------------------------- + +def _newest_source_mtime(): + newest = 0 + for base in ("App", "Drivers/BSP", "Src", "Inc"): + d = REPO_ROOT / base + if not d.is_dir(): + continue + for p in d.rglob("*"): + if p.suffix in (".c", ".h") and p.is_file(): + newest = max(newest, p.stat().st_mtime) + lv = REPO_ROOT / "Lib" / "lv_conf.h" + if lv.is_file(): + newest = max(newest, lv.stat().st_mtime) + return newest + + +def main(argv=None): + for stream in (sys.stdout, sys.stderr): + try: + stream.reconfigure(encoding="utf-8", errors="replace") + except Exception: + pass + ap = argparse.ArgumentParser( + description="RAM 预算门禁 + 趋势台账(N-27 前半 / 报告 §5.5 三件套)") + g = ap.add_mutually_exclusive_group() + g.add_argument("--gate", action="store_true", help="92% 阈值门禁(pre-commit 入口)") + g.add_argument("--write", action="store_true", help="同步台账受管区") + g.add_argument("--update", action="store_true", help="追加 tsv 趋势行(@build 后跑)") + g.add_argument("--trend", action="store_true", help="打印趋势 + 高亮 >1 KB 增长") + ap.add_argument("-n", type=int, default=10, help="--trend 显示行数") + ap.add_argument("--map", default=str(MAP_DEFAULT), help=".map 路径") + args = ap.parse_args(argv) + + if args.write: + return cmd_write(args) + if args.update: + return cmd_update(args) + if args.trend: + return cmd_trend(args) + return cmd_gate(args) # 默认 = --gate + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/ram_baseline.tsv b/scripts/ram_baseline.tsv new file mode 100644 index 00000000..f8342b91 --- /dev/null +++ b/scripts/ram_baseline.tsv @@ -0,0 +1,2 @@ +date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi +2026-10-12 204348 18028 1036 152204 222376 21.2 95816 73.1 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 diff --git a/scripts/stack_report.py b/scripts/stack_report.py index 29bd9b76..55fe3343 100644 --- a/scripts/stack_report.py +++ b/scripts/stack_report.py @@ -46,6 +46,8 @@ ROOTS = { "start_test_task": "testTask", "time_sync_task": "timeSyncTask", "adc_task_func": "adcTask", + "iec104_serv_task": "iec104Task", + "protect_task": "protectTask", } # Runtime lines use the short labels emitted by stack_probe_poll() in freertos.c. @@ -57,6 +59,8 @@ RUNTIME_ALIAS = { "testTask": "test", "timeSyncTask": "timesync", "adcTask": "adc", + "iec104Task": "iec104", + "protectTask": "protect", } FUNC_RE = re.compile( diff --git a/test/host/README.md b/test/host/README.md index 6c28d013..7ccb3923 100644 --- a/test/host/README.md +++ b/test/host/README.md @@ -55,6 +55,7 @@ | `time_sync/run_unit_test.py` | **时间同步单测**:离线编译真实 `App/sync/time_sync.c`,80 断言点覆盖分片喂狗延时 / 监听退避 / 时间包重组(半包·粘连·EOF·真错·预算耗尽·tick 回绕)/ 任务主循环(**N-17 的全部逻辑贡献者**) | | `time_sync/time_sync_test.c` | 测试单元本体(`#include` 生产源码 + 网络 / 事件 / RTOS 可脚本化桩 + `longjmp` 跳出 `for(;;)` 任务循环) | | `time_sync/stub/` | 桩头文件(`FreeRTOS.h` / `task.h` / `cmsis_os2.h` / `net_socket.h` / `sys_clock.h` / `sys_events.h` / `dbg_log.h`) | +| `iec104/run_unit_test.py` | **IEC 60870-5-104 协议栈单测(B4)**:离线编译真实 `App/protocol/iec104/` 三模块 + 数据源(prot_set/prot_elm/phasor/sample_ring),**82** 用例覆盖 CP56 往返 / APCI 半帧·粘帧·坏帧 / STARTDT 握手 / 总召分片+RBT / COV 死区 / k=12 窗满 / w=8 触发 S / t1·t2·t3 / N(R) 倒退判故障 / 遥控·定值两段式与 PN / C_CS / 未知类型·地址错误应答 | > 详见 `docs/测试说明/看门狗单元测试说明.md`、`docs/测试说明/系统时钟单元测试说明.md`、 > `docs/测试说明/配置文件单元测试说明.md`、`docs/测试说明/ADC输入层单元测试说明.md`、 diff --git a/test/host/iec104/iec104_test.c b/test/host/iec104/iec104_test.c new file mode 100644 index 00000000..d7cb37e6 --- /dev/null +++ b/test/host/iec104/iec104_test.c @@ -0,0 +1,868 @@ +/* + * 模块名称:IEC 60870-5-104 被控站协议栈主机侧单元测试 + * 模块功能:在 PC 上对 App/protocol/iec104 全栈(asdu + pts + link)做离线验证。 + * + * 被测对象:真实源文件(#include 原样纳入): + * iec104_asdu.c + iec104_pts.c + iec104_link.c(B4 协议核心) + * prot_set.c + prot_elm.c + phasor.c + sample_ring.c(板端默认源 + * 的链接依赖;定值两段写走**真实 prot_set**) + * 数据源经 iec104_pts_bind_src 注入假源(YC/YX/YK 可控), + * 发送经 send_apdu 回调全量捕获,时基由测试注入。 + * + * 覆盖点(docs/子系统设计/IEC104上行设计说明.md §7): + * TC-104-001 CP56Time2a 往返 / 闰年 / IV / 钳位 + * TC-104-002 IOA 3B 与短浮点小端往返 + * TC-104-003 APCI 重组:半帧 / 粘帧 / 坏起始符 / 坏长度 + * TC-104-004 STARTDT 握手 → RUN + * TC-104-005 OPEN 态 I 帧忽略(序号不消费) + * TC-104-006 总召全流程:actcon→4 分片(首召 COT=4)→actterm;二召 COT=2;RBT→COT=4 + * TC-104-007 遥信变位 COV(COT=3);无效位不触发 + * TC-104-008 遥测死区 COV:死区内不发 / 越死区发 + * TC-104-009 k 窗:12 未确认停发;S 确认后恢复 + * TC-104-010 w 阈:收满 8 发 S + * TC-104-011 t2 到期发 S + * TC-104-012 t3 空闲发 TESTFR act;未答 t1 超时 → IDLE;con 清挂起不误杀 + * TC-104-013 遥控两段式:选择/执行成功;失配 PN;拒绝类选择段即 PN + * TC-104-014 定值两段写(真实 prot_set):越界 PN;执行后 get_f + selfcheck + * TC-104-015 C_RD:YC 命中 / 定值命中 / 未知 IOA COT14+EVI + * TC-104-016 C_CS:clock_sync 收正确 epoch;IV → PN;clock_sync 失败 → PN + * TC-104-017 未知类型 COT12+EVI;错公共地址 COT13+EVI + * TC-104-018 STOPDT:数据停发,TESTFR 仍应答 + * TC-104-019 序号错 → IDLE(链路故障) + * TC-104-020 pts:无效通道 IV / 未就绪 NT / 无效遥信 IV / is_dp / 表尺寸 + * TC-104-021 C_TS / C_RP actcon + * TC-104-022 周期上送 COT=1(YC 组 + 频率) + * TC-104-023 k 窗满 COV 不丢事件(pend 暂存,窗开后补发) + * + * 通过:全部 TC PASS(main 返回 0)。 + * 创建日期:2026-10-12(B4) + */ +#include +#include +#include + +static int s_total = 0, s_passed = 0, s_failed = 0; + +#define CHECK(cond, name) do { \ + s_total++; \ + if (cond) { s_passed++; printf(" [PASS] %s\n", name); } \ + else { s_failed++; printf(" [FAIL] %s (line %d)\n", name, __LINE__); } \ +} while (0) + +#include "iec104_asdu.c" +#include "prot_set.c" +#include "sample_ring.c" +#include "phasor.c" +#include "prot_elm.c" +#include "iec104_pts.c" +#include "iec104_link.c" + +/* ---------------- 假数据源(定值转发真实 prot_set) ---------------- */ +static float s_f_yc[9]; +static int s_f_yc_rc[9]; +static uint64_t s_f_bits; +static uint64_t s_f_valid; +static uint32_t s_f_yk_ioa; +static uint8_t s_f_yk_dpc; +static uint8_t s_f_yk_sel; + +static int f_yc(uint8_t idx, float *out) +{ + if (idx >= 9u) { + return -1; + } + if (s_f_yc_rc[idx] != 0) { + return s_f_yc_rc[idx]; + } + *out = s_f_yc[idx]; + return 0; +} +static uint64_t f_bits(void) { return s_f_bits; } +static uint64_t f_valid(void) { return s_f_valid; } +static int f_yk(uint32_t ioa, uint8_t dpc, uint8_t sel) +{ + s_f_yk_ioa = ioa; + s_f_yk_dpc = dpc; + s_f_yk_sel = sel; + return (ioa == 0x600Au) ? 0 : -1; +} +static int f_set_read(uint32_t addr, float *out) +{ + return s_src_set_read(addr, out); +} +static int f_set_write(uint32_t addr, float v, uint8_t sel) +{ + return s_src_set_write(addr, v, sel); +} +static const iec104_pts_src_t g_fake = { + f_yc, f_bits, f_valid, f_yk, f_set_read, f_set_write +}; + +/* ---------------- 发送捕获 + 对时假回调 ---------------- */ +#define CAP_MAX 48 +#define CAP_SZ 260 +static uint8_t s_cap[CAP_MAX][CAP_SZ]; +static int s_cap_n; +static uint64_t s_clock_ms; +static int s_clock_rc; + +static void cap_send(void *ctx, const uint8_t *apdu, uint16_t len) +{ + (void)ctx; + if ((s_cap_n < CAP_MAX) && (len <= CAP_SZ)) { + (void)memcpy(s_cap[s_cap_n], apdu, len); + s_cap_n++; + } +} +static int f_clock(void *ctx, uint64_t ms) +{ + (void)ctx; + s_clock_ms = ms; + return s_clock_rc; +} + +static iec104_link_t g_lk; +static const iec104_link_cfg_t g_cfg = { 1u, cap_send, f_clock }; + +/* ---------------- 主站侧模拟(N(R) 单调,照真实主站) ---------------- */ +static uint16_t m_ns; +static uint16_t m_nr; + +static void m_reset(void) +{ + m_ns = 0u; + m_nr = 0u; + s_cap_n = 0; +} +static void feed_u(uint8_t q, uint32_t now) +{ + uint8_t b[6]; + + b[0] = 0x68u; b[1] = 4u; b[2] = q; b[3] = 0u; b[4] = 0u; b[5] = 0u; + iec104_link_on_rx(&g_lk, b, 6u, now); +} +static void feed_i(const uint8_t *asdu, uint16_t len, uint32_t now) +{ + uint8_t b[6u + 250u]; + uint16_t fs = (uint16_t)(m_ns << 1); + uint16_t fr = (uint16_t)(m_nr << 1); /* N(R) 单调(feed_s 推进) */ + + b[0] = 0x68u; + b[1] = (uint8_t)(4u + len); + b[2] = (uint8_t)(fs & 0xFFu); + b[3] = (uint8_t)(fs >> 8); + b[4] = (uint8_t)(fr & 0xFFu); + b[5] = (uint8_t)(fr >> 8); + (void)memcpy(&b[6], asdu, len); + iec104_link_on_rx(&g_lk, b, (uint16_t)(6u + len), now); + m_ns = (uint16_t)((m_ns + 1u) % 32768u); +} +static void feed_s(uint16_t nr, uint32_t now) +{ + uint8_t b[6]; + uint16_t f = (uint16_t)(nr << 1); + + b[0] = 0x68u; b[1] = 4u; b[2] = 1u; b[3] = 0u; + b[4] = (uint8_t)(f & 0xFFu); + b[5] = (uint8_t)(f >> 8); + m_nr = nr; /* 主站确认推进(单调) */ + iec104_link_on_rx(&g_lk, b, 6u, now); +} +static uint16_t mk_asdu(uint8_t *b, uint8_t type, uint8_t vsq, uint8_t cot, + uint8_t cot_hi, uint8_t with_ioa, uint32_t ioa, + const uint8_t *body, uint16_t blen) +{ + uint16_t n = iec104_asdu_put_hdr(b, type, vsq, cot, cot_hi, 1u); + + if (with_ioa != 0u) { + iec104_put_ioa(&b[n], ioa); + n += 3u; + } + if (blen > 0u) { + (void)memcpy(&b[n], body, blen); + n += blen; + } + return n; +} + +/* ---------------- 复位 / 握手 ---------------- */ +static void reset_all(uint32_t now) +{ + prot_set_init(); + prot_elm_init(); + iec104_pts_init(); + iec104_pts_bind_src(&g_fake); + (void)memset(s_f_yc, 0, sizeof(s_f_yc)); + (void)memset(s_f_yc_rc, 0, sizeof(s_f_yc_rc)); + s_f_bits = 0u; + s_f_valid = (1uLL << 14) | (1uLL << 15) | (1uLL << 16) | (1uLL << 17) + | (1uLL << 22) | (1uLL << 30); + s_clock_rc = 0; + s_clock_ms = 0u; + iec104_link_init(&g_lk, &g_cfg, NULL); + iec104_link_open(&g_lk, now); + m_reset(); +} +static void handshake(uint32_t now) +{ + feed_u(0x07u, now); /* STARTDT act */ +} + +/* ---------------- 捕获检查 ---------------- */ +typedef struct { + uint8_t type, vsq, cot, cot_hi, oa; + uint32_t ca, ioa; + const uint8_t *obj; /* ioa 之后的信息体 */ + uint16_t obj_len; +} cap_t; + +static int cap_i_count(void) +{ + int k, n = 0; + + for (k = 0; k < s_cap_n; k++) { + if ((s_cap[k][2] & 0x01u) == 0u) { + n++; + } + } + return n; +} +static int cap_u_count(uint8_t q) +{ + int k, n = 0; + + for (k = 0; k < s_cap_n; k++) { + if ((s_cap[k][2] & 0x03u) == 0x03u && s_cap[k][2] == q) { + n++; + } + } + return n; +} +static int cap_has_s(uint16_t *nr_out) +{ + int k; + + for (k = s_cap_n - 1; k >= 0; k--) { + const uint8_t *p = s_cap[k]; + + if ((p[2] & 0x03u) == 0x01u) { + *nr_out = (uint16_t)(((uint16_t)p[4] | ((uint16_t)p[5] << 8)) >> 1); + return 1; + } + } + return 0; +} +static int cap_i(int n, cap_t *o) +{ + int k, seen = 0; + + for (k = 0; k < s_cap_n; k++) { + const uint8_t *p = s_cap[k]; + uint16_t lf = p[1]; + iec104_asdu_hdr_t h; + + if ((p[2] & 0x01u) != 0u) { + continue; + } + if (seen == n) { + if (iec104_asdu_parse_hdr(&p[6], (uint16_t)(lf - 4u), &h) != 0) { + return -1; + } + o->type = h.type; + o->vsq = h.vsq; + o->cot = h.cot; + o->cot_hi = h.cot_hi; + o->oa = h.oa; + o->ca = h.ca; + if (h.obj_len >= 3u) { + o->ioa = iec104_get_ioa(h.obj); + o->obj = h.obj + 3u; + o->obj_len = (uint16_t)(h.obj_len - 3u); + } else { + o->ioa = 0u; + o->obj = h.obj; + o->obj_len = 0u; + } + return 0; + } + seen++; + } + return -1; +} + +/* ============================ 测试用例 ============================ */ + +static void tc_cp56(void) +{ + uint8_t b[7]; + uint64_t e1 = 946684800000ULL; /* 2000-01-01 00:00:00.000 */ + uint64_t e2 = 1709188496789ULL; /* 2024-02-29 06:34:56.789(闰日) */ + uint64_t back = 0u; + int rc; + + iec104_epoch_ms_to_cp56(e1, b); + rc = iec104_cp56_to_epoch_ms(b, &back); + CHECK((rc == 0) && (back == e1), "TC-001 CP56 往返 2000-01-01"); + iec104_epoch_ms_to_cp56(e2, b); + back = 0u; + rc = iec104_cp56_to_epoch_ms(b, &back); + CHECK((rc == 0) && (back == e2), "TC-001 CP56 往返闰日 2024-02-29"); + b[2] |= 0x80u; + CHECK(iec104_cp56_to_epoch_ms(b, &back) == -2, "TC-001 IV → -2"); + iec104_epoch_ms_to_cp56(0u, b); /* 早于 2000 → 钳位 */ + back = 0u; + (void)iec104_cp56_to_epoch_ms(b, &back); + CHECK(back == e1, "TC-001 早于 2000 钳位"); +} + +static void tc_ioa_float(void) +{ + uint8_t b[8]; + + iec104_put_ioa(b, 0x123456u); + CHECK((iec104_get_ioa(b) == 0x123456u) && (b[0] == 0x56u) && (b[1] == 0x34u) + && (b[2] == 0x12u), "TC-002 IOA 3B 小端"); + iec104_put_float(b, 1.0f); + CHECK((b[0] == 0x00u) && (b[1] == 0x00u) && (b[2] == 0x80u) + && (b[3] == 0x3Fu), "TC-002 float IEEE754 小端"); + iec104_put_float(b, -12.5f); + CHECK(iec104_get_float(b) == -12.5f, "TC-002 float 往返"); +} + +static void tc_apci(void) +{ + uint32_t now = 1000u; + + reset_all(now); + { + static const uint8_t b[6] = { 0x68u, 4u, 0x07u, 0u, 0u, 0u }; + + iec104_link_on_rx(&g_lk, b, 3u, now); + CHECK(cap_u_count(0x0Bu) == 0, "TC-003 半帧不触发"); + iec104_link_on_rx(&g_lk, &b[3], 3u, now); + CHECK(cap_u_count(0x0Bu) == 1, "TC-003 半帧重组 → con"); + } + { + static const uint8_t b[12] = { + 0x68u, 4u, 0x43u, 0u, 0u, 0u, /* TESTFR act */ + 0x68u, 4u, 0x13u, 0u, 0u, 0u /* STOPDT act */ + }; + + iec104_link_on_rx(&g_lk, b, 12u, now); + CHECK((cap_u_count(0x83u) == 1) + && (iec104_link_state(&g_lk) == IEC104_ST_STOPPED), + "TC-003 粘帧逐处 + STOPDT 生效"); + } + reset_all(now); + { + static const uint8_t b[6] = { 0x69u, 4u, 0x07u, 0u, 0u, 0u }; + + iec104_link_on_rx(&g_lk, b, 6u, now); + CHECK(iec104_link_state(&g_lk) == IEC104_ST_IDLE, "TC-003 坏起始符 → IDLE"); + } + reset_all(now); + { + static const uint8_t b[6] = { 0x68u, 3u, 0x07u, 0u, 0u, 0u }; + + iec104_link_on_rx(&g_lk, b, 6u, now); + CHECK(iec104_link_state(&g_lk) == IEC104_ST_IDLE, "TC-003 坏长度 → IDLE"); + } +} + +static void tc_startdt(void) +{ + uint32_t now = 1000u; + + reset_all(now); + CHECK(iec104_link_state(&g_lk) == IEC104_ST_OPEN, "TC-004 open → OPEN"); + handshake(now); + CHECK((cap_u_count(0x0Bu) == 1) + && (iec104_link_state(&g_lk) == IEC104_ST_RUN), "TC-004 STARTDT → RUN"); +} + +static void tc_open_ignore(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint16_t n; + + reset_all(now); + n = mk_asdu(a, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_REQ, 0u, 1u, 0x4011u, NULL, 0u); + feed_i(a, n, now); + CHECK((cap_i_count() == 0) && (iec104_link_state(&g_lk) == IEC104_ST_OPEN), + "TC-005 OPEN 态 I 帧忽略"); + handshake(now); + m_ns = 0u; /* OPEN 忽略不消费序号 → 主站仍从 0 起 */ + feed_i(a, n, now); /* ns=0 仍有效(序号未被消费) */ + CHECK(cap_i_count() == 1, "TC-005 RUN 后同 ns 正常应答"); +} + +static void tc_interrogation(void) +{ + uint32_t now = 5000u; + uint8_t a[32]; + uint8_t body[1]; + uint16_t n; + cap_t c; + + reset_all(now); + s_f_yc[0] = 111.0f; + s_f_yc_rc[1] = -1; /* idx1(1Ub)无效通道 */ + handshake(now); + body[0] = IEC104_RQT_GROUP1; + n = mk_asdu(a, IEC104_T_C_IC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, body, 1u); + feed_i(a, n, now); + CHECK((cap_i_count() == 1) && (cap_i(0, &c) == 0) && (c.type == 100u) + && (c.cot == IEC104_COT_ACTCON), "TC-006 actcon 即发 COT7"); + iec104_link_poll(&g_lk, now); + CHECK(cap_i_count() == 5, "TC-006 首 poll 发满预算 4 分片"); + CHECK((cap_i(1, &c) == 0) && (c.type == 3u) && (c.cot == IEC104_COT_INIT) + && (c.vsq == (uint8_t)(IEC104_VSQ_SQ | 4u)) && (c.ioa == 1u), + "TC-006 YX 双点组 首召 COT=4"); + CHECK((cap_i(2, &c) == 0) && (c.type == 1u) + && (c.vsq == (uint8_t)(IEC104_VSQ_SQ | 29u)) && (c.ioa == 5u), + "TC-006 YX 单点组 29 点"); + CHECK((cap_i(3, &c) == 0) && (c.type == 13u) + && (c.vsq == (uint8_t)(IEC104_VSQ_SQ | 8u)) && (c.ioa == 0x4011u) + && (c.obj_len == 40u), "TC-006 YC 组 8 点 40B"); + if (cap_i(3, &c) == 0) { + CHECK((iec104_get_float(c.obj) == 111.0f) && (c.obj[4] == 0u), + "TC-006 YC 值 111.0 QDS=0"); + CHECK(c.obj[9] == IEC104_QDS_IV, "TC-006 无效通道 QDS=IV"); + } + CHECK((cap_i(4, &c) == 0) && (c.ioa == 0x401Du) && (c.vsq == 1u), + "TC-006 频率单点 SQ=0"); + iec104_link_poll(&g_lk, now + 100u); + CHECK((cap_i_count() == 6) && (cap_i(5, &c) == 0) && (c.type == 100u) + && (c.cot == IEC104_COT_ACTTERM), "TC-006 actterm 收尾"); + /* 二召:init 已清 → COT=2 */ + n = mk_asdu(a, IEC104_T_C_IC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, body, 1u); + feed_i(a, n, now + 200u); + iec104_link_poll(&g_lk, now + 200u); + CHECK((cap_i(7, &c) == 0) && (c.type == 3u) && (c.cot == IEC104_COT_BG_SCAN), + "TC-006 二召 COT=2"); + /* RBT 位 → COT=4(actcon3 是第 12 个未确认帧 → 先 S 确认窗才开) */ + n = mk_asdu(a, IEC104_T_C_IC_NA_1, 1u, IEC104_COT_ACT, IEC104_COT_BIT_RBT, + 1u, 0u, body, 1u); + feed_i(a, n, now + 300u); + feed_s(12u, now + 300u); + iec104_link_poll(&g_lk, now + 300u); + CHECK((cap_i(12, &c) == 0) && (c.type == 3u) && (c.cot == IEC104_COT_INIT), + "TC-006 RBT → COT=4"); +} + +static void tc_cov_yx(void) +{ + uint32_t now = 1000u; + cap_t c; + + reset_all(now); + handshake(now); + iec104_link_poll(&g_lk, now); /* 建快照 */ + CHECK(cap_i_count() == 0, "TC-007 首 poll 无自发"); + s_f_bits |= (1uLL << 15); /* YX16(idx15)动作 */ + iec104_link_poll(&g_lk, now + 100u); + CHECK((cap_i_count() == 1) && (cap_i(0, &c) == 0) && (c.type == 1u) + && (c.cot == IEC104_COT_SPONT) && (c.ioa == 16u) + && (c.obj_len == 1u) && (c.obj[0] == 1u), "TC-007 YX16 变位 COT3"); + s_f_bits &= ~(1uLL << 15); /* 复归 */ + iec104_link_poll(&g_lk, now + 200u); + CHECK((cap_i_count() == 2) && (cap_i(1, &c) == 0) && (c.ioa == 16u) + && (c.obj[0] == 0u), "TC-007 YX16 复归再变"); + s_f_bits |= (1uLL << 0); /* idx0 无效位 → 不触发 */ + iec104_link_poll(&g_lk, now + 300u); + CHECK(cap_i_count() == 2, "TC-007 无效位变位不触发"); +} + +static void tc_cov_yc(void) +{ + uint32_t now = 1000u; + cap_t c; + + reset_all(now); + handshake(now); + s_f_yc[0] = 100.0f; + iec104_link_poll(&g_lk, now); /* 快照 = 100 */ + s_f_yc[0] = 105.0f; /* 死区 10 内 */ + iec104_link_poll(&g_lk, now + 100u); + CHECK(cap_i_count() == 0, "TC-008 死区内不上送"); + s_f_yc[0] = 130.0f; /* 130-105=25 > 10 */ + iec104_link_poll(&g_lk, now + 200u); + CHECK((cap_i_count() == 1) && (cap_i(0, &c) == 0) && (c.type == 13u) + && (c.cot == IEC104_COT_SPONT) && (c.ioa == 0x4011u) + && (iec104_get_float(c.obj) == 130.0f), "TC-008 越死区上送"); +} + +static void feed_rd(uint32_t now) +{ + uint8_t a[16]; + uint16_t n = mk_asdu(a, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_REQ, 0u, + 1u, 0x4011u, NULL, 0u); + + feed_i(a, n, now); +} + +static void tc_k_window(void) +{ + uint32_t now = 1000u; + int i; + + reset_all(now); + handshake(now); + for (i = 0; i < 12; i++) { + feed_rd(now); + } + CHECK(cap_i_count() == 12, "TC-009 k=12 封顶"); + feed_rd(now); + CHECK(cap_i_count() == 12, "TC-009 第 13 个被 k 窗抑制"); + feed_s(12u, now); /* 全确认 → 窗开 */ + feed_rd(now); + CHECK(cap_i_count() == 13, "TC-009 S 确认后恢复发送"); +} + +static void tc_w_thresh(void) +{ + uint32_t now = 1000u; + uint16_t nr = 0xFFFFu; + int i; + + reset_all(now); + handshake(now); + for (i = 0; i < 7; i++) { + feed_rd(now); + } + CHECK(cap_has_s(&nr) == 0, "TC-010 收 7 未发 S"); + feed_rd(now); /* 第 8 个 → w 阈 */ + CHECK((cap_has_s(&nr) == 1) && (nr == 8u), "TC-010 w=8 → S nr=8"); +} + +static void tc_t2(void) +{ + uint32_t now = 1000u; + uint16_t nr = 0xFFFFu; + + reset_all(now); + handshake(now); + feed_rd(now); /* rx_unacked=1,t2 起爆 */ + iec104_link_poll(&g_lk, now + 9999u); + CHECK(cap_has_s(&nr) == 0, "TC-011 t2 未到期不发 S"); + iec104_link_poll(&g_lk, now + 10001u); + CHECK((cap_has_s(&nr) == 1) && (nr == 1u), "TC-011 t2 到期发 S"); +} + +static void tc_t3_t1(void) +{ + uint32_t now = 1000u; + + reset_all(now); + handshake(now); + iec104_link_poll(&g_lk, now + 19999u); + CHECK(cap_u_count(0x43u) == 0, "TC-012 t3 未到期无 TESTFR"); + iec104_link_poll(&g_lk, now + 20001u); + CHECK(cap_u_count(0x43u) == 1, "TC-012 t3 到期发 TESTFR act"); + iec104_link_poll(&g_lk, now + 20001u + 15001u); + CHECK(iec104_link_state(&g_lk) == IEC104_ST_IDLE, "TC-012 TESTFR 未答 t1 → IDLE"); + /* con 清挂起 → 不误杀 */ + reset_all(now); + handshake(now); + iec104_link_poll(&g_lk, now + 20001u); + CHECK(cap_u_count(0x43u) == 1, "TC-012 重连 t3 再触发"); + feed_u(0x83u, now + 20100u); /* TESTFR con */ + iec104_link_poll(&g_lk, now + 35000u); + CHECK(iec104_link_state(&g_lk) == IEC104_ST_RUN, "TC-012 con 清挂起后 t1 不误杀"); +} + +static void tc_dc(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint8_t body[1]; + uint16_t n; + cap_t c; + + reset_all(now); + handshake(now); + body[0] = 0x82u; /* S=1, DPC=ON */ + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Au, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(0, &c) == 0) && (c.type == 52u) && (c.cot == IEC104_COT_ACTCON) + && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u), "TC-013 选择段 actcon"); + CHECK((s_f_yk_sel == 1u) && (s_f_yk_ioa == 0x600Au), "TC-013 选择段转发源"); + body[0] = 0x02u; /* 执行 ON */ + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Au, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(1, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u) + && (s_f_yk_sel == 0u), "TC-013 执行段 actcon"); + /* 失配:选 ON 执 OFF */ + body[0] = 0x82u; + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Au, body, 1u); + feed_i(a, n, now); + body[0] = 0x01u; + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Au, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(3, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) != 0u), + "TC-013 执行失配 PN"); + /* 拒绝类(YK1):选择段即 PN */ + body[0] = 0x82u; + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x6000u, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(4, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) != 0u), + "TC-013 无出口硬件 YK 选择段 PN"); +} + +static void tc_se(void) +{ + uint32_t now = 1000u; + uint8_t a[24]; + uint8_t body[5]; + uint16_t n; + uint32_t addr = g_prot_set_meta[PS_OC1_CUR].comm_addr; /* 0x8858 */ + cap_t c; + + reset_all(now); + handshake(now); + CHECK(addr == 0x8858u, "TC-014 OC1 电流定值通讯地址"); + iec104_put_float(body, 5.0f); + body[4] = IEC104_QDC_S; /* 选择段 */ + n = mk_asdu(a, IEC104_T_C_SE_NC_1, 1u, IEC104_COT_ACT, 0u, 1u, addr, body, 5u); + feed_i(a, n, now); + CHECK((cap_i(0, &c) == 0) && (c.type == 50u) + && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u), "TC-014 定值选择 actcon"); + body[4] = 0u; /* 执行段 */ + n = mk_asdu(a, IEC104_T_C_SE_NC_1, 1u, IEC104_COT_ACT, 0u, 1u, addr, body, 5u); + feed_i(a, n, now); + CHECK((cap_i(1, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u), + "TC-014 定值执行 actcon"); + CHECK(prot_set_get_f(PS_OC1_CUR) == 5.0f, "TC-014 定值已写入(真实 prot_set)"); + CHECK(prot_set_selfcheck() == 0, "TC-014 执行后 seal → selfcheck 通过"); + iec104_put_float(body, 100000.0f); /* 越上限 */ + body[4] = IEC104_QDC_S; + n = mk_asdu(a, IEC104_T_C_SE_NC_1, 1u, IEC104_COT_ACT, 0u, 1u, addr, body, 5u); + feed_i(a, n, now); + CHECK((cap_i(2, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) != 0u), + "TC-014 越界选择段 PN"); +} + +static void tc_rd(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint16_t n; + cap_t c; + + reset_all(now); + handshake(now); + s_f_yc[0] = 222.0f; + n = mk_asdu(a, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_REQ, 0u, 1u, 0x4011u, NULL, 0u); + feed_i(a, n, now); + CHECK((cap_i(0, &c) == 0) && (c.type == 13u) && (c.cot == IEC104_COT_REQ) + && (iec104_get_float(c.obj) == 222.0f), "TC-015 C_RD YC 命中"); + n = mk_asdu(a, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_REQ, 0u, 1u, 0x8858u, NULL, 0u); + feed_i(a, n, now); + CHECK((cap_i(1, &c) == 0) && (c.type == 13u) && (c.ioa == 0x8858u), + "TC-015 C_RD 定值命中"); + n = mk_asdu(a, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_REQ, 0u, 1u, 0x9999u, NULL, 0u); + feed_i(a, n, now); + CHECK((cap_i(2, &c) == 0) && (c.type == 102u) + && (c.cot == IEC104_COT_UNK_IOA) && ((c.oa & 0x80u) != 0u), + "TC-015 未知 IOA COT14+EVI"); +} + +static void tc_cs(void) +{ + uint32_t now = 1000u; + uint8_t a[24]; + uint8_t cp[7]; + uint16_t n; + cap_t c; + uint64_t e = 1709188496789ULL; + + reset_all(now); + handshake(now); + (void)iec104_epoch_ms_to_cp56(e, cp); + n = mk_asdu(a, IEC104_T_C_CS_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, cp, 7u); + feed_i(a, n, now); + CHECK((cap_i(0, &c) == 0) && (c.type == 103u) + && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u) && (s_clock_ms == e), + "TC-016 C_CS 对时成功 epoch 精确"); + cp[2] |= 0x80u; /* IV */ + n = mk_asdu(a, IEC104_T_C_CS_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, cp, 7u); + feed_i(a, n, now); + CHECK((cap_i(1, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) != 0u), + "TC-016 CP56 IV → PN"); + (void)iec104_epoch_ms_to_cp56(e, cp); + s_clock_rc = -1; /* 系统侧拒绝 */ + n = mk_asdu(a, IEC104_T_C_CS_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, cp, 7u); + feed_i(a, n, now); + CHECK((cap_i(2, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) != 0u), + "TC-016 clock_sync 失败 → PN"); +} + +static void tc_err_resp(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint16_t n, m; + cap_t c; + + reset_all(now); + handshake(now); + n = mk_asdu(a, 200u, 1u, IEC104_COT_ACT, 0u, 1u, 0u, NULL, 0u); + feed_i(a, n, now); + CHECK((cap_i(0, &c) == 0) && (c.type == 200u) && (c.cot == IEC104_COT_UNK_COT) + && ((c.oa & 0x80u) != 0u), "TC-017 未知类型 COT12+EVI"); + m = iec104_asdu_put_hdr(a, IEC104_T_C_IC_NA_1, 1u, IEC104_COT_ACT, 0u, 2u); + a[m] = IEC104_RQT_GROUP1; + m++; + feed_i(a, m, now); /* ca=2 ≠ 1 */ + CHECK((cap_i(1, &c) == 0) && (c.cot == IEC104_COT_UNK_CA) + && ((c.oa & 0x80u) != 0u), "TC-017 错公共地址 COT13+EVI"); +} + +static void tc_stopdt(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint8_t body[1]; + uint16_t n; + + reset_all(now); + handshake(now); + feed_u(0x13u, now); /* STOPDT act */ + CHECK((cap_u_count(0x23u) == 1) + && (iec104_link_state(&g_lk) == IEC104_ST_STOPPED), "TC-018 STOPDT con"); + body[0] = IEC104_RQT_GROUP1; + n = mk_asdu(a, IEC104_T_C_IC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, body, 1u); + feed_i(a, n, now); + CHECK(cap_i_count() == 0, "TC-018 STOPPED 态数据服务关"); + feed_u(0x43u, now); + CHECK(cap_u_count(0x83u) == 1, "TC-018 STOPPED 态 TESTFR 仍应答"); +} + +static void tc_seq_err(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint16_t n; + + reset_all(now); + handshake(now); + m_ns = 5u; /* 期望 0,投 5 */ + n = mk_asdu(a, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_REQ, 0u, 1u, 0x4011u, NULL, 0u); + feed_i(a, n, now); + CHECK(iec104_link_state(&g_lk) == IEC104_ST_IDLE, "TC-019 序号错 → IDLE"); +} + +static void tc_pts(void) +{ + float v; + uint8_t q; + uint8_t d; + + reset_all(1000u); + CHECK((iec104_pts_yc_count() == 9u) && (iec104_pts_yx_count() == 33u) + && (iec104_pts_yc_ioa(8u) == 0x401Du), "TC-020 表尺寸/IOA"); + s_f_yc[0] = 7.5f; + CHECK((iec104_pts_yc_read(0u, &v, &q) == 0) && (v == 7.5f) && (q == 0u), + "TC-020 有效 YC"); + s_f_yc_rc[1] = -1; + (void)iec104_pts_yc_read(1u, &v, &q); + CHECK((v == 0.0f) && (q == IEC104_QDS_IV), "TC-020 无效通道 IV"); + s_f_yc_rc[2] = -2; + (void)iec104_pts_yc_read(2u, &v, &q); + CHECK(q == IEC104_QDS_NT, "TC-020 未就绪 NT"); + iec104_pts_yx_read(0u, &d); + CHECK(d == IEC104_DIQ_IV, "TC-020 无效遥信 IV"); + CHECK((iec104_pts_yx_is_dp(0u) == 1u) && (iec104_pts_yx_is_dp(4u) == 0u), + "TC-020 is_dp 分界"); + s_f_bits = (1uLL << 15); + iec104_pts_yx_read(15u, &d); + CHECK(d == 1u, "TC-020 有效遥信 ON"); +} + +static void tc_ts_rp(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint8_t body[2]; + uint16_t n; + cap_t c; + + reset_all(now); + handshake(now); + body[0] = 0u; + n = mk_asdu(a, IEC104_T_C_TS_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(0, &c) == 0) && (c.type == 104u) && (c.cot == IEC104_COT_ACTCON), + "TC-021 C_TS actcon"); + n = mk_asdu(a, IEC104_T_C_RP_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0u, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(1, &c) == 0) && (c.type == 105u) && (c.cot == IEC104_COT_ACTCON), + "TC-021 C_RP actcon"); +} + +static void tc_periodic(void) +{ + uint32_t now = 1000u; + cap_t c; + + reset_all(now); + handshake(now); + iec104_link_poll(&g_lk, now + 60001u); + CHECK(cap_i_count() == 2, "TC-022 周期上送 2 分片"); + CHECK((cap_i(0, &c) == 0) && (c.type == 13u) && (c.cot == IEC104_COT_PERIODIC) + && (c.ioa == 0x4011u), "TC-022 周期 YC 组 COT=1"); + CHECK((cap_i(1, &c) == 0) && (c.ioa == 0x401Du), "TC-022 周期频率点"); +} + +static void tc_cov_kfull(void) +{ + uint32_t now = 1000u; + int i; + cap_t c; + + reset_all(now); + handshake(now); + iec104_link_poll(&g_lk, now); /* 先建快照(首 poll 只建不算变位) */ + for (i = 0; i < 12; i++) { + feed_rd(now); /* k 窗占满 */ + } + s_f_bits |= (1uLL << 14); /* YX15 变位 */ + iec104_link_poll(&g_lk, now + 100u); + CHECK(cap_i_count() == 12, "TC-023 k 满时自发发不出"); + feed_s(12u, now + 200u); /* 窗开 */ + iec104_link_poll(&g_lk, now + 300u); + CHECK((cap_i_count() == 13) && (cap_i(12, &c) == 0) && (c.ioa == 15u) + && (c.cot == IEC104_COT_SPONT), "TC-023 窗开后补发不丢事件"); +} + +int main(void) +{ + printf("=== IEC104 Protocol Stack Host Tests ===\n"); + tc_cp56(); + tc_ioa_float(); + tc_apci(); + tc_startdt(); + tc_open_ignore(); + tc_interrogation(); + tc_cov_yx(); + tc_cov_yc(); + tc_k_window(); + tc_w_thresh(); + tc_t2(); + tc_t3_t1(); + tc_dc(); + tc_se(); + tc_rd(); + tc_cs(); + tc_err_resp(); + tc_stopdt(); + tc_seq_err(); + tc_pts(); + tc_ts_rp(); + tc_periodic(); + tc_cov_kfull(); + printf("=== IEC104 Tests: %d/%d PASSED (failed=%d) ===\n", + s_passed, s_total, s_failed); + return (s_failed == 0) ? 0 : 1; +} diff --git a/test/host/iec104/run_unit_test.py b/test/host/iec104/run_unit_test.py new file mode 100644 index 00000000..cf0979b7 --- /dev/null +++ b/test/host/iec104/run_unit_test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""IEC 60870-5-104 被控站协议栈(B4)主机侧单元测试运行器(L0.5,纯标准库)。 + +做什么:用本机 MSVC 离线编译 test/host/iec104/iec104_test.c(#include 纳入 + 生产源文件 iec104_asdu.c + iec104_pts.c + iec104_link.c,及数据源链接 + 依赖 prot_set.c + prot_elm.c + phasor.c + sample_ring.c),验证 + APCI 重组 / STARTDT 握手 / 总召分片 / COV / k-w-t1~t3 / 遥控与定值两段式 / + C_RD / C_CS / 错误应答(EVI)。 + +用法(仓库根目录): + & '.venv\\Scripts\\python.exe' test/host/iec104/run_unit_test.py + +退出码:0=PASS / 1=测试失败 / 2=环境错误。 + +设计依据:docs/子系统设计/IEC104上行设计说明.md §7(测试方案)。 +创建日期:2026-10-12 +""" +import os +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +ROOT = os.path.dirname(os.path.dirname(os.path.dirname(HERE))) +sys.path.insert(0, os.path.join(ROOT, "test", "host", "common")) + +from unit_test_harness import TestBuild, run_host_unit_test # noqa: E402 + +BUILD = TestBuild( + name="IEC104 Tests", + src=os.path.join(HERE, "iec104_test.c"), + include_dirs=[ + os.path.join(ROOT, "App", "algo"), + os.path.join(ROOT, "App", "protocol", "iec104"), + HERE, + ], + summary_marker="=== IEC104 Tests:", +) + +if __name__ == "__main__": + sys.exit(run_host_unit_test(BUILD)) diff --git a/test/host/prot_elm/prot_elm_test.c b/test/host/prot_elm/prot_elm_test.c index 36f2de9c..bd755cb4 100644 --- a/test/host/prot_elm/prot_elm_test.c +++ b/test/host/prot_elm/prot_elm_test.c @@ -18,6 +18,7 @@ * TC-PE-007 时基回绕:跨 0xFFFFFFFF 的延时判定仍正确 * TC-PE-008 动作位图聚合 * TC-PE-009 守卫:state(NULL)/越界编号、name 越界 + * TC-PE-010 跨上下文复归请求(B5):request 不当拍生效、下一拍 eval 头部消费 * * 通过:全部 TC PASS(main 返回 0)。 * 创建日期:2026-10-11 @@ -257,6 +258,31 @@ static void tc_guards(void) { CHECK(1, "TC-PE-009 eval(NULL meas) survives"); } +static void tc_request_reset(void) { + float m[PE_COUNT]; + prot_elm_state_t st; + + prot_set_init(); + prot_elm_init(); + mk_base(m); + m[PE_OC1] = 999.0f; /* OC1 默认 dly=0 → 启动同拍动作 */ + prot_elm_eval(1000u, m); + prot_elm_state(PE_OC1, &st); + CHECK(st.asserted != 0u, "TC-PE-010 pre: OC1 asserted (default dly=0)"); + + prot_elm_request_reset(); /* 跨上下文请求:不当拍生效 */ + prot_elm_state(PE_OC1, &st); + CHECK(st.asserted != 0u, "TC-PE-010 request alone does not reset"); + + /* 下一拍头部消费请求 → 复位;测量落在滞回保持区(9.6 ∈ [返回9.5, 动作10)) + * ——不复位则 picked/asserted 保持,复位后保持清零,可区分 */ + m[PE_OC1] = 9.6f; + prot_elm_eval(1100u, m); + prot_elm_state(PE_OC1, &st); + CHECK((st.picked == 0u) && (st.asserted == 0u), + "TC-PE-010 next eval consumes request -> cleared in hysteresis band"); +} + int main(void) { printf("=== Prot Elm Tests ===\n"); tc_init_clear(); @@ -268,6 +294,7 @@ int main(void) { tc_tick_wrap(); tc_active_mask(); tc_guards(); + tc_request_reset(); printf("\n=== Prot Elm Tests: %d/%d PASSED (failed=%d) ===\n", s_passed, s_total, s_failed); diff --git a/test/host/watchdog/watchdog_test.c b/test/host/watchdog/watchdog_test.c index b689f6f1..4df4bd3a 100644 --- a/test/host/watchdog/watchdog_test.c +++ b/test/host/watchdog/watchdog_test.c @@ -1,4 +1,4 @@ -/* +/* * 模块名称:Task Watchdog 主机侧单元测试 * 模块功能:在 PC 上对 App/util/task_watchdog.c 的**判定状态机**做穷举验证。 * @@ -116,7 +116,7 @@ static void start_and_clear(void) { s_feed_count = 0; } -/* 全员置位(默认必需掩码 0x77 = bit0|1|2|4|5|6,含 adcTask) */ +/* 全员置位(默认必需掩码 0x1F7 = bit0|1|2|4|5|6|7|8,含 adc/iec104/protect) */ static void beat_all(void) { task_wd_beat(TASK_WD_DEFAULT); task_wd_beat(TASK_WD_NET); @@ -124,6 +124,8 @@ static void beat_all(void) { task_wd_beat(TASK_WD_UI); task_wd_beat(TASK_WD_TIMESYNC); task_wd_beat(TASK_WD_ADC); + task_wd_beat(TASK_WD_IEC104); + task_wd_beat(TASK_WD_PROTECT); } /* ===================== 用例 ===================== */ @@ -152,7 +154,7 @@ static void tc_003_all_beat_feeds(void) { beat_all(); poll_advance(100); CHECK(s_feed_count == 1, "全员到位喂狗 1 次"); - CHECK(task_wd_last_mask() == 0x77u, "last_mask == 0x77(bit0|1|2|4|5|6)"); + CHECK(task_wd_last_mask() == 0x1F7u, "last_mask == 0x1F7(bit0|1|2|4|5|6|7|8)"); } static void tc_004_take_and_clear(void) { @@ -174,9 +176,11 @@ static void tc_005_mask_required(void) { task_wd_beat(TASK_WD_FTP); task_wd_beat(TASK_WD_TIMESYNC); task_wd_beat(TASK_WD_ADC); + task_wd_beat(TASK_WD_IEC104); + task_wd_beat(TASK_WD_PROTECT); poll_advance(100); CHECK(s_feed_count == 0, "缺 UI 位 → 不喂狗"); - CHECK(task_wd_last_mask() == (0x77u & ~(1u << TASK_WD_UI)), + CHECK(task_wd_last_mask() == (0x1F7u & ~(1u << TASK_WD_UI)), "last_mask 精确记录缺失位"); } @@ -252,7 +256,7 @@ static void tc_011_observers(void) { CHECK(task_wd_is_armed() == 1, "is_armed == 1(已启动)"); beat_all(); poll_advance(100); - CHECK(task_wd_last_mask() == 0x77u, "last_mask 反映最近一次抽样"); + CHECK(task_wd_last_mask() == 0x1F7u, "last_mask 反映最近一次抽样"); CHECK(task_wd_miss_count() == 0u, "全程达标 → miss_count == 0"); } From d3107f374f8270fd95a5008dbc0e996bf31b3ccf Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 12 Oct 2026 13:42:47 +0800 Subject: [PATCH 2/6] =?UTF-8?q?docs:=20=E5=BE=85=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=86=85=E5=AE=B9.md=20=E8=A7=A3=E8=80=A6=E4=B8=BA=20docs/?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E8=A7=84=E5=88=92/=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9=EF=BC=88README=20=E6=8E=92=E5=BA=8F=E6=9D=83=E5=A8=81?= =?UTF-8?q?=20+=206=20=E4=B8=AA=E8=81=8C=E8=B4=A3=E5=8D=95=E4=B8=80?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rename_ref.py 搬迁:git mv + 全库引用改写 33 文件 82 处 - README.md 保留 §0 编号空间 / §1 未闭环一览 / §2 推进顺序权威 / §3 维护约定 - 拆出 6 文件:W1-采集保护收尾(任务卡五字段)、排期详述、暂缓-RS485、 登记簿、测试与架构专项、基线与待确认 - 外部引用重定位 ~50 处:裸「登记簿 §X」、§5.1→基线与待确认 §2.1、 §2.4→暂缓-RS485、§6→基线与待确认 §3、脚本注释 T-x/N-x→登记簿 - 新增并行写纪律:任务分支不改本文件夹,状态列由 Lead 主工作树更新 - 验证:doc-links 141 文档全绿;mem-numbers 一致;refgraph 重生成; @build 0 错误 0 警告;新文件无 BOM / LF / 零乱码 --- .dsh/skills/task-worktree/SKILL.md | 2 +- .pre-commit-config.yaml | 2 +- AGENTS.md | 6 +- App/app/app_cfg.h | 2 +- App/log/console_log.c | 2 +- App/protocol/iec104/iec104_asdu.h | 2 +- App/task/rs485_task.c | 2 +- App/util/README.md | 2 +- Drivers/BSP/NET/README.md | 4 +- README.md | 4 +- docs/README.md | 8 +- docs/UI设计/UI_设计架构.md | 2 +- docs/images/引用关系图.dot | 203 + docs/images/引用关系图.json | 1484 +++- docs/images/引用关系图.svg | 7522 +++++++++++-------- docs/images/引用关系图_模块.dot | 60 +- docs/images/引用关系图_模块.svg | 1426 ++-- docs/产品需求/产品需求设计文档.md | 6 +- docs/代码规范/pre-commit使用说明.md | 2 +- docs/任务规划/README.md | 137 + docs/任务规划/W1-采集保护收尾.md | 68 + docs/任务规划/基线与待确认.md | 93 + docs/任务规划/排期详述.md | 26 + docs/任务规划/暂缓-RS485.md | 12 + docs/任务规划/测试与架构专项.md | 97 + docs/任务规划/登记簿.md | 53 + docs/内存管理/RAM使用分析与优化方案.md | 2 +- docs/内存管理/RAM预算台账.md | 4 +- docs/子系统设计/ADC采样节拍设计说明.md | 2 +- docs/子系统设计/IEC104上行设计说明.md | 4 +- docs/子系统设计/控制台单写者日志设计说明.md | 4 +- docs/子系统设计/看门狗设计说明.md | 2 +- docs/待处理内容.md | 409 - docs/文档规范.md | 2 +- docs/测试说明/boot_log_data/README.md | 4 +- docs/测试说明/实机测试实施指南.md | 12 +- docs/测试说明/时间同步单元测试说明.md | 2 +- docs/测试说明/模拟器差距清单.md | 2 +- docs/测试说明/测试开发标准流程.md | 4 +- docs/测试说明/链路延迟测试说明.md | 2 +- docs/环境与部署/CI配置指南.md | 2 +- docs/环境与部署/并行任务工作树方案.md | 31 +- docs/环境与部署/项目部署环境要求.md | 2 +- docs/算法/继电保护功能复现规划.md | 4 +- docs/网络/Net层阻塞模型架构设计.md | 6 +- docs/问题记录/CH395F_Trap_Records.md | 2 +- docs/问题记录/错误码传播审计.md | 4 +- docs/问题记录/项目审查与优化建议报告.md | 20 +- scripts/check_registration.py | 2 +- scripts/check_test_suite.py | 2 +- scripts/ram_baseline.py | 4 +- test/host/common/unit_test_harness.py | 2 +- test/host/time_sync/run_unit_test.py | 2 +- test/host/watchdog/run_unit_test.py | 2 +- test/run_all_suites.py | 2 +- 55 files changed, 7366 insertions(+), 4403 deletions(-) create mode 100644 docs/任务规划/README.md create mode 100644 docs/任务规划/W1-采集保护收尾.md create mode 100644 docs/任务规划/基线与待确认.md create mode 100644 docs/任务规划/排期详述.md create mode 100644 docs/任务规划/暂缓-RS485.md create mode 100644 docs/任务规划/测试与架构专项.md create mode 100644 docs/任务规划/登记簿.md delete mode 100644 docs/待处理内容.md diff --git a/.dsh/skills/task-worktree/SKILL.md b/.dsh/skills/task-worktree/SKILL.md index 3ec5084e..7fc10574 100644 --- a/.dsh/skills/task-worktree/SKILL.md +++ b/.dsh/skills/task-worktree/SKILL.md @@ -57,7 +57,7 @@ whenToUse: 要同时推进多个任务、担心同分支同文档互相冲突; 2. **`done` 不 push**。它结束于本地合入 + 门禁全绿;推送需用户明确许可(项目既有纪律)。 3. **`build` 与 `bench` 都必须持锁**:UV4 不能两个实例同时 `-b`;串口 COM6、ST-LINK、 设备 IP `192.168.1.100` 各只有一份。**构建与烧录都不可并发。** -4. **单写者文档**:`docs/待处理内容.md`、`AGENTS.md` 的任务表块、`MDK-ARM/*.uvprojx`、 +4. **单写者文档**:`docs/任务规划/`(整个文件夹)、`AGENTS.md` 的任务表块、`MDK-ARM/*.uvprojx`、 `.pre-commit-config.yaml`、内存快照 —— 任务期**不在任务工作树里改**,留到 `done` 统一处理。 5. **清场必须先摘联接**:脚本会先 `os.rmdir` 掉 `.venv` / `simulator/SDL2` 联接再 `git worktree remove`。**手工清场时千万别直接 `git worktree remove`**——git 可能递归进联接, diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6e7a90e3..8aceebb4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -397,7 +397,7 @@ repos: # TEST_SUITE_CH395F 就是开启状态(.map 含 34 处 test 代码),即仓库里 # 躺着的是测试固件。本钩子抓这个静默漏网:默认要求产品构建,跑套件回归 # 确需提交测试构建时用 `--allow-test-build` / ALLOW_TEST_BUILD=1 显式放行。 - # 详见 docs/待处理内容.md T-1 + # 详见 docs/任务规划/登记簿.md T-1 - id: test-suite-switch name: 测试套件开关=产品构建 entry: python scripts/check_test_suite.py diff --git a/AGENTS.md b/AGENTS.md index df7607b2..c46a9c43 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,7 @@ ## 项目概况 -**现状一句话**:平台能力(网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置)**已实现并台架验收**;采集主线已闭环到业务消费者(L1→L2 相量→L3 保护判据 protectTask→104 遥信,B5);**RS-485 采集尚未接线**(B2 按用户决策冻结,见登记簿 §2.4)——当前最大功能缺口,接线节奏受 E-59 门禁约束(见「平台约束」)。 +**现状一句话**:平台能力(网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置)**已实现并台架验收**;采集主线已闭环到业务消费者(L1→L2 相量→L3 保护判据 protectTask→104 遥信,B5);**RS-485 采集尚未接线**(B2 按用户决策冻结,见 `docs/任务规划/暂缓-RS485.md`)——当前最大功能缺口,接线节奏受 E-59 门禁约束(见「平台约束」)。 **数据主线**(能力视角;分层图与跨层依赖表 → `docs/架构设计/项目架构总览.md`): @@ -150,7 +150,7 @@ ## 文档与图形 -- **登记簿类文档「完成即销项」**:`docs/待处理内容.md` 这类待办登记簿,事项修复/关闭后**直接从表中删除该行**(不保留"已消化"行)——结论与证据应已沉淀进对应模块文档/问题记录。销项时必须:① 先核对目标文档确已含完整记录 ② 同步清理其他文档对该编号的引用 ③ 改完跑 `check_doc_links.py --all` + pre-commit +- **登记簿类文档「完成即销项」**:`docs/任务规划/README.md` 这类待办登记簿,事项修复/关闭后**直接从表中删除该行**(不保留"已消化"行)——结论与证据应已沉淀进对应模块文档/问题记录。销项时必须:① 先核对目标文档确已含完整记录 ② 同步清理其他文档对该编号的引用 ③ 改完跑 `check_doc_links.py --all` + pre-commit - 图形走 **`draw-diagram` skill**:精确布局图用 `tools/arch_diagram/gen_*.py` 生成器(产物放 `docs/images/`,脚本与 .svg 一并提交);拓扑图用 Mermaid;**勿手绘 ASCII 框图**。文件引用关系图走 `tools/refgraph`(`& 'tools\refgraph\gen_refgraph.bat'`) - **改名 / 挪目录一律走 `scripts/rename_ref.py`(先 dry-run,确认后 `--apply`)**:`git mv` + 自动改写全库引用(反引号引用 / Markdown 链接 / 图片 `../` 层级换算 / `#include` / `uvprojx` `` / `CMakeLists.txt`),落盘后自动跑 `check_doc_links --all` 复核——手工扫引用既慢又漏(一次改名历史上波及 10~30 文件)。引用章节用「`路径.md` §N.M」**紧邻写法**(`doc-links` 校验编号是否还在:紧邻/裸名/前缀/别名/自引用**全部拦提交**(钩子带 `--sections-strict`);每次跑打印「可判定比例」,`--section-todo` 出待改清单,昵称歧义就登记 `scripts/section_aliases.json` 或写清楚)→ `docs/文档规范.md` §3.5 / §3.6 - 文档写作规范(编码/BOM/链接/表格/一致性钩子)→ `docs/文档规范.md`;全量索引与推荐阅读顺序 → `docs/README.md` @@ -178,6 +178,6 @@ | 烧录与复位语义 | `docs/测试说明/ST-LINK_CLI_复位使用说明.md` | | 串口助手 | **`serial-assistant` skill**(命令/判据/陷阱,用到自动加载)、`docs/测试说明/串口助手使用指南.md`、`串口助手设计说明.md` | | UI 架构 / 模拟器 / UI 自动化回归 | **`lvgl-simulator` skill**(构建/自检/报错速查,用到自动加载)、`docs/UI设计/UI_设计架构.md`、`LVGL模拟器部署与使用说明.md`、`UI_自动化测试流程.md`;UI 改动回归走 **`ui-verify` skill** | -| 待办与审计发现登记簿 | `docs/待处理内容.md` | +| 待办与审计发现登记簿 | `docs/任务规划/README.md` | | 多任务并行开发(开空间 / 合并回收 / 台架与构建排队) | **`task-worktree` skill**(`@task`,用到自动加载)、`docs/环境与部署/并行任务工作树方案.md` | | 换机 / 工具路径环境变量 / CI | `docs/环境与部署/` | diff --git a/App/app/app_cfg.h b/App/app/app_cfg.h index c7464ff5..2c880253 100644 --- a/App/app/app_cfg.h +++ b/App/app/app_cfg.h @@ -10,7 +10,7 @@ * 零代码引用(grep 仅本文件有定义)——"开关名存实亡"会 * 误导评审者以为模块可裁剪。现如实标注为**预留占位**: * 当前**不门控任何代码**,各模块一律编译进产品。是否/ - * 如何接线取决于产品定义(待处理内容.md §2 阶段 B0), + * 如何接线取决于产品定义(docs/任务规划/README.md §2 阶段 B0), * 确认后再在真实初始化点(如 app_main.c 的 rs485_init / * tpafe5160_init)加门控;在此之前**不要**把它们当开关用。 */ diff --git a/App/log/console_log.c b/App/log/console_log.c index 8836d021..994a9c43 100644 --- a/App/log/console_log.c +++ b/App/log/console_log.c @@ -16,7 +16,7 @@ * 无 stall 日志,纯节奏性饥饿)。修复:发送故障后立即结束本轮 * drain 并进入 300ms 发送冷却(冷却期内 drain 直接让位主循环), * 保证喂狗节奏 ≤ ~300ms。根治(USART1 TX-only 灭 ORE 机制) - * 另行推进(.ioc 结构性修改 + CubeMX 重生成,见待处理内容①)。 + * 另行推进(.ioc 结构性修改 + CubeMX 重生成,见 docs/任务规划/登记簿.md S-3)。 * 2026-10-02 王建锋 round 8b 加固:发送超时判据改用 DWT CYCCNT(时间源无关)。 * 台架 round 8a 取证(见 docs/子系统设计/看门狗设计说明.md 2026-10-02 变更记录)定位到:defaultTask * 冻结在 console 突发行内、无 STALL、复位为 IWDGRSTF。唯一自洽机理 = diff --git a/App/protocol/iec104/iec104_asdu.h b/App/protocol/iec104/iec104_asdu.h index 492b9c2d..7f47d631 100644 --- a/App/protocol/iec104/iec104_asdu.h +++ b/App/protocol/iec104/iec104_asdu.h @@ -10,7 +10,7 @@ * 帧结构(本层只管 ASDU,APCI 6 字节头归 iec104_link): * [type 1B][vsq 1B][cot 2B][ca 2B]( [ioa 3B][元素...] )*n * 多信息体地址对象(SQ=0)每对象带独立 IOA;顺序对象(SQ=1)单 IOA + n 元素。 - * 创建日期:2026-10-12(B4,登记簿 §2.1 W1) + * 创建日期:2026-10-12(B4,W1 功能主线,登记簿见 docs/任务规划/) */ #ifndef IEC104_ASDU_H #define IEC104_ASDU_H diff --git a/App/task/rs485_task.c b/App/task/rs485_task.c index 36961be7..494561bd 100644 --- a/App/task/rs485_task.c +++ b/App/task/rs485_task.c @@ -2,7 +2,7 @@ * 模块名称:RS485 Communication Task * 模块功能:RS-485 轮询收发、协议帧解析与响应 * 状态说明:**预留桩(未启用)**——采集/协议链路尚未实现,产品定义未定 - * (见 docs/待处理内容.md 阶段 B0/B2)。当前 init/func 为空实现, + * (见 docs/任务规划/暂缓-RS485.md,B2 暂缓)。当前 init/func 为空实现, * 不收发、不解析。 * 适用平台:STM32F407ZGTx * 作者:王建锋 diff --git a/App/util/README.md b/App/util/README.md index 93e94ac0..69a164b8 100644 --- a/App/util/README.md +++ b/App/util/README.md @@ -13,7 +13,7 @@ > 两模块**零调用者**且未编入任何构建——CRC 从未被链接使用:名义上的关联点 `net_cfg_legacy.c` > (旧档 `/cfg/netcfg.bin` 迁移,**该文件亦已于 2026-10-10 删除**)自带静态 `s_crc16_modbus()`, > 从不调用本模块;环形缓冲由 `App/log/console_log.c` 内联实现(`s_con_ring`)。 -> 保留只会造成"有统一实现"的误导,故整体移除(详见 `docs/待处理内容.md` E-15 销项)。 +> 保留只会造成"有统一实现"的误导,故整体移除(详见 `docs/任务规划/排期详述.md` E-15(C5))。 ## 设计要点 diff --git a/Drivers/BSP/NET/README.md b/Drivers/BSP/NET/README.md index 7aa85a2b..90423db7 100644 --- a/Drivers/BSP/NET/README.md +++ b/Drivers/BSP/NET/README.md @@ -18,7 +18,7 @@ ### 阻塞模型(L3 pending) - 一期(RECV)已落地:`net_recv` 等支持带超时的阻塞(`pending` 挂起 + tick 唤醒) -- 二期(ACCEPT + SEND)待做 → `docs/待处理内容.md` N-4 +- 二期(ACCEPT + SEND)待做 → `docs/任务规划/登记簿.md` N-4 ### 周期对账自愈(Trap 22 修复) @@ -61,5 +61,5 @@ - 上层用法:`docs/网络/BSD_Socket_API_使用指南.md` - 内部调用关系:`docs/网络/BSD_Socket_API_函数调用关系.md` - 架构设计:`docs/网络/Net层阻塞模型架构设计.md`(阻塞等待 / pending 请求模型) -- 二期设计基线:`docs/待处理内容.md` §5.1 +- 二期设计基线:`docs/任务规划/基线与待确认.md` §2.1 - 测试:`docs/测试说明/CH395F_Test_Guide.md`、`docs/测试说明/FTP_Test_Guide.md` diff --git a/README.md b/README.md index 86bf7dd5..13436d06 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ main.c > 上表与 `Src/freertos.c` 的 `osThreadAttr_t` 一致(2026-09-25 校准);改动栈大小前先读 -> `docs/内存管理/RAM使用分析与优化方案.md` 的定栈规则与 `docs/待处理内容.md` 的内存预算项。 +> `docs/内存管理/RAM使用分析与优化方案.md` 的定栈规则与 `docs/任务规划/基线与待确认.md` 的内存预算项。 ### 任务启动顺序管理 @@ -165,7 +165,7 @@ STM32F4-Base/ │ └── time_sync_server.py # 时间同步推送服务 ├── docs/ # 项目文档(全量索引见 docs/README.md) │ ├── README.md # 文档索引:目录结构 + 推荐阅读顺序 + 全量清单 -│ ├── 待处理内容.md # 统一待办登记簿 +│ ├── 任务规划/ # 统一待办登记簿(README 排序权威 + 拆分文件) │ ├── 架构设计/ # 项目架构总览 / 存储架构 / 启动顺序 / 配图流程 / 引用关系图 │ ├── 子系统设计/ # 配置 / 网络 / 墙钟 / 日志 / 运行自检记录 设计说明 │ ├── 网络/ # BSD Socket API 使用指南 + 内部函数调用关系 diff --git a/docs/README.md b/docs/README.md index 659cecbd..cca2ac08 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,7 +11,7 @@ ``` docs/ ├── README.md 本索引(阅读顺序 + 全量清单) -├── 待处理内容.md 统一待办登记簿(高频入口,保留在顶层) +├── 任务规划/ 统一待办登记簿(README 排序权威 + 6 个拆分文件) ├── 产品需求/ 产品需求设计文档(面向产品的需求基线) ├── 架构设计/ 全局架构与设计方法论 ├── 子系统设计/ 各功能子系统的设计说明 @@ -53,7 +53,7 @@ docs/ - **应用/驱动开发** → §4 架构设计 → §5 子系统设计 → §7 问题记录(**改驱动前必读对应 Trap Records**) - **测试/验证** → §6 测试说明 → §9.2 环境与部署 - **UI 开发** → §8 UI 设计 → §6 测试说明(串口助手、UI 自动化测试流程) -- **接手/评审** → §9.1 评审报告 → §9.3 待处理内容(统一待办登记簿) +- **接手/评审** → §9.1 评审报告 → §9.3 任务规划(统一待办登记簿,见 `任务规划/README.md`) --- @@ -213,7 +213,7 @@ docs/ | 文档 | 内容 | |---|---| -| [`问题记录/项目审查与优化建议报告.md`](问题记录/项目审查与优化建议报告.md) | 项目全景审查:文档/代码/架构/可靠性问题清单(未闭环项:D-1、N-xx、Px-xx;**已修复项按「修复即销项」删除**,去处见其变更记录)——**体系层评审报告,非待办池**(待办见 §9.3 `待处理内容.md`) | +| [`问题记录/项目审查与优化建议报告.md`](问题记录/项目审查与优化建议报告.md) | 项目全景审查:文档/代码/架构/可靠性问题清单(未闭环项:D-1、N-xx、Px-xx;**已修复项按「修复即销项」删除**,去处见其变更记录)——**体系层评审报告,非待办池**(待办见 `任务规划/README.md`) | ### 9.2 环境与部署 @@ -226,7 +226,7 @@ docs/ | 位置 | 内容 | |---|---| -| [`待处理内容.md`](待处理内容.md) | **统一待办登记簿**——审计缺陷(P-x)+ 台架/审计观察(N/S/T-x)+ 测试与架构专项(S1x/A-x)+ 任务排序(阶段 A/B/C/D)+ 诊断基线;只保留未闭环项,完成即删 | +| [`任务规划/`](任务规划/README.md) | **统一待办登记簿(文件夹)**——`README.md` = 排序权威(波次 W1~W7)+ 编号空间 + 维护约定;`W1-采集保护收尾.md` = 当前波次任务卡(里程碑 × 并行道 × 五字段);`登记簿.md` = N/S/T-x 长期观察;`排期详述.md` / `暂缓-RS485.md` / `测试与架构专项.md` / `基线与待确认.md` = 波内详表 / 冻结簇 / 专项 / 基线;只保留未闭环项,完成即删 | | `硬件平台/` | 网表详细分析报告与语义图(V0.0 / V0.1);**[`ADC通道映射说明.md`](硬件平台/ADC通道映射说明.md)——V0.1 十七路 ADC 语义/网名/通道号权威映射表(固件取数、UI 显示、自检注入以此为准)** | | `芯片手册/` | 外部芯片数据手册转录(CH395F / GD5F2GQ5UE / SD2506 / TPAFE5160 / RTL8305NBI 等) | | `images/` | 文档技术配图(`.svg` 产物,由 `tools/arch_diagram/`、`tools/refgraph/` 生成) | diff --git a/docs/UI设计/UI_设计架构.md b/docs/UI设计/UI_设计架构.md index 7cbee291..0795abe7 100644 --- a/docs/UI设计/UI_设计架构.md +++ b/docs/UI设计/UI_设计架构.md @@ -43,7 +43,7 @@ MCU **无物理屏幕**:LVGL 做 160×160 **1bpp 单色离屏渲染**,帧缓 ### 1.4 硬约束(改 UI 必须遵守) -1. **RAM 紧张**:新增页面/控件/缓冲前必须核算 LVGL 池(40KB)与任务栈余量(见 `待处理内容.md`) +1. **RAM 紧张**:新增页面/控件/缓冲前必须核算 LVGL 池(40KB)与任务栈余量(见 `docs/任务规划/基线与待确认.md` §4 内存预算) 2. **新增汉字必须重新生成字体**(`tools/font_gen/` 两步),否则显示空白 3. 文本一律用静态字符串(`lv_label_set_text_static`),不 strdup 4. UI 相关文件为 **UTF-8 带 BOM**(`Drivers/BSP/UI/*`、`ui_task.c`、`Lib/lv_conf.h`),其余源码无 BOM;禁止 PowerShell 整文件重写(编码铁律,见 AGENTS.md) diff --git a/docs/images/引用关系图.dot b/docs/images/引用关系图.dot index 5440d533..792167f0 100644 --- a/docs/images/引用关系图.dot +++ b/docs/images/引用关系图.dot @@ -2,6 +2,18 @@ digraph refgraph_full { graph [rankdir=LR, bgcolor="white", labelloc=t, label="STM32F4-Base 项目文件引用关系图(项目代码视图)", fontname="Microsoft YaHei", fontsize=18]; node [fontname="Microsoft YaHei", fontsize=10, shape=box, style="rounded,filled"]; edge [fontname="Microsoft YaHei", fontsize=8]; + "App/algo/adc_health.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/adc_health.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/adc_input.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/adc_input.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/phasor.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/phasor.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/prot_elm.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/prot_elm.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/prot_set.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/prot_set.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/sample_ring.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/algo/sample_ring.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/app/app_cfg.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/app/app_main.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/app/app_main.h" [fillcolor="#dbeafe", color="#1d4ed8"]; @@ -16,20 +28,34 @@ digraph refgraph_full { "App/log/console_log.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/log/sys_log.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/log/sys_log_mcu.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/protocol/iec104/iec104_asdu.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/protocol/iec104/iec104_asdu.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/protocol/iec104/iec104_link.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/protocol/iec104/iec104_link.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/protocol/iec104/iec104_pts.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/protocol/iec104/iec104_pts.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/sync/time_sync.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/sync/time_sync.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/adc_task.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/adc_task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/default_task.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/default_task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/task/iec104_serv.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/task/iec104_serv.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/net_task.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/net_task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/task/protect_task.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/task/protect_task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/rs485_task.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/rs485_task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/ui_task.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/task/ui_task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/util/sha256.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/util/sha256.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/util/sys_clock.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/util/sys_clock.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/util/task_prof.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "App/util/task_prof.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/util/task_watchdog.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "App/util/task_watchdog.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/CH395F/ch395f.c" [fillcolor="#dbeafe", color="#1d4ed8"]; @@ -39,12 +65,15 @@ digraph refgraph_full { "Drivers/BSP/GD5F2GQ5UE/nand_ftl.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/GD5F2GQ5UE/nand_ftl.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NET/lftpd/lftpd.h" [fillcolor="#f3f4f6", color="#9ca3af"]; + "Drivers/BSP/NET/lftpd/lftpd_auth.c" [fillcolor="#f3f4f6", color="#9ca3af"]; "Drivers/BSP/NET/net_config.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NET/net_select.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NET/net_select.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NET/net_socket.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NET/net_socket.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NET/net_types.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "Drivers/BSP/NETCFG/ftp_cfg.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "Drivers/BSP/NETCFG/ftp_cfg.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NETCFG/net_cfg.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/NETCFG/net_cfg.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Drivers/BSP/RS485/rs485.c" [fillcolor="#dbeafe", color="#1d4ed8"]; @@ -114,6 +143,7 @@ digraph refgraph_full { "Inc/spi.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Inc/stm32f4xx_hal_conf.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Inc/stm32f4xx_it.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "Inc/tim.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Inc/usart.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "Lib/FatFs/diskio.h" [fillcolor="#f3f4f6", color="#9ca3af"]; "Lib/FatFs/ff.h" [fillcolor="#f3f4f6", color="#9ca3af"]; @@ -136,6 +166,7 @@ digraph refgraph_full { "Src/stm32f4xx_hal_timebase_tim.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "Src/stm32f4xx_it.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "Src/system_stm32f4xx.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "Src/tim.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "Src/usart.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "simulator/SDL2/SDL2-2.32.10/include/SDL.h" [fillcolor="#f3f4f6", color="#9ca3af"]; "simulator/dbg_log.h" [fillcolor="#dbeafe", color="#1d4ed8"]; @@ -148,6 +179,8 @@ digraph refgraph_full { "simulator/sim/sim_port.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "simulator/sim/sim_syslog.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "simulator/sim/ui_net_sink_backend_sim.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/board/ch395f_reuse_bench.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/board/ch395f_reuse_bench.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/board/ch395f_test.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/board/ch395f_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/board/ch395f_test_task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; @@ -164,18 +197,65 @@ digraph refgraph_full { "test/board/test_common.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/board/test_config.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/board/test_config.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/adc_health/adc_health_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/adc_input/adc_input_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/adc_input/stub/adc.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/adc_input/stub/tpafe5160.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/cfg_file/cfg_file_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/cfg_file/stub/dbg_log.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/ftp_auth/ftp_auth_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/iec104/iec104_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/phasor/phasor_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/prot_elm/prot_elm_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/prot_set/prot_set_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/sha256/sha256_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/sys_clock/stub/FreeRTOS.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/sys_clock/stub/dbg_log.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/sys_clock/stub/main.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/sys_clock/stub/task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/sys_clock/sys_clock_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/stub/FreeRTOS.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/stub/cmsis_os2.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/stub/dbg_log.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/stub/net_socket.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/stub/sys_clock.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/stub/sys_events.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/stub/task.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/time_sync/time_sync_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/vol_lock/stub/cmsis_os.h" [fillcolor="#dbeafe", color="#1d4ed8"]; + "test/host/vol_lock/vol_lock_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/watchdog/stub/dbg_log.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/watchdog/stub/iwdg.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/watchdog/stub/main.h" [fillcolor="#dbeafe", color="#1d4ed8"]; "test/host/watchdog/watchdog_test.c" [fillcolor="#dbeafe", color="#1d4ed8"]; "外部/系统头文件" [shape=ellipse, fillcolor="#fef3c7", color="#d97706", fontsize=12]; + "App/algo/adc_health.c" -> "App/algo/adc_health.h" [color="#2563eb", penwidth=1.0]; + "App/algo/adc_health.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/adc_input.c" -> "App/algo/adc_input.h" [color="#2563eb", penwidth=1.0]; + "App/algo/adc_input.c" -> "Drivers/BSP/TPAFE5160/tpafe5160.h" [color="#2563eb", penwidth=1.0]; + "App/algo/adc_input.c" -> "Inc/adc.h" [color="#2563eb", penwidth=1.0]; + "App/algo/adc_input.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/adc_input.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/phasor.c" -> "App/algo/phasor.h" [color="#2563eb", penwidth=1.0]; + "App/algo/phasor.c" -> "App/algo/sample_ring.h" [color="#2563eb", penwidth=1.0]; + "App/algo/phasor.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/phasor.h" -> "App/algo/adc_input.h" [color="#2563eb", penwidth=1.0]; + "App/algo/phasor.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/prot_elm.c" -> "App/algo/phasor.h" [color="#2563eb", penwidth=1.0]; + "App/algo/prot_elm.c" -> "App/algo/prot_elm.h" [color="#2563eb", penwidth=1.0]; + "App/algo/prot_elm.c" -> "App/algo/prot_set.h" [color="#2563eb", penwidth=1.0]; + "App/algo/prot_elm.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/prot_elm.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/prot_set.c" -> "App/algo/prot_set.h" [color="#2563eb", penwidth=1.0]; + "App/algo/prot_set.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/sample_ring.c" -> "App/algo/sample_ring.h" [color="#2563eb", penwidth=1.0]; + "App/algo/sample_ring.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/algo/sample_ring.h" -> "App/algo/adc_input.h" [color="#2563eb", penwidth=1.0]; + "App/algo/sample_ring.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/app/app_main.c" -> "App/algo/adc_input.h" [color="#2563eb", penwidth=1.0]; + "App/app/app_main.c" -> "App/algo/phasor.h" [color="#2563eb", penwidth=1.0]; + "App/app/app_main.c" -> "App/algo/prot_elm.h" [color="#2563eb", penwidth=1.0]; + "App/app/app_main.c" -> "App/algo/prot_set.h" [color="#2563eb", penwidth=1.0]; "App/app/app_main.c" -> "App/app/app_cfg.h" [color="#2563eb", penwidth=1.0]; "App/app/app_main.c" -> "App/app/app_main.h" [color="#2563eb", penwidth=1.0]; "App/app/app_main.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0]; @@ -188,7 +268,9 @@ digraph refgraph_full { "App/app/app_main.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; "App/app/app_main.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0]; "App/app/app_main.c" -> "Inc/stm32f4xx_it.h" [color="#2563eb", penwidth=1.0]; + "App/app/app_main.c" -> "Inc/tim.h" [color="#2563eb", penwidth=1.0]; "App/app/app_main.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0]; + "App/app/app_main.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0]; "App/app/app_main.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "App/app/sys_events.h" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h" [color="#94a3b8", penwidth=0.7]; "App/cfg/cfg_file.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0]; @@ -222,6 +304,22 @@ digraph refgraph_full { "App/log/sys_log_mcu.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7]; "App/log/sys_log_mcu.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7]; "App/log/sys_log_mcu.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/protocol/iec104/iec104_asdu.c" -> "App/protocol/iec104/iec104_asdu.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_asdu.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/protocol/iec104/iec104_asdu.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/protocol/iec104/iec104_link.c" -> "App/protocol/iec104/iec104_asdu.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_link.c" -> "App/protocol/iec104/iec104_link.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_link.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/protocol/iec104/iec104_link.h" -> "App/protocol/iec104/iec104_pts.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_link.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/protocol/iec104/iec104_pts.c" -> "App/algo/adc_input.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_pts.c" -> "App/algo/phasor.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_pts.c" -> "App/algo/prot_elm.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_pts.c" -> "App/algo/prot_set.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_pts.c" -> "App/protocol/iec104/iec104_asdu.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_pts.c" -> "App/protocol/iec104/iec104_pts.h" [color="#2563eb", penwidth=1.0]; + "App/protocol/iec104/iec104_pts.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/protocol/iec104/iec104_pts.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "App/sync/time_sync.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0]; "App/sync/time_sync.c" -> "App/sync/time_sync.h" [color="#2563eb", penwidth=1.0]; "App/sync/time_sync.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0]; @@ -230,7 +328,15 @@ digraph refgraph_full { "App/sync/time_sync.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; "App/sync/time_sync.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "App/sync/time_sync.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/task/adc_task.c" -> "App/algo/adc_health.h" [color="#2563eb", penwidth=1.0]; + "App/task/adc_task.c" -> "App/algo/adc_input.h" [color="#2563eb", penwidth=1.0]; + "App/task/adc_task.c" -> "App/algo/phasor.h" [color="#2563eb", penwidth=1.0]; + "App/task/adc_task.c" -> "App/algo/sample_ring.h" [color="#2563eb", penwidth=1.0]; + "App/task/adc_task.c" -> "App/log/console_log.h" [color="#2563eb", penwidth=1.0]; + "App/task/adc_task.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0]; "App/task/adc_task.c" -> "App/task/adc_task.h" [color="#2563eb", penwidth=1.0]; + "App/task/adc_task.c" -> "App/util/task_prof.h" [color="#2563eb", penwidth=1.0]; + "App/task/adc_task.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; "App/task/adc_task.c" -> "Drivers/BSP/TPAFE5160/tpafe5160.h" [color="#2563eb", penwidth=1.0]; "App/task/adc_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; "App/task/adc_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7]; @@ -239,6 +345,7 @@ digraph refgraph_full { "App/task/default_task.c" -> "App/fs/vol_lock.h" [color="#2563eb", penwidth=1.0]; "App/task/default_task.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0]; "App/task/default_task.c" -> "App/task/default_task.h" [color="#2563eb", penwidth=1.0]; + "App/task/default_task.c" -> "App/util/task_prof.h" [color="#2563eb", penwidth=1.0]; "App/task/default_task.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; "App/task/default_task.c" -> "Drivers/BSP/GD5F2GQ5UE/nand_ftl.h" [color="#2563eb", penwidth=1.0]; "App/task/default_task.c" -> "Drivers/BSP/NETCFG/net_cfg.h" [color="#2563eb", penwidth=1.0]; @@ -249,9 +356,20 @@ digraph refgraph_full { "App/task/default_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7]; "App/task/default_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7]; "App/task/default_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "App/protocol/iec104/iec104_link.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "App/protocol/iec104/iec104_pts.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "App/task/iec104_serv.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; + "App/task/iec104_serv.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h" [color="#94a3b8", penwidth=0.7]; + "App/task/iec104_serv.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "App/task/net_task.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0]; "App/task/net_task.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0]; "App/task/net_task.c" -> "App/task/net_task.h" [color="#2563eb", penwidth=1.0]; + "App/task/net_task.c" -> "App/util/task_prof.h" [color="#2563eb", penwidth=1.0]; "App/task/net_task.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; "App/task/net_task.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0]; "App/task/net_task.c" -> "Drivers/BSP/NET/net_select.h" [color="#2563eb", penwidth=1.0]; @@ -261,6 +379,13 @@ digraph refgraph_full { "App/task/net_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7]; "App/task/net_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0]; "App/task/net_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/task/protect_task.c" -> "App/algo/adc_health.h" [color="#2563eb", penwidth=1.0]; + "App/task/protect_task.c" -> "App/algo/prot_elm.h" [color="#2563eb", penwidth=1.0]; + "App/task/protect_task.c" -> "App/algo/prot_set.h" [color="#2563eb", penwidth=1.0]; + "App/task/protect_task.c" -> "App/task/protect_task.h" [color="#2563eb", penwidth=1.0]; + "App/task/protect_task.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; + "App/task/protect_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; + "App/task/protect_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h" [color="#94a3b8", penwidth=0.7]; "App/task/rs485_task.c" -> "App/task/rs485_task.h" [color="#2563eb", penwidth=1.0]; "App/task/rs485_task.c" -> "Drivers/BSP/RS485/rs485.h" [color="#2563eb", penwidth=1.0]; "App/task/rs485_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; @@ -268,6 +393,7 @@ digraph refgraph_full { "App/task/ui_task.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0]; "App/task/ui_task.c" -> "App/task/ui_task.h" [color="#2563eb", penwidth=1.0]; "App/task/ui_task.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0]; + "App/task/ui_task.c" -> "App/util/task_prof.h" [color="#2563eb", penwidth=1.0]; "App/task/ui_task.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; "App/task/ui_task.c" -> "Drivers/BSP/UI/ui_menu.h" [color="#2563eb", penwidth=1.0]; "App/task/ui_task.c" -> "Drivers/BSP/UI/ui_net_sink.h" [color="#2563eb", penwidth=1.0]; @@ -278,6 +404,9 @@ digraph refgraph_full { "App/task/ui_task.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0]; "App/task/ui_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0]; "App/task/ui_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/util/sha256.c" -> "App/util/sha256.h" [color="#2563eb", penwidth=1.0]; + "App/util/sha256.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/util/sha256.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "App/util/sys_clock.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0]; "App/util/sys_clock.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; "App/util/sys_clock.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0]; @@ -286,6 +415,11 @@ digraph refgraph_full { "App/util/sys_clock.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "App/util/sys_clock.h" -> "Drivers/BSP/SD2506/sd2506.h" [color="#2563eb", penwidth=1.0]; "App/util/sys_clock.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/util/task_prof.c" -> "App/log/console_log.h" [color="#2563eb", penwidth=1.0]; + "App/util/task_prof.c" -> "App/util/task_prof.h" [color="#2563eb", penwidth=1.0]; + "App/util/task_prof.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0]; + "App/util/task_prof.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "App/util/task_prof.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "App/util/task_watchdog.c" -> "App/log/console_log.h" [color="#2563eb", penwidth=1.0]; "App/util/task_watchdog.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0]; "App/util/task_watchdog.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; @@ -341,7 +475,12 @@ digraph refgraph_full { "Drivers/BSP/NET/net_socket.h" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7]; "Drivers/BSP/NET/net_types.h" -> "Drivers/BSP/NET/net_config.h" [color="#2563eb", penwidth=1.0]; "Drivers/BSP/NET/net_types.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "Drivers/BSP/NETCFG/ftp_cfg.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0]; + "Drivers/BSP/NETCFG/ftp_cfg.c" -> "Drivers/BSP/NETCFG/ftp_cfg.h" [color="#2563eb", penwidth=1.0]; + "Drivers/BSP/NETCFG/ftp_cfg.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "Drivers/BSP/NETCFG/ftp_cfg.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "Drivers/BSP/NETCFG/net_cfg.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0]; + "Drivers/BSP/NETCFG/net_cfg.c" -> "Drivers/BSP/NETCFG/ftp_cfg.h" [color="#2563eb", penwidth=1.0]; "Drivers/BSP/NETCFG/net_cfg.c" -> "Drivers/BSP/NETCFG/net_cfg.h" [color="#2563eb", penwidth=1.0]; "Drivers/BSP/NETCFG/net_cfg.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; "Drivers/BSP/NETCFG/net_cfg.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; @@ -474,13 +613,17 @@ digraph refgraph_full { "Inc/stm32f4xx_hal_conf.h" -> "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h" [color="#94a3b8", penwidth=0.7]; "Inc/stm32f4xx_hal_conf.h" -> "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h" [color="#94a3b8", penwidth=0.7]; "Inc/stm32f4xx_hal_conf.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "Inc/tim.h" -> "Inc/main.h" [color="#2563eb", penwidth=1.0]; "Inc/usart.h" -> "Inc/main.h" [color="#2563eb", penwidth=1.0]; "Src/adc.c" -> "Inc/adc.h" [color="#2563eb", penwidth=1.0]; "Src/dma.c" -> "Inc/dma.h" [color="#2563eb", penwidth=1.0]; "Src/freertos.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0]; "Src/freertos.c" -> "App/sync/time_sync.h" [color="#2563eb", penwidth=1.0]; + "Src/freertos.c" -> "App/task/adc_task.h" [color="#2563eb", penwidth=1.0]; "Src/freertos.c" -> "App/task/default_task.h" [color="#2563eb", penwidth=1.0]; + "Src/freertos.c" -> "App/task/iec104_serv.h" [color="#2563eb", penwidth=1.0]; "Src/freertos.c" -> "App/task/net_task.h" [color="#2563eb", penwidth=1.0]; + "Src/freertos.c" -> "App/task/protect_task.h" [color="#2563eb", penwidth=1.0]; "Src/freertos.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; "Src/freertos.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0]; "Src/freertos.c" -> "Drivers/BSP/NET/lftpd/lftpd.h" [color="#94a3b8", penwidth=0.7]; @@ -498,6 +641,7 @@ digraph refgraph_full { "Src/i2c.c" -> "Inc/i2c.h" [color="#2563eb", penwidth=1.0]; "Src/iwdg.c" -> "Inc/iwdg.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "App/app/app_main.h" [color="#2563eb", penwidth=1.0]; + "Src/main.c" -> "App/task/adc_task.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0]; @@ -515,6 +659,7 @@ digraph refgraph_full { "Src/main.c" -> "Inc/iwdg.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "Inc/spi.h" [color="#2563eb", penwidth=1.0]; + "Src/main.c" -> "Inc/tim.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0]; "Src/main.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7]; "Src/main.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; @@ -526,6 +671,7 @@ digraph refgraph_full { "Src/stm32f4xx_it.c" -> "Inc/stm32f4xx_it.h" [color="#2563eb", penwidth=1.0]; "Src/stm32f4xx_it.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0]; "Src/system_stm32f4xx.c" -> "Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h" [color="#94a3b8", penwidth=0.7]; + "Src/tim.c" -> "Inc/tim.h" [color="#2563eb", penwidth=1.0]; "Src/usart.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0]; "simulator/dbg_log.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "simulator/main.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0]; @@ -554,6 +700,10 @@ digraph refgraph_full { "simulator/sim/ui_net_sink_backend_sim.c" -> "Drivers/BSP/UI/ui_port.h" [color="#2563eb", penwidth=1.0]; "simulator/sim/ui_net_sink_backend_sim.c" -> "Lib/lvgl/lvgl.h" [color="#94a3b8", penwidth=0.7]; "simulator/sim/ui_net_sink_backend_sim.c" -> "simulator/sim/sim_port.h" [color="#2563eb", penwidth=1.0]; + "test/board/ch395f_reuse_bench.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0]; + "test/board/ch395f_reuse_bench.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; + "test/board/ch395f_reuse_bench.c" -> "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h" [color="#94a3b8", penwidth=0.7]; + "test/board/ch395f_reuse_bench.c" -> "test/board/ch395f_reuse_bench.h" [color="#2563eb", penwidth=1.0]; "test/board/ch395f_test.h" -> "test/board/test_common.h" [color="#2563eb", penwidth=1.0]; "test/board/ch395f_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/board/ch395f_test_task.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0]; @@ -632,12 +782,44 @@ digraph refgraph_full { "test/board/test_config.h" -> "test/board/sd2506_test.h" [color="#2563eb", penwidth=1.0]; "test/board/test_config.h" -> "test/board/storage_test.h" [color="#2563eb", penwidth=1.0]; "test/board/test_config.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/adc_health/adc_health_test.c" -> "App/algo/adc_health.c" [color="#2563eb", penwidth=1.0]; + "test/host/adc_health/adc_health_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/adc_input/adc_input_test.c" -> "App/algo/adc_input.c" [color="#2563eb", penwidth=1.0]; + "test/host/adc_input/adc_input_test.c" -> "App/algo/adc_input.h" [color="#2563eb", penwidth=1.0]; + "test/host/adc_input/adc_input_test.c" -> "Drivers/BSP/TPAFE5160/tpafe5160.h" [color="#2563eb", penwidth=1.0]; + "test/host/adc_input/adc_input_test.c" -> "Inc/adc.h" [color="#2563eb", penwidth=1.0]; + "test/host/adc_input/adc_input_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/adc_input/stub/adc.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/adc_input/stub/tpafe5160.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/cfg_file/cfg_file_test.c" -> "App/cfg/cfg_file.c" [color="#2563eb", penwidth=1.0]; "test/host/cfg_file/cfg_file_test.c" -> "App/cfg/cfg_file_store.h" [color="#2563eb", penwidth=1.0]; "test/host/cfg_file/cfg_file_test.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0]; "test/host/cfg_file/cfg_file_test.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0]; "test/host/cfg_file/cfg_file_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/cfg_file/stub/dbg_log.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/ftp_auth/ftp_auth_test.c" -> "App/util/sha256.c" [color="#2563eb", penwidth=1.0]; + "test/host/ftp_auth/ftp_auth_test.c" -> "Drivers/BSP/NET/lftpd/lftpd_auth.c" [color="#94a3b8", penwidth=0.7]; + "test/host/ftp_auth/ftp_auth_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/iec104/iec104_test.c" -> "App/algo/phasor.c" [color="#2563eb", penwidth=1.0]; + "test/host/iec104/iec104_test.c" -> "App/algo/prot_elm.c" [color="#2563eb", penwidth=1.0]; + "test/host/iec104/iec104_test.c" -> "App/algo/prot_set.c" [color="#2563eb", penwidth=1.0]; + "test/host/iec104/iec104_test.c" -> "App/algo/sample_ring.c" [color="#2563eb", penwidth=1.0]; + "test/host/iec104/iec104_test.c" -> "App/protocol/iec104/iec104_asdu.c" [color="#2563eb", penwidth=1.0]; + "test/host/iec104/iec104_test.c" -> "App/protocol/iec104/iec104_link.c" [color="#2563eb", penwidth=1.0]; + "test/host/iec104/iec104_test.c" -> "App/protocol/iec104/iec104_pts.c" [color="#2563eb", penwidth=1.0]; + "test/host/iec104/iec104_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/phasor/phasor_test.c" -> "App/algo/phasor.c" [color="#2563eb", penwidth=1.0]; + "test/host/phasor/phasor_test.c" -> "App/algo/sample_ring.c" [color="#2563eb", penwidth=1.0]; + "test/host/phasor/phasor_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/prot_elm/prot_elm_test.c" -> "App/algo/phasor.c" [color="#2563eb", penwidth=1.0]; + "test/host/prot_elm/prot_elm_test.c" -> "App/algo/prot_elm.c" [color="#2563eb", penwidth=1.0]; + "test/host/prot_elm/prot_elm_test.c" -> "App/algo/prot_set.c" [color="#2563eb", penwidth=1.0]; + "test/host/prot_elm/prot_elm_test.c" -> "App/algo/sample_ring.c" [color="#2563eb", penwidth=1.0]; + "test/host/prot_elm/prot_elm_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/prot_set/prot_set_test.c" -> "App/algo/prot_set.c" [color="#2563eb", penwidth=1.0]; + "test/host/prot_set/prot_set_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/sha256/sha256_test.c" -> "App/util/sha256.c" [color="#2563eb", penwidth=1.0]; + "test/host/sha256/sha256_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/sys_clock/stub/FreeRTOS.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/sys_clock/stub/dbg_log.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/sys_clock/stub/main.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; @@ -650,6 +832,27 @@ digraph refgraph_full { "test/host/sys_clock/sys_clock_test.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7]; "test/host/sys_clock/sys_clock_test.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7]; "test/host/sys_clock/sys_clock_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/time_sync/stub/FreeRTOS.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/time_sync/stub/cmsis_os2.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/time_sync/stub/dbg_log.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/time_sync/stub/net_socket.h" -> "test/host/time_sync/stub/FreeRTOS.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/stub/net_socket.h" -> "test/host/time_sync/stub/task.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/stub/net_socket.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/time_sync/stub/sys_clock.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/time_sync/stub/sys_events.h" -> "test/host/time_sync/stub/cmsis_os2.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/stub/task.h" -> "test/host/time_sync/stub/FreeRTOS.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/time_sync_test.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/time_sync_test.c" -> "App/sync/time_sync.c" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/time_sync_test.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/time_sync_test.c" -> "App/util/task_watchdog.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/time_sync_test.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0]; + "test/host/time_sync/time_sync_test.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7]; + "test/host/time_sync/time_sync_test.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7]; + "test/host/time_sync/time_sync_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/vol_lock/stub/cmsis_os.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; + "test/host/vol_lock/vol_lock_test.c" -> "App/fs/vol_lock.c" [color="#2563eb", penwidth=1.0]; + "test/host/vol_lock/vol_lock_test.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7]; + "test/host/vol_lock/vol_lock_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/watchdog/stub/dbg_log.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/watchdog/stub/iwdg.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; "test/host/watchdog/stub/main.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed]; diff --git a/docs/images/引用关系图.json b/docs/images/引用关系图.json index 9e36ca10..e5d8a2cf 100644 --- a/docs/images/引用关系图.json +++ b/docs/images/引用关系图.json @@ -1,6 +1,54 @@ { "title": "STM32F4-Base 项目文件引用关系图(项目代码视图)", "nodes": [ + { + "path": "App/algo/adc_health.c", + "class": "fp" + }, + { + "path": "App/algo/adc_health.h", + "class": "fp" + }, + { + "path": "App/algo/adc_input.c", + "class": "fp" + }, + { + "path": "App/algo/adc_input.h", + "class": "fp" + }, + { + "path": "App/algo/phasor.c", + "class": "fp" + }, + { + "path": "App/algo/phasor.h", + "class": "fp" + }, + { + "path": "App/algo/prot_elm.c", + "class": "fp" + }, + { + "path": "App/algo/prot_elm.h", + "class": "fp" + }, + { + "path": "App/algo/prot_set.c", + "class": "fp" + }, + { + "path": "App/algo/prot_set.h", + "class": "fp" + }, + { + "path": "App/algo/sample_ring.c", + "class": "fp" + }, + { + "path": "App/algo/sample_ring.h", + "class": "fp" + }, { "path": "App/app/app_cfg.h", "class": "fp" @@ -57,6 +105,30 @@ "path": "App/log/sys_log_mcu.c", "class": "fp" }, + { + "path": "App/protocol/iec104/iec104_asdu.c", + "class": "fp" + }, + { + "path": "App/protocol/iec104/iec104_asdu.h", + "class": "fp" + }, + { + "path": "App/protocol/iec104/iec104_link.c", + "class": "fp" + }, + { + "path": "App/protocol/iec104/iec104_link.h", + "class": "fp" + }, + { + "path": "App/protocol/iec104/iec104_pts.c", + "class": "fp" + }, + { + "path": "App/protocol/iec104/iec104_pts.h", + "class": "fp" + }, { "path": "App/sync/time_sync.c", "class": "fp" @@ -81,6 +153,14 @@ "path": "App/task/default_task.h", "class": "fp" }, + { + "path": "App/task/iec104_serv.c", + "class": "fp" + }, + { + "path": "App/task/iec104_serv.h", + "class": "fp" + }, { "path": "App/task/net_task.c", "class": "fp" @@ -89,6 +169,14 @@ "path": "App/task/net_task.h", "class": "fp" }, + { + "path": "App/task/protect_task.c", + "class": "fp" + }, + { + "path": "App/task/protect_task.h", + "class": "fp" + }, { "path": "App/task/rs485_task.c", "class": "fp" @@ -105,6 +193,14 @@ "path": "App/task/ui_task.h", "class": "fp" }, + { + "path": "App/util/sha256.c", + "class": "fp" + }, + { + "path": "App/util/sha256.h", + "class": "fp" + }, { "path": "App/util/sys_clock.c", "class": "fp" @@ -113,6 +209,14 @@ "path": "App/util/sys_clock.h", "class": "fp" }, + { + "path": "App/util/task_prof.c", + "class": "fp" + }, + { + "path": "App/util/task_prof.h", + "class": "fp" + }, { "path": "App/util/task_watchdog.c", "class": "fp" @@ -153,6 +257,14 @@ "path": "Drivers/BSP/NET/lftpd/lftpd.h", "class": "tp" }, + { + "path": "Drivers/BSP/NET/lftpd/lftpd_auth.c", + "class": "tp" + }, + { + "path": "Drivers/BSP/NET/lftpd/lftpd_auth.h", + "class": "tp" + }, { "path": "Drivers/BSP/NET/lftpd/lftpd_inet.c", "class": "tp" @@ -161,10 +273,6 @@ "path": "Drivers/BSP/NET/lftpd/lftpd_io.c", "class": "tp" }, - { - "path": "Drivers/BSP/NET/lftpd/lftpd_log.c", - "class": "tp" - }, { "path": "Drivers/BSP/NET/lftpd/lftpd_string.c", "class": "tp" @@ -213,6 +321,14 @@ "path": "Drivers/BSP/NET/net_types.h", "class": "fp" }, + { + "path": "Drivers/BSP/NETCFG/ftp_cfg.c", + "class": "fp" + }, + { + "path": "Drivers/BSP/NETCFG/ftp_cfg.h", + "class": "fp" + }, { "path": "Drivers/BSP/NETCFG/net_cfg.c", "class": "fp" @@ -669,6 +785,10 @@ "path": "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h", "class": "tp" }, + { + "path": "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h", + "class": "tp" + }, { "path": "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h", "class": "tp" @@ -805,6 +925,10 @@ "path": "Inc/stm32f4xx_it.h", "class": "fp" }, + { + "path": "Inc/tim.h", + "class": "fp" + }, { "path": "Inc/usart.h", "class": "fp" @@ -4789,6 +4913,10 @@ "path": "Src/system_stm32f4xx.c", "class": "fp" }, + { + "path": "Src/tim.c", + "class": "fp" + }, { "path": "Src/usart.c", "class": "fp" @@ -5537,6 +5665,14 @@ "path": "simulator/sim/ui_net_sink_backend_sim.c", "class": "fp" }, + { + "path": "test/board/ch395f_reuse_bench.c", + "class": "fp" + }, + { + "path": "test/board/ch395f_reuse_bench.h", + "class": "fp" + }, { "path": "test/board/ch395f_test.h", "class": "fp" @@ -5601,6 +5737,22 @@ "path": "test/board/test_config.h", "class": "fp" }, + { + "path": "test/host/adc_health/adc_health_test.c", + "class": "fp" + }, + { + "path": "test/host/adc_input/adc_input_test.c", + "class": "fp" + }, + { + "path": "test/host/adc_input/stub/adc.h", + "class": "fp" + }, + { + "path": "test/host/adc_input/stub/tpafe5160.h", + "class": "fp" + }, { "path": "test/host/cfg_file/cfg_file_test.c", "class": "fp" @@ -5609,6 +5761,30 @@ "path": "test/host/cfg_file/stub/dbg_log.h", "class": "fp" }, + { + "path": "test/host/ftp_auth/ftp_auth_test.c", + "class": "fp" + }, + { + "path": "test/host/iec104/iec104_test.c", + "class": "fp" + }, + { + "path": "test/host/phasor/phasor_test.c", + "class": "fp" + }, + { + "path": "test/host/prot_elm/prot_elm_test.c", + "class": "fp" + }, + { + "path": "test/host/prot_set/prot_set_test.c", + "class": "fp" + }, + { + "path": "test/host/sha256/sha256_test.c", + "class": "fp" + }, { "path": "test/host/sys_clock/stub/FreeRTOS.h", "class": "fp" @@ -5629,6 +5805,46 @@ "path": "test/host/sys_clock/sys_clock_test.c", "class": "fp" }, + { + "path": "test/host/time_sync/stub/FreeRTOS.h", + "class": "fp" + }, + { + "path": "test/host/time_sync/stub/cmsis_os2.h", + "class": "fp" + }, + { + "path": "test/host/time_sync/stub/dbg_log.h", + "class": "fp" + }, + { + "path": "test/host/time_sync/stub/net_socket.h", + "class": "fp" + }, + { + "path": "test/host/time_sync/stub/sys_clock.h", + "class": "fp" + }, + { + "path": "test/host/time_sync/stub/sys_events.h", + "class": "fp" + }, + { + "path": "test/host/time_sync/stub/task.h", + "class": "fp" + }, + { + "path": "test/host/time_sync/time_sync_test.c", + "class": "fp" + }, + { + "path": "test/host/vol_lock/stub/cmsis_os.h", + "class": "fp" + }, + { + "path": "test/host/vol_lock/vol_lock_test.c", + "class": "fp" + }, { "path": "test/host/watchdog/stub/dbg_log.h", "class": "fp" @@ -5651,6 +5867,150 @@ } ], "edges": [ + { + "from": "App/algo/adc_health.c", + "to": "App/algo/adc_health.h", + "kind": "fp-fp", + "include": "adc_health.h" + }, + { + "from": "App/algo/adc_health.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/algo/adc_input.c", + "to": "App/algo/adc_input.h", + "kind": "fp-fp", + "include": "adc_input.h" + }, + { + "from": "App/algo/adc_input.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "App/algo/adc_input.c", + "to": "Inc/adc.h", + "kind": "fp-fp", + "include": "adc.h" + }, + { + "from": "App/algo/adc_input.c", + "to": "Drivers/BSP/TPAFE5160/tpafe5160.h", + "kind": "fp-fp", + "include": "tpafe5160.h" + }, + { + "from": "App/algo/adc_input.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/algo/phasor.c", + "to": "App/algo/phasor.h", + "kind": "fp-fp", + "include": "phasor.h" + }, + { + "from": "App/algo/phasor.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "math.h" + }, + { + "from": "App/algo/phasor.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "App/algo/phasor.c", + "to": "App/algo/sample_ring.h", + "kind": "fp-fp", + "include": "sample_ring.h" + }, + { + "from": "App/algo/phasor.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/algo/phasor.h", + "to": "App/algo/adc_input.h", + "kind": "fp-fp", + "include": "adc_input.h" + }, + { + "from": "App/algo/prot_elm.c", + "to": "App/algo/prot_elm.h", + "kind": "fp-fp", + "include": "prot_elm.h" + }, + { + "from": "App/algo/prot_elm.c", + "to": "App/algo/prot_set.h", + "kind": "fp-fp", + "include": "prot_set.h" + }, + { + "from": "App/algo/prot_elm.c", + "to": "App/algo/phasor.h", + "kind": "fp-fp", + "include": "phasor.h" + }, + { + "from": "App/algo/prot_elm.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "App/algo/prot_elm.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/algo/prot_set.c", + "to": "App/algo/prot_set.h", + "kind": "fp-fp", + "include": "prot_set.h" + }, + { + "from": "App/algo/prot_set.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/algo/sample_ring.c", + "to": "App/algo/sample_ring.h", + "kind": "fp-fp", + "include": "sample_ring.h" + }, + { + "from": "App/algo/sample_ring.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "App/algo/sample_ring.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/algo/sample_ring.h", + "to": "App/algo/adc_input.h", + "kind": "fp-fp", + "include": "adc_input.h" + }, { "from": "App/app/app_main.c", "to": "App/app/app_main.h", @@ -5681,6 +6041,12 @@ "kind": "fp-fp", "include": "usart.h" }, + { + "from": "App/app/app_main.c", + "to": "Inc/tim.h", + "kind": "fp-fp", + "include": "tim.h" + }, { "from": "App/app/app_main.c", "to": "Drivers/BSP/RS485/rs485.h", @@ -5711,6 +6077,30 @@ "kind": "fp-fp", "include": "tpafe5160.h" }, + { + "from": "App/app/app_main.c", + "to": "App/algo/adc_input.h", + "kind": "fp-fp", + "include": "adc_input.h" + }, + { + "from": "App/app/app_main.c", + "to": "App/algo/phasor.h", + "kind": "fp-fp", + "include": "phasor.h" + }, + { + "from": "App/app/app_main.c", + "to": "App/algo/prot_set.h", + "kind": "fp-fp", + "include": "prot_set.h" + }, + { + "from": "App/app/app_main.c", + "to": "App/algo/prot_elm.h", + "kind": "fp-fp", + "include": "prot_elm.h" + }, { "from": "App/app/app_main.c", "to": "App/log/sys_log.h", @@ -5723,6 +6113,12 @@ "kind": "fp-fp", "include": "task_watchdog.h" }, + { + "from": "App/app/app_main.c", + "to": "test/board/test_config.h", + "kind": "fp-fp", + "include": "test_config.h" + }, { "from": "App/app/app_main.c", "to": "Drivers/BSP/dbg_log.h", @@ -5975,6 +6371,102 @@ "kind": "fp-fp", "include": "vol_lock.h" }, + { + "from": "App/protocol/iec104/iec104_asdu.c", + "to": "App/protocol/iec104/iec104_asdu.h", + "kind": "fp-fp", + "include": "iec104_asdu.h" + }, + { + "from": "App/protocol/iec104/iec104_asdu.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "App/protocol/iec104/iec104_asdu.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/protocol/iec104/iec104_link.c", + "to": "App/protocol/iec104/iec104_link.h", + "kind": "fp-fp", + "include": "iec104_link.h" + }, + { + "from": "App/protocol/iec104/iec104_link.c", + "to": "App/protocol/iec104/iec104_asdu.h", + "kind": "fp-fp", + "include": "iec104_asdu.h" + }, + { + "from": "App/protocol/iec104/iec104_link.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "App/protocol/iec104/iec104_link.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "App/protocol/iec104/iec104_link.h", + "to": "App/protocol/iec104/iec104_pts.h", + "kind": "fp-fp", + "include": "iec104_pts.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.c", + "to": "App/protocol/iec104/iec104_pts.h", + "kind": "fp-fp", + "include": "iec104_pts.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.c", + "to": "App/protocol/iec104/iec104_asdu.h", + "kind": "fp-fp", + "include": "iec104_asdu.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.c", + "to": "App/algo/phasor.h", + "kind": "fp-fp", + "include": "phasor.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.c", + "to": "App/algo/prot_elm.h", + "kind": "fp-fp", + "include": "prot_elm.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.c", + "to": "App/algo/prot_set.h", + "kind": "fp-fp", + "include": "prot_set.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.c", + "to": "App/algo/adc_input.h", + "kind": "fp-fp", + "include": "adc_input.h" + }, + { + "from": "App/protocol/iec104/iec104_pts.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, { "from": "App/sync/time_sync.c", "to": "外部/系统头文件", @@ -6035,12 +6527,60 @@ "kind": "fp-tp", "include": "cmsis_os.h" }, + { + "from": "App/task/adc_task.c", + "to": "App/algo/adc_input.h", + "kind": "fp-fp", + "include": "adc_input.h" + }, + { + "from": "App/task/adc_task.c", + "to": "App/algo/sample_ring.h", + "kind": "fp-fp", + "include": "sample_ring.h" + }, + { + "from": "App/task/adc_task.c", + "to": "App/algo/phasor.h", + "kind": "fp-fp", + "include": "phasor.h" + }, + { + "from": "App/task/adc_task.c", + "to": "App/algo/adc_health.h", + "kind": "fp-fp", + "include": "adc_health.h" + }, { "from": "App/task/adc_task.c", "to": "Drivers/BSP/TPAFE5160/tpafe5160.h", "kind": "fp-fp", "include": "tpafe5160.h" }, + { + "from": "App/task/adc_task.c", + "to": "App/util/task_watchdog.h", + "kind": "fp-fp", + "include": "task_watchdog.h" + }, + { + "from": "App/task/adc_task.c", + "to": "App/log/console_log.h", + "kind": "fp-fp", + "include": "console_log.h" + }, + { + "from": "App/task/adc_task.c", + "to": "App/log/sys_log.h", + "kind": "fp-fp", + "include": "sys_log.h" + }, + { + "from": "App/task/adc_task.c", + "to": "App/util/task_prof.h", + "kind": "fp-fp", + "include": "task_prof.h" + }, { "from": "App/task/adc_task.c", "to": "Drivers/BSP/dbg_log.h", @@ -6131,12 +6671,78 @@ "kind": "fp-fp", "include": "task_watchdog.h" }, + { + "from": "App/task/default_task.c", + "to": "App/util/task_prof.h", + "kind": "fp-fp", + "include": "task_prof.h" + }, { "from": "App/task/default_task.c", "to": "App/fs/vol_lock.h", "kind": "fp-fp", "include": "vol_lock.h" }, + { + "from": "App/task/iec104_serv.c", + "to": "App/task/iec104_serv.h", + "kind": "fp-fp", + "include": "iec104_serv.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "App/protocol/iec104/iec104_link.h", + "kind": "fp-fp", + "include": "iec104_link.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "App/protocol/iec104/iec104_pts.h", + "kind": "fp-fp", + "include": "iec104_pts.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "Drivers/BSP/NET/net_socket.h", + "kind": "fp-fp", + "include": "net_socket.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "App/util/sys_clock.h", + "kind": "fp-fp", + "include": "sys_clock.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "App/app/sys_events.h", + "kind": "fp-fp", + "include": "sys_events.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "App/util/task_watchdog.h", + "kind": "fp-fp", + "include": "task_watchdog.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "Drivers/BSP/dbg_log.h", + "kind": "fp-fp", + "include": "dbg_log.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h", + "kind": "fp-tp", + "include": "cmsis_os2.h" + }, + { + "from": "App/task/iec104_serv.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, { "from": "App/task/net_task.c", "to": "外部/系统头文件", @@ -6203,12 +6809,60 @@ "kind": "fp-fp", "include": "task_watchdog.h" }, + { + "from": "App/task/net_task.c", + "to": "App/util/task_prof.h", + "kind": "fp-fp", + "include": "task_prof.h" + }, { "from": "App/task/net_task.c", "to": "Drivers/BSP/dbg_log.h", "kind": "fp-fp", "include": "dbg_log.h" }, + { + "from": "App/task/protect_task.c", + "to": "App/task/protect_task.h", + "kind": "fp-fp", + "include": "protect_task.h" + }, + { + "from": "App/task/protect_task.c", + "to": "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h", + "kind": "fp-tp", + "include": "cmsis_os2.h" + }, + { + "from": "App/task/protect_task.c", + "to": "Drivers/BSP/dbg_log.h", + "kind": "fp-fp", + "include": "dbg_log.h" + }, + { + "from": "App/task/protect_task.c", + "to": "App/algo/adc_health.h", + "kind": "fp-fp", + "include": "adc_health.h" + }, + { + "from": "App/task/protect_task.c", + "to": "App/algo/prot_elm.h", + "kind": "fp-fp", + "include": "prot_elm.h" + }, + { + "from": "App/task/protect_task.c", + "to": "App/algo/prot_set.h", + "kind": "fp-fp", + "include": "prot_set.h" + }, + { + "from": "App/task/protect_task.c", + "to": "App/util/task_watchdog.h", + "kind": "fp-fp", + "include": "task_watchdog.h" + }, { "from": "App/task/rs485_task.c", "to": "App/task/rs485_task.h", @@ -6305,12 +6959,42 @@ "kind": "fp-fp", "include": "task_watchdog.h" }, + { + "from": "App/task/ui_task.c", + "to": "App/util/task_prof.h", + "kind": "fp-fp", + "include": "task_prof.h" + }, { "from": "App/task/ui_task.c", "to": "Drivers/BSP/dbg_log.h", "kind": "fp-fp", "include": "dbg_log.h" }, + { + "from": "App/util/sha256.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "App/util/sha256.c", + "to": "App/util/sha256.h", + "kind": "fp-fp", + "include": "sha256.h" + }, + { + "from": "App/util/sha256.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "App/util/sha256.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, { "from": "App/util/sys_clock.c", "to": "App/util/sys_clock.h", @@ -6365,6 +7049,36 @@ "kind": "fp-fp", "include": "sd2506.h" }, + { + "from": "App/util/task_prof.c", + "to": "App/util/task_prof.h", + "kind": "fp-fp", + "include": "task_prof.h" + }, + { + "from": "App/util/task_prof.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "App/util/task_prof.c", + "to": "Inc/main.h", + "kind": "fp-fp", + "include": "main.h" + }, + { + "from": "App/util/task_prof.c", + "to": "App/log/console_log.h", + "kind": "fp-fp", + "include": "console_log.h" + }, + { + "from": "App/util/task_prof.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, { "from": "App/util/task_watchdog.c", "to": "App/util/task_watchdog.h", @@ -6851,6 +7565,18 @@ "kind": "tp-tp", "include": "net_config.h" }, + { + "from": "Drivers/BSP/NET/lftpd/lftpd.c", + "to": "Drivers/BSP/NET/lftpd/lftpd_auth.h", + "kind": "tp-tp", + "include": "lftpd_auth.h" + }, + { + "from": "Drivers/BSP/NET/lftpd/lftpd.c", + "to": "Drivers/BSP/NETCFG/ftp_cfg.h", + "kind": "tp-tp", + "include": "ftp_cfg.h" + }, { "from": "Drivers/BSP/NET/lftpd/lftpd.c", "to": "Lib/FatFs/ff.h", @@ -6863,6 +7589,36 @@ "kind": "tp-ext", "include": "stdint.h" }, + { + "from": "Drivers/BSP/NET/lftpd/lftpd_auth.c", + "to": "外部/系统头文件", + "kind": "tp-ext", + "include": "stddef.h" + }, + { + "from": "Drivers/BSP/NET/lftpd/lftpd_auth.c", + "to": "外部/系统头文件", + "kind": "tp-ext", + "include": "string.h" + }, + { + "from": "Drivers/BSP/NET/lftpd/lftpd_auth.c", + "to": "Drivers/BSP/NET/lftpd/lftpd_auth.h", + "kind": "tp-tp", + "include": "lftpd_auth.h" + }, + { + "from": "Drivers/BSP/NET/lftpd/lftpd_auth.c", + "to": "App/util/sha256.h", + "kind": "tp-tp", + "include": "sha256.h" + }, + { + "from": "Drivers/BSP/NET/lftpd/lftpd_auth.h", + "to": "外部/系统头文件", + "kind": "tp-ext", + "include": "stdint.h" + }, { "from": "Drivers/BSP/NET/lftpd/lftpd_inet.c", "to": "Drivers/BSP/NET/lftpd/private/lftpd_inet.h", @@ -6947,36 +7703,6 @@ "kind": "tp-tp", "include": "dbg_log.h" }, - { - "from": "Drivers/BSP/NET/lftpd/lftpd_log.c", - "to": "Drivers/BSP/NET/lftpd/private/lftpd_log.h", - "kind": "tp-tp", - "include": "private/lftpd_log.h" - }, - { - "from": "Drivers/BSP/NET/lftpd/lftpd_log.c", - "to": "外部/系统头文件", - "kind": "tp-ext", - "include": "stdio.h" - }, - { - "from": "Drivers/BSP/NET/lftpd/lftpd_log.c", - "to": "外部/系统头文件", - "kind": "tp-ext", - "include": "stdlib.h" - }, - { - "from": "Drivers/BSP/NET/lftpd/lftpd_log.c", - "to": "外部/系统头文件", - "kind": "tp-ext", - "include": "stdarg.h" - }, - { - "from": "Drivers/BSP/NET/lftpd/lftpd_log.c", - "to": "Drivers/BSP/dbg_log.h", - "kind": "tp-tp", - "include": "dbg_log.h" - }, { "from": "Drivers/BSP/NET/lftpd/lftpd_string.c", "to": "外部/系统头文件", @@ -7019,6 +7745,36 @@ "kind": "tp-tp", "include": "dbg_log.h" }, + { + "from": "Drivers/BSP/NETCFG/ftp_cfg.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "Drivers/BSP/NETCFG/ftp_cfg.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "Drivers/BSP/NETCFG/ftp_cfg.c", + "to": "Drivers/BSP/NETCFG/ftp_cfg.h", + "kind": "fp-fp", + "include": "ftp_cfg.h" + }, + { + "from": "Drivers/BSP/NETCFG/ftp_cfg.c", + "to": "App/cfg/cfg_file.h", + "kind": "fp-fp", + "include": "cfg_file.h" + }, + { + "from": "Drivers/BSP/NETCFG/ftp_cfg.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, { "from": "Drivers/BSP/NETCFG/net_cfg.c", "to": "外部/系统头文件", @@ -7049,6 +7805,12 @@ "kind": "fp-fp", "include": "cfg_file.h" }, + { + "from": "Drivers/BSP/NETCFG/net_cfg.c", + "to": "Drivers/BSP/NETCFG/ftp_cfg.h", + "kind": "fp-fp", + "include": "ftp_cfg.h" + }, { "from": "Drivers/BSP/NETCFG/net_cfg.c", "to": "Drivers/BSP/dbg_log.h", @@ -8675,6 +9437,12 @@ "kind": "tp-tp", "include": "stm32f4xx.h" }, + { + "from": "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h", + "to": "Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h", + "kind": "tp-tp", + "include": "stm32f4xx.h" + }, { "from": "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h", "to": "Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h", @@ -9167,6 +9935,12 @@ "kind": "fp-ext", "include": "stm32f4xx_hal_mmc.h" }, + { + "from": "Inc/tim.h", + "to": "Inc/main.h", + "kind": "fp-fp", + "include": "main.h" + }, { "from": "Inc/usart.h", "to": "Inc/main.h", @@ -39011,6 +39785,24 @@ "kind": "fp-fp", "include": "default_task.h" }, + { + "from": "Src/freertos.c", + "to": "App/task/adc_task.h", + "kind": "fp-fp", + "include": "adc_task.h" + }, + { + "from": "Src/freertos.c", + "to": "App/task/iec104_serv.h", + "kind": "fp-fp", + "include": "iec104_serv.h" + }, + { + "from": "Src/freertos.c", + "to": "App/task/protect_task.h", + "kind": "fp-fp", + "include": "protect_task.h" + }, { "from": "Src/gpio.c", "to": "Inc/gpio.h", @@ -39071,6 +39863,12 @@ "kind": "fp-fp", "include": "spi.h" }, + { + "from": "Src/main.c", + "to": "Inc/tim.h", + "kind": "fp-fp", + "include": "tim.h" + }, { "from": "Src/main.c", "to": "Inc/usart.h", @@ -39155,6 +39953,12 @@ "kind": "fp-fp", "include": "task_watchdog.h" }, + { + "from": "Src/main.c", + "to": "App/task/adc_task.h", + "kind": "fp-fp", + "include": "adc_task.h" + }, { "from": "Src/main.c", "to": "Drivers/BSP/dbg_log.h", @@ -39209,12 +40013,42 @@ "kind": "fp-tp", "include": "stm32f4xx.h" }, + { + "from": "Src/tim.c", + "to": "Inc/tim.h", + "kind": "fp-fp", + "include": "tim.h" + }, { "from": "Src/usart.c", "to": "Inc/usart.h", "kind": "fp-fp", "include": "usart.h" }, + { + "from": "test/board/ch395f_reuse_bench.c", + "to": "test/board/ch395f_reuse_bench.h", + "kind": "fp-fp", + "include": "ch395f_reuse_bench.h" + }, + { + "from": "test/board/ch395f_reuse_bench.c", + "to": "Drivers/BSP/CH395F/ch395f.h", + "kind": "fp-fp", + "include": "ch395f.h" + }, + { + "from": "test/board/ch395f_reuse_bench.c", + "to": "Drivers/BSP/dbg_log.h", + "kind": "fp-fp", + "include": "dbg_log.h" + }, + { + "from": "test/board/ch395f_reuse_bench.c", + "to": "Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h", + "kind": "fp-tp", + "include": "stm32f4xx_hal.h" + }, { "from": "test/board/ch395f_test.h", "to": "外部/系统头文件", @@ -39695,6 +40529,78 @@ "kind": "fp-fp", "include": "sd2506_test.h" }, + { + "from": "test/host/adc_health/adc_health_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/adc_health/adc_health_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/adc_health/adc_health_test.c", + "to": "App/algo/adc_health.c", + "kind": "fp-fp", + "include": "adc_health.c" + }, + { + "from": "test/host/adc_input/adc_input_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "test/host/adc_input/adc_input_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/adc_input/adc_input_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/adc_input/adc_input_test.c", + "to": "Inc/adc.h", + "kind": "fp-fp", + "include": "adc.h" + }, + { + "from": "test/host/adc_input/adc_input_test.c", + "to": "Drivers/BSP/TPAFE5160/tpafe5160.h", + "kind": "fp-fp", + "include": "tpafe5160.h" + }, + { + "from": "test/host/adc_input/adc_input_test.c", + "to": "App/algo/adc_input.h", + "kind": "fp-fp", + "include": "adc_input.h" + }, + { + "from": "test/host/adc_input/adc_input_test.c", + "to": "App/algo/adc_input.c", + "kind": "fp-fp", + "include": "adc_input.c" + }, + { + "from": "test/host/adc_input/stub/adc.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/adc_input/stub/tpafe5160.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, { "from": "test/host/cfg_file/cfg_file_test.c", "to": "外部/系统头文件", @@ -39749,6 +40655,192 @@ "kind": "fp-ext", "include": "stdio.h" }, + { + "from": "test/host/ftp_auth/ftp_auth_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/ftp_auth/ftp_auth_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "test/host/ftp_auth/ftp_auth_test.c", + "to": "App/util/sha256.c", + "kind": "fp-fp", + "include": "sha256.c" + }, + { + "from": "test/host/ftp_auth/ftp_auth_test.c", + "to": "Drivers/BSP/NET/lftpd/lftpd_auth.c", + "kind": "fp-tp", + "include": "lftpd_auth.c" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "App/protocol/iec104/iec104_asdu.c", + "kind": "fp-fp", + "include": "iec104_asdu.c" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "App/algo/prot_set.c", + "kind": "fp-fp", + "include": "prot_set.c" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "App/algo/sample_ring.c", + "kind": "fp-fp", + "include": "sample_ring.c" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "App/algo/phasor.c", + "kind": "fp-fp", + "include": "phasor.c" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "App/algo/prot_elm.c", + "kind": "fp-fp", + "include": "prot_elm.c" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "App/protocol/iec104/iec104_pts.c", + "kind": "fp-fp", + "include": "iec104_pts.c" + }, + { + "from": "test/host/iec104/iec104_test.c", + "to": "App/protocol/iec104/iec104_link.c", + "kind": "fp-fp", + "include": "iec104_link.c" + }, + { + "from": "test/host/phasor/phasor_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "math.h" + }, + { + "from": "test/host/phasor/phasor_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/phasor/phasor_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/phasor/phasor_test.c", + "to": "App/algo/sample_ring.c", + "kind": "fp-fp", + "include": "sample_ring.c" + }, + { + "from": "test/host/phasor/phasor_test.c", + "to": "App/algo/phasor.c", + "kind": "fp-fp", + "include": "phasor.c" + }, + { + "from": "test/host/prot_elm/prot_elm_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/prot_elm/prot_elm_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/prot_elm/prot_elm_test.c", + "to": "App/algo/prot_set.c", + "kind": "fp-fp", + "include": "prot_set.c" + }, + { + "from": "test/host/prot_elm/prot_elm_test.c", + "to": "App/algo/sample_ring.c", + "kind": "fp-fp", + "include": "sample_ring.c" + }, + { + "from": "test/host/prot_elm/prot_elm_test.c", + "to": "App/algo/phasor.c", + "kind": "fp-fp", + "include": "phasor.c" + }, + { + "from": "test/host/prot_elm/prot_elm_test.c", + "to": "App/algo/prot_elm.c", + "kind": "fp-fp", + "include": "prot_elm.c" + }, + { + "from": "test/host/prot_set/prot_set_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/prot_set/prot_set_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/prot_set/prot_set_test.c", + "to": "App/algo/prot_set.c", + "kind": "fp-fp", + "include": "prot_set.c" + }, + { + "from": "test/host/sha256/sha256_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/sha256/sha256_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "test/host/sha256/sha256_test.c", + "to": "App/util/sha256.c", + "kind": "fp-fp", + "include": "sha256.c" + }, { "from": "test/host/sys_clock/sys_clock_test.c", "to": "外部/系统头文件", @@ -39833,6 +40925,162 @@ "kind": "fp-fp", "include": "FreeRTOS.h" }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "setjmp.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "string.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h", + "kind": "fp-tp", + "include": "FreeRTOS.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "Middlewares/Third_Party/FreeRTOS/Source/include/task.h", + "kind": "fp-tp", + "include": "task.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "Drivers/BSP/NET/net_socket.h", + "kind": "fp-fp", + "include": "net_socket.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "App/util/sys_clock.h", + "kind": "fp-fp", + "include": "sys_clock.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "App/app/sys_events.h", + "kind": "fp-fp", + "include": "sys_events.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "App/util/task_watchdog.h", + "kind": "fp-fp", + "include": "task_watchdog.h" + }, + { + "from": "test/host/time_sync/time_sync_test.c", + "to": "App/sync/time_sync.c", + "kind": "fp-fp", + "include": "time_sync.c" + }, + { + "from": "test/host/time_sync/stub/FreeRTOS.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/time_sync/stub/cmsis_os2.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/time_sync/stub/dbg_log.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/time_sync/stub/net_socket.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/time_sync/stub/net_socket.h", + "to": "test/host/time_sync/stub/FreeRTOS.h", + "kind": "fp-fp", + "include": "FreeRTOS.h" + }, + { + "from": "test/host/time_sync/stub/net_socket.h", + "to": "test/host/time_sync/stub/task.h", + "kind": "fp-fp", + "include": "task.h" + }, + { + "from": "test/host/time_sync/stub/sys_clock.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/time_sync/stub/sys_events.h", + "to": "test/host/time_sync/stub/cmsis_os2.h", + "kind": "fp-fp", + "include": "cmsis_os2.h" + }, + { + "from": "test/host/time_sync/stub/task.h", + "to": "test/host/time_sync/stub/FreeRTOS.h", + "kind": "fp-fp", + "include": "FreeRTOS.h" + }, + { + "from": "test/host/vol_lock/vol_lock_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stddef.h" + }, + { + "from": "test/host/vol_lock/vol_lock_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, + { + "from": "test/host/vol_lock/vol_lock_test.c", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdio.h" + }, + { + "from": "test/host/vol_lock/vol_lock_test.c", + "to": "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h", + "kind": "fp-tp", + "include": "cmsis_os.h" + }, + { + "from": "test/host/vol_lock/vol_lock_test.c", + "to": "App/fs/vol_lock.c", + "kind": "fp-fp", + "include": "vol_lock.c" + }, + { + "from": "test/host/vol_lock/stub/cmsis_os.h", + "to": "外部/系统头文件", + "kind": "fp-ext", + "include": "stdint.h" + }, { "from": "test/host/watchdog/watchdog_test.c", "to": "外部/系统头文件", @@ -39889,6 +41137,37 @@ } ], "unresolved": { + "App/algo/adc_health.h": [ + "stdint.h" + ], + "App/algo/adc_input.c": [ + "stddef.h" + ], + "App/algo/adc_input.h": [ + "stdint.h" + ], + "App/algo/phasor.c": [ + "math.h", + "stddef.h" + ], + "App/algo/phasor.h": [ + "stdint.h" + ], + "App/algo/prot_elm.c": [ + "stddef.h" + ], + "App/algo/prot_elm.h": [ + "stdint.h" + ], + "App/algo/prot_set.h": [ + "stdint.h" + ], + "App/algo/sample_ring.c": [ + "stddef.h" + ], + "App/algo/sample_ring.h": [ + "stdint.h" + ], "App/app/app_main.h": [ "stdint.h" ], @@ -39927,18 +41206,46 @@ "stdio.h", "string.h" ], + "App/protocol/iec104/iec104_asdu.c": [ + "string.h" + ], + "App/protocol/iec104/iec104_asdu.h": [ + "stdint.h" + ], + "App/protocol/iec104/iec104_link.c": [ + "string.h" + ], + "App/protocol/iec104/iec104_link.h": [ + "stdint.h" + ], + "App/protocol/iec104/iec104_pts.c": [ + "string.h" + ], + "App/protocol/iec104/iec104_pts.h": [ + "stdint.h" + ], "App/sync/time_sync.c": [ "string.h" ], "App/sync/time_sync.h": [ "stdint.h" ], + "App/task/iec104_serv.c": [ + "string.h" + ], "App/task/net_task.c": [ "string.h" ], "App/task/ui_task.c": [ "string.h" ], + "App/util/sha256.c": [ + "string.h" + ], + "App/util/sha256.h": [ + "stddef.h", + "stdint.h" + ], "App/util/sys_clock.c": [ "stdio.h", "string.h" @@ -39946,6 +41253,12 @@ "App/util/sys_clock.h": [ "stdint.h" ], + "App/util/task_prof.c": [ + "stdio.h" + ], + "App/util/task_prof.h": [ + "stdint.h" + ], "App/util/task_watchdog.c": [ "string.h" ], @@ -39980,6 +41293,13 @@ "Drivers/BSP/NET/lftpd/lftpd.h": [ "stdint.h" ], + "Drivers/BSP/NET/lftpd/lftpd_auth.c": [ + "stddef.h", + "string.h" + ], + "Drivers/BSP/NET/lftpd/lftpd_auth.h": [ + "stdint.h" + ], "Drivers/BSP/NET/lftpd/lftpd_inet.c": [ "string.h" ], @@ -39989,11 +41309,6 @@ "stdlib.h", "string.h" ], - "Drivers/BSP/NET/lftpd/lftpd_log.c": [ - "stdarg.h", - "stdio.h", - "stdlib.h" - ], "Drivers/BSP/NET/lftpd/lftpd_string.c": [ "ctype.h", "string.h" @@ -40017,6 +41332,13 @@ "Drivers/BSP/NET/net_types.h": [ "stdint.h" ], + "Drivers/BSP/NETCFG/ftp_cfg.c": [ + "stddef.h", + "string.h" + ], + "Drivers/BSP/NETCFG/ftp_cfg.h": [ + "stdint.h" + ], "Drivers/BSP/NETCFG/net_cfg.c": [ "stdbool.h", "stdio.h", @@ -41617,6 +42939,21 @@ "test/board/test_config.h": [ "stdint.h" ], + "test/host/adc_health/adc_health_test.c": [ + "stdint.h", + "stdio.h" + ], + "test/host/adc_input/adc_input_test.c": [ + "stddef.h", + "stdint.h", + "stdio.h" + ], + "test/host/adc_input/stub/adc.h": [ + "stdint.h" + ], + "test/host/adc_input/stub/tpafe5160.h": [ + "stdint.h" + ], "test/host/cfg_file/cfg_file_test.c": [ "stdint.h", "stdio.h", @@ -41626,6 +42963,32 @@ "test/host/cfg_file/stub/dbg_log.h": [ "stdio.h" ], + "test/host/ftp_auth/ftp_auth_test.c": [ + "stdio.h", + "string.h" + ], + "test/host/iec104/iec104_test.c": [ + "stdint.h", + "stdio.h", + "string.h" + ], + "test/host/phasor/phasor_test.c": [ + "math.h", + "stdint.h", + "stdio.h" + ], + "test/host/prot_elm/prot_elm_test.c": [ + "stdint.h", + "stdio.h" + ], + "test/host/prot_set/prot_set_test.c": [ + "stdint.h", + "stdio.h" + ], + "test/host/sha256/sha256_test.c": [ + "stdio.h", + "string.h" + ], "test/host/sys_clock/stub/FreeRTOS.h": [ "stdint.h" ], @@ -41640,6 +43003,35 @@ "stdio.h", "string.h" ], + "test/host/time_sync/stub/FreeRTOS.h": [ + "stdint.h" + ], + "test/host/time_sync/stub/cmsis_os2.h": [ + "stdint.h" + ], + "test/host/time_sync/stub/dbg_log.h": [ + "stdio.h" + ], + "test/host/time_sync/stub/net_socket.h": [ + "stdint.h" + ], + "test/host/time_sync/stub/sys_clock.h": [ + "stdint.h" + ], + "test/host/time_sync/time_sync_test.c": [ + "setjmp.h", + "stdint.h", + "stdio.h", + "string.h" + ], + "test/host/vol_lock/stub/cmsis_os.h": [ + "stdint.h" + ], + "test/host/vol_lock/vol_lock_test.c": [ + "stddef.h", + "stdint.h", + "stdio.h" + ], "test/host/watchdog/stub/dbg_log.h": [ "stdio.h" ], @@ -41655,12 +43047,12 @@ ] }, "stats": { - "files_indexed": 1425, - "includes_parsed": 5706, - "resolved": 4637, - "unresolved": 1069, - "nodes_fp": 147, - "nodes_tp": 1264, + "files_indexed": 1479, + "includes_parsed": 5878, + "resolved": 4749, + "unresolved": 1129, + "nodes_fp": 199, + "nodes_tp": 1266, "ext_names": 351 }, "include_dirs": [ @@ -41680,11 +43072,13 @@ "Drivers/BSP/NETCFG", "App", "App/app", + "App/algo", "App/cfg", "App/fs", "App/log", "App/sync", "App/task", + "App/protocol/iec104", "App/util", "Middlewares/Third_Party/FreeRTOS/Source/include", "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2", diff --git a/docs/images/引用关系图.svg b/docs/images/引用关系图.svg index ab0679a5..99b87f48 100644 --- a/docs/images/引用关系图.svg +++ b/docs/images/引用关系图.svg @@ -4,3947 +4,5165 @@ - - + + refgraph_full - -STM32F4-Base 项目文件引用关系图(项目代码视图) - + +STM32F4-Base 项目文件引用关系图(项目代码视图) + -App/app/app_cfg.h - -App/app/app_cfg.h +App/algo/adc_health.c + +App/algo/adc_health.c - + -App/app/app_main.c - -App/app/app_main.c +App/algo/adc_health.h + +App/algo/adc_health.h - + -App/app/app_main.c->App/app/app_cfg.h - - - - - -App/app/app_main.h - -App/app/app_main.h - - - -App/app/app_main.c->App/app/app_main.h - - - - - -App/log/sys_log.h - -App/log/sys_log.h - - - -App/app/app_main.c->App/log/sys_log.h - - - - - -App/util/sys_clock.h - -App/util/sys_clock.h - - - -App/app/app_main.c->App/util/sys_clock.h - - - - - -App/util/task_watchdog.h - -App/util/task_watchdog.h - - - -App/app/app_main.c->App/util/task_watchdog.h - - - - - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - - - -App/app/app_main.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - - - - - -Drivers/BSP/RS485/rs485.h - -Drivers/BSP/RS485/rs485.h - - - -App/app/app_main.c->Drivers/BSP/RS485/rs485.h - - - - - -Drivers/BSP/SD2506/sd2506.h - -Drivers/BSP/SD2506/sd2506.h - - - -App/app/app_main.c->Drivers/BSP/SD2506/sd2506.h - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.h - -Drivers/BSP/TPAFE5160/tpafe5160.h - - - -App/app/app_main.c->Drivers/BSP/TPAFE5160/tpafe5160.h - - - - - -Drivers/BSP/dbg_log.h - -Drivers/BSP/dbg_log.h - - - -App/app/app_main.c->Drivers/BSP/dbg_log.h - - - - - -Inc/main.h - -Inc/main.h - - - -App/app/app_main.c->Inc/main.h - - - - - -Inc/stm32f4xx_it.h - -Inc/stm32f4xx_it.h - - - -App/app/app_main.c->Inc/stm32f4xx_it.h - - - - - -Inc/usart.h - -Inc/usart.h - - - -App/app/app_main.c->Inc/usart.h - - +App/algo/adc_health.c->App/algo/adc_health.h + + - + 外部/系统头文件 - -外部/系统头文件 + +外部/系统头文件 - - -App/app/app_main.h->外部/系统头文件 - - + + +App/algo/adc_health.h->外部/系统头文件 + + - + + +App/algo/adc_input.c + +App/algo/adc_input.c + + -App/app/sys_events.h - -App/app/sys_events.h +App/algo/adc_input.h + +App/algo/adc_input.h - - -Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h - -Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h + + +App/algo/adc_input.c->App/algo/adc_input.h + + - - -App/app/sys_events.h->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h - - - - - -App/cfg/cfg_file.c - -App/cfg/cfg_file.c - - - -App/cfg/cfg_file.h - -App/cfg/cfg_file.h - - - -App/cfg/cfg_file.c->App/cfg/cfg_file.h - - - - - -App/cfg/cfg_file_store.h - -App/cfg/cfg_file_store.h - - - -App/cfg/cfg_file.c->App/cfg/cfg_file_store.h - - - - - -App/cfg/cfg_file.c->App/log/sys_log.h - - - - - -App/cfg/cfg_file.c->Drivers/BSP/dbg_log.h - - - - - -App/cfg/cfg_file.c->外部/系统头文件 - - - - - -App/cfg/cfg_file.h->外部/系统头文件 - - - - - -App/cfg/cfg_file_store.h->外部/系统头文件 - - - - - -App/cfg/cfg_file_store_mcu.c - -App/cfg/cfg_file_store_mcu.c - - - -App/cfg/cfg_file_store_mcu.c->App/cfg/cfg_file_store.h - - - - - -App/fs/vol_lock.h - -App/fs/vol_lock.h - - - -App/cfg/cfg_file_store_mcu.c->App/fs/vol_lock.h - - - - - -Lib/FatFs/ff.h - -Lib/FatFs/ff.h - - - -App/cfg/cfg_file_store_mcu.c->Lib/FatFs/ff.h - - - - - -Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - -Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - -App/cfg/cfg_file_store_mcu.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -App/cfg/cfg_file_store_mcu.c->外部/系统头文件 - - - - - -App/fs/vol_lock.c - -App/fs/vol_lock.c - - - -App/fs/vol_lock.c->App/fs/vol_lock.h - - - - - -Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - -Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - -App/fs/vol_lock.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -App/fs/vol_lock.h->外部/系统头文件 - - - - - -App/log/console_log.c - -App/log/console_log.c - - - -App/log/console_log.c->App/app/sys_events.h - - - - - -App/log/console_log.h - -App/log/console_log.h - - - -App/log/console_log.c->App/log/console_log.h - - - - - -App/log/console_log.c->Inc/usart.h - - - - - -App/log/console_log.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -App/log/console_log.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -Middlewares/Third_Party/FreeRTOS/Source/include/task.h - -Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - -App/log/console_log.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -App/log/console_log.c->外部/系统头文件 - - - - - -App/log/console_log.h->外部/系统头文件 - - - - - -App/log/sys_log.h->外部/系统头文件 - - - - - -App/log/sys_log_mcu.c - -App/log/sys_log_mcu.c - - - -App/log/sys_log_mcu.c->App/fs/vol_lock.h - - - - - -App/log/sys_log_mcu.c->App/log/sys_log.h - - - - - -App/log/sys_log_mcu.c->App/util/sys_clock.h - - - - - -App/log/sys_log_mcu.c->Drivers/BSP/dbg_log.h - - - - - -App/log/sys_log_mcu.c->Lib/FatFs/ff.h - - - - - -App/log/sys_log_mcu.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -App/log/sys_log_mcu.c->外部/系统头文件 - - - - - -App/sync/time_sync.c - -App/sync/time_sync.c - - - -App/sync/time_sync.c->App/app/sys_events.h - - - - - -App/sync/time_sync.h - -App/sync/time_sync.h - - - -App/sync/time_sync.c->App/sync/time_sync.h - - - - - -App/sync/time_sync.c->App/util/sys_clock.h - - - - - -App/sync/time_sync.c->App/util/task_watchdog.h - - - - - -Drivers/BSP/NET/net_socket.h - -Drivers/BSP/NET/net_socket.h - - - -App/sync/time_sync.c->Drivers/BSP/NET/net_socket.h - - - - - -App/sync/time_sync.c->Drivers/BSP/dbg_log.h - - - - - -App/sync/time_sync.c->外部/系统头文件 - - - - - -App/sync/time_sync.h->外部/系统头文件 - - - - - -App/task/adc_task.c - -App/task/adc_task.c - - - -App/task/adc_task.h - -App/task/adc_task.h - - - -App/task/adc_task.c->App/task/adc_task.h - - - - - -App/task/adc_task.c->Drivers/BSP/TPAFE5160/tpafe5160.h - - - - - -App/task/adc_task.c->Drivers/BSP/dbg_log.h - - - - - -App/task/adc_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -App/task/default_task.c - -App/task/default_task.c - - - -App/task/default_task.c->App/app/sys_events.h - - - - - -App/task/default_task.c->App/cfg/cfg_file.h - - - - - -App/task/default_task.c->App/fs/vol_lock.h - - - - - -App/task/default_task.c->App/log/sys_log.h - - - - - -App/task/default_task.h - -App/task/default_task.h - - - -App/task/default_task.c->App/task/default_task.h - - - - - -App/task/default_task.c->App/util/task_watchdog.h - - - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.h - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.h - - - -App/task/default_task.c->Drivers/BSP/GD5F2GQ5UE/nand_ftl.h - - - - - -Drivers/BSP/NETCFG/net_cfg.h - -Drivers/BSP/NETCFG/net_cfg.h - - - -App/task/default_task.c->Drivers/BSP/NETCFG/net_cfg.h - - - - - -App/task/default_task.c->Drivers/BSP/dbg_log.h - - - - - -App/task/default_task.c->Inc/main.h - - - - - -App/task/default_task.c->Lib/FatFs/ff.h - - - - - -App/task/default_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -App/task/default_task.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -App/task/default_task.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -test/board/test_config.h - -test/board/test_config.h - - - -App/task/default_task.c->test/board/test_config.h - - - - - -App/task/net_task.c - -App/task/net_task.c - - - -App/task/net_task.c->App/app/sys_events.h - - - - - -App/task/net_task.c->App/log/sys_log.h - - - - - -App/task/net_task.h - -App/task/net_task.h - - - -App/task/net_task.c->App/task/net_task.h - - - - - -App/task/net_task.c->App/util/task_watchdog.h - - - - - -Drivers/BSP/CH395F/ch395f.h - -Drivers/BSP/CH395F/ch395f.h - - - -App/task/net_task.c->Drivers/BSP/CH395F/ch395f.h - - - - - -Drivers/BSP/NET/net_select.h - -Drivers/BSP/NET/net_select.h - - - -App/task/net_task.c->Drivers/BSP/NET/net_select.h - - - - - -App/task/net_task.c->Drivers/BSP/NET/net_socket.h - - - - - -App/task/net_task.c->Drivers/BSP/NETCFG/net_cfg.h - - - - - -App/task/net_task.c->Drivers/BSP/dbg_log.h - - - - - -App/task/net_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -App/task/net_task.c->test/board/test_config.h - - - - - -App/task/net_task.c->外部/系统头文件 - - - - - -App/task/rs485_task.c - -App/task/rs485_task.c - - - -App/task/rs485_task.h - -App/task/rs485_task.h - - - -App/task/rs485_task.c->App/task/rs485_task.h - - - - - -App/task/rs485_task.c->Drivers/BSP/RS485/rs485.h - - - - - -App/task/rs485_task.c->Drivers/BSP/dbg_log.h - - - - - -App/task/rs485_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -App/task/ui_task.c - -App/task/ui_task.c - - - -App/task/ui_task.c->App/app/sys_events.h - - - - - -App/task/ui_task.h - -App/task/ui_task.h - - - -App/task/ui_task.c->App/task/ui_task.h - - - - - -App/task/ui_task.c->App/util/sys_clock.h - - - - - -App/task/ui_task.c->App/util/task_watchdog.h - - - - - -Drivers/BSP/UI/ui_menu.h - -Drivers/BSP/UI/ui_menu.h - - - -App/task/ui_task.c->Drivers/BSP/UI/ui_menu.h - - - - - -Drivers/BSP/UI/ui_net_sink.h - -Drivers/BSP/UI/ui_net_sink.h - - - -App/task/ui_task.c->Drivers/BSP/UI/ui_net_sink.h - - - - - -Drivers/BSP/UI/ui_port.h - -Drivers/BSP/UI/ui_port.h - - - -App/task/ui_task.c->Drivers/BSP/UI/ui_port.h - - - - - -Drivers/BSP/UI/ui_standby.h - -Drivers/BSP/UI/ui_standby.h - - - -App/task/ui_task.c->Drivers/BSP/UI/ui_standby.h - - - - - -App/task/ui_task.c->Drivers/BSP/dbg_log.h - - - - - -App/task/ui_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -test/board/net_latency_test.h - -test/board/net_latency_test.h - - - -App/task/ui_task.c->test/board/net_latency_test.h - - - - - -App/task/ui_task.c->test/board/test_config.h - - - - - -App/task/ui_task.c->外部/系统头文件 - - - - - -App/util/sys_clock.c - -App/util/sys_clock.c - - - -App/util/sys_clock.c->App/util/sys_clock.h - - - - - -App/util/sys_clock.c->Drivers/BSP/dbg_log.h - - - - - -App/util/sys_clock.c->Inc/main.h - - - - - -App/util/sys_clock.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -App/util/sys_clock.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -App/util/sys_clock.c->外部/系统头文件 - - - - - -App/util/sys_clock.h->Drivers/BSP/SD2506/sd2506.h - - - - - -App/util/sys_clock.h->外部/系统头文件 - - - - - -App/util/task_watchdog.c - -App/util/task_watchdog.c - - - -App/util/task_watchdog.c->App/log/console_log.h - - - - - -App/util/task_watchdog.c->App/log/sys_log.h - - - - - -App/util/task_watchdog.c->App/util/task_watchdog.h - - - - - -Drivers/BSP/NET/lftpd/lftpd.h - -Drivers/BSP/NET/lftpd/lftpd.h - - - -App/util/task_watchdog.c->Drivers/BSP/NET/lftpd/lftpd.h - - - - - -App/util/task_watchdog.c->Drivers/BSP/dbg_log.h - - - - - -Inc/iwdg.h - -Inc/iwdg.h - - - -App/util/task_watchdog.c->Inc/iwdg.h - - - - - -App/util/task_watchdog.c->Inc/main.h - - - - - -App/util/task_watchdog.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -App/util/task_watchdog.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -App/util/task_watchdog.c->外部/系统头文件 - - - - - -App/util/task_watchdog.h->外部/系统头文件 - - - - - -Drivers/BSP/CH395F/ch395f.c - -Drivers/BSP/CH395F/ch395f.c - - - -Drivers/BSP/CH395F/ch395f.c->Drivers/BSP/CH395F/ch395f.h - - - - - -Drivers/BSP/CH395F/ch395f.c->Drivers/BSP/dbg_log.h - - - - - -Inc/spi.h - -Inc/spi.h - - - -Drivers/BSP/CH395F/ch395f.c->Inc/spi.h - - - - - -Drivers/BSP/CH395F/ch395f.c->Inc/usart.h - - - - - -Drivers/BSP/CH395F/ch395f.c->外部/系统头文件 - - - - - -Drivers/BSP/CH395F/ch395f.h->Inc/main.h - - - - - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c - - - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - - - - - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c->外部/系统头文件 - - - - - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h->Inc/main.h - - - - - -Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h->外部/系统头文件 - - - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - - - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Drivers/BSP/dbg_log.h - - - - - -Lib/FatFs/diskio.h - -Lib/FatFs/diskio.h - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/FatFs/diskio.h - - - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/FatFs/ff.h - - - - - -Lib/dhara/map.h - -Lib/dhara/map.h - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/dhara/map.h - - - - - -Lib/dhara/nand.h - -Lib/dhara/nand.h - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/dhara/nand.h - - - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->外部/系统头文件 - - - - - -Drivers/BSP/GD5F2GQ5UE/nand_ftl.h->外部/系统头文件 - - - - - -Drivers/BSP/NET/net_config.h - -Drivers/BSP/NET/net_config.h - - - -Drivers/BSP/NET/net_select.c - -Drivers/BSP/NET/net_select.c - - - -Drivers/BSP/NET/net_select.c->Drivers/BSP/CH395F/ch395f.h - - - - - -Drivers/BSP/NET/net_select.c->Drivers/BSP/NET/net_select.h - - - - - -Drivers/BSP/NET/net_select.c->Drivers/BSP/NET/net_socket.h - - - - - -Drivers/BSP/NET/net_select.c->Inc/main.h - - - - - -Drivers/BSP/NET/net_select.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -Drivers/BSP/NET/net_select.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -Drivers/BSP/NET/net_select.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -Drivers/BSP/NET/net_select.c->外部/系统头文件 - - - - - -Drivers/BSP/NET/net_select.h->Drivers/BSP/NET/net_config.h - - - - - -Drivers/BSP/NET/net_types.h - -Drivers/BSP/NET/net_types.h - - - -Drivers/BSP/NET/net_select.h->Drivers/BSP/NET/net_types.h - - - - - -Drivers/BSP/NET/net_socket.c - -Drivers/BSP/NET/net_socket.c - - - -Drivers/BSP/NET/net_socket.c->Drivers/BSP/CH395F/ch395f.h - - - - - -Drivers/BSP/NET/net_socket.c->Drivers/BSP/NET/net_socket.h - - - - - -Drivers/BSP/NET/net_socket.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/NET/net_socket.c->Inc/main.h - - - - - -Drivers/BSP/NET/net_socket.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - - - - -Drivers/BSP/NET/net_socket.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -Drivers/BSP/NET/net_socket.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -Drivers/BSP/NET/net_socket.c->test/board/net_latency_test.h - - - - - -Drivers/BSP/NET/net_socket.c->test/board/test_config.h - - - - - -Drivers/BSP/NET/net_socket.c->外部/系统头文件 - - - - - -Drivers/BSP/NET/net_socket.h->Drivers/BSP/NET/net_types.h - - - - - -Drivers/BSP/NET/net_socket.h->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -Drivers/BSP/NET/net_socket.h->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -Drivers/BSP/NET/net_types.h->Drivers/BSP/NET/net_config.h - - - - - -Drivers/BSP/NET/net_types.h->外部/系统头文件 - - - - - -Drivers/BSP/NETCFG/net_cfg.c - -Drivers/BSP/NETCFG/net_cfg.c - - - -Drivers/BSP/NETCFG/net_cfg.c->App/cfg/cfg_file.h - - - - - -Drivers/BSP/NETCFG/net_cfg.c->Drivers/BSP/NETCFG/net_cfg.h - - - - - -Drivers/BSP/NETCFG/net_cfg.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/NETCFG/net_cfg.c->外部/系统头文件 - - - - - -Drivers/BSP/NETCFG/net_cfg.h->外部/系统头文件 - - - - - -Drivers/BSP/RS485/rs485.c - -Drivers/BSP/RS485/rs485.c - - - -Drivers/BSP/RS485/rs485.c->Drivers/BSP/RS485/rs485.h - - - - - -Drivers/BSP/RS485/rs485.h->Inc/main.h - - - - - -Drivers/BSP/SD2506/sd2506.c - -Drivers/BSP/SD2506/sd2506.c - - - -Drivers/BSP/SD2506/sd2506.c->Drivers/BSP/SD2506/sd2506.h - - - - - -Drivers/BSP/SD2506/sd2506.c->Drivers/BSP/dbg_log.h - - - - - -Inc/i2c.h - -Inc/i2c.h - - - -Drivers/BSP/SD2506/sd2506.c->Inc/i2c.h - - - - - -Drivers/BSP/SD2506/sd2506.c->外部/系统头文件 - - - - - -Drivers/BSP/SD2506/sd2506.h->Inc/main.h - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.c - -Drivers/BSP/TPAFE5160/tpafe5160.c - - - -Drivers/BSP/TPAFE5160/tpafe5160.c->Drivers/BSP/TPAFE5160/tpafe5160.h - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.c->Inc/main.h - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.c->外部/系统头文件 - - - - - -Drivers/BSP/TPAFE5160/tpafe5160.h->Inc/main.h - - - - - -Drivers/BSP/UI/ui_content_page.c - -Drivers/BSP/UI/ui_content_page.c - - - -Drivers/BSP/UI/ui_content_page.h - -Drivers/BSP/UI/ui_content_page.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_deco.h - -Drivers/BSP/UI/ui_deco.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_deco.h - - - - - -Drivers/BSP/UI/ui_menu_view.h - -Drivers/BSP/UI/ui_menu_view.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_menu_view.h - - - - - -Drivers/BSP/UI/ui_page_ac.h - -Drivers/BSP/UI/ui_page_ac.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_ac.h - - - - - -Drivers/BSP/UI/ui_page_dc.h - -Drivers/BSP/UI/ui_page_dc.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_dc.h - - - - - -Drivers/BSP/UI/ui_page_device_info.h - -Drivers/BSP/UI/ui_page_device_info.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_device_info.h - - - - - -Drivers/BSP/UI/ui_page_net_cfg.h - -Drivers/BSP/UI/ui_page_net_cfg.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_net_cfg.h - - - - - -Drivers/BSP/UI/ui_page_password.h - -Drivers/BSP/UI/ui_page_password.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_password.h - - - - - -Drivers/BSP/UI/ui_page_runlog.h - -Drivers/BSP/UI/ui_page_runlog.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_runlog.h - - - - + -Drivers/BSP/UI/ui_page_selftest.h - -Drivers/BSP/UI/ui_page_selftest.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_selftest.h - - - - - -Drivers/BSP/UI/ui_pwd_def.h - -Drivers/BSP/UI/ui_pwd_def.h - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_pwd_def.h - - - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_standby.h - - - - - -Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/dbg_log.h - - - - - -Lib/lvgl/lvgl.h - -Lib/lvgl/lvgl.h - - - -Drivers/BSP/UI/ui_content_page.c->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_content_page.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_content_page.h->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_content_page.h->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_deco.c - -Drivers/BSP/UI/ui_deco.c - - - -Drivers/BSP/UI/ui_deco.c->Drivers/BSP/UI/ui_deco.h - - - - - -Drivers/BSP/UI/ui_deco.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_deco.h->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_font_cn_12.c - -Drivers/BSP/UI/ui_font_cn_12.c - - - -Drivers/BSP/UI/ui_font_cn_12.c->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_menu.c - -Drivers/BSP/UI/ui_menu.c - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_menu.h - - - - - -Drivers/BSP/UI/ui_menu_tab.h - -Drivers/BSP/UI/ui_menu_tab.h - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_menu_tab.h - - - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_menu_view.h - - - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_page_password.h - - - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_pwd_def.h - - - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_standby.h - - - - - -Drivers/BSP/UI/ui_menu.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/UI/ui_menu.c->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_menu.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_menu_tab.c - -Drivers/BSP/UI/ui_menu_tab.c - - - -Drivers/BSP/UI/ui_menu_tab.c->Drivers/BSP/UI/ui_menu_tab.h - - - - - -Drivers/BSP/UI/ui_menu_tab.h->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_menu_view.c - -Drivers/BSP/UI/ui_menu_view.c - - - -Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/UI/ui_deco.h - - - - - -Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/UI/ui_menu_tab.h - - - - - -Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/UI/ui_menu_view.h - - - - - -Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/UI/ui_menu_view.c->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_menu_view.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_menu_view.h->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_menu_view.h->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_net_sink.c - -Drivers/BSP/UI/ui_net_sink.c - - - -Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/NET/net_socket.h - - - - - -Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/NET/net_types.h - - - - - -Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/UI/ui_net_sink.h - - - - - -Drivers/BSP/UI/ui_net_sink_backend.h - -Drivers/BSP/UI/ui_net_sink_backend.h - - - -Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/UI/ui_net_sink_backend.h - - - - - -Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/UI/ui_net_sink.c->test/board/net_latency_test.h - - - - - -Drivers/BSP/UI/ui_net_sink.c->test/board/test_config.h - - - - - -Drivers/BSP/UI/ui_net_sink.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_net_sink.h->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_net_sink_backend.h->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_net_sink_backend_mcu.c - -Drivers/BSP/UI/ui_net_sink_backend_mcu.c - - - -Drivers/BSP/UI/ui_net_sink_backend_mcu.c->Drivers/BSP/UI/ui_net_sink_backend.h - - - - - -Drivers/BSP/UI/ui_net_sink_backend_mcu.c->Drivers/BSP/UI/ui_port.h - - - - - -Drivers/BSP/UI/ui_net_sink_backend_mcu.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_page_ac.c - -Drivers/BSP/UI/ui_page_ac.c - - - -Drivers/BSP/UI/ui_page_ac.c->Drivers/BSP/UI/ui_page_ac.h - - - - - -Drivers/BSP/UI/ui_page_ac.h->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_page_dc.c - -Drivers/BSP/UI/ui_page_dc.c - - - -Drivers/BSP/UI/ui_page_dc.c->Drivers/BSP/UI/ui_page_dc.h - - - - - -Drivers/BSP/UI/ui_page_dc.h->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_page_device_info.c - -Drivers/BSP/UI/ui_page_device_info.c - - - -Drivers/BSP/UI/ui_page_device_info.c->Drivers/BSP/UI/ui_page_device_info.h - - - - - -Drivers/BSP/UI/ui_page_device_info.h->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_page_net_cfg.c - -Drivers/BSP/UI/ui_page_net_cfg.c - - - -Drivers/BSP/UI/ui_page_net_cfg.c->Drivers/BSP/NETCFG/net_cfg.h - - - - - -Drivers/BSP/UI/ui_page_net_cfg.c->Drivers/BSP/UI/ui_page_net_cfg.h - - - - - -Drivers/BSP/UI/ui_page_net_cfg.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_page_net_cfg.h->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_page_password.c - -Drivers/BSP/UI/ui_page_password.c - - - -Drivers/BSP/UI/ui_page_password.c->Drivers/BSP/UI/ui_page_password.h - - - - - -Drivers/BSP/UI/ui_page_password.c->Drivers/BSP/UI/ui_pwd_def.h - - - - - -Drivers/BSP/UI/ui_page_password.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_page_password.h->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_page_runlog.c - -Drivers/BSP/UI/ui_page_runlog.c - - - -Drivers/BSP/UI/ui_page_runlog.c->App/log/sys_log.h - - - - - -Drivers/BSP/UI/ui_page_runlog.c->Drivers/BSP/UI/ui_page_runlog.h - - - - - -Drivers/BSP/UI/ui_page_runlog.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_page_runlog.h->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_page_selftest.c - -Drivers/BSP/UI/ui_page_selftest.c - - - -Drivers/BSP/UI/ui_page_selftest.c->App/log/sys_log.h - - - - - -Drivers/BSP/UI/ui_page_selftest.c->Drivers/BSP/UI/ui_page_selftest.h - - - - - -Drivers/BSP/UI/ui_page_selftest.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_page_selftest.h->Drivers/BSP/UI/ui_content_page.h - - - - - -Drivers/BSP/UI/ui_port.c - -Drivers/BSP/UI/ui_port.c - - - -Drivers/BSP/UI/ui_port.c->Drivers/BSP/UI/ui_port.h - - - - - -Drivers/BSP/UI/ui_port.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/UI/ui_port.c->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_port.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_port.h->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_pwd_def.h->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_standby.c - -Drivers/BSP/UI/ui_standby.c - - - -Drivers/BSP/UI/ui_standby.c->Drivers/BSP/UI/ui_menu_view.h - - - - - -Drivers/BSP/UI/ui_standby.c->Drivers/BSP/UI/ui_standby.h - - - - - -Drivers/BSP/UI/ui_standby.c->Drivers/BSP/dbg_log.h - - - - - -Drivers/BSP/UI/ui_standby.c->Lib/lvgl/lvgl.h - - - - - -Drivers/BSP/UI/ui_standby.c->外部/系统头文件 - - - - - -Drivers/BSP/UI/ui_standby.h->外部/系统头文件 - - - - - -Drivers/BSP/dbg_cfg.h - -Drivers/BSP/dbg_cfg.h - - - -Drivers/BSP/dbg_log.h->App/log/console_log.h - - - - - -Drivers/BSP/dbg_log.h->App/util/sys_clock.h - - - - - -Drivers/BSP/dbg_log.h->Drivers/BSP/dbg_cfg.h - - - - - -Drivers/BSP/dbg_log.h->外部/系统头文件 - - - - - -Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h - -Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h - - - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h - -Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h - - - -Inc/FreeRTOSConfig.h - -Inc/FreeRTOSConfig.h - - - -Inc/FreeRTOSConfig.h->外部/系统头文件 - - +Drivers/BSP/TPAFE5160/tpafe5160.h + +Drivers/BSP/TPAFE5160/tpafe5160.h + + + +App/algo/adc_input.c->Drivers/BSP/TPAFE5160/tpafe5160.h + + - + Inc/adc.h - -Inc/adc.h + +Inc/adc.h + + + +App/algo/adc_input.c->Inc/adc.h + + + + + +App/algo/adc_input.c->外部/系统头文件 + + + + + +App/algo/adc_input.h->外部/系统头文件 + + + + + +App/algo/phasor.c + +App/algo/phasor.c + + + +App/algo/phasor.h + +App/algo/phasor.h + + + +App/algo/phasor.c->App/algo/phasor.h + + + + + +App/algo/sample_ring.h + +App/algo/sample_ring.h + + + +App/algo/phasor.c->App/algo/sample_ring.h + + + + + +App/algo/phasor.c->外部/系统头文件 + + + + + +App/algo/phasor.h->App/algo/adc_input.h + + + + + +App/algo/phasor.h->外部/系统头文件 + + + + + +App/algo/prot_elm.c + +App/algo/prot_elm.c + + + +App/algo/prot_elm.c->App/algo/phasor.h + + + + + +App/algo/prot_elm.h + +App/algo/prot_elm.h + + + +App/algo/prot_elm.c->App/algo/prot_elm.h + + + + + +App/algo/prot_set.h + +App/algo/prot_set.h + + + +App/algo/prot_elm.c->App/algo/prot_set.h + + + + + +App/algo/prot_elm.c->外部/系统头文件 + + + + + +App/algo/prot_elm.h->外部/系统头文件 + + + + + +App/algo/prot_set.c + +App/algo/prot_set.c + + + +App/algo/prot_set.c->App/algo/prot_set.h + + + + + +App/algo/prot_set.h->外部/系统头文件 + + + + + +App/algo/sample_ring.c + +App/algo/sample_ring.c + + + +App/algo/sample_ring.c->App/algo/sample_ring.h + + + + + +App/algo/sample_ring.c->外部/系统头文件 + + + + + +App/algo/sample_ring.h->App/algo/adc_input.h + + + + + +App/algo/sample_ring.h->外部/系统头文件 + + + + + +App/app/app_cfg.h + +App/app/app_cfg.h + + + +App/app/app_main.c + +App/app/app_main.c + + + +App/app/app_main.c->App/algo/adc_input.h + + + + + +App/app/app_main.c->App/algo/phasor.h + + + + + +App/app/app_main.c->App/algo/prot_elm.h + + + + + +App/app/app_main.c->App/algo/prot_set.h + + + + + +App/app/app_main.c->App/app/app_cfg.h + + + + + +App/app/app_main.h + +App/app/app_main.h + + + +App/app/app_main.c->App/app/app_main.h + + + + + +App/log/sys_log.h + +App/log/sys_log.h + + + +App/app/app_main.c->App/log/sys_log.h + + + + + +App/util/sys_clock.h + +App/util/sys_clock.h + + + +App/app/app_main.c->App/util/sys_clock.h + + + + + +App/util/task_watchdog.h + +App/util/task_watchdog.h + + + +App/app/app_main.c->App/util/task_watchdog.h + + + + + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h + + + +App/app/app_main.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h + + + + + +Drivers/BSP/RS485/rs485.h + +Drivers/BSP/RS485/rs485.h + + + +App/app/app_main.c->Drivers/BSP/RS485/rs485.h + + + + + +Drivers/BSP/SD2506/sd2506.h + +Drivers/BSP/SD2506/sd2506.h + + + +App/app/app_main.c->Drivers/BSP/SD2506/sd2506.h + + + + + +App/app/app_main.c->Drivers/BSP/TPAFE5160/tpafe5160.h + + + + + +Drivers/BSP/dbg_log.h + +Drivers/BSP/dbg_log.h + + + +App/app/app_main.c->Drivers/BSP/dbg_log.h + + + + + +Inc/main.h + +Inc/main.h + + + +App/app/app_main.c->Inc/main.h + + + + + +Inc/stm32f4xx_it.h + +Inc/stm32f4xx_it.h + + + +App/app/app_main.c->Inc/stm32f4xx_it.h + + + + + +Inc/tim.h + +Inc/tim.h + + + +App/app/app_main.c->Inc/tim.h + + + + + +Inc/usart.h + +Inc/usart.h + + + +App/app/app_main.c->Inc/usart.h + + + + + +test/board/test_config.h + +test/board/test_config.h + + + +App/app/app_main.c->test/board/test_config.h + + + + + +App/app/app_main.h->外部/系统头文件 + + + + + +App/app/sys_events.h + +App/app/sys_events.h + + + +Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h + +Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h + + + +App/app/sys_events.h->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h + + + + + +App/cfg/cfg_file.c + +App/cfg/cfg_file.c + + + +App/cfg/cfg_file.h + +App/cfg/cfg_file.h + + + +App/cfg/cfg_file.c->App/cfg/cfg_file.h + + + + + +App/cfg/cfg_file_store.h + +App/cfg/cfg_file_store.h + + + +App/cfg/cfg_file.c->App/cfg/cfg_file_store.h + + + + + +App/cfg/cfg_file.c->App/log/sys_log.h + + + + + +App/cfg/cfg_file.c->Drivers/BSP/dbg_log.h + + + + + +App/cfg/cfg_file.c->外部/系统头文件 + + + + + +App/cfg/cfg_file.h->外部/系统头文件 + + + + + +App/cfg/cfg_file_store.h->外部/系统头文件 + + + + + +App/cfg/cfg_file_store_mcu.c + +App/cfg/cfg_file_store_mcu.c + + + +App/cfg/cfg_file_store_mcu.c->App/cfg/cfg_file_store.h + + + + + +App/fs/vol_lock.h + +App/fs/vol_lock.h + + + +App/cfg/cfg_file_store_mcu.c->App/fs/vol_lock.h + + + + + +Lib/FatFs/ff.h + +Lib/FatFs/ff.h + + + +App/cfg/cfg_file_store_mcu.c->Lib/FatFs/ff.h + + + + + +Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + +Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + +App/cfg/cfg_file_store_mcu.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +App/cfg/cfg_file_store_mcu.c->外部/系统头文件 + + + + + +App/fs/vol_lock.c + +App/fs/vol_lock.c + + + +App/fs/vol_lock.c->App/fs/vol_lock.h + + + + + +Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + +Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + +App/fs/vol_lock.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +App/fs/vol_lock.h->外部/系统头文件 + + + + + +App/log/console_log.c + +App/log/console_log.c + + + +App/log/console_log.c->App/app/sys_events.h + + + + + +App/log/console_log.h + +App/log/console_log.h + + + +App/log/console_log.c->App/log/console_log.h + + + + + +App/log/console_log.c->Inc/usart.h + + + + + +App/log/console_log.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +App/log/console_log.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +Middlewares/Third_Party/FreeRTOS/Source/include/task.h + +Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + +App/log/console_log.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +App/log/console_log.c->外部/系统头文件 + + + + + +App/log/console_log.h->外部/系统头文件 + + + + + +App/log/sys_log.h->外部/系统头文件 + + + + + +App/log/sys_log_mcu.c + +App/log/sys_log_mcu.c + + + +App/log/sys_log_mcu.c->App/fs/vol_lock.h + + + + + +App/log/sys_log_mcu.c->App/log/sys_log.h + + + + + +App/log/sys_log_mcu.c->App/util/sys_clock.h + + + + + +App/log/sys_log_mcu.c->Drivers/BSP/dbg_log.h + + + + + +App/log/sys_log_mcu.c->Lib/FatFs/ff.h + + + + + +App/log/sys_log_mcu.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +App/log/sys_log_mcu.c->外部/系统头文件 + + + + + +App/protocol/iec104/iec104_asdu.c + +App/protocol/iec104/iec104_asdu.c + + + +App/protocol/iec104/iec104_asdu.h + +App/protocol/iec104/iec104_asdu.h + + + +App/protocol/iec104/iec104_asdu.c->App/protocol/iec104/iec104_asdu.h + + + + + +App/protocol/iec104/iec104_asdu.c->外部/系统头文件 + + + + + +App/protocol/iec104/iec104_asdu.h->外部/系统头文件 + + + + + +App/protocol/iec104/iec104_link.c + +App/protocol/iec104/iec104_link.c + + + +App/protocol/iec104/iec104_link.c->App/protocol/iec104/iec104_asdu.h + + + + + +App/protocol/iec104/iec104_link.h + +App/protocol/iec104/iec104_link.h + + + +App/protocol/iec104/iec104_link.c->App/protocol/iec104/iec104_link.h + + + + + +App/protocol/iec104/iec104_link.c->外部/系统头文件 + + + + + +App/protocol/iec104/iec104_pts.h + +App/protocol/iec104/iec104_pts.h + + + +App/protocol/iec104/iec104_link.h->App/protocol/iec104/iec104_pts.h + + + + + +App/protocol/iec104/iec104_link.h->外部/系统头文件 + + + + + +App/protocol/iec104/iec104_pts.c + +App/protocol/iec104/iec104_pts.c + + + +App/protocol/iec104/iec104_pts.c->App/algo/adc_input.h + + + + + +App/protocol/iec104/iec104_pts.c->App/algo/phasor.h + + + + + +App/protocol/iec104/iec104_pts.c->App/algo/prot_elm.h + + + + + +App/protocol/iec104/iec104_pts.c->App/algo/prot_set.h + + + + + +App/protocol/iec104/iec104_pts.c->App/protocol/iec104/iec104_asdu.h + + + + + +App/protocol/iec104/iec104_pts.c->App/protocol/iec104/iec104_pts.h + + + + + +App/protocol/iec104/iec104_pts.c->外部/系统头文件 + + + + + +App/protocol/iec104/iec104_pts.h->外部/系统头文件 + + + + + +App/sync/time_sync.c + +App/sync/time_sync.c + + + +App/sync/time_sync.c->App/app/sys_events.h + + + + + +App/sync/time_sync.h + +App/sync/time_sync.h + + + +App/sync/time_sync.c->App/sync/time_sync.h + + + + + +App/sync/time_sync.c->App/util/sys_clock.h + + + + + +App/sync/time_sync.c->App/util/task_watchdog.h + + + + + +Drivers/BSP/NET/net_socket.h + +Drivers/BSP/NET/net_socket.h + + + +App/sync/time_sync.c->Drivers/BSP/NET/net_socket.h + + + + + +App/sync/time_sync.c->Drivers/BSP/dbg_log.h + + + + + +App/sync/time_sync.c->外部/系统头文件 + + + + + +App/sync/time_sync.h->外部/系统头文件 + + + + + +App/task/adc_task.c + +App/task/adc_task.c + + + +App/task/adc_task.c->App/algo/adc_health.h + + + + + +App/task/adc_task.c->App/algo/adc_input.h + + + + + +App/task/adc_task.c->App/algo/phasor.h + + + + + +App/task/adc_task.c->App/algo/sample_ring.h + + + + + +App/task/adc_task.c->App/log/console_log.h + + + + + +App/task/adc_task.c->App/log/sys_log.h + + + + + +App/task/adc_task.h + +App/task/adc_task.h + + + +App/task/adc_task.c->App/task/adc_task.h + + + + + +App/util/task_prof.h + +App/util/task_prof.h + + + +App/task/adc_task.c->App/util/task_prof.h + + + + + +App/task/adc_task.c->App/util/task_watchdog.h + + + + + +App/task/adc_task.c->Drivers/BSP/TPAFE5160/tpafe5160.h + + + + + +App/task/adc_task.c->Drivers/BSP/dbg_log.h + + + + + +App/task/adc_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +App/task/default_task.c + +App/task/default_task.c + + + +App/task/default_task.c->App/app/sys_events.h + + + + + +App/task/default_task.c->App/cfg/cfg_file.h + + + + + +App/task/default_task.c->App/fs/vol_lock.h + + + + + +App/task/default_task.c->App/log/sys_log.h + + + + + +App/task/default_task.h + +App/task/default_task.h + + + +App/task/default_task.c->App/task/default_task.h + + + + + +App/task/default_task.c->App/util/task_prof.h + + + + + +App/task/default_task.c->App/util/task_watchdog.h + + + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.h + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.h + + + +App/task/default_task.c->Drivers/BSP/GD5F2GQ5UE/nand_ftl.h + + + + + +Drivers/BSP/NETCFG/net_cfg.h + +Drivers/BSP/NETCFG/net_cfg.h + + + +App/task/default_task.c->Drivers/BSP/NETCFG/net_cfg.h + + + + + +App/task/default_task.c->Drivers/BSP/dbg_log.h + + + + + +App/task/default_task.c->Inc/main.h + + + + + +App/task/default_task.c->Lib/FatFs/ff.h + + + + + +App/task/default_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +App/task/default_task.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +App/task/default_task.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +App/task/default_task.c->test/board/test_config.h + + + + + +App/task/iec104_serv.c + +App/task/iec104_serv.c + + + +App/task/iec104_serv.c->App/app/sys_events.h + + + + + +App/task/iec104_serv.c->App/protocol/iec104/iec104_link.h + + + + + +App/task/iec104_serv.c->App/protocol/iec104/iec104_pts.h + + + + + +App/task/iec104_serv.h + +App/task/iec104_serv.h + + + +App/task/iec104_serv.c->App/task/iec104_serv.h + + + + + +App/task/iec104_serv.c->App/util/sys_clock.h + + + + + +App/task/iec104_serv.c->App/util/task_watchdog.h + + + + + +App/task/iec104_serv.c->Drivers/BSP/NET/net_socket.h + + + + + +App/task/iec104_serv.c->Drivers/BSP/dbg_log.h + + + + + +App/task/iec104_serv.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h + + + + + +App/task/iec104_serv.c->外部/系统头文件 + + + + + +App/task/net_task.c + +App/task/net_task.c + + + +App/task/net_task.c->App/app/sys_events.h + + + + + +App/task/net_task.c->App/log/sys_log.h + + + + + +App/task/net_task.h + +App/task/net_task.h + + + +App/task/net_task.c->App/task/net_task.h + + + + + +App/task/net_task.c->App/util/task_prof.h + + + + + +App/task/net_task.c->App/util/task_watchdog.h + + + + + +Drivers/BSP/CH395F/ch395f.h + +Drivers/BSP/CH395F/ch395f.h + + + +App/task/net_task.c->Drivers/BSP/CH395F/ch395f.h + + + + + +Drivers/BSP/NET/net_select.h + +Drivers/BSP/NET/net_select.h + + + +App/task/net_task.c->Drivers/BSP/NET/net_select.h + + + + + +App/task/net_task.c->Drivers/BSP/NET/net_socket.h + + + + + +App/task/net_task.c->Drivers/BSP/NETCFG/net_cfg.h + + + + + +App/task/net_task.c->Drivers/BSP/dbg_log.h + + + + + +App/task/net_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +App/task/net_task.c->test/board/test_config.h + + + + + +App/task/net_task.c->外部/系统头文件 + + + + + +App/task/protect_task.c + +App/task/protect_task.c + + + +App/task/protect_task.c->App/algo/adc_health.h + + + + + +App/task/protect_task.c->App/algo/prot_elm.h + + + + + +App/task/protect_task.c->App/algo/prot_set.h + + + + + +App/task/protect_task.h + +App/task/protect_task.h + + + +App/task/protect_task.c->App/task/protect_task.h + + + + + +App/task/protect_task.c->App/util/task_watchdog.h + + + + + +App/task/protect_task.c->Drivers/BSP/dbg_log.h + + + + + +App/task/protect_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h + + + + + +App/task/rs485_task.c + +App/task/rs485_task.c + + + +App/task/rs485_task.h + +App/task/rs485_task.h + + + +App/task/rs485_task.c->App/task/rs485_task.h + + + + + +App/task/rs485_task.c->Drivers/BSP/RS485/rs485.h + + + + + +App/task/rs485_task.c->Drivers/BSP/dbg_log.h + + + + + +App/task/rs485_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +App/task/ui_task.c + +App/task/ui_task.c + + + +App/task/ui_task.c->App/app/sys_events.h + + + + + +App/task/ui_task.h + +App/task/ui_task.h + + + +App/task/ui_task.c->App/task/ui_task.h + + + + + +App/task/ui_task.c->App/util/sys_clock.h + + + + + +App/task/ui_task.c->App/util/task_prof.h + + + + + +App/task/ui_task.c->App/util/task_watchdog.h + + + + + +Drivers/BSP/UI/ui_menu.h + +Drivers/BSP/UI/ui_menu.h + + + +App/task/ui_task.c->Drivers/BSP/UI/ui_menu.h + + + + + +Drivers/BSP/UI/ui_net_sink.h + +Drivers/BSP/UI/ui_net_sink.h + + + +App/task/ui_task.c->Drivers/BSP/UI/ui_net_sink.h + + + + + +Drivers/BSP/UI/ui_port.h + +Drivers/BSP/UI/ui_port.h + + + +App/task/ui_task.c->Drivers/BSP/UI/ui_port.h + + + + + +Drivers/BSP/UI/ui_standby.h + +Drivers/BSP/UI/ui_standby.h + + + +App/task/ui_task.c->Drivers/BSP/UI/ui_standby.h + + + + + +App/task/ui_task.c->Drivers/BSP/dbg_log.h + + + + + +App/task/ui_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +test/board/net_latency_test.h + +test/board/net_latency_test.h + + + +App/task/ui_task.c->test/board/net_latency_test.h + + + + + +App/task/ui_task.c->test/board/test_config.h + + + + + +App/task/ui_task.c->外部/系统头文件 + + + + + +App/util/sha256.c + +App/util/sha256.c + + + +App/util/sha256.h + +App/util/sha256.h + + + +App/util/sha256.c->App/util/sha256.h + + + + + +App/util/sha256.c->外部/系统头文件 + + + + + +App/util/sha256.h->外部/系统头文件 + + + + + +App/util/sys_clock.c + +App/util/sys_clock.c + + + +App/util/sys_clock.c->App/util/sys_clock.h + + + + + +App/util/sys_clock.c->Drivers/BSP/dbg_log.h + + + + + +App/util/sys_clock.c->Inc/main.h + + + + + +App/util/sys_clock.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +App/util/sys_clock.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +App/util/sys_clock.c->外部/系统头文件 + + + + + +App/util/sys_clock.h->Drivers/BSP/SD2506/sd2506.h + + + + + +App/util/sys_clock.h->外部/系统头文件 + + + + + +App/util/task_prof.c + +App/util/task_prof.c + + + +App/util/task_prof.c->App/log/console_log.h + + + + + +App/util/task_prof.c->App/util/task_prof.h + + + + + +App/util/task_prof.c->Inc/main.h + + + + + +App/util/task_prof.c->外部/系统头文件 + + + + + +App/util/task_prof.h->外部/系统头文件 + + + + + +App/util/task_watchdog.c + +App/util/task_watchdog.c + + + +App/util/task_watchdog.c->App/log/console_log.h + + + + + +App/util/task_watchdog.c->App/log/sys_log.h + + + + + +App/util/task_watchdog.c->App/util/task_watchdog.h + + + + + +Drivers/BSP/NET/lftpd/lftpd.h + +Drivers/BSP/NET/lftpd/lftpd.h + + + +App/util/task_watchdog.c->Drivers/BSP/NET/lftpd/lftpd.h + + + + + +App/util/task_watchdog.c->Drivers/BSP/dbg_log.h + + + + + +Inc/iwdg.h + +Inc/iwdg.h + + + +App/util/task_watchdog.c->Inc/iwdg.h + + + + + +App/util/task_watchdog.c->Inc/main.h + + + + + +App/util/task_watchdog.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +App/util/task_watchdog.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +App/util/task_watchdog.c->外部/系统头文件 + + + + + +App/util/task_watchdog.h->外部/系统头文件 + + + + + +Drivers/BSP/CH395F/ch395f.c + +Drivers/BSP/CH395F/ch395f.c + + + +Drivers/BSP/CH395F/ch395f.c->Drivers/BSP/CH395F/ch395f.h + + + + + +Drivers/BSP/CH395F/ch395f.c->Drivers/BSP/dbg_log.h + + + + + +Inc/spi.h + +Inc/spi.h + + + +Drivers/BSP/CH395F/ch395f.c->Inc/spi.h + + + + + +Drivers/BSP/CH395F/ch395f.c->Inc/usart.h + + + + + +Drivers/BSP/CH395F/ch395f.c->外部/系统头文件 + + + + + +Drivers/BSP/CH395F/ch395f.h->Inc/main.h + + + + + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c + + + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h + + + + + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c->外部/系统头文件 + + + + + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h->Inc/main.h + + + + + +Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h->外部/系统头文件 + + + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h + + + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Drivers/BSP/dbg_log.h + + + + + +Lib/FatFs/diskio.h + +Lib/FatFs/diskio.h + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/FatFs/diskio.h + + + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/FatFs/ff.h + + + + + +Lib/dhara/map.h + +Lib/dhara/map.h + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/dhara/map.h + + + + + +Lib/dhara/nand.h + +Lib/dhara/nand.h + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->Lib/dhara/nand.h + + + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.c->外部/系统头文件 + + + + + +Drivers/BSP/GD5F2GQ5UE/nand_ftl.h->外部/系统头文件 + + + + + +Drivers/BSP/NET/lftpd/lftpd_auth.c + +Drivers/BSP/NET/lftpd/lftpd_auth.c + + + +Drivers/BSP/NET/net_config.h + +Drivers/BSP/NET/net_config.h + + + +Drivers/BSP/NET/net_select.c + +Drivers/BSP/NET/net_select.c + + + +Drivers/BSP/NET/net_select.c->Drivers/BSP/CH395F/ch395f.h + + + + + +Drivers/BSP/NET/net_select.c->Drivers/BSP/NET/net_select.h + + + + + +Drivers/BSP/NET/net_select.c->Drivers/BSP/NET/net_socket.h + + + + + +Drivers/BSP/NET/net_select.c->Inc/main.h + + + + + +Drivers/BSP/NET/net_select.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +Drivers/BSP/NET/net_select.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +Drivers/BSP/NET/net_select.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +Drivers/BSP/NET/net_select.c->外部/系统头文件 + + + + + +Drivers/BSP/NET/net_select.h->Drivers/BSP/NET/net_config.h + + + + + +Drivers/BSP/NET/net_types.h + +Drivers/BSP/NET/net_types.h + + + +Drivers/BSP/NET/net_select.h->Drivers/BSP/NET/net_types.h + + + + + +Drivers/BSP/NET/net_socket.c + +Drivers/BSP/NET/net_socket.c + + + +Drivers/BSP/NET/net_socket.c->Drivers/BSP/CH395F/ch395f.h + + + + + +Drivers/BSP/NET/net_socket.c->Drivers/BSP/NET/net_socket.h + + + + + +Drivers/BSP/NET/net_socket.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/NET/net_socket.c->Inc/main.h + + + + + +Drivers/BSP/NET/net_socket.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +Drivers/BSP/NET/net_socket.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +Drivers/BSP/NET/net_socket.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +Drivers/BSP/NET/net_socket.c->test/board/net_latency_test.h + + + + + +Drivers/BSP/NET/net_socket.c->test/board/test_config.h + + + + + +Drivers/BSP/NET/net_socket.c->外部/系统头文件 + + + + + +Drivers/BSP/NET/net_socket.h->Drivers/BSP/NET/net_types.h + + + + + +Drivers/BSP/NET/net_socket.h->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +Drivers/BSP/NET/net_socket.h->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +Drivers/BSP/NET/net_types.h->Drivers/BSP/NET/net_config.h + + + + + +Drivers/BSP/NET/net_types.h->外部/系统头文件 + + + + + +Drivers/BSP/NETCFG/ftp_cfg.c + +Drivers/BSP/NETCFG/ftp_cfg.c + + + +Drivers/BSP/NETCFG/ftp_cfg.c->App/cfg/cfg_file.h + + + + + +Drivers/BSP/NETCFG/ftp_cfg.h + +Drivers/BSP/NETCFG/ftp_cfg.h + + + +Drivers/BSP/NETCFG/ftp_cfg.c->Drivers/BSP/NETCFG/ftp_cfg.h + + + + + +Drivers/BSP/NETCFG/ftp_cfg.c->外部/系统头文件 + + + + + +Drivers/BSP/NETCFG/ftp_cfg.h->外部/系统头文件 + + + + + +Drivers/BSP/NETCFG/net_cfg.c + +Drivers/BSP/NETCFG/net_cfg.c + + + +Drivers/BSP/NETCFG/net_cfg.c->App/cfg/cfg_file.h + + + + + +Drivers/BSP/NETCFG/net_cfg.c->Drivers/BSP/NETCFG/ftp_cfg.h + + + + + +Drivers/BSP/NETCFG/net_cfg.c->Drivers/BSP/NETCFG/net_cfg.h + + + + + +Drivers/BSP/NETCFG/net_cfg.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/NETCFG/net_cfg.c->外部/系统头文件 + + + + + +Drivers/BSP/NETCFG/net_cfg.h->外部/系统头文件 + + + + + +Drivers/BSP/RS485/rs485.c + +Drivers/BSP/RS485/rs485.c + + + +Drivers/BSP/RS485/rs485.c->Drivers/BSP/RS485/rs485.h + + + + + +Drivers/BSP/RS485/rs485.h->Inc/main.h + + + + + +Drivers/BSP/SD2506/sd2506.c + +Drivers/BSP/SD2506/sd2506.c + + + +Drivers/BSP/SD2506/sd2506.c->Drivers/BSP/SD2506/sd2506.h + + + + + +Drivers/BSP/SD2506/sd2506.c->Drivers/BSP/dbg_log.h + + + + + +Inc/i2c.h + +Inc/i2c.h + + + +Drivers/BSP/SD2506/sd2506.c->Inc/i2c.h + + + + + +Drivers/BSP/SD2506/sd2506.c->外部/系统头文件 + + + + + +Drivers/BSP/SD2506/sd2506.h->Inc/main.h + + + + + +Drivers/BSP/TPAFE5160/tpafe5160.c + +Drivers/BSP/TPAFE5160/tpafe5160.c + + + +Drivers/BSP/TPAFE5160/tpafe5160.c->Drivers/BSP/TPAFE5160/tpafe5160.h + + + + + +Drivers/BSP/TPAFE5160/tpafe5160.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/TPAFE5160/tpafe5160.c->Inc/main.h + + + + + +Drivers/BSP/TPAFE5160/tpafe5160.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +Drivers/BSP/TPAFE5160/tpafe5160.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +Drivers/BSP/TPAFE5160/tpafe5160.c->外部/系统头文件 + + + + + +Drivers/BSP/TPAFE5160/tpafe5160.h->Inc/main.h + + + + + +Drivers/BSP/UI/ui_content_page.c + +Drivers/BSP/UI/ui_content_page.c + + + +Drivers/BSP/UI/ui_content_page.h + +Drivers/BSP/UI/ui_content_page.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_deco.h + +Drivers/BSP/UI/ui_deco.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_deco.h + + + + + +Drivers/BSP/UI/ui_menu_view.h + +Drivers/BSP/UI/ui_menu_view.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_menu_view.h + + + + + +Drivers/BSP/UI/ui_page_ac.h + +Drivers/BSP/UI/ui_page_ac.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_ac.h + + + + + +Drivers/BSP/UI/ui_page_dc.h + +Drivers/BSP/UI/ui_page_dc.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_dc.h + + + + + +Drivers/BSP/UI/ui_page_device_info.h + +Drivers/BSP/UI/ui_page_device_info.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_device_info.h + + + + + +Drivers/BSP/UI/ui_page_net_cfg.h + +Drivers/BSP/UI/ui_page_net_cfg.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_net_cfg.h + + + + + +Drivers/BSP/UI/ui_page_password.h + +Drivers/BSP/UI/ui_page_password.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_password.h + + + + + +Drivers/BSP/UI/ui_page_runlog.h + +Drivers/BSP/UI/ui_page_runlog.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_runlog.h + + + + + +Drivers/BSP/UI/ui_page_selftest.h + +Drivers/BSP/UI/ui_page_selftest.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_page_selftest.h + + + + + +Drivers/BSP/UI/ui_pwd_def.h + +Drivers/BSP/UI/ui_pwd_def.h + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_pwd_def.h + + + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/UI/ui_standby.h + + + + + +Drivers/BSP/UI/ui_content_page.c->Drivers/BSP/dbg_log.h + + + + + +Lib/lvgl/lvgl.h + +Lib/lvgl/lvgl.h + + + +Drivers/BSP/UI/ui_content_page.c->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_content_page.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_content_page.h->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_content_page.h->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_deco.c + +Drivers/BSP/UI/ui_deco.c + + + +Drivers/BSP/UI/ui_deco.c->Drivers/BSP/UI/ui_deco.h + + + + + +Drivers/BSP/UI/ui_deco.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_deco.h->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_font_cn_12.c + +Drivers/BSP/UI/ui_font_cn_12.c + + + +Drivers/BSP/UI/ui_font_cn_12.c->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_menu.c + +Drivers/BSP/UI/ui_menu.c + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_menu.h + + + + + +Drivers/BSP/UI/ui_menu_tab.h + +Drivers/BSP/UI/ui_menu_tab.h + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_menu_tab.h + + + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_menu_view.h + + + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_page_password.h + + + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_pwd_def.h + + + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/UI/ui_standby.h + + + + + +Drivers/BSP/UI/ui_menu.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/UI/ui_menu.c->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_menu.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_menu_tab.c + +Drivers/BSP/UI/ui_menu_tab.c + + + +Drivers/BSP/UI/ui_menu_tab.c->Drivers/BSP/UI/ui_menu_tab.h + + + + + +Drivers/BSP/UI/ui_menu_tab.h->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_menu_view.c + +Drivers/BSP/UI/ui_menu_view.c + + + +Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/UI/ui_deco.h + + + + + +Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/UI/ui_menu_tab.h + + + + + +Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/UI/ui_menu_view.h + + + + + +Drivers/BSP/UI/ui_menu_view.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/UI/ui_menu_view.c->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_menu_view.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_menu_view.h->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_menu_view.h->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_net_sink.c + +Drivers/BSP/UI/ui_net_sink.c + + + +Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/NET/net_socket.h + + + + + +Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/NET/net_types.h + + + + + +Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/UI/ui_net_sink.h + + + + + +Drivers/BSP/UI/ui_net_sink_backend.h + +Drivers/BSP/UI/ui_net_sink_backend.h + + + +Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/UI/ui_net_sink_backend.h + + + + + +Drivers/BSP/UI/ui_net_sink.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/UI/ui_net_sink.c->test/board/net_latency_test.h + + + + + +Drivers/BSP/UI/ui_net_sink.c->test/board/test_config.h + + + + + +Drivers/BSP/UI/ui_net_sink.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_net_sink.h->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_net_sink_backend.h->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_net_sink_backend_mcu.c + +Drivers/BSP/UI/ui_net_sink_backend_mcu.c + + + +Drivers/BSP/UI/ui_net_sink_backend_mcu.c->Drivers/BSP/UI/ui_net_sink_backend.h + + + + + +Drivers/BSP/UI/ui_net_sink_backend_mcu.c->Drivers/BSP/UI/ui_port.h + + + + + +Drivers/BSP/UI/ui_net_sink_backend_mcu.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_page_ac.c + +Drivers/BSP/UI/ui_page_ac.c + + + +Drivers/BSP/UI/ui_page_ac.c->Drivers/BSP/UI/ui_page_ac.h + + + + + +Drivers/BSP/UI/ui_page_ac.h->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_page_dc.c + +Drivers/BSP/UI/ui_page_dc.c + + + +Drivers/BSP/UI/ui_page_dc.c->Drivers/BSP/UI/ui_page_dc.h + + + + + +Drivers/BSP/UI/ui_page_dc.h->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_page_device_info.c + +Drivers/BSP/UI/ui_page_device_info.c + + + +Drivers/BSP/UI/ui_page_device_info.c->Drivers/BSP/UI/ui_page_device_info.h + + + + + +Drivers/BSP/UI/ui_page_device_info.h->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_page_net_cfg.c + +Drivers/BSP/UI/ui_page_net_cfg.c + + + +Drivers/BSP/UI/ui_page_net_cfg.c->Drivers/BSP/NETCFG/net_cfg.h + + + + + +Drivers/BSP/UI/ui_page_net_cfg.c->Drivers/BSP/UI/ui_page_net_cfg.h + + + + + +Drivers/BSP/UI/ui_page_net_cfg.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_page_net_cfg.h->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_page_password.c + +Drivers/BSP/UI/ui_page_password.c + + + +Drivers/BSP/UI/ui_page_password.c->Drivers/BSP/UI/ui_page_password.h + + + + + +Drivers/BSP/UI/ui_page_password.c->Drivers/BSP/UI/ui_pwd_def.h + + + + + +Drivers/BSP/UI/ui_page_password.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_page_password.h->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_page_runlog.c + +Drivers/BSP/UI/ui_page_runlog.c + + + +Drivers/BSP/UI/ui_page_runlog.c->App/log/sys_log.h + + + + + +Drivers/BSP/UI/ui_page_runlog.c->Drivers/BSP/UI/ui_page_runlog.h + + + + + +Drivers/BSP/UI/ui_page_runlog.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_page_runlog.h->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_page_selftest.c + +Drivers/BSP/UI/ui_page_selftest.c + + + +Drivers/BSP/UI/ui_page_selftest.c->App/log/sys_log.h + + + + + +Drivers/BSP/UI/ui_page_selftest.c->Drivers/BSP/UI/ui_page_selftest.h + + + + + +Drivers/BSP/UI/ui_page_selftest.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_page_selftest.h->Drivers/BSP/UI/ui_content_page.h + + + + + +Drivers/BSP/UI/ui_port.c + +Drivers/BSP/UI/ui_port.c + + + +Drivers/BSP/UI/ui_port.c->Drivers/BSP/UI/ui_port.h + + + + + +Drivers/BSP/UI/ui_port.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/UI/ui_port.c->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_port.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_port.h->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_pwd_def.h->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_standby.c + +Drivers/BSP/UI/ui_standby.c + + + +Drivers/BSP/UI/ui_standby.c->Drivers/BSP/UI/ui_menu_view.h + + + + + +Drivers/BSP/UI/ui_standby.c->Drivers/BSP/UI/ui_standby.h + + + + + +Drivers/BSP/UI/ui_standby.c->Drivers/BSP/dbg_log.h + + + + + +Drivers/BSP/UI/ui_standby.c->Lib/lvgl/lvgl.h + + + + + +Drivers/BSP/UI/ui_standby.c->外部/系统头文件 + + + + + +Drivers/BSP/UI/ui_standby.h->外部/系统头文件 + + + + + +Drivers/BSP/dbg_cfg.h + +Drivers/BSP/dbg_cfg.h + + + +Drivers/BSP/dbg_log.h->App/log/console_log.h + + + + + +Drivers/BSP/dbg_log.h->App/util/sys_clock.h + + + + + +Drivers/BSP/dbg_log.h->Drivers/BSP/dbg_cfg.h + + + + + +Drivers/BSP/dbg_log.h->外部/系统头文件 + + + + + +Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h + +Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h + + + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h + +Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h + + + +Inc/FreeRTOSConfig.h + +Inc/FreeRTOSConfig.h + + + +Inc/FreeRTOSConfig.h->外部/系统头文件 + + - + Inc/adc.h->Inc/main.h - - + + - + Inc/dma.h - -Inc/dma.h + +Inc/dma.h - + Inc/dma.h->Inc/main.h - - + + - + Inc/gpio.h - -Inc/gpio.h + +Inc/gpio.h - + Inc/gpio.h->Inc/main.h - - + + - + Inc/i2c.h->Inc/main.h - - + + - + Inc/iwdg.h->Inc/main.h - - + + - + Inc/main.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h - - + + - + Inc/spi.h->Inc/main.h - - + + - + Inc/stm32f4xx_hal_conf.h - -Inc/stm32f4xx_hal_conf.h + +Inc/stm32f4xx_hal_conf.h - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h - - + + - + Inc/stm32f4xx_hal_conf.h->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h - - + + - + Inc/stm32f4xx_hal_conf.h->外部/系统头文件 - - + + + + + +Inc/tim.h->Inc/main.h + + - + Inc/usart.h->Inc/main.h - - + + - + Src/adc.c - -Src/adc.c + +Src/adc.c - + Src/adc.c->Inc/adc.h - - + + - + Src/dma.c - -Src/dma.c + +Src/dma.c - + Src/dma.c->Inc/dma.h - - + + - + Src/freertos.c - -Src/freertos.c + +Src/freertos.c - + Src/freertos.c->App/app/sys_events.h - - + + - + Src/freertos.c->App/sync/time_sync.h - - + + + + + +Src/freertos.c->App/task/adc_task.h + + - + Src/freertos.c->App/task/default_task.h - - + + + + + +Src/freertos.c->App/task/iec104_serv.h + + - + Src/freertos.c->App/task/net_task.h - - + + + + + +Src/freertos.c->App/task/protect_task.h + + - + Src/freertos.c->App/util/task_watchdog.h - - + + - + Src/freertos.c->Drivers/BSP/CH395F/ch395f.h - - + + - + Src/freertos.c->Drivers/BSP/NET/lftpd/lftpd.h - - + + - + Src/freertos.c->Drivers/BSP/NET/net_socket.h - - + + - + Src/freertos.c->Drivers/BSP/dbg_log.h - - + + - + Src/freertos.c->Inc/main.h - - + + - + Src/freertos.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - + + - + Src/freertos.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - + + - + Src/freertos.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - + + - + test/board/ch395f_test.h - -test/board/ch395f_test.h + +test/board/ch395f_test.h - + Src/freertos.c->test/board/ch395f_test.h - - + + - + test/board/ch395f_test_task.h - -test/board/ch395f_test_task.h + +test/board/ch395f_test_task.h - + Src/freertos.c->test/board/ch395f_test_task.h - - + + - + Src/freertos.c->test/board/test_config.h - - + + - + Src/freertos.c->外部/系统头文件 - - + + - + Src/gpio.c - -Src/gpio.c + +Src/gpio.c - + Src/gpio.c->Inc/gpio.h - - + + - + Src/i2c.c - -Src/i2c.c + +Src/i2c.c - + Src/i2c.c->Inc/i2c.h - - + + - + Src/iwdg.c - -Src/iwdg.c + +Src/iwdg.c - + Src/iwdg.c->Inc/iwdg.h - - + + - + Src/main.c - -Src/main.c + +Src/main.c - + Src/main.c->App/app/app_main.h - - + + + + + +Src/main.c->App/task/adc_task.h + + - + Src/main.c->App/util/sys_clock.h - - + + - + Src/main.c->App/util/task_watchdog.h - - + + - + Src/main.c->Drivers/BSP/CH395F/ch395f.h - - + + - + Src/main.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - - + + - + Src/main.c->Drivers/BSP/NET/net_select.h - - + + - + Src/main.c->Drivers/BSP/NET/net_socket.h - - + + - + Src/main.c->Drivers/BSP/RS485/rs485.h - - + + - + Src/main.c->Drivers/BSP/SD2506/sd2506.h - - + + - + Src/main.c->Drivers/BSP/TPAFE5160/tpafe5160.h - - + + - + Src/main.c->Drivers/BSP/dbg_log.h - - + + - + Src/main.c->Inc/adc.h - - + + - + Src/main.c->Inc/dma.h - - + + - + Src/main.c->Inc/gpio.h - - + + - + Src/main.c->Inc/i2c.h - - + + - + Src/main.c->Inc/iwdg.h - - + + - + Src/main.c->Inc/main.h - - + + - + Src/main.c->Inc/spi.h - - + + + + + +Src/main.c->Inc/tim.h + + - + Src/main.c->Inc/usart.h - - + + - + Src/main.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - + + - + Src/main.c->外部/系统头文件 - - + + - + Src/spi.c - -Src/spi.c + +Src/spi.c - + Src/spi.c->Inc/spi.h - - + + - + Src/stm32f4xx_hal_msp.c - -Src/stm32f4xx_hal_msp.c + +Src/stm32f4xx_hal_msp.c - + Src/stm32f4xx_hal_msp.c->Inc/main.h - - + + - + Src/stm32f4xx_hal_timebase_tim.c - -Src/stm32f4xx_hal_timebase_tim.c + +Src/stm32f4xx_hal_timebase_tim.c - + Src/stm32f4xx_hal_timebase_tim.c->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h - - + + - + Src/stm32f4xx_hal_timebase_tim.c->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h - - + + - + Src/stm32f4xx_it.c - -Src/stm32f4xx_it.c + +Src/stm32f4xx_it.c - + Src/stm32f4xx_it.c->Inc/main.h - - + + - + Src/stm32f4xx_it.c->Inc/stm32f4xx_it.h - - + + - + Src/stm32f4xx_it.c->Inc/usart.h - - + + - + Src/system_stm32f4xx.c - -Src/system_stm32f4xx.c + +Src/system_stm32f4xx.c - + Src/system_stm32f4xx.c->Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h - - + + + + + +Src/tim.c + +Src/tim.c + + + +Src/tim.c->Inc/tim.h + + - + Src/usart.c - -Src/usart.c + +Src/usart.c - + Src/usart.c->Inc/usart.h - - + + - + simulator/SDL2/SDL2-2.32.10/include/SDL.h - -simulator/SDL2/SDL2-2.32.10/include/SDL.h + +simulator/SDL2/SDL2-2.32.10/include/SDL.h - + simulator/dbg_log.h - -simulator/dbg_log.h + +simulator/dbg_log.h - + simulator/dbg_log.h->外部/系统头文件 - - + + - + simulator/lv_conf.h - -simulator/lv_conf.h + +simulator/lv_conf.h - + simulator/main.c - -simulator/main.c + +simulator/main.c - + simulator/main.c->App/cfg/cfg_file.h - - + + - + simulator/main.c->App/cfg/cfg_file_store.h - - + + - + simulator/main.c->App/log/sys_log.h - - + + - + simulator/main.c->Drivers/BSP/NETCFG/net_cfg.h - - + + - + simulator/main.c->Drivers/BSP/UI/ui_menu.h - - + + - + simulator/main.c->Drivers/BSP/UI/ui_net_sink.h - - + + - + simulator/main.c->Drivers/BSP/UI/ui_standby.h - - + + - + simulator/main.c->Lib/lvgl/lvgl.h - - + + - + simulator/main.c->simulator/SDL2/SDL2-2.32.10/include/SDL.h - - + + - + simulator/sim/sim_port.h - -simulator/sim/sim_port.h + +simulator/sim/sim_port.h - + simulator/main.c->simulator/sim/sim_port.h - - + + - + simulator/main.c->外部/系统头文件 - - + + - + simulator/sim/cfg_file_store_sim.c - -simulator/sim/cfg_file_store_sim.c + +simulator/sim/cfg_file_store_sim.c - + simulator/sim/cfg_file_store_sim.c->App/cfg/cfg_file_store.h - - + + - + simulator/sim/cfg_file_store_sim.c->外部/系统头文件 - - + + - + simulator/sim/net_socket_sim.c - -simulator/sim/net_socket_sim.c + +simulator/sim/net_socket_sim.c - + simulator/sim/net_socket_sim.c->Drivers/BSP/NET/net_socket.h - - + + - + simulator/sim/net_socket_sim.c->外部/系统头文件 - - + + - + simulator/sim/sim_latency_stub.c - -simulator/sim/sim_latency_stub.c + +simulator/sim/sim_latency_stub.c - + simulator/sim/sim_latency_stub.c->test/board/net_latency_test.h - - + + - + simulator/sim/sim_port.c - -simulator/sim/sim_port.c + +simulator/sim/sim_port.c - + simulator/sim/sim_port.c->Lib/lvgl/lvgl.h - - + + - + simulator/sim/sim_port.c->simulator/SDL2/SDL2-2.32.10/include/SDL.h - - + + - + simulator/sim/sim_port.c->simulator/sim/sim_port.h - - + + - + simulator/sim/sim_port.h->外部/系统头文件 - - + + - + simulator/sim/sim_syslog.c - -simulator/sim/sim_syslog.c + +simulator/sim/sim_syslog.c - + simulator/sim/sim_syslog.c->App/log/sys_log.h - - + + - + simulator/sim/sim_syslog.c->外部/系统头文件 - - + + - + simulator/sim/ui_net_sink_backend_sim.c - -simulator/sim/ui_net_sink_backend_sim.c + +simulator/sim/ui_net_sink_backend_sim.c - + simulator/sim/ui_net_sink_backend_sim.c->Drivers/BSP/UI/ui_net_sink_backend.h - - + + - + simulator/sim/ui_net_sink_backend_sim.c->Drivers/BSP/UI/ui_port.h - - + + - + simulator/sim/ui_net_sink_backend_sim.c->Lib/lvgl/lvgl.h - - + + - + simulator/sim/ui_net_sink_backend_sim.c->simulator/sim/sim_port.h - - + + + + + +test/board/ch395f_reuse_bench.c + +test/board/ch395f_reuse_bench.c + + + +test/board/ch395f_reuse_bench.c->Drivers/BSP/CH395F/ch395f.h + + + + + +test/board/ch395f_reuse_bench.c->Drivers/BSP/dbg_log.h + + + + + +test/board/ch395f_reuse_bench.c->Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h + + + + + +test/board/ch395f_reuse_bench.h + +test/board/ch395f_reuse_bench.h + + + +test/board/ch395f_reuse_bench.c->test/board/ch395f_reuse_bench.h + + - + test/board/test_common.h - -test/board/test_common.h + +test/board/test_common.h - + test/board/ch395f_test.h->test/board/test_common.h - - + + - + test/board/ch395f_test.h->外部/系统头文件 - - + + - + test/board/ch395f_test_task.c - -test/board/ch395f_test_task.c + +test/board/ch395f_test_task.c - + test/board/ch395f_test_task.c->App/app/sys_events.h - - + + - + test/board/ch395f_test_task.c->App/task/net_task.h - - + + - + test/board/ch395f_test_task.c->Drivers/BSP/CH395F/ch395f.h - - + + - + test/board/ch395f_test_task.c->Drivers/BSP/NET/net_socket.h - - + + - + test/board/ch395f_test_task.c->Drivers/BSP/dbg_log.h - - + + - + test/board/ch395f_test_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - + + - + test/board/ch395f_test_task.c->test/board/ch395f_test.h - - + + - + test/board/ch395f_test_task.c->test/board/ch395f_test_task.h - - + + - + test/board/gd5f_test.h - -test/board/gd5f_test.h + +test/board/gd5f_test.h - + test/board/ch395f_test_task.c->test/board/gd5f_test.h - - + + - + test/board/ch395f_test_task.c->test/board/net_latency_test.h - - + + - + test/board/net_test_task.h - -test/board/net_test_task.h + +test/board/net_test_task.h - + test/board/ch395f_test_task.c->test/board/net_test_task.h - - + + - + test/board/sd2506_test.h - -test/board/sd2506_test.h + +test/board/sd2506_test.h - + test/board/ch395f_test_task.c->test/board/sd2506_test.h - - + + - + test/board/storage_test.h - -test/board/storage_test.h + +test/board/storage_test.h - + test/board/ch395f_test_task.c->test/board/storage_test.h - - + + - + test/board/ch395f_test_task.c->test/board/test_config.h - - + + - + test/board/ch395f_test_task.c->外部/系统头文件 - - + + - + test/board/gd5f_test.h->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - - + + - + test/board/gd5f_test.h->test/board/test_common.h - - + + - + test/board/gd5f_test.h->外部/系统头文件 - - + + - + test/board/gd5f_test_task.c - -test/board/gd5f_test_task.c + +test/board/gd5f_test_task.c - + test/board/gd5f_test_task.c->Drivers/BSP/GD5F2GQ5UE/nand_ftl.h - - + + - + test/board/gd5f_test_task.c->Drivers/BSP/dbg_log.h - - + + - + test/board/gd5f_test_task.c->Lib/FatFs/ff.h - - + + - + test/board/gd5f_test_task.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - + + - + test/board/gd5f_test_task.c->test/board/gd5f_test.h - - + + - + test/board/gd5f_test_task.c->test/board/test_config.h - - + + - + test/board/gd5f_test_task.c->外部/系统头文件 - - + + - + test/board/net_latency_test.c - -test/board/net_latency_test.c + +test/board/net_latency_test.c - + test/board/net_latency_test.c->Drivers/BSP/CH395F/ch395f.h - - + + - + test/board/net_latency_test.c->Drivers/BSP/NET/net_socket.h - - + + - + test/board/net_latency_test.c->Drivers/BSP/dbg_log.h - - + + - + test/board/net_latency_test.c->Inc/main.h - - + + - + test/board/net_latency_test.c->test/board/ch395f_test.h - - + + - + test/board/net_latency_test.c->test/board/net_latency_test.h - - + + - + test/board/net_latency_test.c->test/board/test_config.h - - + + - + test/board/net_latency_test.c->外部/系统头文件 - - + + - + test/board/net_latency_test.h->外部/系统头文件 - - + + - + test/board/net_test_task.c - -test/board/net_test_task.c + +test/board/net_test_task.c - + test/board/net_test_task.c->Drivers/BSP/NET/net_select.h - - + + - + test/board/net_test_task.c->Drivers/BSP/NET/net_socket.h - - + + - + test/board/net_test_task.c->Drivers/BSP/NET/net_types.h - - + + - + test/board/net_test_task.c->Drivers/BSP/dbg_log.h - - + + - + test/board/net_test_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - + + - + test/board/net_test_task.c->test/board/ch395f_test.h - - + + - + test/board/net_test_task.c->test/board/ch395f_test_task.h - - + + - + test/board/net_test_task.c->test/board/net_latency_test.h - - + + - + test/board/net_test_task.c->test/board/net_test_task.h - - + + - + test/board/net_test_task.c->外部/系统头文件 - - + + - + test/board/sd2506_test.h->test/board/test_common.h - - + + - + test/board/sd2506_test.h->外部/系统头文件 - - + + - + test/board/sd2506_test_task.c - -test/board/sd2506_test_task.c + +test/board/sd2506_test_task.c - + test/board/sd2506_test_task.c->Drivers/BSP/SD2506/sd2506.h - - + + - + test/board/sd2506_test_task.c->Drivers/BSP/dbg_log.h - - + + - + test/board/sd2506_test_task.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - + + - + test/board/sd2506_test_task.c->test/board/sd2506_test.h - - + + - + test/board/sd2506_test_task.c->test/board/test_config.h - - + + - + test/board/sd2506_test_task.c->外部/系统头文件 - - + + - + test/board/storage_test.h->test/board/test_common.h - - + + - + test/board/storage_test.h->外部/系统头文件 - - + + - + test/board/storage_test_task.c - -test/board/storage_test_task.c + +test/board/storage_test_task.c - + test/board/storage_test_task.c->Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h - - + + - + test/board/storage_test_task.c->Drivers/BSP/GD5F2GQ5UE/nand_ftl.h - - + + - + test/board/storage_test_task.c->Drivers/BSP/dbg_log.h - - + + - + test/board/storage_test_task.c->Inc/main.h - - + + - + test/board/storage_test_task.c->Lib/FatFs/diskio.h - - + + - + test/board/storage_test_task.c->Lib/FatFs/ff.h - - + + - + test/board/storage_test_task.c->test/board/storage_test.h - - + + - + test/board/storage_test_task.c->test/board/test_config.h - - + + - + test/board/storage_test_task.c->外部/系统头文件 - - + + - + test/board/test_common.h->外部/系统头文件 - - + + - + test/board/test_config.c - -test/board/test_config.c + +test/board/test_config.c - + test/board/test_config.c->Drivers/BSP/dbg_log.h - - + + - + test/board/test_config.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h - - + + - + test/board/test_config.c->test/board/ch395f_test_task.h - - + + - + test/board/test_config.c->test/board/gd5f_test.h - - + + - + test/board/test_config.c->test/board/sd2506_test.h - - + + - + test/board/test_config.c->test/board/storage_test.h - - + + - + test/board/test_config.c->test/board/test_config.h - - + + - + test/board/test_config.h->test/board/ch395f_test.h - - + + - + test/board/test_config.h->test/board/gd5f_test.h - - + + - + test/board/test_config.h->test/board/sd2506_test.h - - + + - + test/board/test_config.h->test/board/storage_test.h - - + + - + test/board/test_config.h->外部/系统头文件 - - + + + + + +test/host/adc_health/adc_health_test.c + +test/host/adc_health/adc_health_test.c + + + +test/host/adc_health/adc_health_test.c->App/algo/adc_health.c + + + + + +test/host/adc_health/adc_health_test.c->外部/系统头文件 + + + + + +test/host/adc_input/adc_input_test.c + +test/host/adc_input/adc_input_test.c + + + +test/host/adc_input/adc_input_test.c->App/algo/adc_input.c + + + + + +test/host/adc_input/adc_input_test.c->App/algo/adc_input.h + + + + + +test/host/adc_input/adc_input_test.c->Drivers/BSP/TPAFE5160/tpafe5160.h + + + + + +test/host/adc_input/adc_input_test.c->Inc/adc.h + + + + + +test/host/adc_input/adc_input_test.c->外部/系统头文件 + + + + + +test/host/adc_input/stub/adc.h + +test/host/adc_input/stub/adc.h + + + +test/host/adc_input/stub/adc.h->外部/系统头文件 + + + + + +test/host/adc_input/stub/tpafe5160.h + +test/host/adc_input/stub/tpafe5160.h + + + +test/host/adc_input/stub/tpafe5160.h->外部/系统头文件 + + - + test/host/cfg_file/cfg_file_test.c - -test/host/cfg_file/cfg_file_test.c + +test/host/cfg_file/cfg_file_test.c - + test/host/cfg_file/cfg_file_test.c->App/cfg/cfg_file.c - - + + - + test/host/cfg_file/cfg_file_test.c->App/cfg/cfg_file_store.h - - + + - + test/host/cfg_file/cfg_file_test.c->App/log/sys_log.h - - + + - + test/host/cfg_file/cfg_file_test.c->Drivers/BSP/dbg_log.h - - + + - + test/host/cfg_file/cfg_file_test.c->外部/系统头文件 - - + + - + test/host/cfg_file/stub/dbg_log.h - -test/host/cfg_file/stub/dbg_log.h + +test/host/cfg_file/stub/dbg_log.h - + test/host/cfg_file/stub/dbg_log.h->外部/系统头文件 - - + + + + + +test/host/ftp_auth/ftp_auth_test.c + +test/host/ftp_auth/ftp_auth_test.c + + + +test/host/ftp_auth/ftp_auth_test.c->App/util/sha256.c + + + + + +test/host/ftp_auth/ftp_auth_test.c->Drivers/BSP/NET/lftpd/lftpd_auth.c + + + + + +test/host/ftp_auth/ftp_auth_test.c->外部/系统头文件 + + + + + +test/host/iec104/iec104_test.c + +test/host/iec104/iec104_test.c + + + +test/host/iec104/iec104_test.c->App/algo/phasor.c + + + + + +test/host/iec104/iec104_test.c->App/algo/prot_elm.c + + + + + +test/host/iec104/iec104_test.c->App/algo/prot_set.c + + + + + +test/host/iec104/iec104_test.c->App/algo/sample_ring.c + + + + + +test/host/iec104/iec104_test.c->App/protocol/iec104/iec104_asdu.c + + + + + +test/host/iec104/iec104_test.c->App/protocol/iec104/iec104_link.c + + + + + +test/host/iec104/iec104_test.c->App/protocol/iec104/iec104_pts.c + + + + + +test/host/iec104/iec104_test.c->外部/系统头文件 + + + + + +test/host/phasor/phasor_test.c + +test/host/phasor/phasor_test.c + + + +test/host/phasor/phasor_test.c->App/algo/phasor.c + + + + + +test/host/phasor/phasor_test.c->App/algo/sample_ring.c + + + + + +test/host/phasor/phasor_test.c->外部/系统头文件 + + + + + +test/host/prot_elm/prot_elm_test.c + +test/host/prot_elm/prot_elm_test.c + + + +test/host/prot_elm/prot_elm_test.c->App/algo/phasor.c + + + + + +test/host/prot_elm/prot_elm_test.c->App/algo/prot_elm.c + + + + + +test/host/prot_elm/prot_elm_test.c->App/algo/prot_set.c + + + + + +test/host/prot_elm/prot_elm_test.c->App/algo/sample_ring.c + + + + + +test/host/prot_elm/prot_elm_test.c->外部/系统头文件 + + + + + +test/host/prot_set/prot_set_test.c + +test/host/prot_set/prot_set_test.c + + + +test/host/prot_set/prot_set_test.c->App/algo/prot_set.c + + + + + +test/host/prot_set/prot_set_test.c->外部/系统头文件 + + + + + +test/host/sha256/sha256_test.c + +test/host/sha256/sha256_test.c + + + +test/host/sha256/sha256_test.c->App/util/sha256.c + + + + + +test/host/sha256/sha256_test.c->外部/系统头文件 + + - + test/host/sys_clock/stub/FreeRTOS.h - -test/host/sys_clock/stub/FreeRTOS.h + +test/host/sys_clock/stub/FreeRTOS.h - + test/host/sys_clock/stub/FreeRTOS.h->外部/系统头文件 - - + + - + test/host/sys_clock/stub/dbg_log.h - -test/host/sys_clock/stub/dbg_log.h + +test/host/sys_clock/stub/dbg_log.h - + test/host/sys_clock/stub/dbg_log.h->外部/系统头文件 - - + + - + test/host/sys_clock/stub/main.h - -test/host/sys_clock/stub/main.h + +test/host/sys_clock/stub/main.h - + test/host/sys_clock/stub/main.h->外部/系统头文件 - - + + - + test/host/sys_clock/stub/task.h - -test/host/sys_clock/stub/task.h + +test/host/sys_clock/stub/task.h - + test/host/sys_clock/stub/task.h->test/host/sys_clock/stub/FreeRTOS.h - - + + - + test/host/sys_clock/sys_clock_test.c - -test/host/sys_clock/sys_clock_test.c + +test/host/sys_clock/sys_clock_test.c - + test/host/sys_clock/sys_clock_test.c->App/util/sys_clock.c - - + + - + test/host/sys_clock/sys_clock_test.c->App/util/sys_clock.h - - + + - + test/host/sys_clock/sys_clock_test.c->Drivers/BSP/SD2506/sd2506.h - - + + - + test/host/sys_clock/sys_clock_test.c->Drivers/BSP/dbg_log.h - - + + - + test/host/sys_clock/sys_clock_test.c->Inc/main.h - - + + - + test/host/sys_clock/sys_clock_test.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h - - + + - + test/host/sys_clock/sys_clock_test.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h - - + + - + test/host/sys_clock/sys_clock_test.c->外部/系统头文件 - - + + + + + +test/host/time_sync/stub/FreeRTOS.h + +test/host/time_sync/stub/FreeRTOS.h + + + +test/host/time_sync/stub/FreeRTOS.h->外部/系统头文件 + + + + + +test/host/time_sync/stub/cmsis_os2.h + +test/host/time_sync/stub/cmsis_os2.h + + + +test/host/time_sync/stub/cmsis_os2.h->外部/系统头文件 + + + + + +test/host/time_sync/stub/dbg_log.h + +test/host/time_sync/stub/dbg_log.h + + + +test/host/time_sync/stub/dbg_log.h->外部/系统头文件 + + + + + +test/host/time_sync/stub/net_socket.h + +test/host/time_sync/stub/net_socket.h + + + +test/host/time_sync/stub/net_socket.h->test/host/time_sync/stub/FreeRTOS.h + + + + + +test/host/time_sync/stub/task.h + +test/host/time_sync/stub/task.h + + + +test/host/time_sync/stub/net_socket.h->test/host/time_sync/stub/task.h + + + + + +test/host/time_sync/stub/net_socket.h->外部/系统头文件 + + + + + +test/host/time_sync/stub/sys_clock.h + +test/host/time_sync/stub/sys_clock.h + + + +test/host/time_sync/stub/sys_clock.h->外部/系统头文件 + + + + + +test/host/time_sync/stub/sys_events.h + +test/host/time_sync/stub/sys_events.h + + + +test/host/time_sync/stub/sys_events.h->test/host/time_sync/stub/cmsis_os2.h + + + + + +test/host/time_sync/stub/task.h->test/host/time_sync/stub/FreeRTOS.h + + + + + +test/host/time_sync/time_sync_test.c + +test/host/time_sync/time_sync_test.c + + + +test/host/time_sync/time_sync_test.c->App/app/sys_events.h + + + + + +test/host/time_sync/time_sync_test.c->App/sync/time_sync.c + + + + + +test/host/time_sync/time_sync_test.c->App/util/sys_clock.h + + + + + +test/host/time_sync/time_sync_test.c->App/util/task_watchdog.h + + + + + +test/host/time_sync/time_sync_test.c->Drivers/BSP/NET/net_socket.h + + + + + +test/host/time_sync/time_sync_test.c->Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h + + + + + +test/host/time_sync/time_sync_test.c->Middlewares/Third_Party/FreeRTOS/Source/include/task.h + + + + + +test/host/time_sync/time_sync_test.c->外部/系统头文件 + + + + + +test/host/vol_lock/stub/cmsis_os.h + +test/host/vol_lock/stub/cmsis_os.h + + + +test/host/vol_lock/stub/cmsis_os.h->外部/系统头文件 + + + + + +test/host/vol_lock/vol_lock_test.c + +test/host/vol_lock/vol_lock_test.c + + + +test/host/vol_lock/vol_lock_test.c->App/fs/vol_lock.c + + + + + +test/host/vol_lock/vol_lock_test.c->Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h + + + + + +test/host/vol_lock/vol_lock_test.c->外部/系统头文件 + + - + test/host/watchdog/stub/dbg_log.h - -test/host/watchdog/stub/dbg_log.h + +test/host/watchdog/stub/dbg_log.h - + test/host/watchdog/stub/dbg_log.h->外部/系统头文件 - - + + - + test/host/watchdog/stub/iwdg.h - -test/host/watchdog/stub/iwdg.h + +test/host/watchdog/stub/iwdg.h - + test/host/watchdog/stub/iwdg.h->外部/系统头文件 - - + + - + test/host/watchdog/stub/main.h - -test/host/watchdog/stub/main.h + +test/host/watchdog/stub/main.h - + test/host/watchdog/stub/main.h->外部/系统头文件 - - + + - + test/host/watchdog/watchdog_test.c - -test/host/watchdog/watchdog_test.c + +test/host/watchdog/watchdog_test.c - + test/host/watchdog/watchdog_test.c->App/util/task_watchdog.c - - + + - + test/host/watchdog/watchdog_test.c->Drivers/BSP/dbg_log.h - - + + - + test/host/watchdog/watchdog_test.c->Inc/iwdg.h - - + + - + test/host/watchdog/watchdog_test.c->Inc/main.h - - + + - + test/host/watchdog/watchdog_test.c->外部/系统头文件 - - + + diff --git a/docs/images/引用关系图_模块.dot b/docs/images/引用关系图_模块.dot index 61e6c8c6..e8df23f9 100644 --- a/docs/images/引用关系图_模块.dot +++ b/docs/images/引用关系图_模块.dot @@ -35,11 +35,12 @@ digraph refgraph_module { "App" -> "BSP/NET" [color="#2563eb", penwidth=1.2, label="×1"]; "App" -> "BSP/RS485" [color="#2563eb", penwidth=1.2, label="×1"]; "App" -> "BSP/SD2506" [color="#2563eb", penwidth=1.2, label="×1"]; - "App" -> "BSP/TPAFE5160" [color="#2563eb", penwidth=1.2, label="×1"]; + "App" -> "BSP/TPAFE5160" [color="#2563eb", penwidth=1.2, label="×2"]; "App" -> "FatFs" [color="#2563eb", penwidth=1.2, label="×1"]; "App" -> "FreeRTOS" [color="#2563eb", penwidth=1.2, label="×3"]; - "App" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×3"]; - "App" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×8"]; + "App" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×5"]; + "App" -> "test" [color="#2563eb", penwidth=1.2, label="×1"]; + "App" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×24"]; "App/log" -> "App" [color="#2563eb", penwidth=1.2, label="×2"]; "App/log" -> "App/util" [color="#2563eb", penwidth=1.2, label="×1"]; "App/log" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×1"]; @@ -47,29 +48,29 @@ digraph refgraph_module { "App/log" -> "FreeRTOS" [color="#2563eb", penwidth=1.2, label="×4"]; "App/log" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×1"]; "App/log" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×4"]; - "App/task" -> "App" [color="#2563eb", penwidth=1.2, label="×5"]; - "App/task" -> "App/log" [color="#2563eb", penwidth=1.2, label="×2"]; - "App/task" -> "App/util" [color="#2563eb", penwidth=1.2, label="×4"]; - "App/task" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×5"]; + "App/task" -> "App" [color="#2563eb", penwidth=1.2, label="×15"]; + "App/task" -> "App/log" [color="#2563eb", penwidth=1.2, label="×4"]; + "App/task" -> "App/util" [color="#2563eb", penwidth=1.2, label="×12"]; + "App/task" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×7"]; "App/task" -> "BSP/CH395F" [color="#2563eb", penwidth=1.2, label="×1"]; "App/task" -> "BSP/GD5F2GQ5UE" [color="#2563eb", penwidth=1.2, label="×1"]; - "App/task" -> "BSP/NET" [color="#2563eb", penwidth=1.2, label="×2"]; + "App/task" -> "BSP/NET" [color="#2563eb", penwidth=1.2, label="×3"]; "App/task" -> "BSP/NETCFG" [color="#2563eb", penwidth=1.2, label="×2"]; "App/task" -> "BSP/RS485" [color="#2563eb", penwidth=1.2, label="×1"]; "App/task" -> "BSP/TPAFE5160" [color="#2563eb", penwidth=1.2, label="×1"]; "App/task" -> "BSP/UI" [color="#2563eb", penwidth=1.2, label="×4"]; "App/task" -> "FatFs" [color="#2563eb", penwidth=1.2, label="×1"]; - "App/task" -> "FreeRTOS" [color="#2563eb", penwidth=1.2, label="×7"]; + "App/task" -> "FreeRTOS" [color="#2563eb", penwidth=1.2, label="×9"]; "App/task" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×1"]; "App/task" -> "test" [color="#2563eb", penwidth=1.2, label="×4"]; - "App/task" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×2"]; - "App/util" -> "App/log" [color="#2563eb", penwidth=1.2, label="×2"]; + "App/task" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×3"]; + "App/util" -> "App/log" [color="#2563eb", penwidth=1.2, label="×3"]; "App/util" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×2"]; "App/util" -> "BSP/SD2506" [color="#2563eb", penwidth=1.2, label="×1"]; "App/util" -> "FreeRTOS" [color="#2563eb", penwidth=1.2, label="×4"]; - "App/util" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×3"]; + "App/util" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×4"]; "App/util" -> "lftpd" [color="#2563eb", penwidth=1.2, label="×1"]; - "App/util" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×4"]; + "App/util" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×8"]; "BSP(公共)" -> "App/log" [color="#2563eb", penwidth=1.2, label="×1"]; "BSP(公共)" -> "App/util" [color="#2563eb", penwidth=1.2, label="×1"]; "BSP(公共)" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×1"]; @@ -87,9 +88,9 @@ digraph refgraph_module { "BSP/NET" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×2"]; "BSP/NET" -> "test" [color="#2563eb", penwidth=1.2, label="×2"]; "BSP/NET" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×3"]; - "BSP/NETCFG" -> "App" [color="#2563eb", penwidth=1.2, label="×1"]; + "BSP/NETCFG" -> "App" [color="#2563eb", penwidth=1.2, label="×2"]; "BSP/NETCFG" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×1"]; - "BSP/NETCFG" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×2"]; + "BSP/NETCFG" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×4"]; "BSP/RS485" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×1"]; "BSP/SD2506" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×1"]; "BSP/SD2506" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×2"]; @@ -114,7 +115,7 @@ digraph refgraph_module { "FreeRTOS" -> "CMSIS" [color="#94a3b8", penwidth=0.7, label="×1"]; "FreeRTOS" -> "Src/Inc (CubeMX)" [color="#94a3b8", penwidth=0.7, label="×1"]; "FreeRTOS" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×14"]; - "HAL" -> "CMSIS" [color="#94a3b8", penwidth=0.7, label="×15"]; + "HAL" -> "CMSIS" [color="#94a3b8", penwidth=0.7, label="×16"]; "HAL" -> "Src/Inc (CubeMX)" [color="#94a3b8", penwidth=0.7, label="×1"]; "HAL" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×1"]; "LVGL" -> "FatFs" [color="#94a3b8", penwidth=0.7, label="×1"]; @@ -124,7 +125,7 @@ digraph refgraph_module { "LVGL" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×204"]; "SDL2" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×36"]; "Src/Inc (CubeMX)" -> "App" [color="#2563eb", penwidth=1.2, label="×3"]; - "Src/Inc (CubeMX)" -> "App/task" [color="#2563eb", penwidth=1.2, label="×2"]; + "Src/Inc (CubeMX)" -> "App/task" [color="#2563eb", penwidth=1.2, label="×6"]; "Src/Inc (CubeMX)" -> "App/util" [color="#2563eb", penwidth=1.2, label="×3"]; "Src/Inc (CubeMX)" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×2"]; "Src/Inc (CubeMX)" -> "BSP/CH395F" [color="#2563eb", penwidth=1.2, label="×2"]; @@ -141,11 +142,13 @@ digraph refgraph_module { "Src/Inc (CubeMX)" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×4"]; "dhara" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×5"]; "lftpd" -> "App" [color="#94a3b8", penwidth=0.7, label="×1"]; - "lftpd" -> "BSP(公共)" [color="#94a3b8", penwidth=0.7, label="×4"]; + "lftpd" -> "App/util" [color="#94a3b8", penwidth=0.7, label="×1"]; + "lftpd" -> "BSP(公共)" [color="#94a3b8", penwidth=0.7, label="×3"]; "lftpd" -> "BSP/NET" [color="#94a3b8", penwidth=0.7, label="×3"]; + "lftpd" -> "BSP/NETCFG" [color="#94a3b8", penwidth=0.7, label="×1"]; "lftpd" -> "FatFs" [color="#94a3b8", penwidth=0.7, label="×2"]; "lftpd" -> "FreeRTOS" [color="#94a3b8", penwidth=0.7, label="×2"]; - "lftpd" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×8"]; + "lftpd" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×9"]; "simulator" -> "App" [color="#2563eb", penwidth=1.2, label="×3"]; "simulator" -> "App/log" [color="#2563eb", penwidth=1.2, label="×2"]; "simulator" -> "BSP/NET" [color="#2563eb", penwidth=1.2, label="×1"]; @@ -155,17 +158,20 @@ digraph refgraph_module { "simulator" -> "SDL2" [color="#2563eb", penwidth=1.2, label="×2"]; "simulator" -> "test" [color="#2563eb", penwidth=1.2, label="×1"]; "simulator" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×6"]; - "test" -> "App" [color="#2563eb", penwidth=1.2, label="×3"]; + "test" -> "App" [color="#2563eb", penwidth=1.2, label="×23"]; "test" -> "App/log" [color="#2563eb", penwidth=1.2, label="×1"]; "test" -> "App/task" [color="#2563eb", penwidth=1.2, label="×1"]; - "test" -> "App/util" [color="#2563eb", penwidth=1.2, label="×3"]; - "test" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×10"]; - "test" -> "BSP/CH395F" [color="#2563eb", penwidth=1.2, label="×2"]; + "test" -> "App/util" [color="#2563eb", penwidth=1.2, label="×7"]; + "test" -> "BSP(公共)" [color="#2563eb", penwidth=1.2, label="×11"]; + "test" -> "BSP/CH395F" [color="#2563eb", penwidth=1.2, label="×3"]; "test" -> "BSP/GD5F2GQ5UE" [color="#2563eb", penwidth=1.2, label="×4"]; - "test" -> "BSP/NET" [color="#2563eb", penwidth=1.2, label="×5"]; + "test" -> "BSP/NET" [color="#2563eb", penwidth=1.2, label="×6"]; "test" -> "BSP/SD2506" [color="#2563eb", penwidth=1.2, label="×2"]; + "test" -> "BSP/TPAFE5160" [color="#2563eb", penwidth=1.2, label="×1"]; "test" -> "FatFs" [color="#2563eb", penwidth=1.2, label="×3"]; - "test" -> "FreeRTOS" [color="#2563eb", penwidth=1.2, label="×7"]; - "test" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×5"]; - "test" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×23"]; + "test" -> "FreeRTOS" [color="#2563eb", penwidth=1.2, label="×10"]; + "test" -> "HAL" [color="#2563eb", penwidth=1.2, label="×1"]; + "test" -> "Src/Inc (CubeMX)" [color="#2563eb", penwidth=1.2, label="×6"]; + "test" -> "lftpd" [color="#2563eb", penwidth=1.2, label="×1"]; + "test" -> "外部/系统头文件" [color="#94a3b8", penwidth=0.7, label="×41"]; } diff --git a/docs/images/引用关系图_模块.svg b/docs/images/引用关系图_模块.svg index d29713cb..f0b36343 100644 --- a/docs/images/引用关系图_模块.svg +++ b/docs/images/引用关系图_模块.svg @@ -4,1147 +4,1189 @@ - - + + refgraph_module - -STM32F4-Base 模块引用概览 + +STM32F4-Base 模块引用概览 App - -App + +App App/log - -App/log + +App/log App->App/log - - -×2 + + +×2 App/util - -App/util + +App/util App->App/util - - -×4 + + +×4 BSP(公共) - -BSP(公共) + +BSP(公共) App->BSP(公共) - - -×3 + + +×3 BSP/GD5F2GQ5UE - -BSP/GD5F2GQ5UE + +BSP/GD5F2GQ5UE App->BSP/GD5F2GQ5UE - - -×1 + + +×1 BSP/NET - -BSP/NET + +BSP/NET App->BSP/NET - - -×1 + + +×1 BSP/RS485 - -BSP/RS485 + +BSP/RS485 App->BSP/RS485 - - -×1 + + +×1 BSP/SD2506 - -BSP/SD2506 + +BSP/SD2506 App->BSP/SD2506 - - -×1 + + +×1 BSP/TPAFE5160 - -BSP/TPAFE5160 + +BSP/TPAFE5160 App->BSP/TPAFE5160 - - -×1 + + +×2 FatFs - -FatFs + +FatFs App->FatFs - - -×1 + + +×1 FreeRTOS - -FreeRTOS + +FreeRTOS App->FreeRTOS - - -×3 + + +×3 Src/Inc (CubeMX) - -Src/Inc (CubeMX) + +Src/Inc (CubeMX) App->Src/Inc (CubeMX) - - -×3 - - - -外部/系统头文件 - -外部/系统头文件 - - - -App->外部/系统头文件 - - -×8 - - - -App/log->App - - -×2 - - - -App/log->App/util - - -×1 - - - -App/log->BSP(公共) - - -×1 - - - -App/log->FatFs - - -×1 - - - -App/log->FreeRTOS - - -×4 - - - -App/log->Src/Inc (CubeMX) - - -×1 - - - -App/log->外部/系统头文件 - - -×4 - - - -App/task - -App/task - - - -App/task->App - - -×5 - - - -App/task->App/log - - -×2 - - - -App/task->App/util - - -×4 - - - -App/task->BSP(公共) - - -×5 - - - -BSP/CH395F - -BSP/CH395F - - - -App/task->BSP/CH395F - - -×1 - - - -App/task->BSP/GD5F2GQ5UE - - -×1 - - - -App/task->BSP/NET - - -×2 - - - -BSP/NETCFG - -BSP/NETCFG - - - -App/task->BSP/NETCFG - - -×2 - - - -App/task->BSP/RS485 - - -×1 - - - -App/task->BSP/TPAFE5160 - - -×1 - - - -BSP/UI - -BSP/UI - - - -App/task->BSP/UI - - -×4 - - - -App/task->FatFs - - -×1 - - - -App/task->FreeRTOS - - -×7 - - - -App/task->Src/Inc (CubeMX) - - -×1 + + +×5 test - -test + +test + + + +App->test + + +×1 + + + +外部/系统头文件 + +外部/系统头文件 + + + +App->外部/系统头文件 + + +×24 + + + +App/log->App + + +×2 + + + +App/log->App/util + + +×1 + + + +App/log->BSP(公共) + + +×1 + + + +App/log->FatFs + + +×1 + + + +App/log->FreeRTOS + + +×4 + + + +App/log->Src/Inc (CubeMX) + + +×1 + + + +App/log->外部/系统头文件 + + +×4 + + + +App/task + +App/task + + + +App/task->App + + +×15 + + + +App/task->App/log + + +×4 + + + +App/task->App/util + + +×12 + + + +App/task->BSP(公共) + + +×7 + + + +BSP/CH395F + +BSP/CH395F + + + +App/task->BSP/CH395F + + +×1 + + + +App/task->BSP/GD5F2GQ5UE + + +×1 + + + +App/task->BSP/NET + + +×3 + + + +BSP/NETCFG + +BSP/NETCFG + + + +App/task->BSP/NETCFG + + +×2 + + + +App/task->BSP/RS485 + + +×1 + + + +App/task->BSP/TPAFE5160 + + +×1 + + + +BSP/UI + +BSP/UI + + + +App/task->BSP/UI + + +×4 + + + +App/task->FatFs + + +×1 + + + +App/task->FreeRTOS + + +×9 + + + +App/task->Src/Inc (CubeMX) + + +×1 - + App/task->test - - -×4 + + +×4 - + App/task->外部/系统头文件 - - -×2 + + +×3 - + App/util->App/log - - -×2 + + +×3 - + App/util->BSP(公共) - - -×2 + + +×2 - + App/util->BSP/SD2506 - - -×1 + + +×1 - + App/util->FreeRTOS - - -×4 + + +×4 - + App/util->Src/Inc (CubeMX) - - -×3 + + +×4 lftpd - -lftpd + +lftpd - + App/util->lftpd - - -×1 + + +×1 - + App/util->外部/系统头文件 - - -×4 + + +×8 - + BSP(公共)->App/log - - -×1 + + +×1 - + BSP(公共)->App/util - - -×1 + + +×1 - + BSP(公共)->外部/系统头文件 - - -×1 + + +×1 - + BSP/CH395F->BSP(公共) - - -×1 + + +×1 - + BSP/CH395F->Src/Inc (CubeMX) - - -×3 + + +×3 - + BSP/CH395F->外部/系统头文件 - - -×1 + + +×1 - + BSP/GD5F2GQ5UE->BSP(公共) - - -×2 + + +×2 - + BSP/GD5F2GQ5UE->FatFs - - -×2 + + +×2 - + BSP/GD5F2GQ5UE->Src/Inc (CubeMX) - - -×1 + + +×1 dhara - -dhara + +dhara - + BSP/GD5F2GQ5UE->dhara - - -×2 + + +×2 - + BSP/GD5F2GQ5UE->外部/系统头文件 - - -×4 + + +×4 - + BSP/NET->BSP(公共) - - -×1 + + +×1 - + BSP/NET->BSP/CH395F - - -×2 + + +×2 - + BSP/NET->FreeRTOS - - -×8 + + +×8 - + BSP/NET->Src/Inc (CubeMX) - - -×2 + + +×2 - + BSP/NET->test - - -×2 + + +×2 - + BSP/NET->外部/系统头文件 - - -×3 + + +×3 - + BSP/NETCFG->App - - -×1 + + +×2 - + BSP/NETCFG->BSP(公共) - - -×1 + + +×1 - + BSP/NETCFG->外部/系统头文件 - - -×2 + + +×4 - + BSP/RS485->Src/Inc (CubeMX) - - -×1 + + +×1 - + BSP/SD2506->BSP(公共) - - -×1 + + +×1 - + BSP/SD2506->Src/Inc (CubeMX) - - -×2 + + +×2 - + BSP/SD2506->外部/系统头文件 - - -×1 + + +×1 - + BSP/TPAFE5160->BSP(公共) - - -×1 + + +×1 - + BSP/TPAFE5160->FreeRTOS - - -×2 + + +×2 - + BSP/TPAFE5160->Src/Inc (CubeMX) - - -×2 + + +×2 - + BSP/TPAFE5160->外部/系统头文件 - - -×1 + + +×1 - + BSP/UI->App/log - - -×2 + + +×2 - + BSP/UI->BSP(公共) - - -×6 + + +×6 - + BSP/UI->BSP/NET - - -×2 + + +×2 - + BSP/UI->BSP/NETCFG - - -×1 + + +×1 LVGL - -LVGL + +LVGL - + BSP/UI->LVGL - - -×9 + + +×9 - + BSP/UI->test - - -×2 + + +×2 - + BSP/UI->外部/系统头文件 - - -×20 + + +×20 CMSIS - -CMSIS + +CMSIS HAL - -HAL + +HAL - + CMSIS->HAL - - -×1 + + +×1 - + CMSIS->外部/系统头文件 - - -×22 + + +×22 - + FatFs->App/util - - -×1 + + +×1 - + FatFs->BSP(公共) - - -×1 + + +×1 - + FatFs->FreeRTOS - - -×1 + + +×1 - + FatFs->外部/系统头文件 - - -×2 + + +×2 - + FreeRTOS->CMSIS - - -×1 + + +×1 - + FreeRTOS->Src/Inc (CubeMX) - - -×1 + + +×1 - + FreeRTOS->外部/系统头文件 - - -×14 + + +×14 - + HAL->CMSIS - - -×15 + + +×16 - + HAL->Src/Inc (CubeMX) - - -×1 + + +×1 - + HAL->外部/系统头文件 - - -×1 + + +×1 - + LVGL->FatFs - - -×1 + + +×1 - + LVGL->FreeRTOS - - -×6 + + +×6 SDL2 - -SDL2 + +SDL2 - + LVGL->SDL2 - - -×1 + + +×1 其他(第三方) - -其他(第三方) + +其他(第三方) - + LVGL->其他(第三方) - - -×1 + + +×1 - + LVGL->外部/系统头文件 - - -×204 + + +×204 - + SDL2->外部/系统头文件 - - -×36 + + +×36 - + Src/Inc (CubeMX)->App - - -×3 + + +×3 - + Src/Inc (CubeMX)->App/task - - -×2 + + +×6 - + Src/Inc (CubeMX)->App/util - - -×3 + + +×3 - + Src/Inc (CubeMX)->BSP(公共) - - -×2 + + +×2 - + Src/Inc (CubeMX)->BSP/CH395F - - -×2 + + +×2 - + Src/Inc (CubeMX)->BSP/GD5F2GQ5UE - - -×1 + + +×1 - + Src/Inc (CubeMX)->BSP/NET - - -×3 + + +×3 - + Src/Inc (CubeMX)->BSP/RS485 - - -×1 + + +×1 - + Src/Inc (CubeMX)->BSP/SD2506 - - -×1 + + +×1 - + Src/Inc (CubeMX)->BSP/TPAFE5160 - - -×1 + + +×1 - + Src/Inc (CubeMX)->CMSIS - - -×1 + + +×1 - + Src/Inc (CubeMX)->FreeRTOS - - -×4 + + +×4 - + Src/Inc (CubeMX)->HAL - - -×16 + + +×16 - + Src/Inc (CubeMX)->lftpd - - -×1 + + +×1 - + Src/Inc (CubeMX)->test - - -×3 + + +×3 - + Src/Inc (CubeMX)->外部/系统头文件 - - -×4 + + +×4 - + dhara->外部/系统头文件 - - -×5 + + +×5 - + lftpd->App - - -×1 + + +×1 + + + +lftpd->App/util + + +×1 - + lftpd->BSP(公共) - - -×4 + + +×3 - + lftpd->BSP/NET - - -×3 + + +×3 + + + +lftpd->BSP/NETCFG + + +×1 - + lftpd->FatFs - - -×2 + + +×2 - + lftpd->FreeRTOS - - -×2 + + +×2 - + lftpd->外部/系统头文件 - - -×8 + + +×9 simulator - -simulator + +simulator - + simulator->App - - -×3 + + +×3 - + simulator->App/log - - -×2 + + +×2 - + simulator->BSP/NET - - -×1 + + +×1 - + simulator->BSP/NETCFG - - -×1 + + +×1 - + simulator->BSP/UI - - -×5 + + +×5 - + simulator->LVGL - - -×3 + + +×3 - + simulator->SDL2 - - -×2 + + +×2 - + simulator->test - - -×1 + + +×1 - + simulator->外部/系统头文件 - - -×6 + + +×6 - + test->App - - -×3 + + +×23 - + test->App/log - - -×1 + + +×1 - + test->App/task - - -×1 + + +×1 - + test->App/util - - -×3 + + +×7 - + test->BSP(公共) - - -×10 + + +×11 - + test->BSP/CH395F - - -×2 + + +×3 - + test->BSP/GD5F2GQ5UE - - -×4 + + +×4 - + test->BSP/NET - - -×5 + + +×6 - + test->BSP/SD2506 - - -×2 + + +×2 + + + +test->BSP/TPAFE5160 + + +×1 - + test->FatFs - - -×3 + + +×3 - + test->FreeRTOS - - -×7 + + +×10 + + + +test->HAL + + +×1 - + test->Src/Inc (CubeMX) - - -×5 + + +×6 + + + +test->lftpd + + +×1 - + test->外部/系统头文件 - - -×23 + + +×41 diff --git a/docs/产品需求/产品需求设计文档.md b/docs/产品需求/产品需求设计文档.md index 2a663a60..d63abc67 100644 --- a/docs/产品需求/产品需求设计文档.md +++ b/docs/产品需求/产品需求设计文档.md @@ -24,7 +24,7 @@ 3. **产品当前做到哪一步**——已实现、已验收、待实现的**明确边界**。 **不含**:具体代码实现细节(见各模块设计文档)、测试用例步骤(见 `docs/测试说明/`)、 -未闭环事项的逐条跟踪(见 [`docs/待处理内容.md`](../../docs/待处理内容.md))。 +未闭环事项的逐条跟踪(见 [`docs/任务规划/README.md`](../任务规划/README.md))。 ### 1.2 术语与缩写 @@ -780,7 +780,7 @@ cfg-file-unit-test、test-suite-switch、gitlint。 ### 9.2 阶段路线图 -> **顺序唯一权威 → [`../待处理内容.md`](../待处理内容.md) §2(统一推进顺序,波次 W1~W7; +> **顺序唯一权威 → [`../任务规划/README.md`](../任务规划/README.md) §2(统一推进顺序,波次 W1~W7; > RS-485/B2 整簇暂缓见其 §2.4,2026-10-12 用户决定)**。 > 本节自 2026-10-11 起不再维护路线图(原阶段图删除,避免与登记簿漂移;原 C4"defaultTask 栈余量 10%" > 已于 2026-10-10 削链闭环销项,见 `../内存管理/RAM使用分析与优化方案.md`)。 @@ -863,7 +863,7 @@ cfg-file-unit-test、test-suite-switch、gitlint。 | 远程显示协议 | [`docs/UI设计/RemoDispBus协议与接收设计说明.md`](../../docs/UI设计/RemoDispBus协议与接收设计说明.md) | | 部署环境 | [`docs/环境与部署/项目部署环境要求.md`](../../docs/环境与部署/项目部署环境要求.md) | | 硬件网表 | [`docs/硬件平台/V0.1_网表详细分析报告.md`](../../docs/硬件平台/V0.1_网表详细分析报告.md) | -| 待办登记簿 | [`docs/待处理内容.md`](../../docs/待处理内容.md) | +| 待办登记簿 | [`docs/任务规划/README.md`](../任务规划/README.md) | | 体系层评审报告 | [`docs/问题记录/项目审查与优化建议报告.md`](../../docs/问题记录/项目审查与优化建议报告.md) | | 错误码审计 | [`docs/问题记录/错误码传播审计.md`](../../docs/问题记录/错误码传播审计.md) | | 实机测试指南 | [`docs/测试说明/实机测试实施指南.md`](../../docs/测试说明/实机测试实施指南.md) | diff --git a/docs/代码规范/pre-commit使用说明.md b/docs/代码规范/pre-commit使用说明.md index 5ef112e5..af3a4732 100644 --- a/docs/代码规范/pre-commit使用说明.md +++ b/docs/代码规范/pre-commit使用说明.md @@ -378,7 +378,7 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法 | 项 | 说明 | |---|---| | **触发条件** | 全部自研代码目录(`App/` `Drivers/BSP/` `Src/` `Inc/`)+ `Lib/lv_conf.h` + `test/board/` + `scripts/ram_baseline.*` + `docs/内存管理/` + 本配置文件 | -| **处理方式** | **阻止提交**(RW_IRAM1 / RW_CCM 任一区占比 >92%,或台账受管区与 `.map` 漂移);无 `.map` 自适应跳过(同 `mem-numbers` 在 CI 的行为,盲区登记 `docs/待处理内容.md` A-5 残余) | +| **处理方式** | **阻止提交**(RW_IRAM1 / RW_CCM 任一区占比 >92%,或台账受管区与 `.map` 漂移);无 `.map` 自适应跳过(同 `mem-numbers` 在 CI 的行为,盲区登记 `docs/任务规划/测试与架构专项.md` A-5 残余) | | **检查逻辑** | 解析 `.map` 执行区占比 → 超阈值即 FAIL 并附 **Top-10 RW+ZI 对象表**(定位增量元凶);同时校验 `docs/内存管理/RAM预算台账.md` 受管区与 `.map` 一致(漂移 → 提示 `--write`) | | **软提醒**(不拦) | tsv 末行落后于 `.map`(忘跑 `--update`);`.map` 早于最新源码(忘 `@build`) | | **配套三件套** | `scripts/ram_baseline.py`(门禁/趋势/受管区生成)+ `scripts/ram_baseline.tsv`(每次 `@build` 后 `--update` 追加的趋势基线,`--trend` 高亮 RW+ZI 增长 >1 KB 的对象)+ `docs/内存管理/RAM预算台账.md`(子系统配额 + CCM 台账 + 超配额流程) | diff --git a/docs/任务规划/README.md b/docs/任务规划/README.md new file mode 100644 index 00000000..4535a3bd --- /dev/null +++ b/docs/任务规划/README.md @@ -0,0 +1,137 @@ +# 任务规划(统一待办登记簿 · 索引与排序权威) + +> **这个文件夹是什么**:全项目唯一的未闭环事项清单 + 全项目唯一权威的工作先后顺序。 +> 2026-10-12 按「变更频率 + 职责」解耦成多文件——并行任务写范围互不相交,各改各的文件。 +> +> **文件地图(谁改哪个)**: +> +> | 文件 | 内容 | 变更频率 / 写者 | +> |---|---|---| +> | `README.md`(本文件) | 编号空间(§0)· 未闭环一览(§1)· **推进顺序权威(§2)** · 维护约定(§3) | 低频;仅主工作树 | +> | `W1-采集保护收尾.md` | 当前波次:里程碑 / 并行道 / 任务卡(DoD·依赖·资源·写范围·状态) | **高频**——状态流转只改它;Lead 在 claim/完成时更新 | +> | `排期详述.md` | W4 结构债 / W5 验证常态 波内详表 | 低频 | +> | `暂缓-RS485.md` | B2 RS-485 整簇冻结清单(用户决定) | 极少 | +> | `登记簿.md` | N-x / S-x / T-x 长期登记(网络 / 存储 / 硬件 / 测试 / 报告并轨) | 中频——新发现进对应表 | +> | `测试与架构专项.md` | P1-10 收尾 + S1x / A-x 专项 | 低频 | +> | `基线与待确认.md` | 待确认 · 设计基线(pending 二期 / 错误码四要素)· 诊断基线 · 内存预算 | 参考,少改 | +> +> **怎么用**:想知道"现在该做什么、按什么顺序" → 本文件 **§2**;想知道"当前波次任务卡状态 / 验收判据 / 并行道" → `W1-采集保护收尾.md`; +> 想知道"某条待办的来龙去脉" → 按编号查 `登记簿.md` / `测试与架构专项.md`;想知道"还差哪些验证" → `排期详述.md` §2。 +> +> **只保留待办**:已完成条目直接删除,不留变更记录(历史见 `git log` 与各模块文档); +> 已闭环项的**结论与证据沉淀进对应模块文档/问题记录**,本文件夹不再重复。 +> **消化即销项**:事项修复/关闭后,直接删除对应条目,并同步清理其它文档对本编号的引用。 +> +> **不在本文件夹范围**:`../问题记录/错误码传播审计.md`(E-xx,审计报告,非待办池)、 +> `../问题记录/项目审查与优化建议报告.md`(体系层评审报告)、`../测试说明/实机测试实施指南.md`(执行流程)。 +> +> **修订**:2026-10-04 四档合并;2026-10-11 统一排序 + 审查报告并轨; +> **2026-10-12 按用户决定 RS-485(B2)整簇暂缓,波次重排为 W1~W7,清除已销项残留**; +> **2026-10-12 W1-0 台账三件套落地(N-27 前半闭环,`mem-budget` 钩子),N-23 钩子落地残余并入 C5**; +> **2026-10-12 B4/B5 销项——W1 功能主线代码侧全部完成**; +> **2026-10-12 用户决定:新 W1 = ADC 采集 + 保护相关功能收尾闭环(B6~B10 + N-33),W2~W7 顺延**, +> 波次切换为「里程碑 × 并行道 × 任务卡(五字段)」模式(方法论 → `../环境与部署/并行任务工作树方案.md` §7.3); +> **2026-10-12 解耦为 `docs/任务规划/` 文件夹**(README 索引 + 6 个职责单一文件;编号空间与 §2 排序权威不变)。 + +--- + +## 0. 编号空间与来源 + +| 编号 | 含义 | 备注 | +|---|---|---| +| `P0-x`~`P3-x` | 审计缺陷/改进项(2026-09-15/09-21 审计) | P0=功能 bug、P1=疑似 bug/健壮性、P2=改进、P3=卫生 | +| `N-x` / `S-x` / `T-x` | 台架/审计观察登记项 / 存储·日志管线 / 测试与工具链 | 编号**不回收**;`N-x` 含硬件改版项(需下一版硬件,固件侧只记口径,如 N-18) | +| `S1~S14` / `A-1~A-7` | 2026-10-02 复审的测试充分性与架构专项 | 编号**不回收** | +| `E-xx` | 错误码传播审计发现 | 独立维护于 `错误码传播审计.md`,**不并入本文件夹**,只交叉引用 | +| `B`/`C`/`D` 前缀 | §2 排序条目编号:B=功能主线、C=结构债、D=验证窗口 | 编号不回收,见 §2 | +| 报告 `N-x`/`R-x`/`F-x`/`S-x`/`U-x`/`D-x` | `项目审查与优化建议报告.md` **自有编号** | ⚠ **与本登记簿同名不同义**(报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架)→ **引用一律带文档名**。其未闭环项 2026-10-11 并入本登记簿(新编 `N-19`~`N-29` + U 簇,出处列保留报告编号) | + +**严重度定义**(沿用审计口径):P0 = 确认功能 bug|P1 = 疑似 bug 或健壮性风险|P2 = 改进|P3 = 卫生。 +**置信度**:high = 代码级确证|medium = 依赖外部条件(手册/硬件/产品定义)。 + +--- + +## 1. 未闭环一览(按类别) + +| 类别 | 数量 | 条目 | +|---|---|---| +| P1 收尾 | 1 | P1-10 测试固件构建实测(`测试与架构专项.md` §1) | +| 网络 | 5 | N-2(49s 日志静默,**低风险观察项**)· N-3(L5 基线重验)· N-4(pending 二期)· N-16(A2/A4 负向台架)· N-17(探针窗口心跳缺口) | +| 存储 / 日志 | 3 | **S-3(USART1 TX-only 根治)** · S-4(dhara 重试自旋)· S-5(可选全序列卷锁) | +| 数据正确性 | 1 | **N-21(dhara `is_free`/`copy`,全簿最高风险)** | +| 结构 / 健壮性 | 9 | N-20(Error_Handler 死循环)· N-22(写回 flush)· N-23(注册校验残余白名单)· N-24(日志逐条开关)· N-25(性能/语义簇)· N-26(NAND DMA 断言)· N-27(内存优化簇,三件套 ✅ 前半落地)· N-28(Flash 死代码簇)· **N-33(栈余量收口,W1)** | +| 仓库 | 1 | N-29(`.git` 149 MB,**已决策暂不处理、登记观察**) | +| 硬件 | 1 | N-18(V0.2 改版项) | +| 测试 / 基础设施 | 6 | T-7(CI runner + 推送闭环 + 第二机交叉验证)· S12(断言宏)· S1-c(可选单测)· A-4(采集链路测试约束,RS485 侧随 B2 暂缓)· A-5 残余(CI 体积门禁盲区)· D7(串口助手 A6/A7 待 CH340) | +| UI | 1 簇 | U 簇(27 页标准化,**本轮不排期**) | +| **暂缓** | 1 簇 | **B2 RS-485 整簇(2026-10-12 用户决定,`暂缓-RS485.md`)** | + +> **网络侧另有 E-xx 未闭环项**(E-12/15/16/23/24/25/26/27/28/30/47/48/49/50/58/59/61,共 17 项) +> 与 1 项回归监督(E-62),详见 `../问题记录/错误码传播审计.md` §3——其中 **E-49/E-50 随 RS-485 暂缓**。 +> 本文件夹不重复登记。UI 标准化簇与覆盖率缺口(lftpd/dhara 移植层无主机测试)为整簇排期项,见 §2 W6 / N-21。 + +### 1.1 结构性判断(排序依据) + +1. **用户决定(2026-10-12):先把 ADC 采集、保护等相关功能完成**——"转发 + 保护"两环代码已落地(B4/B5,2026-10-12),但**尚未台架闭环、功能面不完整**(定值不落盘、无频率保护、无动作记录/SOE、栈安全线两处 FAIL)。新 W1 = 采集→相量→保护→上送链路的**收尾与闭环**(B6~B10 + N-33,见 `W1-采集保护收尾.md`),其余波次顺延。**RS-485 对下采集(B2)按用户决定暂缓(2026-10-12,`暂缓-RS485.md`),主线不再等它**。 +2. **数据正确性最高风险 = N-21**(dhara `is_free` 只查页首 64 B / `copy` 不处理哨兵):低概率、后果重(数据丢失),且至今只能靠人工读代码发现——修复须配主机侧移植层测试(一并补报告"覆盖率"缺口)。 +3. **内存预算红线已机械化(2026-10-12,W1-0)**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势基线 → `docs/内存管理/RAM预算台账.md`;实际优化 R-9→R-2 排 W3(**B5 堆扩容 48→56 KB 后 CCM 只剩 ≈8,160 B**,解锁链见 `docs/内存管理/RAM预算台账.md` §3)。 +4. **验证债仅剩窗口性事项**(D2/D5/D6/D7 + P1-10 收尾),不单独排期、逢窗口顺手做。 + +--- + +## 2. 统一推进顺序(全项目唯一权威) + +> **本节是全项目所有工作流唯一的权威顺序**:`产品需求设计文档.md` §9.2、`../算法/继电保护功能复现规划.md`、 +> `项目审查与优化建议报告.md` §0.3 中的路线图均为局部视图,**顺序变更只改本节,其它文档只留指针**。 +> 排序原则:**安全风险 > 产品功能主线 > 数据正确性 > 预算/结构债 > 验证常态 > UI 扩展 > 仓库决策**(当前无未闭环安全项)。 +> 波内详表在挂接文件里(`W1-采集保护收尾.md` / `排期详述.md` / `暂缓-RS485.md`),但**波次增删与先后只改 §2.0**。 + +### 2.0 波次总览 + +| 波次 | 内容 | 为什么在这 | +|---|---|---| +| **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) | +| **W5 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · D7 串口助手 · S12 · S1-c · A-5(详表 `排期详述.md` §2) | 窗口性,逢机顺带,不单独排期 | +| **W6 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5);**本轮不排期(2026-10-11 已确认)** | +| **W7 仓库决策** | **N-29** `.git` 149 MB + 图片 36.3 MB | **已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(`git filter-repo` 历史重写影响未推送提交与协作者) | +| **暂缓** | **B2 RS-485 整簇**(`暂缓-RS485.md`) | **用户决定(2026-10-12):当前不处理 RS-485** | +| **硬件改版** | N-18 8 路电气量全接 TPAFE(V0.2) | 下一版硬件;固件侧已用语义映射隔离,改版只动映射表 | + +### 2.1 顺序一图 + +``` +W1 收尾 台架道: B6→N-33(M1) ∥ 代码道: B7→{B8∥B9}(M2) → B10 送检(M3, Fixed Date) 详表 W1-采集保护收尾.md + (B4 IEC104 ✅ / B5 protectTask ✅ 2026-10-12 已销项;台账三件套 ✅) + ↓ +W2 数据 N-21 dhara is_free/copy(配主机侧移植层测试) + ↓ +W3 预算 R-9 池瘦身 → R-2 后半(54KB→CCM)→ R-3~R-6 评估 + ↓ +W4 结构 N-20 → C6(S-3) → C3(N-2/N-24) → C1 pending 二期 → C5(含 N-23 残余) → N-22/25/26/28 + ↓ +W5 验证 P1-10 · T-7 CI · D2/D5/D6/D7 · S12 · S1-c · A-5 + ↓ +W6 UI U4 残余 → U1 令牌层 → U2/U3 → 27 页(单独立项,本轮不排期) +W7 仓库 N-29 .git 149MB(已决策暂不处理) 硬件:N-18 V0.2 +暂缓 B2 RS-485 整簇(2026-10-12 用户决定,见 暂缓-RS485.md) +``` + +--- + +## 3. 维护约定 + +- 本文件夹是**全项目唯一的未闭环事项登记簿**——"盘点 + 排序 + 明细"三合一,明细按职责拆进本文件夹各文件(2026-10-12 解耦),不再分散到其它文档。 +- **并行写纪律**:任务分支(worktree)**不改本文件夹任何文件**;任务卡状态列(⬜/🟦)与销项一律由 Lead 在主工作树更新。解耦的收益 = 不同波次 / 不同登记之间互不冲突,**不是**任务分支可以写。 +- **任一项完成后直接删除对应条目**(先销本文件夹条目,再清理其它文档对本编号的引用);**不留变更记录**,历史见 `git log` 与各模块文档。 +- 已闭环条目的**结论与证据沉淀进模块文档**,本文件夹不再重复。 +- 编号一律**沿用且不回收**(P-x / N-x / S-x / T-x / S1x / A-x / B·C·D 前缀);`错误码传播审计.md` 的 E-xx 独立维护。 +- **引用审查报告编号一律带文档名**(报告 N-16 ≠ 登记簿 N-16、报告 S-3 ≠ 登记簿 S-3); + 报告并轨项用本登记簿新编号(N-19~N-29 + U 簇),出处列保留报告编号。 +- **§2 是全项目唯一的推进顺序权威**:`产品需求设计文档.md` 等文档中的路线图只留指针,顺序变更只改 §2.0(详表文件跟着挪,不改顺序)。 +- **暂缓块(`暂缓-RS485.md`)不是销项**:条目仍在簿,只是不占波次;重启或关闭时更新该文件与 §1/§2.0。 +- 新增发现按既有惯例分流:能立即修的进 §2 波次(W4 C5);需排期的进 `登记簿.md` / `测试与架构专项.md` 对应编号空间;跨版本观察的进 `登记簿.md`。 +- 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、`问题记录/错误码传播审计.md`(E-xx)、 + `测试说明/实机测试实施指南.md`(执行流程)——三者均不在本文件夹合并范围。 diff --git a/docs/任务规划/W1-采集保护收尾.md b/docs/任务规划/W1-采集保护收尾.md new file mode 100644 index 00000000..ed70a73d --- /dev/null +++ b/docs/任务规划/W1-采集保护收尾.md @@ -0,0 +1,68 @@ +# W1 采集 + 保护收尾(当前波次任务卡) + +> **本文件是全文件夹改动最频繁的规划文件**:当前波次的里程碑 / 并行道 / 任务卡。 +> 状态变更(⬜ 未开始 → 🟦 进行中 → 销项删行)只改本文件;**排序权威(波次总览)在 `docs/任务规划/README.md` §2**。 +> 方法论出处与执行层映射(工作树 / 锁 / 并行道)→ `../环境与部署/并行任务工作树方案.md` §7.3。 + +## 1. 背景(已闭环,只留指针) + +B0 产品定义 2026-10-10 确认——上行 **IEC 60870-5-104**(以太网 TCP 2404,遥测短浮点系数 1)/ +持续采集 / **1000 Hz(20 点/周波)** / RS-485 对下 ModBus RTU,结论详见 +`../算法/继电保护功能复现规划.md` §1.5 与 `../产品需求/产品需求设计文档.md` §5.9/§5.10/§9; +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 用例)。 + +**本波目标(用户决定 2026-10-12)**:把"采集→相量→保护→上送"链路从"代码落地"收口到 +**"台架闭环 + 功能面完整 + 可送检"**。规划方式 = **里程碑(时间驱动、判据退出)× +并行道(按资源约束切分)× 任务卡(五字段)**。 + +## 2. 里程碑(时间驱动:功能可顺延,里程碑不拖延) + +| 里程碑 | 退出判据(全部满足才算完成,随后销项) | 服务分类 | +|---|---|---| +| **M1 台架闭环** | B6 `@test` PASS + N-33 `stack_report` 0 FAIL(含 `@test` 复测腿) | Standard | +| **M2 功能面完整** | B7/B8/B9 全部合入 + `ci_local` 全绿 + PC 客户端往返含"定值掉电保持"与"SOE 时标" | Standard | +| **M3 可送检** | B10 注入判据 + 第三方主站全流程通过,证据归档 | **Fixed Date**(送检窗口一到全道让路;窗口前 2 日特性冻结,只修稳定——Zephyr RC 语义) | + +## 3. 并行道(台架 = 约束资源永不空转;代码道 = worktree 并行、绿即合) + +```mermaid +graph LR + subgraph BL[台架道 🔴 串行独占 bench.lock] + B6[B6 @test 复测] --> N33[N-33 栈收口+复测] + end + subgraph CL[代码道 🟢 worktree 并行 绿即合] + B7[B7 定值持久化] -->|合并次序| B8[B8 频率保护] + B7 -->|合并次序| B9[B9 动作记录/SOE] + end + N33 --> M1((M1)) + B8 --> M2((M2)) + B9 --> M2 + M1 --> B10[B10 送检窗口 🟡 Fixed Date] + M2 --> B10 +``` + +## 4. 任务卡(五字段:DoD / 硬依赖 / 资源 / 写范围 / 状态;完成即销项删行) + +> 资源图例:🔴 台架(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(互不相交)。 + +| 序 | 任务 | 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`(无新固件代码) | ⬜ | 保护规划 §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 背书,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` | ⬜ | 保护规划 §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 | + +## 5. 并行规则(执行层映射 → `../环境与部署/并行任务工作树方案.md` §7.3) + +> ① **WIP ≤ 2**:每道最多 1 个进行中(台架道 + 代码道各一),先完再开(Kanban); +> ② worktree 分支**存活 ≤2 天、绿即合**(`done` 预演合并;31 钩子强门禁是并行安全底座); +> ③ 写范围相交必须声明合并次序(见 §4 表注); +> ④ **里程碑不拖延、功能顺延下一轮**(时间驱动,Zephyr 发布语义); +> ⑤ 台架道永不空转:代码道在跑时,为下一个台架任务备料(约束优先,TOC)。 diff --git a/docs/任务规划/基线与待确认.md b/docs/任务规划/基线与待确认.md new file mode 100644 index 00000000..7c77f53a --- /dev/null +++ b/docs/任务规划/基线与待确认.md @@ -0,0 +1,93 @@ +# 基线与待确认(设计参考,少改动) + +> 本文件是**参考基线**,不是待办池:待确认项(§1)、设计基线(§2)、诊断基线(§3)、内存预算(§4)。 +> 待办的排序与登记在 `docs/任务规划/README.md` §2 与 `docs/任务规划/登记簿.md`;**同一事实以内存管理文档为权威**(§3/§4 只是快照指针)。 + +## 1. 待确认(需手册/硬件/产品定义,暂不直接改码) + +1. TPAFE5160 是否有自动扫描模式(**已不影响**:1 kHz 硬件定时器触发已于 2026-10-10 由 **TIM3 更新中断**方案落地,不依赖自动扫描,见 `docs/子系统设计/ADC采样节拍设计说明.md`)。 +2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**;B1 取数不依赖该宏。**RS-485 侧门控随 B2 暂缓,见 `暂缓-RS485.md`**)。 +3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)——**随 B2 暂缓(`暂缓-RS485.md`)**。 + +## 2. 设计基线(供后续接入参考) + +### 2.1 pending 二期设计基线(ACCEPT + SEND) + +> **来源**:一期(RECV)架构现状见 `docs/网络/Net层阻塞模型架构设计.md`(含演进溯源附录); +> 本节仅保留**二期仍要用的设计基线**。 + +**一期已验证的机制骨架**(二期沿用,勿重新发明):独立静态 pending 表 + `net_pending_tick` +主循环节拍了结(五路:数据/到点/断连/同 fd 串行/重建取消必通知)+ 登记守卫(每 fd 至多一个、 +不覆盖、拒绝 netTask 自等待)+ 1s 看门狗强结算。 + +**二期扩展点**: + +| 项 | 目标 | 对应缺陷 | +|---|---|---| +| **ACCEPT pending** | accept 等待改为"登记 → CONNECT 事件完成",退役 100ms/200ms 轮询循环 | E-06(accept 轮询计时失真) | +| **SEND pending** | 发送续传改为"登记 → send_ready 完成",消除 1s/分片 stall 对队列的冻结 | E-02 残余(SEND 位置) | + +**二期门禁**(一期门禁的加强版): + +1. CH395F NET 层全套件(含一期未跑的 Phase 7 / Phase 10,视 RAM 预算); +2. L3/L5 基线重锁(一期已重锁 M3,二期须再锁); +3. `e02_probe.py` **探针族扩充**:close / reconfig / EOF / disconnect-during-pending 四专项; +4. `ftp_regression.py`(D20)+ E-06 假 425 场景**独立重跑**(一期是借 M3 压力档覆盖的); +5. UI 远端推流压力 + timeSync 三场景; +6. 产品 `@test` 闭环 + ST-LINK 全片回读; +7. `ram_report.py` / `stack_report.py` 前后对比(铁律); +8. 看门狗接 selftest 留痕 + 模拟器差距清单 +1(`net_socket_sim.c` 无法建模 pending)。 + +**已知代价(延续一期,需文档化)**:pending 完成判定随主循环节拍运行,被长操作占用时超时 +顺延(~1ms 级);二期把 SEND 也 pending 化后,该顺延面反而**收窄**。 + +**改动量估算**:再 ~300-500 行,集中在 `net_socket.c`;公开 API 不变。风险评级**中** +(执行器核心 + D 系列前科)——**大的是验证,不是代码**。 + +### 2.2 错误码通道四要素(CH395F 范式) + +> **来源**:`../问题记录/错误码传播审计.md`。GD5F 错误通道统一(E-10 / E-42 / E-53 / E-54 / E-56 / E-57) +> 即按此骨架落地(2026-10-03,套件回归 16/16 PASS)。**后续任何驱动 / 子系统建立错误通道时应沿用。** + +``` +① 分类:区分「超时 / 真故障 / 参数错」——不得混为一个返回码 +② 透传:底层错误码逐层上报,不吞不猜(禁 `(void)ret`) +③ 分级:可恢复(重试)/ 不可恢复(上报自检 + 降级)显式判定 +④ 留痕:不可恢复项写 syslog selftest,可恢复项计数并在 UI / 日志可见 +``` + +**关键纪律**(呼应 `AGENTS.md` 已有铁律):**自愈逻辑严禁把"名字 / 参数类错误码" +归入"卷损坏触发集"**——`.fschk` 无限重格式化事故即此类(2026-09-20)。 + +## 3. 诊断基线(供后续对照) + +> **2026-10-10 重采(栈)/ 2026-10-04 重采(堆)**:栈 = **运行时高水位 + armlink 静态最坏链双口径** +> (产品构建 `suite=NONE`,开机 + 空闲采样,串口 `[STACK]` + `stack_report.py`);静态区 = `.map` 受管快照。 +> 栈水位口径:2026-10-10 削链后 defaultTask 实测 **2152 B**、静态最坏链 **2776 B**,**未抬栈**即达标 +> (完整核算见 `docs/内存管理/RAM使用分析与优化方案.md`)。 +> ⚠ 下表为**历史快照**(2026-10-04/10-10 口径);**现行权威数字**看 `docs/内存管理/RAM预算台账.md` +> 与 `docs/内存管理/内存内容分配策略.md` §6(2026-10-12 B5 后:堆 56 KB、RW_CCM 87.9%)。 + +| 项 | 当前值(栈:2026-10-10;其余:2026-10-04) | 出处 | +|---|---|---| +| 产品构建 Flash (ER_IROM1) | 266,632 B / 1024 KB(25.4%);ROM 合计 **267,372 B** | `.map` 受管快照 | +| 产品构建 RW_IRAM1 | **84,960 / 131,072 B(64.8%)** | `.map` 受管快照(`RAM使用分析与优化方案.md` §2.1) | +| 产品构建 RW_CCM | 49,184 / 65,280 B(75.3%,历史当时值。2026-10-12 B5 后堆 56 KB / 87.9%) | 同上 | +| 实测堆 | free=8,664 / **min_ever=4,728 B**(历史当时值,48 KB 堆时代) | V5 串口 `[STACK] heap` | +| **defaultTask 栈峰值** | **2152 / 4096(余 1944 B = 47%);静态最坏链 2776 B(余 32%)** | `[STACK]` + `stack_report.py`(产品构建) | +| netTask 栈峰值 | 920 / 3840(余 76%);静态 1872 B | 同上 | +| ftpTask 栈峰值 | 740 / 4096(余 81%);静态 1216 B | 同上 | +| uiTask 栈峰值 | 4016 / 16384(余 75%);静态 1336 B | 同上 | +| timeSyncTask 栈峰值 | 792 / 2048(余量 61%) | 同上 | +| adcTask 栈峰值(B1,2026-10-10 新建) | **496 / 2048**(余 1552 B / 75%,台架 `@test` 实测);静态最坏链 504 B | 台架 `@test` + `stack_report.py` | +| testTask 栈峰值(产品态空转) | 496 / 8192(余量 93%) | 同上 | +| 队列响应性(挂起客户端) | 92.5ms(pending 一期) | `e02_probe.py` | +| M3 压力档帧周期 | med 60.1 / p95 66.4 / max 69.3ms,零尖峰 | `链路延迟测试说明.md` | + +## 4. 内存预算(支撑 §3 与定栈规则) + +现行权威数据 = `docs/内存管理/RAM使用分析与优化方案.md` v1.2(2026-09-21,§2.1 受管快照): +任务栈在 CCM 堆(defaultTask 1024w / netTask 960w / ftpTask 1024w / testTask 2048w / uiTask 4096w / timeSyncTask 512w / **adcTask 512w**); +产品构建 RW_IRAM1 84,960/131,072 B(64.8%)+ RW_CCM 49,184/65,280 B(75.3%,历史当时值。2026-10-12 B5 后堆 56 KB / 87.9%); +实测堆 `free=8,664 / min_ever=4,728` B(历史当时值,48 KB 堆时代);台账工具 `scripts/ram_report.py` + `scripts/stack_report.py`。 +**旧栈表/旧余量数字作废,勿引用。** diff --git a/docs/任务规划/排期详述.md b/docs/任务规划/排期详述.md new file mode 100644 index 00000000..68c04d30 --- /dev/null +++ b/docs/任务规划/排期详述.md @@ -0,0 +1,26 @@ +# 排期详述(W4 结构债 · W5 验证常态) + +> 波次总览与顺序权威在 `docs/任务规划/README.md` §2;当前波次任务卡在 `W1-采集保护收尾.md`。 +> 本文件只放**已排期但非当前波次**的详述表——低频改动,随窗口更新。 + +## 1. W4 结构债详述 + +> 波内顺序 = 性价比:先可靠性根治,后大体量重构;评估簇随窗口。 + +| 序 | 任务 | 说明 | 出处 | +|---|---|---|---| +| **N-20** | **`Error_Handler` 统一降级** | 一处初始化失败 = 整机挂死(只剩 IWDG 兜底)→ 记自检 + 禁用该子系统 + 其余照常。详见 `登记簿.md` | 报告 N-03c | +| **C6** | **USART1 TX-only 结构根治(S-3)** | 灭 ORE 僵尸机制根源(2026-10-02 台架 IWDG 误复位的机制根源):改 `.ioc` 令 USART1 不使能 RX / PA10 不复用为 `USART1_RX` → CubeMX 重生成 → 跑 `check_cubemx_survival.py`。结构性改动,需单开一轮 + 复跑台架闭环 | S-3 | +| **C3** | **存储侧日志管线(N-2 + N-24)** | 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop`+`[ERR] CONSOLE dropped`、`sys_log_mcu.c` 队列满 `DBG_ERROR`、TX 僵尸通道自愈);V5 30 min 日志**未复现 49s 静默**(运行期 >10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。剩余:与 S8(非阻塞日志)合并评估 + 日志逐条 `f_open/f_write/f_close` 改造评估(N-24) | N-2 / N-24 | +| **C1** | **pending 二期(ACCEPT + SEND)** | 沿一期机制扩展;同期消化 E-25(net_select 语义)、E-24/E-27/E-28(跨上下文收口);基线重锁 + 探针族扩充 + 看门狗接 selftest。**设计基线见 `基线与待确认.md` §2.1** | N-4 | +| **C5** | 一档剩余 | E-15(ringbuf 定去留——**已确认零调用者,倾向删除**)、E-61(SD2506 注释订正)、E-16(cfg_file 段名长度)、E-26(UDP 定案,倾向移除)、E-23、E-30;**N-23 残余**(`KNOWN_GAPS` 白名单清理 + `app_cfg.h` 未接线开关,见 `登记簿.md`)。**E-49(RS485 DE 收尾)已移入 `暂缓-RS485.md`** | 一档/二档 | +| **N-22/25/26/28** | 评估簇 | 写回 flush / 性能与语义一致性 / NAND DMA 断言 / Flash 死代码——逐项见 `登记簿.md` 对应行,随窗口评估 | 报告各条 | + +## 2. W5 验证常态详述 + +| 序 | 任务 | 说明 | +|---|---|---| +| **D2** | N-3 L5 基线重锁 | 下次 Phase 13 窗口顺带做(低风险:阈值余量 >8×;**需 PC peer**) | +| **D5** | **N-16 专项负向台架窗口** | A2/A4 负向场景:PHY 拔线(需断 DTU 侧/关受管交换机端口)、A2 芯片级 `net_init` 失败(SPI 故障注入)、A4 短写压测 | +| **D6** | **N-17 探针窗口心跳缺口** | 定位 `time_sync` 监听重建为何阻塞 NET/FTP/UI(~1s 缺口,余量仅 ~0.7s);评估缩短重建重试或让掉线路径不阻塞其它任务 | +| **D7** | **串口助手 A6/A7 正路径补验** | 需 CH340 硬件接入后补验(`../测试说明/串口助手设计说明.md` 状态行 A1–A5/A8 已过) | diff --git a/docs/任务规划/暂缓-RS485.md b/docs/任务规划/暂缓-RS485.md new file mode 100644 index 00000000..0ae7547b --- /dev/null +++ b/docs/任务规划/暂缓-RS485.md @@ -0,0 +1,12 @@ +# 暂缓:RS-485 整簇(用户决定,2026-10-12) + +> **当前没有处理 RS-485 的打算**,以下条目整体冻结、不占波次;**重启 B2 时先回本文件评估前置,勿直接开工**。 +> 本文件**不是销项**:条目仍在簿,只是不占波次(`docs/任务规划/README.md` §3 维护约定)。 + +| 项 | 内容 | 重启时的前置 | +|---|---|---| +| **B2** | **RS-485 采集链路实现**(消化 E-50、E-49):双缓冲 + 序号(防包撕裂)+ DE 收尾(超时路径等 TC)+ ModBus RTU 状态机(`App/protocol/` 正是为此预留) | **E-59 门禁尚未满足**:先修 E-50(单缓冲包撕裂)、E-49(TX 超时拉 DE 未等 TC),修完驱动契约才允许接消费者 | +| E-49 | RS485 DE 收尾(原 C5 一档剩余,已移出) | 同上 | +| A-4 RS485 侧 | 采集链路测试可验证性约束(双缓冲 + 序号、DE 超时路径覆盖,`测试与架构专项.md` §2.3) | 随 B2 设计文档落地 | +| 待确认-3 | RS-485 PD0 DE 半双工方向语义硬件实测确认(`基线与待确认.md` §1 第 3 项) | 需硬件实测窗口 | +| N-25 中 DE 项 | `HAL_Delay(1)` 阻塞 DE | 随 B2 | diff --git a/docs/任务规划/测试与架构专项.md b/docs/任务规划/测试与架构专项.md new file mode 100644 index 00000000..389df5cc --- /dev/null +++ b/docs/任务规划/测试与架构专项.md @@ -0,0 +1,97 @@ +# 测试与架构改进专项(P1 收尾 / S1x / A-x) + +> 编号空间见 `docs/任务规划/README.md` §0;排期位置见 `docs/任务规划/README.md` §2(W5 验证常态)。 +> **S1~S14 / T-1~T-5 / A-1~A-7** 是 2026-10-02 版复审的**条目编号**——编号**不随条目删除而回收**; +> 其他文档若引用这些编号,其证据见对应模块文档与 `git log`。已完成事项的证据沉淀: +> `../测试说明/系统时钟单元测试说明.md`(S1-a)、`../测试说明/配置文件单元测试说明.md`(S1-b)、 +> `../测试说明/测试开发标准流程.md` §4.2.1(L0.5 适格台账)、`../测试说明/模拟器差距清单.md`(S13)、 +> `../测试说明/实机测试实施指南.md`(S4/S5/S7/S9/S11)、`../问题记录/GD5F2GQ5UE_Trap_Records.md`(S9)。 + +## 1. P1 收尾(1 项:P1-10 剩构建实测闭环) + +### P1-10 测试固件静态 RAM 预算(基线已重建、测试缓冲已瘦身,剩构建实测闭环) + +- **位置**:`MDK-ARM/STM32F407-Demo/STM32F407-Demo.sct`(`RW_IRAM1 0x20000000 0x00020000` = 128KB;芯片 192KB 的上部 64KB 有意未映射,克隆芯片兼容性考量) +- **历史**(2026-09-15 审计 / 09-16 复现):产品构建静态镜像曾 = 123.6KB/128KB(余量仅 4.4KB);HW 全阶段固件的 PHASE5 三缓冲(3×4093B)→ 超 8.7KB(`L6406E` 实测);NET 固件的 32KB `s_rx_buf` → 超约 28KB。 +- **进展**(2026-09-21,已复核):① 预算基线重建(`docs/内存管理/RAM使用分析与优化方案.md` v1.2):FreeRTOS 堆迁 CCM,任务栈改由 CCM 堆分配;产品构建 RW_IRAM1 余 ~49KB;② NET 层测试 32KB `s_rx_buf`/`s_tx_buf` 已移除,改小局部缓冲;③ STORAGE 套件固件 2026-09-20/21 实测可构建可运行。 +- **剩余**:① CH395F 套件(`TEST_SUITE_CH395F`,HW 全阶段 / NET 层 7 配置)实际构建确认链接通过——PHASE5 三静态缓冲 3×4093B 仍在,理论余量足够但未实测;② `@test` 闭环;③ **不建议**扩 scatter 到 192KB(破坏既有克隆芯片兼容决策)。 +- **置信度**:high(基线数据来自 2026-09-21 map;测试固件构建未复验)。 + +## 2. 测试与架构改进专项(S1x / A-x) + +**未闭环一览** + +| 编号 | 事项 | 状态 | 详述 | +|---|---|---|---| +| **S12** | 模块级轻量断言宏 | ⬜ 待做(第 4 波按需) | §2.1 | +| **S1-c** | `sys_log` / `time_sync` 主机侧单测 | ⬜ 可选(价值递减) | §2.2 | +| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ ADC 侧随 B1 闭环;**RS485 侧随 B2 暂缓(`暂缓-RS485.md`)** | §2.3 | +| **A-5 残余** | CI 体积门禁盲区(`mem-numbers` 在 CI 被跳过) | ⬜ 未消除 | §2.4 | + +### 2.1 S12:模块级轻量断言宏 ⬜ + +**动机**:`configASSERT` 只覆盖 FreeRTOS 内部;自研代码的"不该发生"靠散落的 `if`。 + +**设计要点**(**必须零生产开销**): + +```c +/* App/util/app_assert.h —— 示意,非最终实现 */ +#ifdef APP_ASSERT_ENABLE + #define APP_ASSERT(cond) do { if (!(cond)) { \ + DBG_ERROR("[ASSERT] %s:%d", __FILE__, __LINE__); vApplicationAssertFailed(__FILE__, __LINE__); } \ + } while (0) +#else + #define APP_ASSERT(cond) ((void)0) /* 生产构建:编译期消失,零符号零开销 */ +#endif +``` + +**⚠️ 关键纪律**: +- **不得**在中断 / 高频路径使用(`DBG_ERROR` 有代价); +- **不得**替代正常的错误返回(断言是"内部不变量",不是"外部输入校验"); +- 生产构建 `APP_ASSERT_ENABLE` **关闭**——与 `ENABLE_DESTRUCTIVE_TESTS` 同级策略。 + +**建议先在 1~2 处试点**(如 `net_socket.c` 的状态机不变量),验证收益后再推广。 + +**完成判据**:宏存在 + 生产构建 `@build` 0/0 且 `.map` 无新增符号;试点处有实际使用。 + +### 2.2 S1-c(可选):`sys_log` / `time_sync` 主机侧单测 ⬜ + +**范围**:`App/log/sys_log_mcu.c`(定长 64B 记录编解码;落盘部分需桩)、 +`App/sync/time_sync.c`(协议帧编解码;与网络耦合,需先判定可解耦面)。 + +**为何低优先**:两者边界密度低于 `sys_clock` / `cfg_file`,且已有真机路径覆盖 +(`@test` 标记 / `time_sync_server.py`)。**按剩余收益评估后再决定是否做**, +范式完全复用 `../测试说明/看门狗单元测试说明.md`。 + +**完成判据**:`test/host/<模块>/run_unit_test.py` 退出码 0 + 挂 pre-commit 钩子。 + +### 2.3 A-4:ADC / RS485 采集链路的测试可验证性约束 ⏸ + +**背景**:`adc_task.c` 已实现(B1,2026-10-10),`rs485_task.c` 仍是空桩,`App/protocol/` 只有 README 与 `.gitkeep`。 +本项不是"缺陷",而是**对上游 B2 的设计约束**(B1 已完成;**B2 暂缓中,见 `暂缓-RS485.md`——重启 B2 动手前必须先落实本约束**,否则后续无法补测)。 + +**约束**(建议纳入 B2 设计): + +1. **协议解析必须与硬件 I/O 分离**——`App/protocol/` 的解析函数应接受 + `(const uint8_t *buf, size_t len)` 并返回解析结果,使其成为 L0.5 的**天然适格对象** + (参考 `cfg_file` 的"核心 + 后端"模式); +2. **采集缓冲必须双缓冲 + 序号**(上游 E-49 / E-50)——否则消费者读到撕裂数据, + 且**撕裂在单测里测不出来**(时序相关),必须在设计上消除; +3. **DE 收尾必须有超时路径覆盖**(RS485 半双工特有陷阱)。 + +**完成判据**:B2 设计文档体现上述三条;协议解析函数有对应 L0.5 单测。(B1 侧:ADC 无协议解析面,其"同一时刻性"由 E-58 原子快照保证、已闭环。) + +### 2.4 A-5 残余:CI 体积门禁盲区 ⬜ + +**现状**:`mem-numbers` 钩子**在 CI 上被跳过**(CI 无 `.map`)→ **CI 不守体积门禁**。 +S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 `../环境与部署/CI配置指南.md` 声明, +但**盲区本身未消除**——看到 CI 全绿仍可能误以为体积也守住了。 + +**可选处置**: +- 让 runner 具备 Keil 后,在 CI 增 `@build` job(成本高,需授权与许可证); +- 或把"体积校验"固化为**提交前必跑的本地门禁**(`scripts/ci_local.py`,当前已是事实标准)。 + +**完成判据**:存在**强制的**体积校验路径(CI 侧或本地侧),且文档明确其边界。 + +> **注**:本项与栈预算是同一话题的两面——**具体栈风险(原 S-1)已于 2026-10-10 削链闭环** +> (核算见 `docs/内存管理/RAM使用分析与优化方案.md`),本项仍是**门禁缺口**。 diff --git a/docs/任务规划/登记簿.md b/docs/任务规划/登记簿.md new file mode 100644 index 00000000..3a871a13 --- /dev/null +++ b/docs/任务规划/登记簿.md @@ -0,0 +1,53 @@ +# 登记簿(N-x / S-x / T-x 长期观察项) + +> 编号空间与"不回收"规则见 `docs/任务规划/README.md` §0;排期位置见 `docs/任务规划/README.md` §2 波次总览; +> 当前波次任务卡(带 DoD / 写范围 / 状态)在 `W1-采集保护收尾.md`。 +> **本文件是低频文件**:新发现按类别进对应表;销项 = 删行 + 清引用(`docs/任务规划/README.md` §3)。 + +## 1. 网络(CH395F / net 层) + +| # | 事项 | 发现 | 证据与现状 | 出处 | +|---|---|---|---|---| +| N-2 | **49s 全系统日志静默(defaultTask/NAND syslog 排空停滞)**——串口日志 49s 无行,期间 net 栈照常处理外部连接 → 日志管线停滞,队列满后各任务日志行被丢;系统功能不受损 | 2026-09-22(L3 台架 F2,gen 181) | **A/B 归因:既有存储侧现象**。**2026-10-03 降级为低风险观察项**:① 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop` + `[ERR] CONSOLE dropped`;`sys_log_mcu.c` 队列满 `DBG_ERROR`;UART TX 僵尸通道自愈);② V5 30 min **未复现 49s**(>10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。**残余待办**:与 S8(非阻塞日志)合并评估(C3) | `错误码传播审计.md` E-02 阶段二 | +| N-3 | **L5 队列往返基线(1223/988µs)的 L3 后重验**——L5 测 DONTWAIT 队列全程;L3 对该路径逐位不变 → 机制上无影响,但基线数值属分片时代,严格重锁需跑一轮 Phase 13(需 PC peer) | 2026-09-22(L3 收尾留档) | 低风险:10ms/100ms 阈值余量 >8×;下次 Phase 13 窗口顺带重锁即可 | `链路延迟测试说明.md` §6.4 L5 注¹ | +| N-4 | **pending 机制二期:ACCEPT + SEND 阻塞路径 pending 化**——E-06、E-20、E-21 剩余分量共用该机制扩展;届时 L3/L5 基线再重锁、探针族扩充、看门狗接 selftest 留痕、模拟器差距清单 +1 | — | 一期(RECV)已落地并入主线;架构现状见 `Net层阻塞模型架构设计.md`,二期设计基线见 `基线与待确认.md` §2.1 | `错误码传播审计.md` 第二档 #2 | +| N-16 | **A2/A4 专项场景台架验证待办**(正常路径已实测零回归):① PHY 拔线负向测试——断链需断 **DTU 侧**线缆或关**受管交换机端口**;② A2 芯片级 `net_init` 失败分支(需 SPI 故障注入);③ A4 短写压测(需远显客户端 + UI 推流压力) | 2026-10-03(台架拓扑 = CH395↔交换机,拔线操作受限) | 待专项台架窗口 | `实机测试实施指南.md` §10 | +| N-17 | **`time_sync` 30s 挂起客户端掉线 + 监听重建期间,网络任务心跳缺口达 800ms~1s(声明 stall 但未复位)。**待办**:定位监听重建为何阻塞 NET/FTP/UI;评估缩短重建重试(5×2s)或让掉线路径不阻塞其它任务 | 2026-10-03(V5 台架) | V5 长跑 44 次 `task stall: mask=0x00000001`,**100% 与 `e02_probe` 的 30s 挂起客户端触发 `time_sync: no TIME packet in 30s, drop conn` → 监听重建(约 4s)重合**;隔离实验(仅 FTP,120s)**0 次 stall** → 探针场景专属。缺口(~1s)< IWDG 最坏超时(1701ms),余量仅 ~0.7s。 | `实机测试实施指南.md` §4;`../子系统设计/看门狗设计说明.md` | +| N-32 | **CH395F 监听生命周期根治(B10 残余)**——现仅靠对账④兜底(提交 `4f2cc8b`)。根治两步:**P1 把"会话已结束"从边沿改成电平**(`net_sock_t` 增 `session_dead`;`net_recv_locked` DONTWAIT 判据改 `state==CLOSED \|\| session_dead`;`ui_net_sink.c:563` 补 `g_client != g_listen` 护栏;accept 门控换 `net_listener_armed`);**P2 单一所有者**(新增 `net_listener_pump`,删 `net_accept_locked:1346`/`net_recv_locked:1884`/`net_pending_tick:2451` 散点 relisten;消灭 netTask 内 500 ms 忙等 `:2597-2616`/`:1115-1126`)。**已定案不走芯片多连接模式(A′ 出局:不支持多监听)** | 2026-10-12(B10 定案;⚠ ④ 有副作用——抢先 relisten 会把慢消费者的 EOF 永久吞掉,新客户端数据被旧会话静默吸收,待 P1 消除) | 原理 + 证据附录(实测数据 / 官方例程所有权 / 状态机 15 迁移点 / 三服务契约不一致表)+ **决策记录 D1~D7** + 可勾选执行清单 → `../子系统设计/网络Socket监听生命周期设计说明.md` §7~§9;现象与回归见 `../问题记录/CH395F_Trap_Records.md` B10 行 | + +## 2. 存储 / 日志管线 + +| # | 事项 | 发现 | 证据与现状 | 出处 | +|---|---|---|---|---| +| S-3 | **USART1 TX-only 结构根治(灭 ORE 僵尸机制)**——ORE 锁存在外设软复位后毫秒级重锁(PA10 悬空 + RX 使能),是 2026-10-02 台架"背靠背 drain 拉长主循环 → 喂狗节奏饥饿 → IWDG 误复位"的**机制根源**。现仅有缓解(单次 drain 250ms 预算 + 发送故障后 300ms 冷却),**未根治** | 2026-10-02(台架 gen-288) | **待办**:改 `.ioc` 令 USART1 为 TX-only → CubeMX 重生成 → 跑 `scripts/check_cubemx_survival.py`。结构性改动,需单开一轮并复跑台架闭环 | `../子系统设计/控制台单写者日志设计说明.md` §12(含 O4) | +| S-4 | **dhara 重试自旋残留**——`try_recover()` 的 `DHARA_MAX_RETRIES`(8) 自旋在坏块密集时仍可能长时间占用 defaultTask(喂狗点) | 2026-10-02 | 低优先:现有 `vol_lock` + 喂狗节奏缓解;若台架再出"存储侧喂狗饥饿"再排期 | `Lib/dhara/map.c` | +| S-5 | **可选全序列卷锁**——现卷锁仅覆盖 `syslog` / `cfg` / `lftpd` 三条路径(`vol_lock_wait(0)` try 语义),其它潜在访问点(如 UI 读日志)未纳入 | 2026-10-02 | 待评估:先确认是否真有第二写者;无则关闭本项 | `App/fs/vol_lock.{c,h}` | + +## 3. 硬件(V0.1 缺陷 → V0.2 改版项) + +| # | 事项 | 发现 | 证据与现状 | 出处 | +|---|---|---|---|---| +| N-18 | **8 路电气量分属两片转换器(V0.1 硬件缺陷,需下一版硬件修改)**——UA/UN/IA 走 TPAFE5160(16 位、8 通道同步、±5 V 双极性),UB/UC/IB/IC/IN 走 STM32 ADC(12 位、顺序扫描、0~3.3 V 单极性):① 两片转换器无共同采样触发 + STM32 侧顺序扫描(9 通道一轮 ≈ 67 µs)→ 跨转换器通道**无同一时刻性、相位关系不确定**,主板侧功率/功率因数/相角/对称分量类运算不成立;② 同族电气量精度与量程不一致(LSB ≈ 152.6 µV vs ≈ 806 µV,且 STM32 侧前端无中点偏置、负半周削顶);③ 语义与硬件归属交叉,固件映射/UI 通道序/自检注入须逐通道查表绕开 | 2026-10-10 定性更正(**撤销** 2026-10-09 建档时"有意分配、不要修正"的说法) | **V0.2 改版要求**:8 路电气量 UA/UB/UC/UN/IA/IB/IC/IN **全部接 TPAFE5160**,与 TPAFE 上 5 路备用路(AIN5/13/7/15/12)对调串联电阻在转换器一侧的目的地——元件数量与料号不变,属走线级改动。**V0.1 现板软件口径**:主板侧只做逐通道独立监视,禁止跨转换器做相位/功率/功率因数/矢量类运算(此类量取子板计量模块结果)。固件侧消费者已落地(B1,2026-10-10,按语义映射表取数)→ V0.2 改版只改映射表内容,上层语义与代码不动 | `../硬件平台/ADC通道映射说明.md` §1/§7;`../硬件平台/V0.1_网表详细分析报告.md` §1.4 V10、§6-3 | + +## 4. 测试与验证基础设施 + +| # | 事项 | 优先级 | 问题与证据 | 处置方向 | 出处 | +|---|---|---|---|---|---| +| T-7 | **CI runner 未就绪(部署前置)** | 中 | `.gitea/workflows/ci.yml` 已落地,但 CI 仅在 runner 就绪后才真正生效:① Gitea 实例 `[actions] ENABLED = true`;② 注册 Windows runner(labels 含 `windows`),装 Python 3.x / cppcheck / pre-commit / MSVC;③ runner 就绪后**推送远端跑一次两 job 闭环验证**(当前 21 个提交未推送,CI 从未真实执行);④ **第二机交叉验证**(不同工具安装路径,验 `DTU_*` 环境变量方案,→ `../环境与部署/本地工具路径环境变量方案.md` 变更记录 TODO) | runner 未就绪前,**提交前仍须在本地跑 `scripts/ci_local.py` 或 `pre-commit run --all-files` 自查**(L0 唯一保障,不能因"已配 CI"而放宽) | `.gitea/workflows/ci.yml`;`../测试说明/测试开发标准流程.md` §9 | + +## 5. 审查报告并轨(2026-10-11;⚠ 报告编号与本登记簿同名不同义,出处列保留报告编号,引用一律带文档名) + +| # | 事项 | 影响 / 现状 | 处置方向 | 波次 | 出处 | +|---|---|---|---|---|---| +| N-20 | `Error_Handler` 仍 `__disable_irq(); while(1){}`(`Src/main.c:274-282`) | 一处初始化失败 = 整机挂死(只剩 IWDG 兜底),无自检日志 | 统一降级策略:记自检 + 禁用该子系统 + 其余照常 | W4 | 报告 N-03c | +| N-21 | **dhara 两处**:`dhara_nand_is_free()` 只查页首 64 B;`dhara_nand_copy()` 不处理 `DHARA_NO_PAGE` 哨兵 | 映射恢复误判 → **数据丢失风险**(低概率、后果重);哨兵页号被当真实页 → 未定义行为;至今只能靠人工读代码发现 | 整页(或首/中/尾)扫描 + 返回 `DHARA_E_UNSUPPORTED`;**必须配主机侧移植层单测**(一并补报告"覆盖率"缺口) | **W2** | 报告 N-12/N-13 + §7 | +| N-22 | 写回缓存无空闲/掉电强制 flush(整页写与换页已 flush) | 写回窗口内掉电丢最近日志/配置写 | defaultTask 空闲 N ms flush | W4 | 报告 N-14 | +| N-23 残余 | **钩子已落地**(2026-10-12 `registration-check` 挂 pre-commit,存量缺口走 `KNOWN_GAPS` 白名单只 WARN);**残余** = 白名单清理:`rs485_task.c`(随 B2 暂缓一并处置:删除或注册)、`lftpd_log.c`;`app_cfg.h` 未接线开关(C5) | 白名单不清 = "写了不编译"盲区仍在 | 逐项清白名单(`--strict` 供审计复跑);开关随 C5 处置 | W4(C5) | 报告 N-06 残余 + 报告 S-3 | +| N-24 | 日志每条 `f_open+f_write+f_close`(`sys_log_mcu.c:123-140`) | 每条日志 2–4 次 NAND 页读写;UI 翻记录逐条 open/seek/close | 与 C3 日志管线合并评估(现仅 `FIL` static 化省 528 B 栈) | W4 | 报告 N-16(**≠ 本登记簿 N-16**) | +| N-25 | 性能/资源建议簇:PASV 每次新建监听;`NET_RECV_TIMEOUT_MS 30000`;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(**DE 项随 B2 暂缓,见 `暂缓-RS485.md`**) | 次级性能/语义一致性 | 逐项见 `../问题记录/项目审查与优化建议报告.md` §4.2/§4.5/§4.7,随窗口评估 | W4 | 报告 N-09/P2-8/PHY/P3-x/rs485 | +| N-26 | NAND 直 DMA 调用方缓冲(已加运行时守卫,阈值 1024) | CCM 缓冲被 DMA = 静默传错(与 ADC DMA 不可达 CCM 同类坑) | 补编译期/启动期地址断言 + **新铁律:堆缓冲不可被 DMA 直接寻址** | W4 | 报告 N-11 | +| N-27 | **内存优化簇**:LVGL 池 + UI 两份缓冲 54,146 B 仍在 SRAM1,CCM 只剩 ≈8,160 B(2026-10-12 B5 堆扩容 48→56 KB 后) | R-2 后半段(迁 CCM)被堵死 → 后续功能预算看不清 | **三件套 ✅ 2026-10-12 落地**(`ram_baseline.py` 四模式 + `ram_baseline.tsv` 趋势 + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子 92% 门禁)→ **W3** 再做 R-9(`LV_MEM_SIZE` 40→16 KB,池水位门禁数据已具备)→ R-2 后半;R-3/R-4/R-5/R-6 逐项评估(R-6 前置已满足) | **W3** | 报告 R-2 剩余/R-3~R-6/R-9/§5.5 | +| N-28 | Flash 死代码评估簇:剩余 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个空 LVGL TU(F-1/F-2/F-3 已闭环,省的是编译时长) | 编译时长 + 文档噪音 | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制必经路径,**不可盲关** | W4 | 报告 F-4/F-5/F-6 | +| N-29 | **仓库膨胀**:`.git` 149 MB + 图片 36.3 MB | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(届时未推送提交更少、重写代价最低) | **W7** | 报告 D-1 | +| N-33 | **栈余量收口:defaultTask / timeSyncTask `stack_report` FAIL**(2026-10-12 复测:defaultTask 静态 3016 B/余 1080 B < 30% 线,链含 dhara GC→控制台回显→`(Cycle)`;timeSyncTask 静态 1264 B/余 784 B < ISR 底线 1024 B)——**既有债,非 B4/B5 引入** | 深链 + ISR 嵌套场景栈溢出风险(保护链稳定性相关) | 抬栈(需 B6 min_ever 背书)或瘦链(控制台回显尾 / Error_Handler 环),详表见 `W1-采集保护收尾.md` | **W1** | 2026-10-12 `stack_report.py` 实测 | +| U 簇 | UI 标准化:无令牌层/组件库/页注册表(手写 `case` 仍在),**27 页**未落地;golden 未挂 pre-commit、字符集差集检查仍是约定 | 新增一页成本仍是 8 处手工改动 | 按 `../问题记录/项目审查与优化建议报告.md` §6.5:U4 残余(两脚本入门禁,可逢窗口顺带)→ U1 令牌层 → U2/U3 → 页面落地;U4 golden 可直接当 U1 验收工具。**已确认(2026-10-11):本轮不排期**,等功能主线出结果后按产品需求启动 | W6 | 报告 U1~U5 | diff --git a/docs/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index ff904c66..80bf930a 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -9,7 +9,7 @@ ## 1. 背景与目标 -`待处理内容.md` 已提出:"所有任务的内存都是往大的给的,导致内存不够用,要仔细排查内存的预算情况"。 +登记簿(原 `待处理内容.md`,现 `docs/任务规划/`)已提出:"所有任务的内存都是往大的给的,导致内存不够用,要仔细排查内存的预算情况"。 分析起点(2026-09-11 快照,逐符号见 `data/ram_report_20260911.md`): diff --git a/docs/内存管理/RAM预算台账.md b/docs/内存管理/RAM预算台账.md index 1a395a81..aa00c622 100644 --- a/docs/内存管理/RAM预算台账.md +++ b/docs/内存管理/RAM预算台账.md @@ -32,7 +32,7 @@ - **门禁**:pre-commit `mem-budget` 钩子(`scripts/ram_baseline.py --gate`)—— RW_IRAM1 / RW_CCM 任一 >92% 即拦提交,并打印 Top-10 RW+ZI 对象定位增量; - 无 `.map` 时自适应跳过(CI 盲区登记在 `docs/待处理内容.md` A-5 残余)。 + 无 `.map` 时自适应跳过(CI 盲区登记在 `docs/任务规划/测试与架构专项.md` A-5 残余)。 - **阈值依据**:92% = `docs/问题记录/项目审查与优化建议报告.md` §5.5 第 1 条——留 ~8% 给突发缓冲与栈抬升, 触线即触发排期,而不是静默逼近溢出。 - **软提醒**(不拦提交):tsv 末行落后于 `.map`(忘跑 `--update`)、`.map` 早于最新源码(忘 `@build`)。 @@ -58,7 +58,7 @@ UI 16 KB / RTOS 堆 56 KB / 应用 8 KB**。归集口径(按 `.map` 对象名 - **UI ⚠ 超配额 = W3 的既有债务,不是新增违规**:LVGL 池 40 KB(R-9 目标 16 KB)+ 帧/远显缓冲 ≈12.8 KB(R-2 目标迁 CCM)——配额 16 KB 描述的是 **R-9/R-2 落地后的目标态**(排期见 - `docs/待处理内容.md` §2 W3)。 + `docs/任务规划/README.md` §2 W3)。 - **RTOS 堆 = 配额本身**:56 KB 即 `configTOTAL_HEAP_SIZE`(2026-10-12 B5 由 48 KB 扩容,见 §6; `heap_4.o` 另含 32 B 元数据,不计超);**改堆 = 改配额**,必须先过本文件 §6 登记。 - **应用 ⚠ 小幅超**:8 KB 为报告规划值;2026-10-10 栈整改把 3 处 `FIL` 从栈搬进 BSS diff --git a/docs/子系统设计/ADC采样节拍设计说明.md b/docs/子系统设计/ADC采样节拍设计说明.md index fb4c246d..fbf38a59 100644 --- a/docs/子系统设计/ADC采样节拍设计说明.md +++ b/docs/子系统设计/ADC采样节拍设计说明.md @@ -131,7 +131,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) ### 4.5 文档同步(2026-10-10 已执行) - `docs/算法/继电保护功能复现规划.md`:§3.2 L1-1 由 🔶 改为 ✅(TIM6 硬件触发)、§1.2 采样软件行 + 变更记录同步。 -- `docs/待处理内容.md` §4:TPAFE 自动扫描模式待确认项标注"已不影响"(TIM6 方案不依赖它)。 +- `docs/任务规划/基线与待确认.md` §1:TPAFE 自动扫描模式待确认项标注"已不影响"(TIM6 方案不依赖它)。 - `AGENTS.md` 架构要点 `adcTask` 条 + `app_main_init` 序列:改为"TIM6 硬件触发 + 纯消费者"。 - `Drivers/BSP/TPAFE5160/README.md`:周期重触发改为"由 TIM6 更新中断提供"。 diff --git a/docs/子系统设计/IEC104上行设计说明.md b/docs/子系统设计/IEC104上行设计说明.md index 346c7b12..8c0d995f 100644 --- a/docs/子系统设计/IEC104上行设计说明.md +++ b/docs/子系统设计/IEC104上行设计说明.md @@ -3,7 +3,7 @@ > **定位**:DTU 上行规约 IEC 60870-5-104(DL/T 634.5104-2009)的设计基线—— > 范围、点表、链路流程、板端接入、预算与测试。规格来源 > `docs/算法/继电保护功能复现规划.md` §1.5(B0 产品定义,验收 = 省电科院点表); -> 代码落点 `App/protocol/iec104/`;登记项 `docs/待处理内容.md` §2.1(W1 / B4)。 +> 代码落点 `App/protocol/iec104/`;登记项 `docs/任务规划/W1-采集保护收尾.md`(W1 / B4)。 > **角色**:本 DTU = **被控站(受控端)**,104 **TCP 服务器,端口 2404**;主站 > (控制端,点表参考 `192.168.1.199`)主动连入。 @@ -58,7 +58,7 @@ | 19~20 | 零序过流 Ⅰ/Ⅱ | L3-2 未实现 | ❌ IV | | 21~22 | 接地故障/重载 | 未实现 | ❌ IV | | 23 | 过载 | `PE_OL` asserted | ✅ | -| 24~30 | 外部遥信(RS-485) | B2 暂缓(`docs/待处理内容.md` §2.4) | ❌ IV | +| 24~30 | 外部遥信(RS-485) | B2 暂缓(`docs/任务规划/暂缓-RS485.md`) | ❌ IV | | 31 | 保护闭锁 | `prot_set_locked()` | ✅ | | 32~33 | 预留 | — | ❌ IV | diff --git a/docs/子系统设计/控制台单写者日志设计说明.md b/docs/子系统设计/控制台单写者日志设计说明.md index ace3d478..2983ca8d 100644 --- a/docs/子系统设计/控制台单写者日志设计说明.md +++ b/docs/子系统设计/控制台单写者日志设计说明.md @@ -323,7 +323,7 @@ sequenceDiagram **未做(根治)**:让 USART1 为 **TX-only**(.ioc 中不再使能 RX / PA10 不作 USART1_RX), 从机制上消除 ORE。属 `.ioc` 结构性改动 + CubeMX 重生成,需单开一轮并复跑台架闭环 -→ 已登记为 `待处理内容.md` **S-3**。 +→ 已登记为 `docs/任务规划/登记簿.md` **S-3**。 ## 13. 开放问题 @@ -332,7 +332,7 @@ sequenceDiagram | O1 | 未注册期裸发无互斥 | 启动窗口(内核启动 → attach)`dbg_console_write_raw` 无互斥 → 多任务并发会**逐字节交错**(非旧 `HAL_BUSY` 丢整行)。2026-10-10 已固化"周期任务用 `dbg_console_writer_ready()` 门控"纪律;若未来开机日志密度上升,可升级为"内核前静态待发行 + attach 后统一补发"或给裸发加轻量互斥 | | O2 | `HAL_UART_Transmit` 超时未计数 | 超时块(UART 物理失效)丢弃但不入 `s_con_drop`;v2 可加独立超时计数 | | O3 | `printf` 逐字节开销 | 遗留 `printf` 路径 = 逐字节临界区 + 逐字节事件置位;遗留调用点全部切 `DBG_*` 宏后开销自然消失(不改变机制) | -| O4 | **ORE 僵尸未根治** | §12:现仅有缓解(250ms 预算 / 300ms 冷却 / DWT 超时),机制根源是 USART1 使能了 RX。根治需 `.ioc` 改 TX-only + CubeMX 重生成 → 已登记 `待处理内容.md` **S-3** | +| O4 | **ORE 僵尸未根治** | §12:现仅有缓解(250ms 预算 / 300ms 冷却 / DWT 超时),机制根源是 USART1 使能了 RX。根治需 `.ioc` 改 TX-only + CubeMX 重生成 → 已登记 `docs/任务规划/登记簿.md` **S-3** | ## 14. 相关文档 diff --git a/docs/子系统设计/看门狗设计说明.md b/docs/子系统设计/看门狗设计说明.md index 9f99f809..e44f28db 100644 --- a/docs/子系统设计/看门狗设计说明.md +++ b/docs/子系统设计/看门狗设计说明.md @@ -6,7 +6,7 @@ > **日期**:2026-09-29 创建;**2026-10-10 按当前代码重写正文**(旧正文含大量立项前的 > 描述,已清理;实施史与逐次决策见 §10 与文末变更记录,未删)。 > **相关文档**: -> [`../待处理内容.md`](../待处理内容.md)(未办项 N-17 / S-3 / N-4)、 +> [`../任务规划/README.md`](../任务规划/README.md)(登记簿未办项 N-17 / S-3 / N-4,见 `../任务规划/登记簿.md`)、 > [`运行与自检记录设计说明.md`](运行与自检记录设计说明.md)(复位记录与 `selftest.log`)、 > [`../测试说明/看门狗单元测试说明.md`](../测试说明/看门狗单元测试说明.md)(L0.5 判定状态机单测)、 > [`../测试说明/实机测试实施指南.md`](../测试说明/实机测试实施指南.md)(故障注入台架流程)、 diff --git a/docs/待处理内容.md b/docs/待处理内容.md deleted file mode 100644 index 3571d97d..00000000 --- a/docs/待处理内容.md +++ /dev/null @@ -1,409 +0,0 @@ -# 待处理内容(统一待办登记簿) - -> **这个文件是什么**:全项目唯一的未闭环事项清单 + 全项目唯一权威的工作先后顺序。 -> -> **怎么用**:想知道"现在该做什么、按什么顺序" → 只看 **§2**;想知道"某条待办的来龙去脉" → 按编号查 **§3**; -> 想知道"还差哪些验证" → §2.3。其余章节:编号规则(§0/§8)、待确认(§4)、设计与诊断基线(§5~§7)。 -> -> **只保留待办**:已完成条目直接删除,不留变更记录(历史见 `git log` 与各模块文档); -> 已闭环项的**结论与证据沉淀进对应模块文档/问题记录**,本文件不再重复。 -> **消化即销项**:事项修复/关闭后,直接删除对应条目,并同步清理其它文档对本编号的引用。 -> -> **不在本文件范围**:`问题记录/错误码传播审计.md`(E-xx,审计报告,非待办池)、 -> `问题记录/项目审查与优化建议报告.md`(体系层评审报告)、`测试说明/实机测试实施指南.md`(执行流程)。 -> -> **修订**:2026-10-04 四档合并;2026-10-11 统一排序 + 审查报告并轨; -> **2026-10-12 按用户决定 RS-485(B2)整簇暂缓(§2.4),波次重排为 W1~W7,清除已销项残留**; -> **2026-10-12 W1-0 台账三件套落地(N-27 前半闭环,`mem-budget` 钩子),N-23 钩子落地残余并入 C5**; -> **2026-10-12 B4/B5 销项——W1 功能主线代码侧全部完成**(验收窗口见 §2.1)。 - ---- - -## 0. 编号空间与来源 - -| 编号 | 含义 | 备注 | -|---|---|---| -| `P0-x`~`P3-x` | 审计缺陷/改进项(2026-09-15/09-21 审计) | P0=功能 bug、P1=疑似 bug/健壮性、P2=改进、P3=卫生 | -| `N-x` / `S-x` / `T-x` | 台架/审计观察登记项 / 存储·日志管线 / 测试与工具链 | 编号**不回收**;`N-x` 含硬件改版项(需下一版硬件,固件侧只记口径,如 N-18) | -| `S1~S14` / `A-1~A-7` | 2026-10-02 复审的测试充分性与架构专项 | 编号**不回收** | -| `E-xx` | 错误码传播审计发现 | 独立维护于 `错误码传播审计.md`,**不并入本文件**,只交叉引用 | -| `B`/`C`/`D` 前缀 | §2 排序条目编号:B=功能主线、C=结构债、D=验证窗口 | 编号不回收,见 §2 | -| 报告 `N-x`/`R-x`/`F-x`/`S-x`/`U-x`/`D-x` | `项目审查与优化建议报告.md` **自有编号** | ⚠ **与本登记簿同名不同义**(报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架)→ **引用一律带文档名**。其未闭环项 2026-10-11 并入本登记簿(新编 `N-19`~`N-29` + U 簇,出处列保留报告编号) | - -**严重度定义**(沿用审计口径):P0 = 确认功能 bug|P1 = 疑似 bug 或健壮性风险|P2 = 改进|P3 = 卫生。 -**置信度**:high = 代码级确证|medium = 依赖外部条件(手册/硬件/产品定义)。 - ---- - -## 1. 未闭环一览(按类别) - -| 类别 | 数量 | 条目 | -|---|---|---| -| P1 收尾 | 1 | P1-10 测试固件构建实测(§3.1) | -| 网络 | 5 | N-2(49s 日志静默,**低风险观察项**)· N-3(L5 基线重验)· N-4(pending 二期)· N-16(A2/A4 负向台架)· N-17(探针窗口心跳缺口) | -| 存储 / 日志 | 3 | **S-3(USART1 TX-only 根治)** · S-4(dhara 重试自旋)· S-5(可选全序列卷锁) | -| 数据正确性 | 1 | **N-21(dhara `is_free`/`copy`,全簿最高风险)** | -| 结构 / 健壮性 | 8 | N-20(Error_Handler 死循环)· N-22(写回 flush)· N-23(注册校验残余白名单)· N-24(日志逐条开关)· N-25(性能/语义簇)· N-26(NAND DMA 断言)· N-27(内存优化簇,三件套 ✅ 前半落地)· N-28(Flash 死代码簇) | -| 仓库 | 1 | N-29(`.git` 149 MB,**已决策暂不处理、登记观察**) | -| 硬件 | 1 | N-18(V0.2 改版项) | -| 测试 / 基础设施 | 6 | T-7(CI runner + 推送闭环 + 第二机交叉验证)· S12(断言宏)· S1-c(可选单测)· A-4(采集链路测试约束,RS485 侧随 B2 暂缓)· A-5 残余(CI 体积门禁盲区)· D7(串口助手 A6/A7 待 CH340) | -| UI | 1 簇 | U 簇(27 页标准化,**本轮不排期**) | -| **暂缓** | 1 簇 | **B2 RS-485 整簇(2026-10-12 用户决定,§2.4)** | - -> **网络侧另有 E-xx 未闭环项**(E-12/15/16/23/24/25/26/27/28/30/47/48/49/50/58/59/61,共 17 项) -> 与 1 项回归监督(E-62),详见 `问题记录/错误码传播审计.md` §3——其中 **E-49/E-50 随 RS-485 暂缓**。 -> 本文件不重复登记。UI 标准化簇与覆盖率缺口(lftpd/dhara 移植层无主机测试)为整簇排期项,见 §2 W6 / N-21。 - -### 1.1 结构性判断(排序依据) - -1. **产品功能主线"转发 + 保护"两环代码已落地(2026-10-12)**:采集侧 ADC(B1)已台架闭环;上行 IEC104(B4)与保护判据 protectTask(B5)代码均已落地(`App/protocol/iec104/` + iec104Task;`App/task/protect_task.c` 20 ms 判据节拍→104 遥信),**遗留为验收窗口**(台架主站往返随送检、标准源注入、`@test` 水位)。**RS-485 对下采集(B2)按用户决定暂缓(2026-10-12,§2.4),主线不再等它**。 -2. **数据正确性最高风险 = N-21**(dhara `is_free` 只查页首 64 B / `copy` 不处理哨兵):低概率、后果重(数据丢失),且至今只能靠人工读代码发现——修复须配主机侧移植层测试(一并补报告"覆盖率"缺口)。 -3. **内存预算红线已机械化(2026-10-12,W1-0)**:`mem-budget` 钩子拦 RW_IRAM1/RW_CCM >92%,子系统配额 / CCM 台账 / 趋势基线 → `docs/内存管理/RAM预算台账.md`;实际优化 R-9→R-2 排 W3(**B5 堆扩容 48→56 KB 后 CCM 只剩 ≈8,160 B**,解锁链见 `docs/内存管理/RAM预算台账.md` §3)。 -4. **验证债仅剩窗口性事项**(D2/D5/D6/D7 + P1-10 收尾),不单独排期、逢窗口顺手做。 - ---- - -## 2. 统一推进顺序(全项目唯一权威) - -> **本节是全项目所有工作流唯一的权威顺序**:`产品需求设计文档.md` §9.2、`算法/继电保护功能复现规划.md`、 -> `项目审查与优化建议报告.md` §0.3 中的路线图均为局部视图,**顺序变更只改本节,其它文档只留指针**。 -> 排序原则:**安全风险 > 产品功能主线 > 数据正确性 > 预算/结构债 > 验证常态 > UI 扩展 > 仓库决策**(当前无未闭环安全项)。 - -### 2.0 波次总览 - -| 波次 | 内容 | 为什么在这 | -|---|---|---| -| **W1 功能主线** | **B4 IEC104 上行 ✅ 2026-10-12 → B5 protectTask ✅ 2026-10-12(W1 代码侧全部完成)**(W1-0 台账三件套 ✅ 2026-10-12 落地,见 N-27) | DTU 核心职责"转发 + 保护"两环代码均已落地:B4(`App/protocol/iec104/` 三件套 + iec104Task 2404,82 断言 L0.5 + `iec104-unit-test` 钩子);B5(`App/task/protect_task.c` 20 ms 判据节拍 + L5-4 采样闭锁 + IWDG bit8 + 栈 512 words 静态链 872 B/余 57% + 堆 48→56 KB,见 `docs/算法/继电保护功能复现规划.md` §7 变更记录)。**遗留 = 验收窗口**:台架第三方主站往返(`docs/子系统设计/IEC104上行设计说明.md` §7/§8)+ 标准源注入动作判据 + `@test` PROT 锚点/水位 | -| **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** | 无紧急,按性价比排:C6 灭 IWDG 误复位机制根源;C1 体量大、验证重,放后(N-23 钩子已落地 2026-10-12,残余并入 C5) | -| **W5 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · D7 串口助手 · S12 · S1-c · A-5 | 窗口性,逢机顺带,不单独排期 | -| **W6 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5);**本轮不排期(2026-10-11 已确认)** | -| **W7 仓库决策** | **N-29** `.git` 149 MB + 图片 36.3 MB | **已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(`git filter-repo` 历史重写影响未推送提交与协作者) | -| **暂缓** | **B2 RS-485 整簇**(§2.4) | **用户决定(2026-10-12):当前不处理 RS-485** | -| **硬件改版** | N-18 8 路电气量全接 TPAFE(V0.2) | 下一版硬件;固件侧已用语义映射隔离,改版只动映射表 | - -### 2.1 W1 功能主线详述 - -> **背景(已闭环,只留指针)**:B0 产品定义 2026-10-10 确认——上行 **IEC 60870-5-104**(以太网 TCP 2404, -> 遥测短浮点系数 1)/ 持续采集 / **1000 Hz(20 点/周波)** / RS-485 对下 ModBus RTU,结论详见 -> `docs/算法/继电保护功能复现规划.md` §1.5 与 `docs/产品需求/产品需求设计文档.md` §5.9/§5.10/§9; -> B1 ADC 采集链路已 `@test` 实机闭环;B3 纪律门禁已固化进 `AGENTS.md`。 -> -> **W1 全部销项(2026-10-12)**:B4 证据见 `docs/子系统设计/IEC104上行设计说明.md`(82 断言 + 钩子 + `@build` 0/0); -> B5 证据见 `docs/算法/继电保护功能复现规划.md` §7 变更记录(protectTask 20 ms 判据节拍 + L5-4 采样闭锁 + -> IWDG `TASK_WD_PROTECT` bit8 + 栈 512 words 静态链 872 B/余 57% + 堆 48→56 KB + prot_elm 28 用例)。 -> **遗留验收窗口**(非代码空洞):台架第三方 104 主站往返(随送检窗口)、标准源注入动作判据、 -> `@test` PROT 锚点 + `[STACK] protect` 水位 + 新堆 min_ever 复测。 - -### 2.2 W4 结构债详述 - -> 波内顺序 = 性价比:先可靠性根治,后大体量重构;评估簇随窗口。 - -| 序 | 任务 | 说明 | 出处 | -|---|---|---|---| -| **N-20** | **`Error_Handler` 统一降级** | 一处初始化失败 = 整机挂死(只剩 IWDG 兜底)→ 记自检 + 禁用该子系统 + 其余照常。详见 §3.2 | 报告 N-03c | -| **C6** | **USART1 TX-only 结构根治(S-3)** | 灭 ORE 僵尸机制根源(2026-10-02 台架 IWDG 误复位的机制根源):改 `.ioc` 令 USART1 不使能 RX / PA10 不复用为 `USART1_RX` → CubeMX 重生成 → 跑 `check_cubemx_survival.py`。结构性改动,需单开一轮 + 复跑台架闭环 | S-3 | -| **C3** | **存储侧日志管线(N-2 + N-24)** | 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop`+`[ERR] CONSOLE dropped`、`sys_log_mcu.c` 队列满 `DBG_ERROR`、TX 僵尸通道自愈);V5 30 min 日志**未复现 49s 静默**(运行期 >10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。剩余:与 S8(非阻塞日志)合并评估 + 日志逐条 `f_open/f_write/f_close` 改造评估(N-24) | N-2 / N-24 | -| **C1** | **pending 二期(ACCEPT + SEND)** | 沿一期机制扩展;同期消化 E-25(net_select 语义)、E-24/E-27/E-28(跨上下文收口);基线重锁 + 探针族扩充 + 看门狗接 selftest。**设计基线见 §5.1** | N-4 | -| **C5** | 一档剩余 | E-15(ringbuf 定去留——**已确认零调用者,倾向删除**)、E-61(SD2506 注释订正)、E-16(cfg_file 段名长度)、E-26(UDP 定案,倾向移除)、E-23、E-30;**N-23 残余**(`KNOWN_GAPS` 白名单清理 + `app_cfg.h` 未接线开关,见 §3.2)。**E-49(RS485 DE 收尾)已移入暂缓(§2.4)** | 一档/二档 | -| **N-22/25/26/28** | 评估簇 | 写回 flush / 性能与语义一致性 / NAND DMA 断言 / Flash 死代码——逐项见 §3.2 对应行,随窗口评估 | 报告各条 | - -### 2.3 W5 验证常态详述 - -| 序 | 任务 | 说明 | -|---|---|---| -| **D2** | N-3 L5 基线重锁 | 下次 Phase 13 窗口顺带做(低风险:阈值余量 >8×;**需 PC peer**) | -| **D5** | **N-16 专项负向台架窗口** | A2/A4 负向场景:PHY 拔线(需断 DTU 侧/关受管交换机端口)、A2 芯片级 `net_init` 失败(SPI 故障注入)、A4 短写压测 | -| **D6** | **N-17 探针窗口心跳缺口** | 定位 `time_sync` 监听重建为何阻塞 NET/FTP/UI(~1s 缺口,余量仅 ~0.7s);评估缩短重建重试或让掉线路径不阻塞其它任务 | -| **D7** | **串口助手 A6/A7 正路径补验** | 需 CH340 硬件接入后补验(`串口助手设计说明.md` 状态行 A1–A5/A8 已过) | - -### 2.4 暂缓:RS-485 整簇(用户决定,2026-10-12) - -> **当前没有处理 RS-485 的打算**,以下条目整体冻结、不占波次;**重启 B2 时先回本节评估前置,勿直接开工**。 - -| 项 | 内容 | 重启时的前置 | -|---|---|---| -| **B2** | **RS-485 采集链路实现**(消化 E-50、E-49):双缓冲 + 序号(防包撕裂)+ DE 收尾(超时路径等 TC)+ ModBus RTU 状态机(`App/protocol/` 正是为此预留) | **E-59 门禁尚未满足**:先修 E-50(单缓冲包撕裂)、E-49(TX 超时拉 DE 未等 TC),修完驱动契约才允许接消费者 | -| E-49 | RS485 DE 收尾(原 C5 一档剩余,已移出) | 同上 | -| A-4 RS485 侧 | 采集链路测试可验证性约束(双缓冲 + 序号、DE 超时路径覆盖,§3.3.3) | 随 B2 设计文档落地 | -| §4-3 | RS-485 PD0 DE 半双工方向语义硬件实测确认 | 需硬件实测窗口 | -| N-25 中 DE 项 | `HAL_Delay(1)` 阻塞 DE | 随 B2 | - -### 2.5 顺序一图 - -``` -W1 功能 B4 IEC104 上行 ✅ 2026-10-12 → B5 protectTask ✅ 2026-10-12(W1 完成;台账三件套 ✅) - ↓ -W2 数据 N-21 dhara is_free/copy(配主机侧移植层测试) - ↓ -W3 预算 R-9 池瘦身 → R-2 后半(54KB→CCM)→ R-3~R-6 评估 - ↓ -W4 结构 N-20 → C6(S-3) → C3(N-2/N-24) → C1 pending 二期 → C5(含 N-23 残余) → N-22/25/26/28 - ↓ -W5 验证 P1-10 · T-7 CI · D2/D5/D6/D7 · S12 · S1-c · A-5 - ↓ -W6 UI U4 残余 → U1 令牌层 → U2/U3 → 27 页(单独立项,本轮不排期) -W7 仓库 N-29 .git 149MB(已决策暂不处理) 硬件:N-18 V0.2 -暂缓 B2 RS-485 整簇(2026-10-12 用户决定,§2.4) -``` - ---- - -## 3. 待办详述 - -### 3.1 P1(1 项收尾:P1-10 剩构建实测闭环) - -#### P1-10 测试固件静态 RAM 预算(基线已重建、测试缓冲已瘦身,剩构建实测闭环) -- **位置**:`MDK-ARM/STM32F407-Demo/STM32F407-Demo.sct`(`RW_IRAM1 0x20000000 0x00020000` = 128KB;芯片 192KB 的上部 64KB 有意未映射,克隆芯片兼容性考量) -- **历史**(2026-09-15 审计 / 09-16 复现):产品构建静态镜像曾 = 123.6KB/128KB(余量仅 4.4KB);HW 全阶段固件的 PHASE5 三缓冲(3×4093B)→ 超 8.7KB(`L6406E` 实测);NET 固件的 32KB `s_rx_buf` → 超约 28KB。 -- **进展**(2026-09-21,已复核):① 预算基线重建(`docs/内存管理/RAM使用分析与优化方案.md` v1.2):FreeRTOS 堆迁 CCM,任务栈改由 CCM 堆分配;产品构建 RW_IRAM1 余 ~49KB;② NET 层测试 32KB `s_rx_buf`/`s_tx_buf` 已移除,改小局部缓冲;③ STORAGE 套件固件 2026-09-20/21 实测可构建可运行。 -- **剩余**:① CH395F 套件(`TEST_SUITE_CH395F`,HW 全阶段 / NET 层 7 配置)实际构建确认链接通过——PHASE5 三静态缓冲 3×4093B 仍在,理论余量足够但未实测;② `@test` 闭环;③ **不建议**扩 scatter 到 192KB(破坏既有克隆芯片兼容决策)。 -- **置信度**:high(基线数据来自 2026-09-21 map;测试固件构建未复验)。 - -### 3.2 登记簿(N-x / S-x / T-x) - -**网络(CH395F / net 层)** - -| # | 事项 | 发现 | 证据与现状 | 出处 | -|---|---|---|---|---| -| N-2 | **49s 全系统日志静默(defaultTask/NAND syslog 排空停滞)**——串口日志 49s 无行,期间 net 栈照常处理外部连接 → 日志管线停滞,队列满后各任务日志行被丢;系统功能不受损 | 2026-09-22(L3 台架 F2,gen 181) | **A/B 归因:既有存储侧现象**。**2026-10-03 降级为低风险观察项**:① 丢弃可观测性**代码已具备**(`console_log.c` `s_con_drop` + `[ERR] CONSOLE dropped`;`sys_log_mcu.c` 队列满 `DBG_ERROR`;UART TX 僵尸通道自愈);② V5 30 min **未复现 49s**(>10s 静默全为 ~28s、均在 `e02_probe` 窗口内=N-17)。**残余待办**:与 S8(非阻塞日志)合并评估(C3) | `错误码传播审计.md` E-02 阶段二 | -| N-3 | **L5 队列往返基线(1223/988µs)的 L3 后重验**——L5 测 DONTWAIT 队列全程;L3 对该路径逐位不变 → 机制上无影响,但基线数值属分片时代,严格重锁需跑一轮 Phase 13(需 PC peer) | 2026-09-22(L3 收尾留档) | 低风险:10ms/100ms 阈值余量 >8×;下次 Phase 13 窗口顺带重锁即可 | `链路延迟测试说明.md` §6.4 L5 注¹ | -| N-4 | **pending 机制二期:ACCEPT + SEND 阻塞路径 pending 化**——E-06、E-20、E-21 剩余分量共用该机制扩展;届时 L3/L5 基线再重锁、探针族扩充、看门狗接 selftest 留痕、模拟器差距清单 +1 | — | 一期(RECV)已落地并入主线;架构现状见 `Net层阻塞模型架构设计.md`,二期设计基线见 §5.1 | `错误码传播审计.md` 第二档 #2 | -| N-16 | **A2/A4 专项场景台架验证待办**(正常路径已实测零回归):① PHY 拔线负向测试——断链需断 **DTU 侧**线缆或关**受管交换机端口**;② A2 芯片级 `net_init` 失败分支(需 SPI 故障注入);③ A4 短写压测(需远显客户端 + UI 推流压力) | 2026-10-03(台架拓扑 = CH395↔交换机,拔线操作受限) | 待专项台架窗口 | `实机测试实施指南.md` §10 | -| N-17 | **`time_sync` 30s 挂起客户端掉线 + 监听重建期间,网络任务心跳缺口达 800ms~1s(声明 stall 但未复位)。**待办**:定位监听重建为何阻塞 NET/FTP/UI;评估缩短重建重试(5×2s)或让掉线路径不阻塞其它任务 | 2026-10-03(V5 台架) | V5 长跑 44 次 `task stall: mask=0x00000001`,**100% 与 `e02_probe` 的 30s 挂起客户端触发 `time_sync: no TIME packet in 30s, drop conn` → 监听重建(约 4s)重合**;隔离实验(仅 FTP,120s)**0 次 stall** → 探针场景专属。缺口(~1s)< IWDG 最坏超时(1701ms),余量仅 ~0.7s。 | `实机测试实施指南.md` §4;`子系统设计/看门狗设计说明.md` | -| N-32 | **CH395F 监听生命周期根治(B10 残余)**——现仅靠对账④兜底(提交 `4f2cc8b`)。根治两步:**P1 把"会话已结束"从边沿改成电平**(`net_sock_t` 增 `session_dead`;`net_recv_locked` DONTWAIT 判据改 `state==CLOSED \|\| session_dead`;`ui_net_sink.c:563` 补 `g_client != g_listen` 护栏;accept 门控换 `net_listener_armed`);**P2 单一所有者**(新增 `net_listener_pump`,删 `net_accept_locked:1346`/`net_recv_locked:1884`/`net_pending_tick:2451` 散点 relisten;消灭 netTask 内 500 ms 忙等 `:2597-2616`/`:1115-1126`)。**已定案不走芯片多连接模式(A′ 出局:不支持多监听)** | 2026-10-12(B10 定案;⚠ ④ 有副作用——抢先 relisten 会把慢消费者的 EOF 永久吞掉,新客户端数据被旧会话静默吸收,待 P1 消除) | 原理 + 证据附录(实测数据 / 官方例程所有权 / 状态机 15 迁移点 / 三服务契约不一致表)+ **决策记录 D1~D7** + 可勾选执行清单 → `子系统设计/网络Socket监听生命周期设计说明.md` §7~§9;现象与回归见 `问题记录/CH395F_Trap_Records.md` B10 行 | - -**存储 / 日志管线** - -| # | 事项 | 发现 | 证据与现状 | 出处 | -|---|---|---|---|---| -| S-3 | **USART1 TX-only 结构根治(灭 ORE 僵尸机制)**——ORE 锁存在外设软复位后毫秒级重锁(PA10 悬空 + RX 使能),是 2026-10-02 台架"背靠背 drain 拉长主循环 → 喂狗节奏饥饿 → IWDG 误复位"的**机制根源**。现仅有缓解(单次 drain 250ms 预算 + 发送故障后 300ms 冷却),**未根治** | 2026-10-02(台架 gen-288) | **待办**:改 `.ioc` 令 USART1 为 TX-only → CubeMX 重生成 → 跑 `scripts/check_cubemx_survival.py`。结构性改动,需单开一轮并复跑台架闭环 | `子系统设计/控制台单写者日志设计说明.md` §12(含 O4) | -| S-4 | **dhara 重试自旋残留**——`try_recover()` 的 `DHARA_MAX_RETRIES`(8) 自旋在坏块密集时仍可能长时间占用 defaultTask(喂狗点) | 2026-10-02 | 低优先:现有 `vol_lock` + 喂狗节奏缓解;若台架再出"存储侧喂狗饥饿"再排期 | `Lib/dhara/map.c` | -| S-5 | **可选全序列卷锁**——现卷锁仅覆盖 `syslog` / `cfg` / `lftpd` 三条路径(`vol_lock_wait(0)` try 语义),其它潜在访问点(如 UI 读日志)未纳入 | 2026-10-02 | 待评估:先确认是否真有第二写者;无则关闭本项 | `App/fs/vol_lock.{c,h}` | - -**硬件(V0.1 缺陷 → V0.2 改版项)** - -| # | 事项 | 发现 | 证据与现状 | 出处 | -|---|---|---|---|---| -| N-18 | **8 路电气量分属两片转换器(V0.1 硬件缺陷,需下一版硬件修改)**——UA/UN/IA 走 TPAFE5160(16 位、8 通道同步、±5 V 双极性),UB/UC/IB/IC/IN 走 STM32 ADC(12 位、顺序扫描、0~3.3 V 单极性):① 两片转换器无共同采样触发 + STM32 侧顺序扫描(9 通道一轮 ≈ 67 µs)→ 跨转换器通道**无同一时刻性、相位关系不确定**,主板侧功率/功率因数/相角/对称分量类运算不成立;② 同族电气量精度与量程不一致(LSB ≈ 152.6 µV vs ≈ 806 µV,且 STM32 侧前端无中点偏置、负半周削顶);③ 语义与硬件归属交叉,固件映射/UI 通道序/自检注入须逐通道查表绕开 | 2026-10-10 定性更正(**撤销** 2026-10-09 建档时"有意分配、不要修正"的说法) | **V0.2 改版要求**:8 路电气量 UA/UB/UC/UN/IA/IB/IC/IN **全部接 TPAFE5160**,与 TPAFE 上 5 路备用路(AIN5/13/7/15/12)对调串联电阻在转换器一侧的目的地——元件数量与料号不变,属走线级改动。**V0.1 现板软件口径**:主板侧只做逐通道独立监视,禁止跨转换器做相位/功率/功率因数/矢量类运算(此类量取子板计量模块结果)。固件侧消费者已落地(B1,2026-10-10,按语义映射表取数)→ V0.2 改版只改映射表内容,上层语义与代码不动 | `硬件平台/ADC通道映射说明.md` §1/§7;`硬件平台/V0.1_网表详细分析报告.md` §1.4 V10、§6-3 | - -**测试与验证基础设施** - -| # | 事项 | 优先级 | 问题与证据 | 处置方向 | 出处 | -|---|---|---|---|---|---| -| T-7 | **CI runner 未就绪(部署前置)** | 中 | `.gitea/workflows/ci.yml` 已落地,但 CI 仅在 runner 就绪后才真正生效:① Gitea 实例 `[actions] ENABLED = true`;② 注册 Windows runner(labels 含 `windows`),装 Python 3.x / cppcheck / pre-commit / MSVC;③ runner 就绪后**推送远端跑一次两 job 闭环验证**(当前 21 个提交未推送,CI 从未真实执行);④ **第二机交叉验证**(不同工具安装路径,验 `DTU_*` 环境变量方案,→ `环境与部署/本地工具路径环境变量方案.md` 变更记录 TODO) | runner 未就绪前,**提交前仍须在本地跑 `scripts/ci_local.py` 或 `pre-commit run --all-files` 自查**(L0 唯一保障,不能因"已配 CI"而放宽) | `.gitea/workflows/ci.yml`;`测试说明/测试开发标准流程.md` §9 | - -**审查报告并轨(2026-10-11;⚠ 报告编号与本登记簿同名不同义,出处列保留报告编号,引用一律带文档名)** - -| # | 事项 | 影响 / 现状 | 处置方向 | 波次 | 出处 | -|---|---|---|---|---|---| -| N-20 | `Error_Handler` 仍 `__disable_irq(); while(1){}`(`Src/main.c:274-282`) | 一处初始化失败 = 整机挂死(只剩 IWDG 兜底),无自检日志 | 统一降级策略:记自检 + 禁用该子系统 + 其余照常 | W4 | 报告 N-03c | -| N-21 | **dhara 两处**:`dhara_nand_is_free()` 只查页首 64 B;`dhara_nand_copy()` 不处理 `DHARA_NO_PAGE` 哨兵 | 映射恢复误判 → **数据丢失风险**(低概率、后果重);哨兵页号被当真实页 → 未定义行为;至今只能靠人工读代码发现 | 整页(或首/中/尾)扫描 + 返回 `DHARA_E_UNSUPPORTED`;**必须配主机侧移植层单测**(一并补报告"覆盖率"缺口) | **W2** | 报告 N-12/N-13 + §7 | -| N-22 | 写回缓存无空闲/掉电强制 flush(整页写与换页已 flush) | 写回窗口内掉电丢最近日志/配置写 | defaultTask 空闲 N ms flush | W4 | 报告 N-14 | -| N-23 残余 | **钩子已落地**(2026-10-12 `registration-check` 挂 pre-commit,存量缺口走 `KNOWN_GAPS` 白名单只 WARN);**残余** = 白名单清理:`rs485_task.c`(随 B2 暂缓一并处置:删除或注册)、`lftpd_log.c`;`app_cfg.h` 未接线开关(C5) | 白名单不清 = "写了不编译"盲区仍在 | 逐项清白名单(`--strict` 供审计复跑);开关随 C5 处置 | W4(C5) | 报告 N-06 残余 + 报告 S-3 | -| N-24 | 日志每条 `f_open+f_write+f_close`(`sys_log_mcu.c:123-140`) | 每条日志 2–4 次 NAND 页读写;UI 翻记录逐条 open/seek/close | 与 C3 日志管线合并评估(现仅 `FIL` static 化省 528 B 栈) | W4 | 报告 N-16(**≠ 本登记簿 N-16**) | -| N-25 | 性能/资源建议簇:PASV 每次新建监听;`NET_RECV_TIMEOUT_MS 30000`;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(**DE 项随 B2 暂缓,§2.4**) | 次级性能/语义一致性 | 逐项见 `docs/问题记录/项目审查与优化建议报告.md` §4.2/§4.5/§4.7,随窗口评估 | W4 | 报告 N-09/P2-8/PHY/P3-x/rs485 | -| N-26 | NAND 直 DMA 调用方缓冲(已加运行时守卫,阈值 1024) | CCM 缓冲被 DMA = 静默传错(与 ADC DMA 不可达 CCM 同类坑) | 补编译期/启动期地址断言 + **新铁律:堆缓冲不可被 DMA 直接寻址** | W4 | 报告 N-11 | -| N-27 | **内存优化簇**:LVGL 池 + UI 两份缓冲 54,146 B 仍在 SRAM1,CCM 只剩 ≈8,160 B(2026-10-12 B5 堆扩容 48→56 KB 后) | R-2 后半段(迁 CCM)被堵死 → 后续功能预算看不清 | **三件套 ✅ 2026-10-12 落地**(`ram_baseline.py` 四模式 + `ram_baseline.tsv` 趋势 + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子 92% 门禁)→ **W3** 再做 R-9(`LV_MEM_SIZE` 40→16 KB,池水位门禁数据已具备)→ R-2 后半;R-3/R-4/R-5/R-6 逐项评估(R-6 前置已满足) | **W3** | 报告 R-2 剩余/R-3~R-6/R-9/§5.5 | -| N-28 | Flash 死代码评估簇:剩余 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个空 LVGL TU(F-1/F-2/F-3 已闭环,省的是编译时长) | 编译时长 + 文档噪音 | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制必经路径,**不可盲关** | W4 | 报告 F-4/F-5/F-6 | -| N-29 | **仓库膨胀**:`.git` 149 MB + 图片 36.3 MB | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(届时未推送提交更少、重写代价最低) | **W7** | 报告 D-1 | -| U 簇 | UI 标准化:无令牌层/组件库/页注册表(手写 `case` 仍在),**27 页**未落地;golden 未挂 pre-commit、字符集差集检查仍是约定 | 新增一页成本仍是 8 处手工改动 | 按 `docs/问题记录/项目审查与优化建议报告.md` §6.5:U4 残余(两脚本入门禁,可逢窗口顺带)→ U1 令牌层 → U2/U3 → 页面落地;U4 golden 可直接当 U1 验收工具。**已确认(2026-10-11):本轮不排期**,等功能主线出结果后按产品需求启动 | W6 | 报告 U1~U5 | - -### 3.3 测试与架构改进专项(S1x / A-x) - -> **编号约定**:**S1~S14 / T-1~T-5 / A-1~A-7** 是 2026-10-02 版复审的**条目编号**——编号**不随条目删除而回收**; -> 其他文档若引用这些编号,其证据见对应模块文档与 `git log`。已完成事项的证据沉淀: -> `测试说明/系统时钟单元测试说明.md`(S1-a)、`测试说明/配置文件单元测试说明.md`(S1-b)、 -> `测试说明/测试开发标准流程.md` §4.2.1(L0.5 适格台账)、`测试说明/模拟器差距清单.md`(S13)、 -> `测试说明/实机测试实施指南.md`(S4/S5/S7/S9/S11)、`问题记录/GD5F2GQ5UE_Trap_Records.md`(S9)。 - -**未闭环一览** - -| 编号 | 事项 | 状态 | 详述 | -|---|---|---|---| -| **S12** | 模块级轻量断言宏 | ⬜ 待做(第 4 波按需) | 3.3.1 | -| **S1-c** | `sys_log` / `time_sync` 主机侧单测 | ⬜ 可选(价值递减) | 3.3.2 | -| **A-4** | ADC / RS485 采集链路的**测试可验证性约束** | ⏸ ADC 侧随 B1 闭环;**RS485 侧随 B2 暂缓(§2.4)** | 3.3.3 | -| **A-5 残余** | CI 体积门禁盲区(`mem-numbers` 在 CI 被跳过) | ⬜ 未消除 | 3.3.4 | - -#### 3.3.1 S12:模块级轻量断言宏 ⬜ - -**动机**:`configASSERT` 只覆盖 FreeRTOS 内部;自研代码的"不该发生"靠散落的 `if`。 - -**设计要点**(**必须零生产开销**): - -```c -/* App/util/app_assert.h —— 示意,非最终实现 */ -#ifdef APP_ASSERT_ENABLE - #define APP_ASSERT(cond) do { if (!(cond)) { \ - DBG_ERROR("[ASSERT] %s:%d", __FILE__, __LINE__); vApplicationAssertFailed(__FILE__, __LINE__); } \ - } while (0) -#else - #define APP_ASSERT(cond) ((void)0) /* 生产构建:编译期消失,零符号零开销 */ -#endif -``` - -**⚠️ 关键纪律**: -- **不得**在中断 / 高频路径使用(`DBG_ERROR` 有代价); -- **不得**替代正常的错误返回(断言是"内部不变量",不是"外部输入校验"); -- 生产构建 `APP_ASSERT_ENABLE` **关闭**——与 `ENABLE_DESTRUCTIVE_TESTS` 同级策略。 - -**建议先在 1~2 处试点**(如 `net_socket.c` 的状态机不变量),验证收益后再推广。 - -**完成判据**:宏存在 + 生产构建 `@build` 0/0 且 `.map` 无新增符号;试点处有实际使用。 - -#### 3.3.2 S1-c(可选):`sys_log` / `time_sync` 主机侧单测 ⬜ - -**范围**:`App/log/sys_log_mcu.c`(定长 64B 记录编解码;落盘部分需桩)、 -`App/sync/time_sync.c`(协议帧编解码;与网络耦合,需先判定可解耦面)。 - -**为何低优先**:两者边界密度低于 `sys_clock` / `cfg_file`,且已有真机路径覆盖 -(`@test` 标记 / `time_sync_server.py`)。**按剩余收益评估后再决定是否做**, -范式完全复用 `看门狗单元测试说明.md`。 - -**完成判据**:`test/host/<模块>/run_unit_test.py` 退出码 0 + 挂 pre-commit 钩子。 - -#### 3.3.3 A-4:ADC / RS485 采集链路的测试可验证性约束 ⏸ - -**背景**:`adc_task.c` 已实现(B1,2026-10-10),`rs485_task.c` 仍是空桩,`App/protocol/` 只有 README 与 `.gitkeep`。 -本项不是"缺陷",而是**对上游 B2 的设计约束**(B1 已完成;**B2 暂缓中,§2.4——重启 B2 动手前必须先落实本约束**,否则后续无法补测)。 - -**约束**(建议纳入 B2 设计): - -1. **协议解析必须与硬件 I/O 分离**——`App/protocol/` 的解析函数应接受 - `(const uint8_t *buf, size_t len)` 并返回解析结果,使其成为 L0.5 的**天然适格对象** - (参考 `cfg_file` 的"核心 + 后端"模式); -2. **采集缓冲必须双缓冲 + 序号**(上游 E-49 / E-50)——否则消费者读到撕裂数据, - 且**撕裂在单测里测不出来**(时序相关),必须在设计上消除; -3. **DE 收尾必须有超时路径覆盖**(RS485 半双工特有陷阱)。 - -**完成判据**:B2 设计文档体现上述三条;协议解析函数有对应 L0.5 单测。(B1 侧:ADC 无协议解析面,其"同一时刻性"由 E-58 原子快照保证、已闭环。) - -#### 3.3.4 A-5 残余:CI 体积门禁盲区 ⬜ - -**现状**:`mem-numbers` 钩子**在 CI 上被跳过**(CI 无 `.map`)→ **CI 不守体积门禁**。 -S14 已在 workflow 显式提示"体积门禁未执行"(`::notice::`)并在 `CI配置指南.md` 声明, -但**盲区本身未消除**——看到 CI 全绿仍可能误以为体积也守住了。 - -**可选处置**: -- 让 runner 具备 Keil 后,在 CI 增 `@build` job(成本高,需授权与许可证); -- 或把"体积校验"固化为**提交前必跑的本地门禁**(`scripts/ci_local.py`,当前已是事实标准)。 - -**完成判据**:存在**强制的**体积校验路径(CI 侧或本地侧),且文档明确其边界。 - -> **注**:本项与栈预算是同一话题的两面——**具体栈风险(原 S-1)已于 2026-10-10 削链闭环** -> (核算见 `docs/内存管理/RAM使用分析与优化方案.md`),本项仍是**门禁缺口**。 - ---- - -## 4. 待确认(需手册/硬件/产品定义,暂不直接改码) - -1. TPAFE5160 是否有自动扫描模式(**已不影响**:1 kHz 硬件定时器触发已于 2026-10-10 由 **TIM3 更新中断**方案落地,不依赖自动扫描,见 `docs/子系统设计/ADC采样节拍设计说明.md`)。 -2. `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 是否应在产品构建真实门控模块(当前宏已如实标注为"未接线占位",此处确认的是**是否接入真实门控**;B1 取数不依赖该宏。**RS-485 侧门控随 B2 暂缓,§2.4**)。 -3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)——**随 B2 暂缓(§2.4)**。 - ---- - -## 5. 设计基线(供后续接入参考) - -### 5.1 pending 二期设计基线(ACCEPT + SEND) - -> **来源**:一期(RECV)架构现状见 `docs/网络/Net层阻塞模型架构设计.md`(含演进溯源附录); -> 本节仅保留**二期仍要用的设计基线**。 - -**一期已验证的机制骨架**(二期沿用,勿重新发明):独立静态 pending 表 + `net_pending_tick` -主循环节拍了结(五路:数据/到点/断连/同 fd 串行/重建取消必通知)+ 登记守卫(每 fd 至多一个、 -不覆盖、拒绝 netTask 自等待)+ 1s 看门狗强结算。 - -**二期扩展点**: - -| 项 | 目标 | 对应缺陷 | -|---|---|---| -| **ACCEPT pending** | accept 等待改为"登记 → CONNECT 事件完成",退役 100ms/200ms 轮询循环 | E-06(accept 轮询计时失真) | -| **SEND pending** | 发送续传改为"登记 → send_ready 完成",消除 1s/分片 stall 对队列的冻结 | E-02 残余(SEND 位置) | - -**二期门禁**(一期门禁的加强版): - -1. CH395F NET 层全套件(含一期未跑的 Phase 7 / Phase 10,视 RAM 预算); -2. L3/L5 基线重锁(一期已重锁 M3,二期须再锁); -3. `e02_probe.py` **探针族扩充**:close / reconfig / EOF / disconnect-during-pending 四专项; -4. `ftp_regression.py`(D20)+ E-06 假 425 场景**独立重跑**(一期是借 M3 压力档覆盖的); -5. UI 远端推流压力 + timeSync 三场景; -6. 产品 `@test` 闭环 + ST-LINK 全片回读; -7. `ram_report.py` / `stack_report.py` 前后对比(铁律); -8. 看门狗接 selftest 留痕 + 模拟器差距清单 +1(`net_socket_sim.c` 无法建模 pending)。 - -**已知代价(延续一期,需文档化)**:pending 完成判定随主循环节拍运行,被长操作占用时超时 -顺延(~1ms 级);二期把 SEND 也 pending 化后,该顺延面反而**收窄**。 - -**改动量估算**:再 ~300-500 行,集中在 `net_socket.c`;公开 API 不变。风险评级**中** -(执行器核心 + D 系列前科)——**大的是验证,不是代码**。 - -### 5.2 错误码通道四要素(CH395F 范式) - -> **来源**:`错误码传播审计.md`。GD5F 错误通道统一(E-10 / E-42 / E-53 / E-54 / E-56 / E-57) -> 即按此骨架落地(2026-10-03,套件回归 16/16 PASS)。**后续任何驱动 / 子系统建立错误通道时应沿用。** - -``` -① 分类:区分「超时 / 真故障 / 参数错」——不得混为一个返回码 -② 透传:底层错误码逐层上报,不吞不猜(禁 `(void)ret`) -③ 分级:可恢复(重试)/ 不可恢复(上报自检 + 降级)显式判定 -④ 留痕:不可恢复项写 syslog selftest,可恢复项计数并在 UI / 日志可见 -``` - -**关键纪律**(呼应 `AGENTS.md` 已有铁律):**自愈逻辑严禁把"名字 / 参数类错误码" -归入"卷损坏触发集"**——`.fschk` 无限重格式化事故即此类(2026-09-20)。 - ---- - -## 6. 诊断基线(供后续对照) - -> **2026-10-10 重采(栈)/ 2026-10-04 重采(堆)**:栈 = **运行时高水位 + armlink 静态最坏链双口径** -> (产品构建 `suite=NONE`,开机 + 空闲采样,串口 `[STACK]` + `stack_report.py`);静态区 = `.map` 受管快照。 -> 栈水位口径:2026-10-10 削链后 defaultTask 实测 **2152 B**、静态最坏链 **2776 B**,**未抬栈**即达标 -> (完整核算见 `docs/内存管理/RAM使用分析与优化方案.md`)。 - -| 项 | 当前值(栈:2026-10-10;其余:2026-10-04) | 出处 | -|---|---|---| -| 产品构建 Flash (ER_IROM1) | 266,632 B / 1024 KB(25.4%);ROM 合计 **267,372 B** | `.map` 受管快照 | -| 产品构建 RW_IRAM1 | **84,960 / 131,072 B(64.8%)** | `.map` 受管快照(`RAM使用分析与优化方案.md` §2.1) | -| 产品构建 RW_CCM | 49,184 / 65,280 B(75.3%) | 同上 | -| 实测堆 | free=8,664 / **min_ever=4,728 B** | V5 串口 `[STACK] heap` | -| **defaultTask 栈峰值** | **2152 / 4096(余 1944 B = 47%);静态最坏链 2776 B(余 32%)** | `[STACK]` + `stack_report.py`(产品构建) | -| netTask 栈峰值 | 920 / 3840(余 76%);静态 1872 B | 同上 | -| ftpTask 栈峰值 | 740 / 4096(余 81%);静态 1216 B | 同上 | -| uiTask 栈峰值 | 4016 / 16384(余 75%);静态 1336 B | 同上 | -| timeSyncTask 栈峰值 | 792 / 2048(余量 61%) | 同上 | -| adcTask 栈峰值(B1,2026-10-10 新建) | **496 / 2048**(余 1552 B / 75%,台架 `@test` 实测);静态最坏链 504 B | 台架 `@test` + `stack_report.py` | -| testTask 栈峰值(产品态空转) | 496 / 8192(余量 93%) | 同上 | -| 队列响应性(挂起客户端) | 92.5ms(pending 一期) | `e02_probe.py` | -| M3 压力档帧周期 | med 60.1 / p95 66.4 / max 69.3ms,零尖峰 | `链路延迟测试说明.md` | - ---- - -## 7. 内存预算(支撑 §6 与定栈规则) - -现行权威数据 = `docs/内存管理/RAM使用分析与优化方案.md` v1.2(2026-09-21,§2.1 受管快照): -任务栈在 CCM 堆(defaultTask 1024w / netTask 960w / ftpTask 1024w / testTask 2048w / uiTask 4096w / timeSyncTask 512w / **adcTask 512w**); -产品构建 RW_IRAM1 84,960/131,072 B(64.8%)+ RW_CCM 49,184/65,280 B(75.3%); -实测堆 `free=8,664 / min_ever=4,728` B;台账工具 `scripts/ram_report.py` + `scripts/stack_report.py`。 -**旧栈表/旧余量数字作废,勿引用。** - ---- - -## 8. 维护约定 - -- 本文件是**全项目唯一的未闭环事项登记簿**——"盘点 + 排序 + 明细"三合一,明细不再分散到多份文件。 -- **任一项完成后直接删除对应条目**(先销本文件条目,再清理其它文档对本编号的引用); - **不留变更记录**,历史见 `git log` 与各模块文档。 -- 已闭环条目的**结论与证据沉淀进模块文档**,本文件不再重复。 -- 编号一律**沿用且不回收**(P-x / N-x / S-x / T-x / S1x / A-x / B·C·D 前缀);`错误码传播审计.md` 的 E-xx 独立维护。 -- **引用审查报告编号一律带文档名**(报告 N-16 ≠ 登记簿 N-16、报告 S-3 ≠ 登记簿 S-3); - 报告并轨项用本登记簿新编号(N-19~N-29 + U 簇),出处列保留报告编号。 -- **§2 是全项目唯一的推进顺序权威**:`产品需求设计文档.md` §9.2 等只留指针,顺序变更只改 §2。 -- **暂缓块(§2.4)不是销项**:条目仍在簿,只是不占波次;重启或关闭时更新 §2.4 与 §1。 -- 功能主线(B4/B5)完成后重写 §1。 -- 新增发现按既有惯例分流:能立即修的进 §2(W4 C5);需排期的进 §3 对应编号空间;跨版本观察的进 §3.2(登记簿)。 -- 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、`问题记录/错误码传播审计.md`(E-xx)、 - `测试说明/实机测试实施指南.md`(执行流程)——三者均不在本文件合并范围。 diff --git a/docs/文档规范.md b/docs/文档规范.md index c874e887..e74905d7 100644 --- a/docs/文档规范.md +++ b/docs/文档规范.md @@ -300,7 +300,7 @@ | 项目级铁律、构建/烧录/测试命令、平台约束 | `AGENTS.md`(AI 协作上下文,**精简优先**) | | 开发者入门、架构速览、目录导航 | `README.md` | | 详细设计、专项说明、测试指南 | `docs/` 下对应子目录 | -| 跨文档待办登记 | `docs/待处理内容.md`(统一登记簿) | +| 跨文档待办登记 | `docs/任务规划/README.md`(统一登记簿) | | 评审报告与专项审计 | `docs/问题记录/` | > **避免重复**:同一事实只在一处详述,其它位置用链接指向。典型如 FreeRTOS 任务表——`Src/freertos.c` 是唯一事实源,`README.md`/`AGENTS.md` 的表由脚本生成,不在别处再抄一份。 diff --git a/docs/测试说明/boot_log_data/README.md b/docs/测试说明/boot_log_data/README.md index 5c0c0cd6..ea5880cb 100644 --- a/docs/测试说明/boot_log_data/README.md +++ b/docs/测试说明/boot_log_data/README.md @@ -34,5 +34,5 @@ - 沉淀约定:`../测试开发标准流程.md` §7.3 - 栈水位探针与基线:`../../内存管理/RAM使用分析与优化方案.md` §0.2 / §0.6 -- 当前诊断基线:`../../待处理内容.md` §6 -- 本流程立项:原 `../../待处理内容.md` S-2(2026-09-22 提出;2026-10-05 固化为本节流程后销项) +- 当前诊断基线:`../../任务规划/基线与待确认.md` §3 +- 本流程立项:原 `../../任务规划/README.md` S-2(2026-09-22 提出;2026-10-05 固化为本节流程后销项) diff --git a/docs/测试说明/实机测试实施指南.md b/docs/测试说明/实机测试实施指南.md index 27fcae45..20d91808 100644 --- a/docs/测试说明/实机测试实施指南.md +++ b/docs/测试说明/实机测试实施指南.md @@ -5,7 +5,7 @@ > **已完成事项**(S7、A1~A4)的实施细节与证据**不在本文**,见对应模块文档(§10 状态与去向)。 > **前置铁律**:本文所有步骤**均在接上 MCU / 串口 / ST-LINK 之后**执行; > 无实机时**只读本文,不执行任何烧录**。 -> **上游**:`错误码传播审计.md`(E-xx)· `待处理内容.md`(统一登记簿:P-x / N·S·T-x / +> **上游**:`错误码传播审计.md`(E-xx)· `docs/任务规划/README.md`(统一登记簿:P-x / N·S·T-x / > S1x·A-x / 阶段排序 / 诊断基线)· > `子系统设计/看门狗设计说明.md`(§7 验证记录)。 > **约定**:本文事项完成后**先销上游登记**,再在文末变更记录留一行; @@ -101,7 +101,7 @@ > **2026-10-03 台架结论**(实施细节与证据见 `子系统设计/看门狗设计说明.md` 变更记录): > V2/V4/V5 三用例全部通过——V2(任务饿死)声明 stall 后 ≤2.5s `reset cause: IWDG`;V4(关中断死循环)每 ~4.9s 稳定 IWDG 复位(IWDG 独立于中断);V5(30 min 真实负载)**120/120 次 FTP 传输全 PASS、零 IWDG 复位**。 -> **遗留观察**:V5 期间 44 次 stall 声明 100% 与 `e02_probe` 探针的 time_sync 30s 掉线+监听重建重合;隔离实验(仅 FTP 120s)**0 次 stall** → 探针场景专属,非一般负载误杀(已登记 `待处理内容.md`)。 +> **遗留观察**:V5 期间 44 次 stall 声明 100% 与 `e02_probe` 探针的 time_sync 30s 掉线+监听重建重合;隔离实验(仅 FTP 120s)**0 次 stall** → 探针场景专属,非一般负载误杀(已登记 `docs/任务规划/登记簿.md`)。 > 来源:`子系统设计/看门狗设计说明.md` §7 验证记录(原实施步骤已并入该文档文末变更记录)。 > 判定状态机与 IWDG 配置(PR/RLR 按设计值写入)已落地并经真机验证(2026-10-02,`930215f`, @@ -191,7 +191,7 @@ $cli = if ($env:DTU_STLINK_CLI) { $env:DTU_STLINK_CLI } else { (Get-Command ST-L > **顺带修复(编排器缺陷,非本次代码引入)**:`run_all_suites.py` 原对所有套件统一 `--forbidden "HardFault;assert;[ERR]"`,而 GD5F 的 `TC-GD5F-704`(CCM 非 DMA 可达缓冲)会**预期**打出 `[ERR][NAND] RX DMA buffer not DMA-reachable ... fallback poll`(用例 PASS)→ GD5F 套件**永远被判 FAIL**(自 `2055de0` 起)。按 `verify_log.py` 的说明改为**按套件覆盖 `--forbidden`**(GD5F = `HardFault;assert`),修复后 PASS。 > **来源**:`错误码传播审计.md` 第二档 #1(E-10/E-42/E-53/E-54/E-56/E-57); -> `待处理内容.md` §5.2 四要素骨架(设计基线)。 +> `docs/任务规划/基线与待确认.md` §2.2 四要素骨架(设计基线)。 **现状证据**:`ch395f.c`(1330 行) 与 `gd5f2gq5ue.c`(1496 行) 是同代驱动,但**只有 CH395F** 形成了"分类 + 传播 + 审计"完整体系;GD5F 错误处理散落各函数,`Trap_Records` 仅 198 行。 @@ -249,7 +249,7 @@ $cli = if ($env:DTU_STLINK_CLI) { $env:DTU_STLINK_CLI } else { (Get-Command ST-L - **正常路径 ✅**:V5 长跑(30 min,FTP 512 KB 上/下传)**120/120 PASS、零 IWDG 复位**, 网络重建后的 FTP/time_sync 服务据代次号重建监听、功能正常(证据 `/tmp/v5_soak_serial_20261003.log`)。 - **负向路径(拔线/芯片级 `net_init` 失败)**受**台架拓扑**限制(CH395↔交换机, - 拔交换机侧线缆链路仍 UP;芯片级失败需 SPI 故障注入)→ 已登记 `待处理内容.md` **N-16** + 拔交换机侧线缆链路仍 UP;芯片级失败需 SPI 故障注入)→ 已登记 `docs/任务规划/登记簿.md` **N-16** (① PHY 拔线负向 ② A2 `net_init` 失败分支 ③ A4 短写压测),需专项窗口。 ### 7.2 N-2:49s 全系统日志静默复现与定位 · ✅ 判据②已满足 / 判据①未复现 @@ -424,7 +424,7 @@ CH395F / STORAGE / GD5F,未含 RTC;怀疑 RTC 构建下 `testTask` 不被创 | 2026-10-02 台架取证链(IWDG PR/RLR 错配 / dhara resume 回滚 / ORE 僵尸通道) | ✅ 已修 | `子系统设计/看门狗设计说明.md` 2026-10-02 变更记录 · `架构设计/STM32F4-Base存储架构说明.md` §5.4.1 · `子系统设计/控制台单写者日志设计说明.md` §12;提交 `930215f` | > **真机判定汇总**(2026-10-03,本机 MCU,新固件全闭环 `@test` PASS 7/7):A1 ✅ PASS(含配置持久化); -> A2/A3/A4 正常路径零回归;芯片级失败分支 / 短写 / 拔线负向场景记 `待处理内容.md` N-16,待专项台架窗口。 +> A2/A3/A4 正常路径零回归;芯片级失败分支 / 短写 / 拔线负向场景记 `docs/任务规划/登记簿.md` N-16,待专项台架窗口。 --- @@ -436,7 +436,7 @@ CH395F / STORAGE / GD5F,未含 RTC;怀疑 RTC 构建下 `testTask` 不被创 | V2/V4/V5 | `子系统设计/看门狗设计说明.md` §7 验证记录 | `子系统设计/看门狗设计说明.md` 变更记录(2026-10-03) | | S11 堆告警 | —(原复审项,已闭环 2026-10-03) | `内存管理/RAM使用分析与优化方案.md`(基线更新) | | S9 GD5F | `问题记录/错误码传播审计.md` 第二档 #1 | `问题记录/GD5F2GQ5UE_Trap_Records.md`、`测试说明/GD5F2GQ5UE_Test_Guide.md` | -| N-2 日志静默 | `待处理内容.md` N-2 | `问题记录/错误码传播审计.md` E-02 | +| N-2 日志静默 | `docs/任务规划/登记簿.md` N-2 | `问题记录/错误码传播审计.md` E-02 | | P1-8 网络重建 | —(原台账项,已闭环 2026-10-02) | `网络/Net层阻塞模型架构设计.md` | | S5/S4 | —(原复审项,已闭环 2026-10-03) | `测试说明/测试开发标准流程.md` | | 模拟器差距 | `测试说明/模拟器差距清单.md` §3 决策规则 | 本文为"需回真机"项的执行面 | diff --git a/docs/测试说明/时间同步单元测试说明.md b/docs/测试说明/时间同步单元测试说明.md index ac8a683d..c5fd3180 100644 --- a/docs/测试说明/时间同步单元测试说明.md +++ b/docs/测试说明/时间同步单元测试说明.md @@ -12,7 +12,7 @@ > [`看门狗单元测试说明.md`](看门狗单元测试说明.md)(喂狗位图判定状态机)、 > [`卷锁单元测试说明.md`](卷锁单元测试说明.md)(同批落地的姊妹篇)、 > [`../子系统设计/看门狗设计说明.md`](../子系统设计/看门狗设计说明.md)(`required_mask` / 抽样窗 / 长耗时白名单)、 -> [`../待处理内容.md`](../待处理内容.md)(**N-17** 登记条目)、 +> [`../任务规划/README.md`](../任务规划/README.md)(**N-17** 登记条目)、 > [`../问题记录/错误码传播审计.md`](../问题记录/错误码传播审计.md)(**E-02** 头阻塞) --- diff --git a/docs/测试说明/模拟器差距清单.md b/docs/测试说明/模拟器差距清单.md index 05f77ce4..ea85b38e 100644 --- a/docs/测试说明/模拟器差距清单.md +++ b/docs/测试说明/模拟器差距清单.md @@ -3,7 +3,7 @@ > **用途**:把散落在各子系统文档里的"模拟器无法建模 X"汇成**单一事实源**,回答一个关键问题—— > **模拟器回归通过 ≠ 真机通过,那么差在哪?差多少?哪些必须真机补测?** > **性质**:**登记册**(living document)。新增模拟器后端差异时必须在此登记一行,不得只写在别处。 -> **上游依据**:`待处理内容.md` §5.1(N-4 二期门禁)。 +> **上游依据**:`docs/任务规划/基线与待确认.md` §2.1(N-4 二期门禁)。 > **相关**:`UI设计/LVGL模拟器部署与使用说明.md`(部署与使用)、`simulator/README.md`(目录与架构)、 > `测试说明/测试开发标准流程.md`(L3 门禁在测试分层中的位置)。 diff --git a/docs/测试说明/测试开发标准流程.md b/docs/测试说明/测试开发标准流程.md index 644608e8..56bcf6b7 100644 --- a/docs/测试说明/测试开发标准流程.md +++ b/docs/测试说明/测试开发标准流程.md @@ -619,10 +619,10 @@ CI 只在 push / PR 时跑,且需 runner 就绪。**提交前自查、或 runn | 2026-10-02 | **S6**:`test/run_all_suites.py` 新增 **`--check-build`**(只编译不烧录,纯离机,不需要 MCU/串口/ST-LINK);新增 **§3.6.1** 说明其解决的问题(测试构建无独立门禁,2026-08~09 CH395F 套件实例)、判定语义与用法。**实测 4 套件全部 `BUILD_OK: 0 errors, 0 warnings`**(即 T-4 提到的"CH395F 不可编译"已修复) | | 2026-10-02 | **S1-b + S2**:新增 **§4.2.1「L0.5 适格模块台账」**(判据 + 模块状态表 + "两条实证":sys_clock / cfg_file 首测即各抓一处生产缺陷);§4.1 登记 `test/host/cfg_file/` 新单测。同步新增 [`配置文件单元测试说明.md`](配置文件单元测试说明.md)(含抓出的 `s_encode` 返回值误判 P0 缺陷记录) | | 2026-10-02 | **S3 + S14**:§9.1 第 2 条改正(原文"强制跑 `mem-numbers`"自相矛盾 → 改为"按 `.map` 有无自适应跳过")并加 🔴 门禁盲区声明;§9.2 补 S3 结果可见性(`Tee-Object` 落盘 + `$GITHUB_STEP_SUMMARY` + `::notice::` 汇总行,不用 `actions/upload-artifact`)。另:§4.1 登记 `test/host/sys_clock/` 新单测(S1-a) | -| 2026-10-01 | 新增 **§9 CI 持续集成(Gitea Actions,T-6)**:`.gitea/workflows/ci.yml`(`l0-gates` + `l05-host-unit-tests`,Windows runner);**L0 + L0.5 上 CI、L1/L2/L3 留本地**;刻意不跑 `@build`、`.map` 缺失时自适应跳过 `mem-numbers`;新增 `scripts/ci_local.py` 本地等价命令(§4.1 登记);§1 补 CI 说明;`docs/待处理内容.md` T-6 销项 | +| 2026-10-01 | 新增 **§9 CI 持续集成(Gitea Actions,T-6)**:`.gitea/workflows/ci.yml`(`l0-gates` + `l05-host-unit-tests`,Windows runner);**L0 + L0.5 上 CI、L1/L2/L3 留本地**;刻意不跑 `@build`、`.map` 缺失时自适应跳过 `mem-numbers`;新增 `scripts/ci_local.py` 本地等价命令(§4.1 登记);§1 补 CI 说明;`docs/任务规划/README.md` T-6 销项 | | 2026-10-01 | §3.6 新增 **`test/run_all_suites.py`** 多套件回归编排(`try/finally` 无条件还原套件开关;T-5);`test/README.md` 同步 | | 2026-10-01 | §3.2 断言宏改为**集中内核**:新增 `test/board/test_common.h`(`test_stats_t` + `TEST_CHECK_IMPL`/`TEST_REPORT_IMPL`),4 套件各自用一行宏绑定自身统计变量(T-4;零行为变化、零 RAM 增量、`@build` 0/0,四套件均 0/0 验证)。附 `test_common.h` 不 include `dbg_log.h` 的原因(`DBG_TAG` 冻结 → `#47-D`) | -| 2026-10-01 | 新增 §7.1 钩子 **`test-suite-switch`**(测试套件开关=产品构建,防测试固件静默提交)+ §3.1 铁律(跑完套件回归务必改回产品构建);依据 `docs/待处理内容.md` T-1(测试架构评审 P0)。同步更新 `../代码规范/pre-commit使用说明.md` §2.13 | +| 2026-10-01 | 新增 §7.1 钩子 **`test-suite-switch`**(测试套件开关=产品构建,防测试固件静默提交)+ §3.1 铁律(跑完套件回归务必改回产品构建);依据 `docs/任务规划/README.md` T-1(测试架构评审 P0)。同步更新 `../代码规范/pre-commit使用说明.md` §2.13 | | 2026-10-01 | §4.1/§4.2 更新:主机侧单测运行器统一走通用 harness `test/host/common/unit_test_harness.py`(T-3),模块运行器只做声明式配置;§6.2.1 新增套件汇总行校验(T-2) | | 2026-10-01 | §4.2 补 **L0.5 环境要求表**(MSVC `cl.exe` = 装了 VS 即有、与模拟器共用;Windows SDK;纯标准库 Python;缺失时退出码 2 且 pre-commit 钩子拦截)+ "不调 `vcvars64.bat`(`reg.exe` 受限)"原因说明;§4.1 工具清单标注该运行器需 VS。同步更新 `../环境与部署/项目部署环境要求.md`(§2.3 / §2.7 / 第 3、10 步 / 清单 / 下载表 / 速查表) | | 2026-09-15 | §3.4 更新:P1-6 修复落地(基础线程策略)——USER CODE 区冗余 netTask 创建删除 + `net_task_func` 入口 `ENABLE_HW_LAYER_TESTS` 自挂起守卫;"代码事实/设计约束"按修复后现状重写(硬件层模式中断断言恢复安全、NET 层/产品仍按"netTask 恒在轮询"设计);彻底方案(`.ioc` 移除)经评估未采用。同日构建验证发现两处**存量**测试固件缺陷(与 P1-6 无关,A/B 对照确证):① `net_test_task.c` `s_rx_buf` 使用先于声明 → NET 层配置自 2026-08(88160a5)起不可编译;② 128KB 静态 RAM 预算溢出(产品镜像 123.6KB,HW 全阶段固件超 8.7KB、NET 固件超 ~28KB)——已立 P1-9/P1-10 跟踪 | diff --git a/docs/测试说明/链路延迟测试说明.md b/docs/测试说明/链路延迟测试说明.md index a1a9a4ff..98e295a7 100644 --- a/docs/测试说明/链路延迟测试说明.md +++ b/docs/测试说明/链路延迟测试说明.md @@ -444,7 +444,7 @@ med 65.0ms/max 133.5ms(133.5 = 压力启动瞬态单帧);**L3 pending 化 ¹ L5 两行为 2026-09-22 上午分片时代(M2 B2 档)数值:L3 对 DONTWAIT 快速路径**逐位不变**(dispatch → `net_poll` → `get_recv_len` 读,无 readable 门控),pending tick 无 pending 时为纯指针读零 SPI -(µs 级)——机制上不影响 L5;M2 重验未在本轮执行(低风险,留待 Phase 13 下次窗口,见 `docs/待处理内容.md` N-3)。 +(µs 级)——机制上不影响 L5;M2 重验未在本轮执行(低风险,留待 Phase 13 下次窗口,见 `docs/任务规划/README.md` N-3)。 数据来源:L1/L2 = §6.1;L3/L5/L6/L7 = M2 B2 档(200ms、per-recv 日志已删)串口 `[LAT]` 行 (`m2_data/m2_quiet_r200.json`);L8/L9/L11 = **L3 pending 构建 2026-09-22 16:42/16:43 重锁** diff --git a/docs/环境与部署/CI配置指南.md b/docs/环境与部署/CI配置指南.md index 206d5bfb..bde1f0ea 100644 --- a/docs/环境与部署/CI配置指南.md +++ b/docs/环境与部署/CI配置指南.md @@ -358,7 +358,7 @@ github.com 会在 checkout 步骤卡住/失败。三种处置: - **钩子集变化**(`.pre-commit-config.yaml` 增删钩子):CI 自动跟随,无需改 workflow; - **`@build` / L1 / L2**:永远留在本地,不要往 CI 加(需 Keil 授权与真机); - **runner 长时间不可用**时:CI 只是"多一道网",**提交前的本地 `ci_local.py` 仍是 L0 的唯一保障**, - 不能因"已经配了 CI"放宽(见 `docs/待处理内容.md` 的部署前置警示块)。 + 不能因"已经配了 CI"放宽(见 `docs/任务规划/README.md` 的部署前置警示块)。 --- diff --git a/docs/环境与部署/并行任务工作树方案.md b/docs/环境与部署/并行任务工作树方案.md index ad97868b..224ef741 100644 --- a/docs/环境与部署/并行任务工作树方案.md +++ b/docs/环境与部署/并行任务工作树方案.md @@ -14,7 +14,7 @@ ## 1. 目的与范围 **要解决的问题**:多个任务同时推进时,若共用同一个工作目录,会互相踩——构建产物、日志目录、 -Python 环境、以及 `docs/待处理内容.md` 这类**全局唯一登记簿**都会被并发写坏。 +Python 环境、以及 `docs/任务规划/` 这类**全局唯一登记簿**都会被并发写坏。 **做法**:每个任务一棵 `git worktree` + 一条任务分支,任务之间物理隔离;干完由固定命令合回主干。 @@ -104,7 +104,7 @@ D:/Code/DTU Code/ | -------- | ---------------------------------------------------------------------------------------------------- | | 集成分支(主干) | `v2-on-ui` | | 任务分支 | `task/-`,从主干当前 HEAD 切出 | -| `` | **沿用 `docs/待处理内容.md` 的编号空间**(`P0-x`/`N-x`/`S-x`/`T-x`/`B-x`/`C-x`/`D-x`);无对应条目的临时任务用 `X-<日期>-` | +| `` | **沿用 `docs/任务规划/README.md` 的编号空间**(`P0-x`/`N-x`/`S-x`/`T-x`/`B-x`/`C-x`/`D-x`);无对应条目的临时任务用 `X-<日期>-` | | 合并方式 | `git merge --no-ff` 合入主干 | | 并发上限 | **同时最多 3 棵工作树** | @@ -142,7 +142,7 @@ D:/Code/DTU Code/ | 文件 | 冲突原因 | 回收时的处理 | | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -| `docs/待处理内容.md` | 全项目唯一登记簿,每个任务都要销项 | 由主工作树统一改,任务分支不碰 | +| `docs/任务规划/`(整个文件夹) | 全项目唯一登记簿,每个任务都要销项 | 由主工作树统一改,任务分支不碰 | | `AGENTS.md`、`docs/README.md`(索引/登记类) | 每个任务都要在「按主题查哪份文档」表、`docs/README.md` §9.2 环境表、变更记录里**各加一行** → 两任务必冲突(2026-10-12 实测:主工作树里本任务的行与他任务的行已并排混在**同一 hunk**) | 由主工作树统一追加;提交时**只 `git add` 本任务的行**(`git apply --cached` 选择性入库),勿整文件 `git add` | | `AGENTS.md` 的 `TASK_TABLE` 块 | 生成物,两个任务都抬栈就冲突 | 合并后重跑 `scripts/gen_task_table.py` **重新生成**,不手工并 | | `MDK-ARM/STM32F407-Demo.uvprojx` | 新源文件注册 + UV4 自动改写 | 手工并 `` 条目 → 重跑 `registration-check` → `@build` | @@ -199,6 +199,29 @@ D:/Code/DTU Code/ > 结论:任务期真正可并行的只有**编码与静态门禁**(`ci_local.py` 的 L0 / L0.5,纯软件、零硬件); > `@build` 与烧录/台架都必须排队。 +### 7.3 并行道与写范围规则(规划层 ↔ 执行层映射) + +规划层(登记簿 `docs/任务规划/W1-采集保护收尾.md`,任务卡五字段 = **DoD / 硬依赖 / 资源 / 写范围 / 状态**) +按**资源属性**把任务切进三条道,本方案(工作树 + 锁)是它的执行层: + +| 道 | 资源 | 并行性 | 锁 / 机制 | +|---|---|---|---| +| **台架道** | COM6 / ST-LINK / 设备(§7.1) | **串行**——约束资源,**永不空转**(约束优先,TOC):代码道在跑时必须为下一个台架任务备料 | `bench.lock` | +| **代码道** | CPU / 源码 | **并行**——worktree 独立空间;前提 = 写范围互不相交 + 强门禁(31 钩子 `ci_local`,同 Linux 内核子系统树并行而能合回的逻辑,见 `docs.kernel.org/process/2.Process.html` 的 subsystem tree 模型) | 无锁;分支 ≤2 天、绿即合(trunk-based 短分支) | +| **外部窗口** | 标准源 / 第三方主站等外部设备 | **Fixed Date 类**(Kanban 服务分类):窗口一到全道让路;窗口前 2 日特性冻结(只修稳定,Zephyr RC 语义 → `docs.zephyrproject.org/latest/project/release_process.html`) | `bench.lock` + 外部预约 | + +**四条规则**: + +1. **WIP ≤ 2**:每道最多 1 个进行中(典型 = 台架道 1 + 代码道 1),先完再开——登记簿需可见 + `⬜ 未开始 / 🟦 进行中` 两态,销项仍删行。 +2. **写范围相交 = 声明合并次序**:任务卡必须写写范围(目录级);相交不排队等待,而是**声明谁先合** + (后合者在主工作树 rebase 后继续),claim 时定。 +3. **分支存活 ≤2 天、绿即合**:合并走 `done` 预演(§6.3);单写者文档(§6.1)仍由主工作树统一处理。 +4. **里程碑不拖延、功能顺延下一轮**(时间驱动):里程碑的退出判据写在登记簿,判据不满足则该**功能** + 移入下一波次,里程碑本身按判据改期而非无限等待。 + +> 登记簿是规划层唯一权威(§2 铁律不变);本节只定义执行层映射,**不在本文排任务顺序**。 + --- ## 8. SKILL 设计 @@ -371,4 +394,4 @@ docs\内存管理\RAM使用分析与优化方案.md:585 [路径引用] docs/内 | 自动化测试与台架流程 | `docs/测试说明/自动化测试流程.md` | | 文档写作规范(编码/链接/登记) | `docs/文档规范.md` | | 工具路径环境变量(换机) | `docs/环境与部署/本地工具路径环境变量方案.md` | -| 待办与排序登记簿 | `docs/待处理内容.md` | +| 待办与排序登记簿 | `docs/任务规划/README.md` | diff --git a/docs/环境与部署/项目部署环境要求.md b/docs/环境与部署/项目部署环境要求.md index 77b0c77c..0b2dab5d 100644 --- a/docs/环境与部署/项目部署环境要求.md +++ b/docs/环境与部署/项目部署环境要求.md @@ -532,7 +532,7 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级 | 开关 | 位置 | 当前值 | 说明 | |---|---|---|---| -| `APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` | `App/app/app_cfg.h` | 全定义 | **未接线占位,不门控任何代码**(P2-12,2026-10-04 核实):三个宏全库零消费点,各模块一律编译进产品;"能否裁剪"取决于产品定义(待处理内容.md §2 阶段 B0),落定后再接入真实门控。**不要把它们当开关** | +| `APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` | `App/app/app_cfg.h` | 全定义 | **未接线占位,不门控任何代码**(P2-12,2026-10-04 核实):三个宏全库零消费点,各模块一律编译进产品;"能否裁剪"取决于产品定义(docs/任务规划/README.md §2 阶段 B0),落定后再接入真实门控。**不要把它们当开关** | | `TEST_SUITE_*` | `test/board/test_config.h` | 全注释(产品构建) | 测试套件**互斥**:一次构建只开一个(CH395F / 存储 / GD5F / RTC);全注释 = 正常产品固件 | --- diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index 2841fda2..e0b66781 100644 --- a/docs/算法/继电保护功能复现规划.md +++ b/docs/算法/继电保护功能复现规划.md @@ -3,7 +3,7 @@ > **定位**:把参考系统(CLS100 DTU 保护测控装置)的**继电保护链路**在本项目(STM32F4-Base DTU 平台)上分层复现的**总规划**——给出要实现的功能、性能指标、定值参数、平台适配口径与分阶段路线图。 > **参考来源**:`D:\Code\DTU\参考资料\huaiyuan\huaiyuan\Scatter_P_HV03.01_SV01.01\项目分析文档\04-算法与采样专题\ADC采集至数据使用全流程详解`(同专题另有《项目详细分析-交流采样与有效值计算》《傅氏算法详解》《项目详细分析-阶段6-继电器保护单元分析》)。 > **阅读前提**:先读 `docs/算法/傅氏算法详解.md`(算法原理)与 `docs/硬件平台/ADC通道映射说明.md`(采样通道权威口径)。 -> **相关文档**:`docs/产品需求/产品需求设计文档.md`、`docs/待处理内容.md`、`docs/内存管理/RAM使用分析与优化方案.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)上送;**出口记录(L4)与标准源注入验收为下一步**(见 §7)。 --- @@ -540,7 +540,7 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5) | R5 | **STM32 侧无中点偏置** | 交流量负半周削顶,无法算 RMS | V0.1 只做监视;V0.2 补偏置 | | R6 | **栈预算** | 新任务栈溢出 | 建任务前后跑 `scripts/stack_report.py`;纳入看门狗 | | R7 | **出口硬件未确认** | 跳闸出口无法验证 | 确认出口继电器/回读电路;无硬件时先做逻辑级验证 | -| R8 | **TPAFE 自动扫描模式未知** | 影响采样实现方式 | 查手册确认(登记簿 §4 待确认项) | +| R8 | **TPAFE 自动扫描模式未知** | 影响采样实现方式 | 查手册确认(`docs/任务规划/基线与待确认.md` §1 待确认项) | --- diff --git a/docs/网络/Net层阻塞模型架构设计.md b/docs/网络/Net层阻塞模型架构设计.md index ed95d301..e181ed8a 100644 --- a/docs/网络/Net层阻塞模型架构设计.md +++ b/docs/网络/Net层阻塞模型架构设计.md @@ -9,7 +9,7 @@ > `docs/网络/BSD_Socket_API_使用指南.md`(应用视角 API 语义)、 > `docs/网络/BSD_Socket_API_函数调用关系.md`(调用链与执行域)、 > `docs/测试说明/链路延迟测试说明.md`(延迟基线与故障对照)、 -> `docs/待处理内容.md` §5.1(二期 ACCEPT/SEND 扩展设计) +> `docs/任务规划/基线与待确认.md` §2.1(二期 ACCEPT/SEND 扩展设计) --- @@ -147,7 +147,7 @@ CONNECT → ESTABLISHED 是合法迁移,推断取消会误杀正在建链的 | **模拟器不可建模** | `net_socket_sim.c` 单线程 Winsock 无法复现挂起模型 | 该路径在模拟器上零覆盖,只能硬件验证 | **二期扩展设计**(ACCEPT / SEND 的挂起化、门禁清单、改动量)见 -`docs/待处理内容.md` §5.1。 +`docs/任务规划/基线与待确认.md` §2.1。 --- @@ -208,7 +208,7 @@ CONNECT → ESTABLISHED 是合法迁移,推断取消会误杀正在建链的 - 看门狗接 selftest 留痕 → 二期; - 模拟器差距 +1(`net_socket_sim.c` 无法建模挂起)→ 二期更新清单; - 台架期间另发现一次 49s 全系统日志静默(defaultTask/NAND syslog 排空停滞,net 栈照常工作) - ——既有存储侧现象,与本层无关,见 `docs/待处理内容.md` N-2。 + ——既有存储侧现象,与本层无关,见 `docs/任务规划/README.md` N-2。 ## 附录 B:修订记录 diff --git a/docs/问题记录/CH395F_Trap_Records.md b/docs/问题记录/CH395F_Trap_Records.md index 1a04899f..476d0853 100644 --- a/docs/问题记录/CH395F_Trap_Records.md +++ b/docs/问题记录/CH395F_Trap_Records.md @@ -654,7 +654,7 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报 自愈实测计数(整轮会话):`chip closed -> disconnect` **12** 次、`connection completed w/o CONNECT irq -> accept` **1** 次、`listen lost -> relisten` **1** 次——三类失同步均真实出现并被自愈;`relisten give up` 0 次。 ### 对应文件 -`Drivers/BSP/NET/net_socket.c`(`net_reconcile_tick` / `handle_disconnect_event` LISTENING 分支);`MDK-ARM/tcp_reconnect_probe.py`(可信用例);`docs/待处理内容.md` N-6(✅ 已销项,2026-09-26 清理)。 +`Drivers/BSP/NET/net_socket.c`(`net_reconcile_tick` / `handle_disconnect_event` LISTENING 分支);`MDK-ARM/tcp_reconnect_probe.py`(可信用例);`docs/任务规划/README.md` N-6(✅ 已销项,2026-09-26 清理)。 ### 发现时间 2026-09-22(台架偶发 1/1)→ 2026-09-23(生产固件确定性复现 + 当日修复闭环)。 diff --git a/docs/问题记录/错误码传播审计.md b/docs/问题记录/错误码传播审计.md index ec32126a..f098233a 100644 --- a/docs/问题记录/错误码传播审计.md +++ b/docs/问题记录/错误码传播审计.md @@ -10,7 +10,7 @@ > **本版**:2026-09-25 重写 —— ① 已闭环项从正文移除,只在 §2 留一行索引;② 全部未闭环项 > **逐项回到当前代码复核**;③ 新增本轮复核发现。 > **代码基线**:`v2-on-ui` @ `9a8255f`(2026-09-24),复核日期 2026-09-25 -> **配套文档**:`docs/待处理内容.md`(N-2/N-4 登记项)、`docs/网络/Net层阻塞模型架构设计.md`(E-02 架构现状)、 +> **配套文档**:`docs/任务规划/README.md`(N-2/N-4 登记项)、`docs/网络/Net层阻塞模型架构设计.md`(E-02 架构现状)、 > `docs/问题记录/*_Trap_Records.md`(模块陷阱史)、`AGENTS.md`(已固化铁律) --- @@ -196,7 +196,7 @@ E-57(`int` / `int32_t` 混用)、**E-10 / E-42 / E-56(GD5F init / BBT / ra - **验证**:构建 0 错误 0 警告;cppcheck(warning/performance/portability)无告警; `git diff --check` 无空白问题;编码无 `U+FFFD` 且 BOM 状态与原文一致 - **代码代价**:BSS +64 B(8×(4+4)) -- **登记**:`docs/待处理内容.md` N-5(✅ 已销项,2026-09-26 清理) +- **登记**:`docs/任务规划/README.md` N-5(✅ 已销项,2026-09-26 清理) - **残留**:`net_recv_to` 继续用返回码 `-2` 表达超时(不依赖 errno),保持既有正确做法 --- diff --git a/docs/问题记录/项目审查与优化建议报告.md b/docs/问题记录/项目审查与优化建议报告.md index 35f7b0bc..4b114413 100644 --- a/docs/问题记录/项目审查与优化建议报告.md +++ b/docs/问题记录/项目审查与优化建议报告.md @@ -11,7 +11,7 @@ | 审查方式 | 静态审查 + 链接图(.map)量化分析 + 构建脚本/门禁核对;**未做上机动态验证**(除特别标注外) | | 目标 | 结构合理性、文档分布合理性、模块设计合理性、改进路线图、内存优化、UI 标准化 | -> **与既有文档的关系**:本报告不重复 `docs/待处理内容.md`(逐条缺陷台账)与 `docs/内存管理/RAM使用分析与优化方案.md`(内存专项方案),而是做**体系层评审 + 量化补强 + 新增发现**。新增发现统一编号 `N-xx`,已在台账中的条目按 `P1-x/P2-x/P3-x` 引用。 +> **与既有文档的关系**:本报告不重复 `docs/任务规划/README.md`(逐条缺陷台账)与 `docs/内存管理/RAM使用分析与优化方案.md`(内存专项方案),而是做**体系层评审 + 量化补强 + 新增发现**。新增发现统一编号 `N-xx`,已在台账中的条目按 `P1-x/P2-x/P3-x` 引用。 > > **销项约定(2026-10-11 起)**:本报告采用与登记簿相同的**「修复即销项」**——问题修复后其分析正文与表格行**从本报告删除**,完整记录沉淀到对应模块文档(去处清单见文末**变更记录**)。因此本报告**只呈现未闭环问题**,不再随时间膨胀。 @@ -36,7 +36,7 @@ | # | 编号 | 问题 | 影响 | 现状 | |---|------|------|------|------| -| 1 | **N-02** | `lftpd.c cmd_pass` 对任意口令无条件回 `230`(现 `:375-379`;`cmd_user :553-557` 同) | 局域网内任意主机可读写 `/config.ini`(含 IP/MAC/网关)→ 可远程断网;单连接 CH395F 上还可挤掉 UI/对时服务 | ❌ 一行未改;⚠ 且**不在 `../待处理内容.md` 登记簿内** → 建议补登 | +| 1 | **N-02** | `lftpd.c cmd_pass` 对任意口令无条件回 `230`(现 `:375-379`;`cmd_user :553-557` 同) | 局域网内任意主机可读写 `/config.ini`(含 IP/MAC/网关)→ 可远程断网;单连接 CH395F 上还可挤掉 UI/对时服务 | ❌ 一行未改;⚠ 且**不在 `../任务规划/README.md` 登记簿内** → 建议补登 | | 2 | **N-04 / R-2 剩余** | LVGL 池 `work_mem_int` 40,960 B + UI 帧/绘制 `ui_port.o` 6,420 + UI 发送 `ui_net_sink.o` 6,766 = **54,146 B 仍在 SRAM1** | 堆迁 CCM 后 **CCM 只剩 16,304 B**,这 54 KB 装不下 → R-2 后半段被堵死 | 🟡 必须先做 R-9(`LV_MEM_SIZE` 40 KB→16 KB)或 R-4(帧副本 4→2)腾出空间 | | 3 | **N-12 / N-13** | `dhara_nand_is_free()` 只查页首 64 B;`dhara_nand_copy()` 不处理 `DHARA_NO_PAGE` 哨兵 | 映射恢复误判 → **数据丢失风险**(低概率、后果重);哨兵页号被当真实页 → 未定义行为 | ❌ 两处原样;⚠ 也不在登记簿 | | 4 | **N-06 残余** | `rs485_task.c`、`lftpd_log.c` 既不在 uvprojx 也不在 simulator | "写了不编译"= 死代码 + 误导 | ❌ 未处理;❌ `check_registration.py`(S-3)仍未建 | @@ -55,8 +55,8 @@ ## 0.4 未闭环清单(2026-10-11 复核) > 只列**未办 / 半办**项;已修项已按「修复即销项」删除(去处见变更记录)。图例:❌ 未办 / 🟡 半办。 -> **统一排序与推进**:本表各项已于 2026-10-11 并入 [`../待处理内容.md`](../待处理内容.md) §2/§3.2 -> (新编号 N-19~N-29 + U 簇,出处列保留本报告编号);**顺序权威在登记簿 §2,本表为评审快照**。 +> **统一排序与推进**:本表各项已于 2026-10-11 并入 [`../任务规划/README.md`](../任务规划/README.md) §2 与 [`../任务规划/登记簿.md`](../任务规划/登记簿.md) +> (新编号 N-19~N-29 + U 簇,出处列保留本报告编号);**顺序权威在 `docs/任务规划/README.md` §2,本表为评审快照**。 > ⚠ 本报告编号与登记簿同名不同义(报告 N-16 = 日志逐条开关,登记簿 N-16 = A2/A4 负向台架)→ 引用带文档名。 | 类别 | 编号 | 未闭环内容 | 下一步 | @@ -187,7 +187,7 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap | 观察 | 证据 | 判定 | |------|------|------| -| 根目录散置工作文件 | `ui_menu_tree.txt`、`ui_cn_chars.txt` | 菜单树/字符集是**生成器输入**,放根目录合理且已在 `docs/` 有权威说明(原点名的根目录 `待处理内容.md` 已并入 `docs/待处理内容.md` 统一登记簿) | +| 根目录散置工作文件 | `ui_menu_tree.txt`、`ui_cn_chars.txt` | 菜单树/字符集是**生成器输入**,放根目录合理且已在 `docs/` 有权威说明(原点名的根目录 `待处理内容.md` 已并入 `docs/任务规划/README.md` 统一登记簿) | | `Lib/` 命名 | `Lib/` 下混放 `lvgl/`、`lv_conf.h`、`FatFs/`、`dhara/` | `lv_conf.h` 是**工程配置**不是库文件;建议移到 `Config/lv_conf.h` 并同步 include 路径(低风险、提升可读性) | | 功能开关名存实亡 | `App/app/app_cfg.h` 的 `APP_NET_ENABLE/APP_ADC_ENABLE/APP_RS485_ENABLE` **全库零引用** | 与台账 **P2-12** 同源。开关不生效比没有开关更糟——评审者会误信"ADC 可裁剪"。**2026-10-11 复核:🟡 已订正表述但未接线**——文件头 v1.1(2026-10-04)已如实标注"预留占位、不门控任何代码",`APP_CCM_ENABLE`/`APP_UI_NET_SINK` 已删除,三个 `APP_*_ENABLE` 仍在且仍零引用 | @@ -217,7 +217,7 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap ### 3.2 做得好的(应保留并显式制度化) 1. **文档密度与可执行性**:每篇都带"步骤 + 判据"(如 UI 制作流程有 P0→P4 Gate);测试说明按模块拆分并给出预期串口标记,可直接接 `@test`。 -2. **陷阱台账**:`docs/问题记录/*_Trap_Records.md` + `docs/待处理内容.md`(P1-1..P3-13,带 ✅ 状态与日期)——这是本工程最有价值的资产,多数嵌入式项目没有。 +2. **陷阱台账**:`docs/问题记录/*_Trap_Records.md` + `docs/任务规划/README.md`(P1-1..P3-13,带 ✅ 状态与日期)——这是本工程最有价值的资产,多数嵌入式项目没有。 3. **图与脚本同提交**:`tools/arch_diagram/`、`tools/refgraph/` 生成器 + 产物入库,图可再生而非手绘。 4. **UI 设计资产链完整**:原始参考图 → 说明 md → 代码,可追溯。 @@ -272,7 +272,7 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap | 编号 | 问题 | 证据 | 建议 | |------|------|------|------| -| **N-02** | **FTP 无鉴权**:`cmd_pass` 无条件 `send_simple_response(socket, 230, STATUS_230)` | `lftpd.c:367-371`(`cmd_user :539` 亦不校验) | 最小可用方案:`config.ini` 增 `[ftp] user/pwd_hash`,`cmd_pass` 用**定长比较 + 失败计数锁定**;生产固件默认关闭 FTP 写权限(`FF_FS_READONLY` 式的只读模式)。**❌ 2026-10-11 复核:一行未改**(现 `lftpd.c:375-379` / `:553-557`,全文件无 password/auth/attempt/read_only);⚠ 且**未登记进 `待处理内容.md`** → 建议补登为 P0/P1 | +| **N-02** | **FTP 无鉴权**:`cmd_pass` 无条件 `send_simple_response(socket, 230, STATUS_230)` | `lftpd.c:367-371`(`cmd_user :539` 亦不校验) | 最小可用方案:`config.ini` 增 `[ftp] user/pwd_hash`,`cmd_pass` 用**定长比较 + 失败计数锁定**;生产固件默认关闭 FTP 写权限(`FF_FS_READONLY` 式的只读模式)。**❌ 2026-10-11 复核:一行未改**(现 `lftpd.c:375-379` / `:553-557`,全文件无 password/auth/attempt/read_only);⚠ 且**未登记进 `docs/任务规划/登记簿.md`** → 建议补登为 P0/P1 | | N-09 | `cmd_pasv` 每次新建监听 `lftpd_inet_listen(0)`(随机端口) | `lftpd.c:373` | 在**单连接 socket** 上与 UI `:7003`、对时 `:8888` 争用同一物理 socket;建议限定监听资源池 + 显式"FTP 会话独占"策略,并在文档写明"一次只允许一个 TCP 服务活动"。**❌ 复核仍在**(现 `lftpd.c:392`,3 次重试 + 200 ms 间隔) | | P2-8 | `net_recv` 阻塞超时 30 s | 台账 | 缩短并让上层可取消。**❌ 复核仍在**:`net_config.h:39` `NET_RECV_TIMEOUT_MS 30000` | | — | PHY 强制 100M 全双工,忽略自协商 | AGENTS/architecture | 与某些交换机会联不通;至少加"链路 up 失败 3 次后回退自协商"。**❌ 复核仍在**:`net_task.c:110` 无条件 `ch395f_set_phy(CH395F_PHY_100M_FULL)`,仅 3 s 链路等待 + DISCONN 时上报 `comms fault` 自检 | @@ -351,7 +351,7 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap | 编号 | 问题 | 建议 | |------|------|------| -| P1-10 | CH395F 硬件测试套件 RAM 溢出(`L6406E`):HW 套 +8.7 KB、NET 层固件 +28 KB(`s_rx_buf` 32 KB) | 测试缓冲改为**分 Phase 复用同一块静态缓冲**(union 或分阶段 `memset`);`待处理内容.md` 的这条待办应升级为正式任务。**🟡 2026-10-11 复核:已升级为登记簿唯一 P 类收尾项**(RAM 侧因堆迁 CCM 大幅缓解,剩"CH395F 套件构建实测链接确认 + `@test` 闭环"两步) | +| P1-10 | CH395F 硬件测试套件 RAM 溢出(`L6406E`):HW 套 +8.7 KB、NET 层固件 +28 KB(`s_rx_buf` 32 KB) | 测试缓冲改为**分 Phase 复用同一块静态缓冲**(union 或分阶段 `memset`);`docs/任务规划/测试与架构专项.md` 的这条待办应升级为正式任务。**🟡 2026-10-11 复核:已升级为登记簿唯一 P 类收尾项**(RAM 侧因堆迁 CCM 大幅缓解,剩"CH395F 套件构建实测链接确认 + `@test` 闭环"两步) | --- @@ -691,10 +691,10 @@ UI 剩余页面批量落地(U5)、目录级层次迁移(S-1 的物理搬 **报告结束。** > **2026-10-11 复核收尾**: -> - ⚠ **台账漏登两条**:本报告 **N-02(FTP 无鉴权)** 与 **N-12/N-13(dhara 移植缺陷)** 既未修复也未登记在 `../待处理内容.md` → 建议补登。 +> - ⚠ **台账漏登两条**:本报告 **N-02(FTP 无鉴权)** 与 **N-12/N-13(dhara 移植缺陷)** 既未修复也未登记在 `../任务规划/README.md` → 建议补登。 > - ⚠ **编号撞车**:本报告曾用 N-18 指"无 CI"(该条已销项删除),而登记簿的 N-18 = "8 路电气量分属两片转换器(V0.2 改版项)"。引用时一律带文档名。 > - ✅ `docs/内存管理/RAM预算台账.md` 与 `scripts/ram_baseline.tsv` **已于 2026-10-12 创建**(见 §5.5 各条闭环标注)。 -> - 本报告按 `docs/README.md` 的定位是**体系层评审报告,不是待办池**——待办一律以 `../待处理内容.md` 为准;本报告只保留**未闭环问题的发现 + 证据**,修复即销项。 +> - 本报告按 `docs/README.md` 的定位是**体系层评审报告,不是待办池**——待办一律以 `../任务规划/README.md` 为准;本报告只保留**未闭环问题的发现 + 证据**,修复即销项。 --- diff --git a/scripts/check_registration.py b/scripts/check_registration.py index 66717ae2..bf0afbf1 100644 --- a/scripts/check_registration.py +++ b/scripts/check_registration.py @@ -38,7 +38,7 @@ & '.venv\\Scripts\\python.exe' scripts/check_registration.py & '.venv\\Scripts\\python.exe' scripts/check_registration.py --strict -设计依据:docs/待处理内容.md N-23;.dsh/skills/new-source-file +设计依据:docs/任务规划/登记簿.md N-23;.dsh/skills/new-source-file 创建日期:2026-10-12 """ diff --git a/scripts/check_test_suite.py b/scripts/check_test_suite.py index 179aa9ec..51078094 100644 --- a/scripts/check_test_suite.py +++ b/scripts/check_test_suite.py @@ -37,7 +37,7 @@ & '.venv\\Scripts\\python.exe' scripts/check_test_suite.py --allow-test-build & '.venv\\Scripts\\python.exe' scripts/check_test_suite.py --file <路径> -设计依据:docs/待处理内容.md T-1;docs/测试说明/测试开发标准流程.md §3.1 +设计依据:docs/任务规划/登记簿.md T-1;docs/测试说明/测试开发标准流程.md §3.1 创建日期:2026-10-01 """ diff --git a/scripts/ram_baseline.py b/scripts/ram_baseline.py index 7207a513..36d3cee1 100644 --- a/scripts/ram_baseline.py +++ b/scripts/ram_baseline.py @@ -8,7 +8,7 @@ RAM 预算门禁 + 趋势台账(登记簿 N-27 前半 / 审查报告 §5.5 三 1. **92% 阈值门禁**(`--gate`,pre-commit `mem-budget` 钩子入口): RW_IRAM1 / RW_CCM 任一区占比 > 92% → FAIL,并附 Top-10 RW+ZI 对象表; 无 `.map`(未做 Keil 构建)→ 自适应跳过(与 `mem-numbers` 同口径, - CI 盲区登记在 `docs/待处理内容.md` A-5 残余)。 + CI 盲区登记在 `docs/任务规划/测试与架构专项.md` A-5 残余)。 `--gate` 同时校验台账受管区与 `.map` 一致(防漂移,同 `mem-numbers` 思路)。 2. **趋势基线** `scripts/ram_baseline.tsv`(`--update` 每次 @build 后追加一行; `--trend` 看趋势并高亮 RW+ZI 较上一行增长 >1 KB 的对象——方案 §0.3 @@ -173,7 +173,7 @@ def cmd_gate(args): map_path = _map_or_skip(args) if map_path is None: print("[SKIP] 无 .map(未做 Keil 构建)→ RAM 预算门禁不适用") - print(" (CI 盲区已登记 docs/待处理内容.md A-5 残余;" + print(" (CI 盲区已登记 docs/任务规划/测试与架构专项.md A-5 残余;" "本地改过代码请先 @build)") return 0 info = collect(map_path) diff --git a/test/host/common/unit_test_harness.py b/test/host/common/unit_test_harness.py index 3d520fd2..6519baac 100644 --- a/test/host/common/unit_test_harness.py +++ b/test/host/common/unit_test_harness.py @@ -36,7 +36,7 @@ summary_marker="=== Task Watchdog Tests:", ))) -设计依据:docs/待处理内容.md T-3;docs/测试说明/测试开发标准流程.md §4.2 +设计依据:docs/任务规划/登记簿.md T-3;docs/测试说明/测试开发标准流程.md §4.2 创建日期:2026-10-01 """ diff --git a/test/host/time_sync/run_unit_test.py b/test/host/time_sync/run_unit_test.py index d23c58ec..664871ce 100644 --- a/test/host/time_sync/run_unit_test.py +++ b/test/host/time_sync/run_unit_test.py @@ -25,7 +25,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:App/sync/time_sync.c 文件头注释 + docs/待处理内容.md N-17; +设计依据:App/sync/time_sync.c 文件头注释 + docs/任务规划/登记簿.md N-17; 创建日期:2026-10-10 """ import os diff --git a/test/host/watchdog/run_unit_test.py b/test/host/watchdog/run_unit_test.py index 1922f12e..0fb5e4bf 100644 --- a/test/host/watchdog/run_unit_test.py +++ b/test/host/watchdog/run_unit_test.py @@ -22,7 +22,7 @@ 退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。 -设计依据:docs/测试说明/看门狗单元测试说明.md;docs/待处理内容.md T-3 +设计依据:docs/测试说明/看门狗单元测试说明.md;docs/任务规划/登记簿.md T-3 创建日期:2026-10-01 """ import os diff --git a/test/run_all_suites.py b/test/run_all_suites.py index 0a579913..15227338 100644 --- a/test/run_all_suites.py +++ b/test/run_all_suites.py @@ -40,7 +40,7 @@ ② 防止"某套件长期编不过而无人知"(2026-08~09 CH395F 套件实例)。 注意 RAM 溢出(P1-9)会自然暴露为链接错误 L6406E——这正是想要的。 -设计依据:docs/待处理内容.md T-5;docs/测试说明/测试开发标准流程.md §3.1 +设计依据:docs/任务规划/登记簿.md T-5;docs/测试说明/测试开发标准流程.md §3.1 创建日期:2026-10-01 """ From 1fe163ba7b09e510649acda2e1271f125891013b Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 12 Oct 2026 15:01:49 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat(protect):=20B7=20=E5=AE=9A=E5=80=BC?= =?UTF-8?q?=E6=8C=81=E4=B9=85=E5=8C=96=20+=20=E5=85=A8=E5=B1=80=E8=BD=AF?= =?UTF-8?q?=E5=8E=8B=E6=9D=BF=20+=20L5-1=20=E7=AB=9E=E6=80=81=E6=94=B6?= =?UTF-8?q?=E5=8F=A3=EF=BC=88W1=20=E4=BB=A3=E7=A0=81=E8=85=BF=E5=AE=8C?= =?UTF-8?q?=E6=88=90=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - prot_set:新增 PS_GLOBAL_EN(枚举尾追加);值区双缓冲 + 单字交换, prot_set_set_sealed 原子写+封存;selfcheck 改 seqlock 式复核 (提交撞见 = 本轮跳过)→ 收口 B5 登记的 µs 级误锁窗口 - 持久化:新增 App/cfg/prot_set_store.c/h,/prot_set.bin blob (magic+版本+计数+值区+sum32 正/反码对,144 B)走 cfg_store_write_atomic; uvprojx 注册 + 模拟器豁免点名(check_registration 同步) - 写路径:C_SE/YK12 执行段置脏 → iec104Task 投递 SYS_EVT_PROT_SET_SAVE (事件位 bit7)→ defaultTask(配置引擎属主)落盘,写失败脏回置 = 天然 重试;装载 = STORAGE_READY 屏障前整表原子 parse(损坏保出厂默认 + 自检留痕 prot set corrupt;文件缺失 = 首启静默) - YK12 转真:两段式(选择段校验 DPC / 执行段 set_sealed),protectTask 下一拍读退出态 → 复位元件 + 停判据(global plate OUT/IN 边沿日志); 本地定值项 comm_addr=0 显式不可寻址(防 IOA=0 误命中首个本地项) - 单测:prot_set 63 断言(+33:软压板/原子写/脏握手/blob 往返/损坏拒绝/ 伪造自洽越界对抗样本)、iec104 94 断言(+7:YK12 两段转真/置脏/本地项 C_RD EVI) - 文档:IEC104 设计说明 §3.3/§3.4/§7、保护规划 §3.5 L5-1/§7 P4/变更记录、 App/algo 与 App/cfg README、W1 任务卡 B7→🟦(台架腿 🔴 待窗口,随 B6 同窗) - 验证:@build 0 错 0 警(Code=205500,ZI +280 = 双缓冲+blob 缓冲); ci_local 全绿(L0 27 钩子 + L0.5 13 套件 826 断言);ram_baseline 台账 受管区与内存快照已同步;19 个改动文件无 BOM / LF / 零乱码 --- App/algo/README.md | 13 +- App/algo/prot_set.c | 247 +++++++++++++++++++++++-- App/algo/prot_set.h | 55 +++++- App/app/sys_events.h | 3 + App/cfg/README.md | 4 +- App/cfg/prot_set_store.c | 64 +++++++ App/cfg/prot_set_store.h | 31 ++++ App/protocol/iec104/iec104_pts.c | 37 ++-- App/protocol/iec104/iec104_pts.h | 11 +- App/task/default_task.c | 21 ++- App/task/iec104_serv.c | 7 + App/task/protect_task.c | 27 ++- MDK-ARM/STM32F407-Demo.uvprojx | 5 + docs/任务规划/W1-采集保护收尾.md | 4 +- docs/内存管理/RAM使用分析与优化方案.md | 6 +- docs/内存管理/RAM预算台账.md | 6 +- docs/子系统设计/IEC104上行设计说明.md | 20 +- docs/算法/继电保护功能复现规划.md | 7 +- scripts/check_registration.py | 1 + scripts/ram_baseline.tsv | 2 +- test/host/iec104/iec104_test.c | 52 ++++++ test/host/prot_set/prot_set_test.c | 103 +++++++++++ 22 files changed, 655 insertions(+), 71 deletions(-) create mode 100644 App/cfg/prot_set_store.c create mode 100644 App/cfg/prot_set_store.h diff --git a/App/algo/README.md b/App/algo/README.md index 32432413..ee3b12d1 100644 --- a/App/algo/README.md +++ b/App/algo/README.md @@ -154,16 +154,19 @@ flowchart TD ### 3.5 `prot_set.c` / `prot_set.h` — 保护定值模型(P1 / L5-1 载体) **解决的问题**:保护判据的"输入宪法"。参考系统把定值放 EEPROM + `tagPRS` 常量表 -校验和自检;本层先做 **RAM 模型**(cfg_file 持久化属 P4),把编号 / 通讯地址 / -范围 / 默认值 / 校验和闭环钉死。 +校验和自检;本层做 **RAM 模型 + 持久化纯逻辑层**(blob 序列化/解析;文件胶水在 +`App/cfg/prot_set_store.c`,B7),把编号 / 通讯地址 / 范围 / 默认值 / 校验和闭环钉死。 | API | 干什么 | 注意 | |---|---|---| | `prot_set_init()` | 装默认值 + 封存校验和(幂等) | 内核启动前可调 | -| `prot_set_load_raw(vals)` | 整表装载(P4 起 cfg_file 调用),逐项范围校验 | **all-or-nothing**:任一项越界整表不装载,`prot_set_bad_mask()` 指认越界项 | -| `prot_set_set(id, q10)` | 单项写入(范围校验) | **不自动重封存**——批量改完必须 `prot_set_seal()`,否则 selfcheck 判"非法改写" | +| `prot_set_load_raw(vals)` | 整表装载(B7 由 `prot_set_store_parse` 内部走同一路径),逐项范围校验 | **all-or-nothing**:任一项越界整表不装载,`prot_set_bad_mask()` 指认越界项;影子区 + 单字交换,读侧无中间态 | +| `prot_set_set(id, q10)` | 单项写入(范围校验,批处理路径) | **不自动重封存**——批量改完必须 `prot_set_seal()`,否则 selfcheck 判"非法改写";板端单项写一律用下行 | +| `prot_set_set_sealed(id, q10)` | **原子写+封存(B7)**:影子区改好重封后单字交换 | selfcheck 永不见中间态(收口 B5 竞态窗口);置脏标志 | +| `prot_set_dirty_peek/take/mark()` | 脏标志三件套(B7 落盘握手) | peek=iec104Task 通知;take=属主落盘前消费;mark=写失败回置重试 | +| `prot_set_store_serialize/parse(buf,len)` | 持久化 blob(`PSET`+版本+值区+sum32 正/反码对) | parse **整表原子**:magic/版本/长度/校验对/范围任一失败 = 一字不动 | | `prot_set_get_f()` / `get_ctl()` | 工程量浮点 / 投退读取 | 单字读原子 | -| `prot_set_selfcheck()` | 重算 sum32 与封存正/反码比对,失配 → 闭锁 | L5-1;`prot_set_seal()` 是解锁的唯一合法路径 | +| `prot_set_selfcheck()` | 重算 sum32 与封存正/反码比对,失配 → 闭锁 | L5-1;seqlock 式复核:提交撞见 = 本轮跳过不误锁;`prot_set_seal()` 是解锁的唯一合法路径 | **要点** diff --git a/App/algo/prot_set.c b/App/algo/prot_set.c index cfefead3..4b07260f 100644 --- a/App/algo/prot_set.c +++ b/App/algo/prot_set.c @@ -9,6 +9,8 @@ */ #include "prot_set.h" +#include /* memcpy(set_sealed 影子区拷贝,B7) */ + /* 元数据表:顺序必须与 prot_set_id_t 严格一致(逐行带地址注释,同 phasor * k_inst 的朴素行式风格) */ const prot_set_meta_t g_prot_set_meta[PS_ID_COUNT] = { @@ -44,25 +46,30 @@ const prot_set_meta_t g_prot_set_meta[PS_ID_COUNT] = { { 0x8821, 0u, PROT_SET_Q10(100.0), PROT_SET_Q10(1.0), PROT_SET_Q10(200.0) }, { 0x8825, 0u, PROT_SET_Q10(100.0), PROT_SET_Q10(1.0), PROT_SET_Q10(10000.0) }, { 0x8826, 0u, PROT_SET_Q10(5.0), PROT_SET_Q10(1.0), PROT_SET_Q10(10.0) }, + { 0x0000, 1u, PROT_SET_Q10(1), 0, PROT_SET_Q10(1) }, /* 全局软压板投退(YK12,B7) */ }; -static uint32_t s_val[PS_ID_COUNT]; /* RAM 值区(uint32 承载 int32,校验和按字覆盖) */ +static uint32_t s_val[2][PS_ID_COUNT]; /* 双缓冲值区(uint32 承载 int32,校验和按字覆盖) + * B7:写者改影子区后单字交换 s_act, + * 读侧(protectTask selfcheck/get)永远看到一致快照 */ +static volatile uint8_t s_act; /* 活跃区下标(0/1);交换 = 单字存储 */ static uint32_t s_sum; /* 封存的正码 */ static uint32_t s_sumn; /* 封存的反码 */ -static uint32_t s_bad_mask; /* load_raw 越界位图 */ +static uint32_t s_bad_mask; /* load_raw/parse 越界位图 */ static uint8_t s_locked; /* 定值非法 → 闭锁(L5-1) */ +static uint8_t s_dirty; /* 未落盘定值改动(B7 持久化脏标志) */ /* - * 函数功能:sum32 覆盖 RAM 值区(参考 Fun_CalSum32 同款:32 位字累加自然回绕) - * 入口参数:无 + * 函数功能:sum32 覆盖指定值区(参考 Fun_CalSum32 同款:32 位字累加自然回绕) + * 入口参数:vals - PS_ID_COUNT 个字的值区 * 返 回 值:校验和正码 */ -static uint32_t prot_sum32(void) { +static uint32_t prot_sum_buf(const uint32_t *vals) { uint32_t sum = 0u; uint32_t i; for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { - sum += s_val[i]; + sum += vals[i]; } return sum; } @@ -76,7 +83,7 @@ static void prot_load_defaults(void) { uint32_t i; for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { - s_val[i] = (uint32_t)g_prot_set_meta[i].def; + s_val[s_act][i] = (uint32_t)g_prot_set_meta[i].def; } } @@ -89,6 +96,7 @@ void prot_set_init(void) { prot_load_defaults(); s_bad_mask = 0u; s_locked = 0u; + s_dirty = 0u; prot_set_seal(); } @@ -110,6 +118,8 @@ uint32_t prot_set_bad_mask(void) { */ int prot_set_load_raw(const int32_t *vals) { uint32_t mask = 0u; + uint32_t cur_act; + uint32_t *shadow; uint32_t i; if (vals == 0) { @@ -124,10 +134,16 @@ int prot_set_load_raw(const int32_t *vals) { if (mask != 0u) { return -1; } + /* 原子装载(B7):写影子区 → 封存 → 单字交换;读侧无中间态 */ + cur_act = s_act; + shadow = s_val[cur_act ^ 1u]; for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { - s_val[i] = (uint32_t)vals[i]; + shadow[i] = (uint32_t)vals[i]; } - prot_set_seal(); + s_sum = prot_sum_buf(shadow); + s_sumn = ~s_sum; + s_locked = 0u; + s_act = (uint8_t)(cur_act ^ 1u); return 0; } @@ -145,10 +161,64 @@ int prot_set_set(prot_set_id_t id, int32_t q10) { if ((q10 < g_prot_set_meta[id].min) || (q10 > g_prot_set_meta[id].max)) { return -1; } - s_val[(uint32_t)id] = (uint32_t)q10; + s_val[s_act][(uint32_t)id] = (uint32_t)q10; return 0; } +/* + * 函数功能:单项**原子**写入+封存(B7,收口 B5 竞态窗口) + * 入口参数:id - 定值项编号;q10 - Q10 定点值 + * 返 回 值:0 / -1 越界或非法编号拒写(原值不动) + * 函数说明:影子区拷贝 → 改影子 → 按影子重封校验和 → 单字交换活跃区。 + * selfcheck 任何时刻看到的都是"值区与封存一致"的完整快照 + * (区别于 prot_set_set+seal 批处理路径;两路径勿在一次批处理中交错)。 + * 置脏标志 → 104 任务通知 defaultTask(配置引擎属主)落盘。 + */ +int prot_set_set_sealed(prot_set_id_t id, int32_t q10) { + uint32_t cur_act; + uint32_t *shadow; + + if (id >= PS_ID_COUNT) { + return -1; + } + if ((q10 < g_prot_set_meta[id].min) || (q10 > g_prot_set_meta[id].max)) { + return -1; + } + cur_act = s_act; + shadow = s_val[cur_act ^ 1u]; + (void)memcpy(shadow, s_val[cur_act], sizeof(s_val[0])); + shadow[(uint32_t)id] = (uint32_t)q10; + s_sum = prot_sum_buf(shadow); + s_sumn = ~s_sum; + s_locked = 0u; + s_act = (uint8_t)(cur_act ^ 1u); /* 单字交换:读侧原子切换 */ + s_dirty = 1u; + return 0; +} + +/* + * 函数功能:脏标志三件套(B7 持久化握手) + * 入口参数:无 + * 返 回 值:peek/take = 1 存在未落盘改动 / 0 干净;mark 无返回 + * 函数说明:peek 非消费(iec104Task 每轮通知,直到落盘成功); + * take 消费(defaultTask 落盘前);mark 写盘失败回置(等下轮重试)。 + * 单字节标志,多读者安全;写者只有 set_sealed(置)与属主任务(清/置)。 + */ +uint8_t prot_set_dirty_peek(void) { + return s_dirty; +} + +uint8_t prot_set_dirty_take(void) { + uint8_t d = s_dirty; + + s_dirty = 0u; + return d; +} + +void prot_set_dirty_mark(void) { + s_dirty = 1u; +} + /* * 函数功能:读定值 Q10 原值 * 入口参数:id - 定值项编号 @@ -158,7 +228,7 @@ int32_t prot_set_get(prot_set_id_t id) { if (id >= PS_ID_COUNT) { return 0; } - return (int32_t)s_val[(uint32_t)id]; + return (int32_t)s_val[s_act][(uint32_t)id]; } /* @@ -185,7 +255,7 @@ uint8_t prot_set_get_ctl(prot_set_id_t id) { * 返 回 值:sum32 正码 */ uint32_t prot_set_checksum(void) { - return prot_sum32(); + return prot_sum_buf(s_val[s_act]); } /* @@ -193,9 +263,12 @@ uint32_t prot_set_checksum(void) { * 入口参数:无 * 返 回 值:无 * 函数说明:封存同时解除闭锁——selfcheck 失配后的唯一合法解锁路径。 + * ⚠ 批处理路径(prot_set_set 多次 + 本函数收尾)在 set 与 seal + * 之间存在"已改值未封存"窗口,selfcheck 会如实判失配(防篡改语义); + * 板端单项写一律走 prot_set_set_sealed(原子,无此窗口)。 */ void prot_set_seal(void) { - s_sum = prot_sum32(); + s_sum = prot_sum_buf(s_val[s_act]); s_sumn = ~s_sum; s_locked = 0u; } @@ -206,16 +279,23 @@ void prot_set_seal(void) { * 返 回 值:0 通过 / -1 失配(已置闭锁) * 函数说明:失配 → s_locked 置位并保持,直到下一次 seal; * 元件层每拍读 prot_set_locked() 决定整体复位(联动闭锁)。 + * B7 双缓冲 + seqlock 式复核:先读封存和、再读值区、再读封存和, + * 两次不同 = 检查期间发生了原子提交 → 本轮不作数(下拍再查), + * 杜绝"提交瞬间被巡检撞见"的误锁(收口 B5 竞态窗口)。 */ int prot_set_selfcheck(void) { - if (prot_sum32() != s_sum) { + uint32_t sum_a = s_sum; + uint32_t calc = prot_sum_buf(s_val[s_act]); + uint32_t sum_b = s_sum; + + if (sum_a != sum_b) { + /* 检查期间有 set_sealed/load_raw 提交:快照不一致,本轮跳过 */ + return (s_locked != 0u) ? -1 : 0; + } + if ((calc != sum_a) || (sum_a != ~s_sumn)) { s_locked = 1u; /* 值区与封存不符:定值被非法改写 → 闭锁 */ } - if ((s_sum != (~s_sumn)) || (s_locked != 0u)) { - s_locked = 1u; - return -1; - } - return 0; + return (s_locked != 0u) ? -1 : 0; } /* @@ -226,3 +306,132 @@ int prot_set_selfcheck(void) { uint8_t prot_set_locked(void) { return s_locked; } + +/* ==================== 持久化 blob(B7,纯逻辑) ========================= */ + +/* 小端编解码(blob 跨端一致;主机单测与 MCU 同一份字节口径) */ + +/* + * 函数功能:16 位值按小端写入缓冲 + * 入口参数:p - 写位置(≥2 字节余量);v - 值 + * 返 回 值:无 + */ +static void s_put16(uint8_t *p, uint16_t v) { + p[0] = (uint8_t)(v & 0xFFu); + p[1] = (uint8_t)(v >> 8); +} + +/* + * 函数功能:32 位值按小端写入缓冲 + * 入口参数:p - 写位置(≥4 字节余量);v - 值 + * 返 回 值:无 + */ +static void s_put32(uint8_t *p, uint32_t v) { + p[0] = (uint8_t)(v & 0xFFu); + p[1] = (uint8_t)((v >> 8) & 0xFFu); + p[2] = (uint8_t)((v >> 16) & 0xFFu); + p[3] = (uint8_t)(v >> 24); +} + +/* + * 函数功能:从小端缓冲读 16 位值 + * 入口参数:p - 读位置 + * 返 回 值:值 uint16_t + */ +static uint16_t s_get16(const uint8_t *p) { + return (uint16_t)((uint32_t)p[0] | ((uint32_t)p[1] << 8)); +} + +/* + * 函数功能:从小端缓冲读 32 位值 + * 入口参数:p - 读位置 + * 返 回 值:值 uint32_t + */ +static uint32_t s_get32(const uint8_t *p) { + return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) + | ((uint32_t)p[3] << 24); +} + +/* + * 函数功能:把当前值区序列化为 blob(校验和按值区现算,不依赖封存值) + * 入口参数:p_buf - 输出缓冲;cap - 容量;p_len - 实际长度输出 + * 返 回 值:0 / -1 参数非法或容量不足 + */ +int prot_set_store_serialize(uint8_t *p_buf, uint32_t cap, uint32_t *p_len) { + const uint32_t *vals = s_val[s_act]; + uint32_t sum = 0u; + uint32_t i; + + if ((p_buf == 0) || (p_len == 0) || (cap < PROT_SET_BLOB_SZ)) { + return -1; + } + s_put32(p_buf, PROT_SET_BLOB_MAGIC); + s_put16(p_buf + 4u, (uint16_t)PROT_SET_BLOB_VER); + s_put16(p_buf + 6u, (uint16_t)PS_ID_COUNT); + for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { + s_put32(p_buf + PROT_SET_BLOB_HDR_SZ + 4u * i, vals[i]); + sum += vals[i]; + } + s_put32(p_buf + PROT_SET_BLOB_SZ - 8u, sum); + s_put32(p_buf + PROT_SET_BLOB_SZ - 4u, ~sum); + *p_len = PROT_SET_BLOB_SZ; + return 0; +} + +/* + * 函数功能:解析 blob 并**整表原子**装载(all-or-nothing) + * 入口参数:p_buf/len - blob 字节流 + * 返 回 值:0 已装载并封存 / -1 拒绝(magic/版本/长度/校验对不符或任一项 + * 越界 → 活跃值区一字不动;越界项经 prot_set_bad_mask() 指认) + * 函数说明:解码/校验全在影子区进行,只有全部通过才交换活跃区—— + * 损坏 blob 不可能污染在用的定值(掉电/写坏/版本换代同一路径)。 + */ +int prot_set_store_parse(const uint8_t *p_buf, uint32_t len) { + uint32_t cur_act; + uint32_t *shadow; + uint32_t sum = 0u; + uint32_t mask = 0u; + uint32_t i; + + if ((p_buf == 0) || (len != PROT_SET_BLOB_SZ)) { + return -1; + } + if (s_get32(p_buf) != PROT_SET_BLOB_MAGIC) { + return -1; + } + if (s_get16(p_buf + 4u) != (uint16_t)PROT_SET_BLOB_VER) { + return -1; + } + if (s_get16(p_buf + 6u) != (uint16_t)PS_ID_COUNT) { + return -1; + } + cur_act = s_act; + shadow = s_val[cur_act ^ 1u]; + for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { + uint32_t v = s_get32(p_buf + PROT_SET_BLOB_HDR_SZ + 4u * i); + + shadow[i] = v; + sum += v; + } + if (sum != s_get32(p_buf + PROT_SET_BLOB_SZ - 8u)) { + return -1; /* 校验和正码不符(影子区未交换前不可见,无害) */ + } + if (~sum != s_get32(p_buf + PROT_SET_BLOB_SZ - 4u)) { + return -1; /* 反码对不符 */ + } + for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { + if (((int32_t)shadow[i] < g_prot_set_meta[i].min) + || ((int32_t)shadow[i] > g_prot_set_meta[i].max)) { + mask |= (1uL << i); + } + } + s_bad_mask = mask; + if (mask != 0u) { + return -1; /* 校验对一致但含越界项:同样整表拒绝 */ + } + s_sum = sum; + s_sumn = ~sum; + s_locked = 0u; + s_act = (uint8_t)(cur_act ^ 1u); + return 0; +} diff --git a/App/algo/prot_set.h b/App/algo/prot_set.h index a4cff982..f26c54ff 100644 --- a/App/algo/prot_set.h +++ b/App/algo/prot_set.h @@ -1,8 +1,8 @@ /* * 模块名称:保护定值模型(P1,L5-1 载体) - * 模块功能:保护定值的 RAM 模型——编号 / 通讯地址 / 范围 / 默认值 / 校验和自检。 - * 纯逻辑(仅 stdint.h),主机侧可离线单测;持久化(cfg_file 定值段) - * 属 P4,本层只提供 load_raw/validate 的装载接口。 + * 模块功能:保护定值的 RAM 模型——编号 / 通讯地址 / 范围 / 默认值 / 校验和自检, + * 以及 B7 定值持久化的**纯逻辑层**(blob 序列化/解析 + 原子装载)。 + * 文件读写胶水在 App/cfg/prot_set_store.c(MCU 端)。 * * 设计口径(docs/算法/继电保护功能复现规划.md §5): * - 定点存储:Q10(×1024),与参考系统定点系数 2^10 一致(§5.3); @@ -13,8 +13,11 @@ * - ⚠ 默认值/范围为**拟定值**:参考 EEPROM 出厂默认表未在本仓库, * 待对照后逐项修订(规划 §10.3 待补项);范围先按 DTU 馈线典型量级。 * - * 线程约定:装载(init/load_raw)在 defaultTask(P4 起);读在保护消费者任务。 - * 读接口返回快照值(单个 int32 读取原子);写与封存必须同一任务(P4 定)。 + * 线程约定(B7 定):装载(init/store_parse)在 defaultTask(存储 bring-up, + * STORAGE_READY 前);单项写在 iec104Task(C_SE/YK12,经 set_sealed 原子路径); + * 落盘在 defaultTask(配置引擎属主)。读在保护消费者任务(快照值原子)。 + * 双缓冲交换 = 单字写,读侧永远看到一致快照;写者之间靠启动时序串行 + * (装载先于 NET_READY,104 写在其后)。 * * 创建日期:2026-10-11 */ @@ -65,6 +68,8 @@ typedef enum { PS_PT_SEC, /* 0x8821 PT 二次额定(V) */ PS_CT_PRI, /* 0x8825 CT 一次额定(A) */ PS_CT_SEC, /* 0x8826 CT 二次额定(A) */ + /* --- 全局软压板(B7):104 YK12 两段式投退;0 = 保护退出服务 --- */ + PS_GLOBAL_EN, /* 本地项(无通讯地址,经 YK12 写、C_RD 不可读) */ PS_ID_COUNT } prot_set_id_t; @@ -113,4 +118,44 @@ void prot_set_seal(void); int prot_set_selfcheck(void); uint8_t prot_set_locked(void); +/* + * 函数功能:单项**原子**写入+封存(B7,收口 B5 竞态窗口) + * 入口参数:id - 定值项编号;q10 - Q10 定点值 + * 返 回 值:0 / -1 越界或非法编号拒写(原值不动) + * 函数说明:影子缓冲拷贝 → 改影子 → 重封校验和 → 单字交换活跃区。 + * selfcheck 永远看到"值区与封存一致"的完整快照,不存在 + * "已改值未封存"中间态(区别于 prot_set_set+seal 的批处理路径, + * 两条路径不得在一次批处理中途交错)。置脏标志(待持久化)。 + */ +int prot_set_set_sealed(prot_set_id_t id, int32_t q10); + +/* 脏标志(存在未落盘的定值改动):set_sealed 置位;load/init 不置 */ +uint8_t prot_set_dirty_peek(void); /* 非消费(生产者用它通知属主任务) */ +uint8_t prot_set_dirty_take(void); /* 消费(属主任务落盘前取) */ +void prot_set_dirty_mark(void); /* 写盘失败回置(等下轮重试) */ + +/* ---------------- 持久化 blob(B7;纯逻辑,主机可单测) ---------------- + * 格式(小端):magic 'PSET'(4B) + version u16 + count u16 + * + values u32×count + sum32 u32 + ~sum32 u32 + * 版本 1;count 必须等于 PS_ID_COUNT(定值表增项 → 旧 blob 整体作废, + * 编号不回收但格式换代,宁可用出厂默认也不半装载)。 */ +#define PROT_SET_BLOB_MAGIC 0x50534554uL /* 字节序 P,S,E,T */ +#define PROT_SET_BLOB_VER 1u +#define PROT_SET_BLOB_HDR_SZ 8u /* magic(4)+ver(2)+cnt(2) */ +#define PROT_SET_BLOB_SZ (PROT_SET_BLOB_HDR_SZ + 4u * (uint32_t)PS_ID_COUNT + 8u) + +/* + * 函数功能:把当前值区序列化为 blob(校验和按值区现算,不依赖封存值) + * 返 回 值:0 / -1 缓冲不足或参数非法;*p_len 输出实际长度 + */ +int prot_set_store_serialize(uint8_t *p_buf, uint32_t cap, uint32_t *p_len); + +/* + * 函数功能:解析 blob 并**整表原子**装载(all-or-nothing) + * 入口参数:p_buf/len - blob 字节流 + * 返 回 值:0 已装载并封存 / -1 拒绝(magic/版本/长度/校验对不符或 + * 任一项越界 → 值区一字不动;越界项经 prot_set_bad_mask() 指认) + */ +int prot_set_store_parse(const uint8_t *p_buf, uint32_t len); + #endif /* PROT_SET_H */ diff --git a/App/app/sys_events.h b/App/app/sys_events.h index b8f257c3..f2d63d8b 100644 --- a/App/app/sys_events.h +++ b/App/app/sys_events.h @@ -31,6 +31,9 @@ extern osEventFlagsId_t sys_evtHandle; #define SYS_EVT_CFG_SAVE (1u << 5) /* UI:网口配置保存请求(defaultTask = 配置引擎属主,消费并写盘) */ #define SYS_EVT_CONSOLE_TX (1u << 6) /* 控制台单写者:生产者入环形缓冲后置位,defaultTask 消费并发送 * (消费型命令位,非就绪位——就绪位必须 osFlagsNoClear) */ +#define SYS_EVT_PROT_SET_SAVE (1u << 7) /* 保护定值落盘请求(B7):iec104Task 检测到定值脏置位, + * defaultTask(配置引擎属主)消费并写 /prot_set.bin + * (消费型命令位;写盘失败脏标志保留 → 下轮再通知重试) */ #ifdef __cplusplus } diff --git a/App/cfg/README.md b/App/cfg/README.md index f09a590c..2b56fbe9 100644 --- a/App/cfg/README.md +++ b/App/cfg/README.md @@ -10,11 +10,13 @@ | `cfg_file.c/h` | **配置引擎核心**:解析 / 查询 / 保存 / 2s 周期 `cfg_file_poll` | | `cfg_file_store.h` | **存储后端抽象接口**(MCU=FreeRTOS 堆 / 模拟器=宿主堆,共享核心零分配符号) | | `cfg_file_store_mcu.c` | **MCU 端后端实现**:`/config.ini`(临时名由目标路径同目录推导 + `f_rename` 原子写) | +| `prot_set_store.c/h` | **保护定值持久化胶水(B7)**:`/prot_set.bin` blob 读写(blob 格式/校验/原子装载在 `App/algo/prot_set.c` 纯逻辑层);装载 = storage bring-up(屏障前),落盘 = defaultTask 消费 `SYS_EVT_PROT_SET_SAVE` | ## 设计要点 - **单任务收敛**:`cfg_file` 为静态态,只有 defaultTask 操作;UI 保存请求经 - `SYS_EVT_CFG_SAVE` 事件唤醒 defaultTask 执行(netTask/uiTask 不得直接调用) + `SYS_EVT_CFG_SAVE` 事件唤醒 defaultTask 执行(netTask/uiTask 不得直接调用); + 定值落盘同构——iec104Task 只置事件位(`SYS_EVT_PROT_SET_SAVE`),不碰文件系统 - **零分配共享核心**:核心逻辑不含任何分配符号,动态内存收进平台后端 (`cfg_store_alloc/free`:MCU→`pvPortMalloc`,模拟器→宿主堆) - **原子写**:写 `/config.TMP` 后 `f_rename` 替换,避免掉电损坏 diff --git a/App/cfg/prot_set_store.c b/App/cfg/prot_set_store.c new file mode 100644 index 00000000..4e0f3b85 --- /dev/null +++ b/App/cfg/prot_set_store.c @@ -0,0 +1,64 @@ +/* + * 模块名称:prot_set_store(B7 定值持久化)——实现 + * 模块功能:见 prot_set_store.h。blob 格式/校验/原子装载全在 prot_set.c + * (纯逻辑,主机单测覆盖),本文件只做"读文件→parse、 + * serialize→原子写"的平台胶水。 + * 文件口径:"/prot_set.bin"(卷根,8.3 合规,FF_USE_LFN=0 约束); + * 原子写临时名由 cfg_store_write_atomic 按目标目录推导 + * (固定 config.TMP),与 /config.ini 的保存同在 defaultTask + * 串行执行,无并发竞争。 + * 创建日期:2026-10-12(B7) + */ +#include "prot_set_store.h" + +#include + +#include "cfg_file_store.h" +#include "prot_set.h" + +#define PROT_SET_STORE_PATH "/prot_set.bin" + +/* blob 收发缓冲(静态:defaultTask 栈深已是全项目最深链,勿再压 144 B 局部) */ +static uint8_t s_blob[PROT_SET_BLOB_SZ]; + +/* + * 函数功能:开机装载定值 blob + * 入口参数:无 + * 返 回 值:0 已装载 / 1 文件缺失或读失败(保持默认)/ -1 损坏被拒 + * 函数说明:读失败与"文件不存在"同归 1——启动期卷锁无竞争(本任务独占 + * bring-up),try-lock 失败即真 I/O 故障,此时保持出厂默认并让 + * 调用方按"无档"处理是安全侧(定值仍封存自洽,L5-1 不误锁)。 + */ +int prot_set_store_load(void) { + size_t nread = 0u; + + if (cfg_store_read(PROT_SET_STORE_PATH, s_blob, sizeof(s_blob), &nread) != 0) { + return 1; + } + if (prot_set_store_parse(s_blob, (uint32_t)nread) != 0) { + return -1; + } + return 0; +} + +/* + * 函数功能:落盘当前定值(消费脏标志;失败回置等重试) + * 入口参数:无 + * 返 回 值:0 无待写或成功 / -1 写失败 + */ +int prot_set_store_save(void) { + uint32_t len = 0u; + + if (prot_set_dirty_take() == 0u) { + return 0; + } + if (prot_set_store_serialize(s_blob, (uint32_t)sizeof(s_blob), &len) != 0) { + prot_set_dirty_mark(); + return -1; + } + if (cfg_store_write_atomic(PROT_SET_STORE_PATH, s_blob, (size_t)len) != 0) { + prot_set_dirty_mark(); /* 卷忙/写失败:脏保留,iec104Task 下轮再通知 */ + return -1; + } + return 0; +} diff --git a/App/cfg/prot_set_store.h b/App/cfg/prot_set_store.h new file mode 100644 index 00000000..c4570709 --- /dev/null +++ b/App/cfg/prot_set_store.h @@ -0,0 +1,31 @@ +/* + * 模块名称:prot_set_store + * 模块功能:保护定值持久化胶水(B7)——把 prot_set 的纯逻辑 blob + * (prot_set_store_serialize/parse)落到 cfg 存储后端的 + * "/prot_set.bin"(MCU = NAND/FatFs 原子写,模拟器 = 宿主文件系统)。 + * 装载在 defaultTask 存储 bring-up(STORAGE_READY 前); + * 落盘在 defaultTask(配置引擎属主,iec104Task 经 + * SYS_EVT_PROT_SET_SAVE 投递请求,本模块只被属主调用)。 + * 适用平台:双端接口(MCU 与模拟器共用 cfg_file_store 抽象) + * 创建日期:2026-10-12(B7) + */ +#ifndef PROT_SET_STORE_H +#define PROT_SET_STORE_H + +/* + * 函数功能:开机装载定值 blob(整表原子,all-or-nothing) + * 返回值:0 - 已装载;1 - 文件缺失(首启正常,保持出厂默认); + * -1 - blob 损坏/越界被拒(保持出厂默认,调用方留痕) + * 限定条件:仅 defaultTask、卷已挂载(storage_bring_up 内调用) + */ +int prot_set_store_load(void); + +/* + * 函数功能:落盘当前定值(内部先消费脏标志;无改动 = 空操作返回 0) + * 返回值:0 - 无待写或写成功;-1 - 写失败(脏标志已回置,等下轮重试) + * 限定条件:仅 defaultTask 调用(配置引擎属主;原子写 = 临时文件 + rename, + * 与 /config.ini 共用同目录 config.TMP——两者都在本任务串行执行,无并发) + */ +int prot_set_store_save(void); + +#endif /* PROT_SET_STORE_H */ diff --git a/App/protocol/iec104/iec104_pts.c b/App/protocol/iec104/iec104_pts.c index 49560e6c..c3ffd6fd 100644 --- a/App/protocol/iec104/iec104_pts.c +++ b/App/protocol/iec104/iec104_pts.c @@ -358,19 +358,32 @@ static uint64_t s_src_yx_valid(void) { } /* - * 函数功能:板端默认源 - 遥控(V0.1 仅 YK11 复归 → prot_elm_request_reset) - * 返 回 值:0 / -1 无出口硬件或未知 IOA(YK1~4/12~14 负向确认) + * 函数功能:板端默认源 - 遥控(YK11 复归 → prot_elm_request_reset; + * YK12 全局软压板 → PS_GLOBAL_EN 两段式转真,B7) + * 返 回 值:0 / -1 无出口硬件或未知 IOA(YK1~4/13/14 负向确认) * 函数说明:本回调跑在 iec104Task 上下文,**不得**直接 prot_elm_init() * (与 protectTask 的 eval 竞态)→ 落请求,下一拍 eval 头部消费(B5)。 + * YK12 走 prot_set_set_sealed(原子写+封存,B7);protectTask 下一拍 + * 读到压板态即复位元件并停判据(protect_task.c)。 */ static int s_src_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select) { - (void)dpc; /* 本期仅 YK11 与双点值无关(复归) */ switch (ioa) { case 0x600Au: /* YK11 信号复归 → 元件状态复位(异步一拍) */ + (void)dpc; /* 复归与双点值无关 */ if (select == 0u) { prot_elm_request_reset(); } return 0; + case 0x600Bu: /* YK12 全局软压板(PS_GLOBAL_EN)两段式 */ + if ((dpc != (uint8_t)IEC104_DPC_ON) && (dpc != (uint8_t)IEC104_DPC_OFF)) { + return -1; /* 非法双点命令:选择段即拒 */ + } + if (select != 0u) { + return 0; /* 选择段 = 只校验 */ + } + return prot_set_set_sealed(PS_GLOBAL_EN, + (dpc == (uint8_t)IEC104_DPC_ON) + ? PROT_SET_Q10(1) : PROT_SET_Q10(0)); default: return -1; /* 其余 YK:无出口硬件/无对应能力 → 拒绝 */ } @@ -378,7 +391,7 @@ static int s_src_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select) { /* * 函数功能:板端默认源 - 定值读(扫 g_prot_set_meta 通讯地址映射) - * 返 回 值:0 / -1 未知地址 + * 返 回 值:0 / -1 未知地址(本地项 comm_addr=0 不可寻址,B7 起显式排除) */ static int s_src_set_read(uint32_t addr, float *out) { uint32_t i; @@ -387,7 +400,8 @@ static int s_src_set_read(uint32_t addr, float *out) { return -1; } for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { - if (g_prot_set_meta[i].comm_addr == (uint16_t)addr) { + if ((g_prot_set_meta[i].comm_addr != 0u) + && (g_prot_set_meta[i].comm_addr == (uint16_t)addr)) { *out = prot_set_get_f((prot_set_id_t)i); return 0; } @@ -396,8 +410,9 @@ static int s_src_set_read(uint32_t addr, float *out) { } /* - * 函数功能:板端默认源 - 定值写(Q10 范围校验;执行段 prot_set_set + seal) - * 返 回 值:0 / -1 越界或未知地址 + * 函数功能:板端默认源 - 定值写(Q10 范围校验;执行段 prot_set_set_sealed + * 原子写+封存,B7 收口 B5 竞态窗口;置脏 → 104 任务通知落盘) + * 返 回 值:0 / -1 越界或未知地址(本地项 comm_addr=0 不可寻址) */ static int s_src_set_write(uint32_t addr, float v, uint8_t select) { uint32_t i; @@ -406,7 +421,7 @@ static int s_src_set_write(uint32_t addr, float v, uint8_t select) { for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { const prot_set_meta_t *meta = &g_prot_set_meta[i]; - if (meta->comm_addr != (uint16_t)addr) { + if ((meta->comm_addr == 0u) || (meta->comm_addr != (uint16_t)addr)) { continue; } q10 = PROT_SET_Q10(v); @@ -416,11 +431,7 @@ static int s_src_set_write(uint32_t addr, float v, uint8_t select) { if (select != 0u) { return 0; /* 选择段 = 只做范围校验 */ } - if (prot_set_set((prot_set_id_t)i, q10) != 0) { - return -1; - } - prot_set_seal(); /* 执行段:写入 + 封存校验和(L5-1) */ - return 0; + return prot_set_set_sealed((prot_set_id_t)i, q10); } return -1; /* 未知地址 */ } diff --git a/App/protocol/iec104/iec104_pts.h b/App/protocol/iec104/iec104_pts.h index d488a41e..d2438bd8 100644 --- a/App/protocol/iec104/iec104_pts.h +++ b/App/protocol/iec104/iec104_pts.h @@ -10,10 +10,13 @@ * (无效位),频率随 L1-7 落地前同样置 IV; * - YX:IOA 1~33(§1.5 表(3));双点 = 开关位置类(YX1~4,本期无硬件 → IV), * 保护动作类 YX15~23 映射 prot_elm 状态,闭锁类 YX31~33 映射 prot_set; - * - YK:IOA 0x6000+(§1.5 表(3));V0.1 无出口硬件(规划 R7)——除 - * YK11 信号复归(→ prot_elm_init)外一律否定确认(COT|PN),如实回; - * - 定值:IOA = prot_set 元数据 comm_addr(0x8820 基址 + 告警段 0x8027~0x802A), - * 读经 C_RD、写经 C_SE_NC(选择/执行两段,执行完成统一 seal 校验和); + * - YK:IOA 0x6000+(§1.5 表(3));V0.1 无出口硬件(规划 R7)—— + * YK11 信号复归(→ prot_elm_request_reset)与 YK12 全局软压板 + * (→ PS_GLOBAL_EN 两段式转真,B7)转真执行,其余一律否定确认(COT|PN),如实回; + * - 定值:IOA = prot_set 元数据 comm_addr(0x8820 基址 + 告警段 0x8027~0x802A; + * comm_addr=0 本地项不可寻址), + * 读经 C_RD、写经 C_SE_NC(选择/执行两段,执行段原子写+封存并置脏, + * 持久化 /prot_set.bin 由 defaultTask 执行,B7); * - 固有参数 8001H~800AH:本期**不实现**(字符串类无法用短浮点上送), * 按未知 IOA(COT 14 + EVI)应答,登记为待办(设计文档)。 * 线程约定:init/bind 内核启动前或建服务前;cov_check/read 仅 104 服务任务上下文。 diff --git a/App/task/default_task.c b/App/task/default_task.c index 4439702d..68dd7a6a 100644 --- a/App/task/default_task.c +++ b/App/task/default_task.c @@ -35,6 +35,7 @@ #include "nand_ftl.h" #include "net_cfg.h" #include "cfg_file.h" +#include "prot_set_store.h" #include "sys_log.h" #include "sys_events.h" /* 深调用链模块(本任务 = 存储 bring-up + 配置引擎属主 + syslog 唯一写者, @@ -221,7 +222,8 @@ void default_task_func(void *argument) { task_wd_seg(TASK_WD_SEG_EVTWAIT); if (sys_evtHandle != NULL) { (void)osEventFlagsWait(sys_evtHandle, - SYS_EVT_CFG_SAVE | SYS_EVT_CONSOLE_TX, + SYS_EVT_CFG_SAVE | SYS_EVT_CONSOLE_TX + | SYS_EVT_PROT_SET_SAVE, osFlagsWaitAny, 50u); } /* 控制台唯一发送点:把环形缓冲中的日志按块发出(无待发时立即返回) */ @@ -242,6 +244,9 @@ void default_task_func(void *argument) { #if !defined(TEST_SUITE_STORAGE) task_wd_seg(TASK_WD_SEG_CFGSAVE); net_cfg_save_run(); + /* 保护定值落盘(B7):内部消费脏标志,无改动 = 空操作; + * 写失败脏回置 → iec104Task 下轮 poll 再投递事件 = 天然重试 */ + (void)prot_set_store_save(); #endif /* 配置文件变更轮询(2s 周期;沉降去抖在引擎内) */ if ((cfg_poll_cnt++ % 40u) == 0u) { @@ -527,6 +532,20 @@ static FRESULT storage_bring_up(FATFS *fs) { * 文件缺失/损坏 = 工厂默认,不阻塞组网)。须在置位 STORAGE_READY 前, * 使"存储就绪"屏障蕴含"配置已就绪",netTask 组网时配置恒有效 */ (void)net_cfg_load(); + /* 装载保护定值持久化档(B7):文件缺失 = 出厂默认(首启正常, + * 静默);blob 损坏/越界 = 整表拒绝保持默认 + 自检留痕 + * (all-or-nothing,prot_set_store_parse 保证一字不半装载)。 + * 须在 STORAGE_READY 前——netTask 等此屏障,104 定值写必在装载后 */ + { + int ps_rc = prot_set_store_load(); + + if (ps_rc == 0) { + DBG_INFO("[CFG] prot set loaded (/prot_set.bin)"); + } else if (ps_rc < 0) { + DBG_ERROR("[CFG] prot set blob CORRUPT, defaults in use"); + syslog_post(SYSLOG_SELFTEST, "prot set corrupt"); + } + } /* 广播"存储就绪"(= 卷挂载 + 配置加载完成),唤醒依赖文件系统的任务 */ if (sys_evtHandle != NULL) { osEventFlagsSet(sys_evtHandle, SYS_EVT_STORAGE_READY); diff --git a/App/task/iec104_serv.c b/App/task/iec104_serv.c index 35b18417..db6ba923 100644 --- a/App/task/iec104_serv.c +++ b/App/task/iec104_serv.c @@ -15,6 +15,7 @@ #include "iec104_link.h" #include "iec104_pts.h" #include "net_socket.h" +#include "prot_set.h" /* 定值脏标志 peek(B7 落盘通知) */ #include "sys_clock.h" #include "sys_events.h" #include "task_watchdog.h" @@ -290,6 +291,12 @@ void iec104_serv_task(void *argument) { for (;;) { task_wd_beat(TASK_WD_IEC104); s_serv_poll(); + /* 定值改动(C_SE 执行段 / YK12)→ 通知属主任务落盘 /prot_set.bin(B7)。 + * peek 非消费:写盘失败时脏标志仍在,下一轮再投递 = 天然重试; + * 本任务不碰文件系统(配置引擎属主 = defaultTask,模块约定) */ + if ((prot_set_dirty_peek() != 0u) && (sys_evtHandle != NULL)) { + (void)osEventFlagsSet(sys_evtHandle, SYS_EVT_PROT_SET_SAVE); + } osDelay(IEC104_POLL_MS); } } diff --git a/App/task/protect_task.c b/App/task/protect_task.c index b29b9dc6..22a22a98 100644 --- a/App/task/protect_task.c +++ b/App/task/protect_task.c @@ -5,7 +5,9 @@ * 复位(防陈旧判据)+ 本拍不 eval; * ② prot_set_selfcheck()(L5-1 定值完整性巡检,31 项 sum32,开销 * 可忽略;失配 → prot_set 内部闭锁,eval 自动复位全元件); - * ③ prot_elm_run()(phasor rms → 判据步进)+ 动作位图边沿日志。 + * ③ prot_elm_run()(phasor rms → 判据步进)+ 动作位图边沿日志; + * ④ 全局软压板 PS_GLOBAL_EN(104 YK12 两段式投退,B7):退出 = + * 复位元件 + 停判据(与采样闭锁同构,独立边沿日志)。 * 定值/元件初始化在 app_main_init(内核前,B5);本任务只消费。 * 线程约定:prot_elm_run / prot_set_selfcheck 仅本任务上下文(prot_elm.h); * 跨上下文复归(104 YK11)经 prot_elm_request_reset 落请求。 @@ -31,6 +33,7 @@ static uint32_t s_prev_active; /* 上拍动作位图(边沿日志用) */ static uint8_t s_prev_hf_lock; /* 上拍采样闭锁态(边沿日志用) */ +static uint8_t s_prev_plate_out; /* 上拍全局软压板退出态(边沿日志用,B7) */ /* * 函数功能:动作位图变化沿日志(逐变化元件打名字与状态) @@ -90,11 +93,25 @@ void protect_task(void *argument) { s_prev_hf_lock = 0u; } /* L5-1 巡检:定值区与封存校验和不符 → prot_set 闭锁(下一拍起 - * eval 自动复位全元件)。⚠ 与 104 定值写(iec104Task set+seal) - * 的竞态窗口为 µs 级:selfcheck 误锁后同一次写的 seal 即清锁 - * (prot_set.c),V0.1 如实登记,P4 定值持久化时收口。 */ + * eval 自动复位全元件)。B7 收口:104 定值写改走 + * prot_set_set_sealed(影子区写+封存后单字交换),selfcheck 另有 + * seqlock 式复核(提交撞见 = 本轮跳过),误锁窗口已消除。 */ (void)prot_set_selfcheck(); - prot_elm_run(now); + /* 全局软压板(PS_GLOBAL_EN,104 YK12 两段式投退,B7):退出 = + * 保护停止判据并复位元件状态(重新投入从干净快照起步) */ + if (prot_set_get_ctl(PS_GLOBAL_EN) == 0u) { + if (s_prev_plate_out == 0u) { + DBG_INFO("global plate OUT -> protection disabled"); + s_prev_plate_out = 1u; + } + prot_elm_init(); + } else { + if (s_prev_plate_out != 0u) { + DBG_INFO("global plate IN -> protection enabled"); + s_prev_plate_out = 0u; + } + prot_elm_run(now); + } } s_log_active_edge(prot_elm_active_mask()); diff --git a/MDK-ARM/STM32F407-Demo.uvprojx b/MDK-ARM/STM32F407-Demo.uvprojx index 7b575f6f..3b1975b6 100644 --- a/MDK-ARM/STM32F407-Demo.uvprojx +++ b/MDK-ARM/STM32F407-Demo.uvprojx @@ -887,6 +887,11 @@ 1 ..\App\cfg\cfg_file_store_mcu.c + + prot_set_store.c + 1 + ..\App\cfg\prot_set_store.c + sys_log_mcu.c 1 diff --git a/docs/任务规划/W1-采集保护收尾.md b/docs/任务规划/W1-采集保护收尾.md index ed70a73d..0df64fa8 100644 --- a/docs/任务规划/W1-采集保护收尾.md +++ b/docs/任务规划/W1-采集保护收尾.md @@ -52,9 +52,9 @@ graph LR | 序 | 任务 | 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`(无新固件代码) | ⬜ | 保护规划 §7 变更记录"遗留";`../测试说明/自动化测试流程.md` | +| **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`(无新固件代码) | 🟦 | 保护规划 §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 背书,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` | ⬜ | 保护规划 §3.5 L5-1、§5;`../子系统设计/IEC104上行设计说明.md` §3.3 | +| **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 转真 + 竞态收口已落地);**台架腿待窗口 🔴**(与 B6 同窗跑:C_SE 写→断电重启→定值保持 + 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/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index 80bf930a..7c7d57ed 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -36,10 +36,10 @@ | 区域 | 用量 | 容量 | 占比 | |---|---|---|---| -| ER_IROM1 | 222,376 B (217.16 KB) | 1,048,576 B (1024 KB) | 21.2% | -| RW_IRAM1 | 95,816 B (93.57 KB) | 131,072 B (128 KB) | 73.1% | +| ER_IROM1 | 223,544 B (218.30 KB) | 1,048,576 B (1024 KB) | 21.3% | +| RW_IRAM1 | 96,096 B (93.84 KB) | 131,072 B (128 KB) | 73.3% | | RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% | -| **Flash (ROM 合计)** | **223,412 B (218.2 KB)** | 1,048,576 B (1024 KB) | **21.3%** | +| **Flash (ROM 合计)** | **224,580 B (219.3 KB)** | 1,048,576 B (1024 KB) | **21.4%** | 各区的容量与常量来源: diff --git a/docs/内存管理/RAM预算台账.md b/docs/内存管理/RAM预算台账.md index aa00c622..3a06ba13 100644 --- a/docs/内存管理/RAM预算台账.md +++ b/docs/内存管理/RAM预算台账.md @@ -15,10 +15,10 @@ | 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) | |---|---|---|---|---| -| ER_IROM1 (Flash) | 222,376 B | 1,048,576 B | 21.2% | 参考 | +| ER_IROM1 (Flash) | 223,544 B | 1,048,576 B | 21.3% | 参考 | | RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS | | UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 | -| RW_IRAM1 | 95,816 B | 131,072 B | 73.1% | PASS | +| RW_IRAM1 | 96,096 B | 131,072 B | 73.3% | PASS | | 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 | |---|---|---|---| @@ -26,7 +26,7 @@ | 存储 | 7,056 B | 12 KB | OK | | UI | 54,988 B | 16 KB | ⚠ 超 37.7 KB | | RTOS 堆 | 57,376 B | 56 KB | 堆=配额 | -| 应用 | 12,843 B | 8 KB | ⚠ 超 4.5 KB | +| 应用 | 13,119 B | 8 KB | ⚠ 超 4.8 KB | | 其它 | 7,596 B | — | 参考 | diff --git a/docs/子系统设计/IEC104上行设计说明.md b/docs/子系统设计/IEC104上行设计说明.md index 8c0d995f..bb646a0b 100644 --- a/docs/子系统设计/IEC104上行设计说明.md +++ b/docs/子系统设计/IEC104上行设计说明.md @@ -74,7 +74,7 @@ |---|---|---| | 0x6000~0x6003 | YK1~4 开关 | **否定确认**(无出口硬件,`docs/算法/继电保护功能复现规划.md` R7) | | 0x600A | YK11 信号复归 | ✅ 执行段 → `prot_elm_request_reset()`(B5 起跨上下文安全:请求由 protectTask 下一拍 eval 头部消费,不当拍直接复位) | -| 0x600B | YK12 遥控软压板 | 否定确认(无全局压板项,随 P4 定值集成) | +| 0x600B | YK12 遥控软压板 | ✅ 两段式转真(B7):选择段校验 DPC(ON/OFF,非法即 PN);执行段 → `prot_set_set_sealed(PS_GLOBAL_EN)` 原子写+封存;protectTask 下一拍读到退出态即复位元件并停判据(`App/task/protect_task.c`) | | 0x600C | YK13 电池活化 | 否定确认(无对应硬件) | | 0x600D | YK14 解除闭锁 | 否定确认(闭锁源于定值校验和,只能重写定值解除) | @@ -82,9 +82,16 @@ - 地址 = `App/algo/prot_set.h` 元数据 `comm_addr`(0x8820 基址 + 告警段 0x8027~0x802A, 逐项对照参考项目 `Const_CommSetPara.c`,见 `docs/算法/继电保护功能复现规划.md` §5.4)—— - **点表不另立地址表**,prot_set 即单一事实源。 -- 写两段式:选择 = 范围校验;执行 = `prot_set_set` + `prot_set_seal`(校验和封存, - L5-1 闭环:主站改错值 → 自检闭锁链自动生效)。 + **点表不另立地址表**,prot_set 即单一事实源。`comm_addr = 0` 的本地项(投退/返回系数/ + 全局软压板)不可经 C_RD/C_SE 寻址(B7 起显式排除,防 IOA=0 误命中首个本地项)。 +- 写两段式:选择 = 范围校验;执行 = `prot_set_set_sealed`(**原子写+封存**:影子区 + 写好后单字交换活跃区,protectTask 的 L5-1 巡检任何时刻都看到自洽快照, + 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`;写盘失败脏标志保留 = 下轮重试。 ## 4. 链路与流程 @@ -143,7 +150,7 @@ | 层 | 内容 | |---|---| -| L0.5 | `test/host/iec104/`:APCI 重组/坏帧、STARTDT 握手、总召全流程(含 RBT/分片/预算)、COV、k/w 窗、t1/t2/t3(假时基)、遥控两段式与 PN、定值两段写 + seal 后 selfcheck、C_RD、C_CS(含闰年)、错地址/错类型 EVI | +| 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 服务启动/监听行);主站工具(lib60870 或等效)总召+遥测+遥控往返,随 B4 收尾 | @@ -151,7 +158,7 @@ 1. 固有参数 8001H~800AH 未实现(字符串类无法短浮点上送)→ 未知 IOA 应答;随送检需求再设计。 2. SOE 带时标(M_SP_TB_1)随 L4-4 SOE 记录落地;现突发只发 COT=3。 -3. YK1~4/12/13/14 否定确认——出口硬件确认后(R7)转真执行。 +3. YK1~4/13/14 否定确认——出口硬件确认后(R7)转真执行(YK12 已于 B7 转真)。 4. 遥测死区 10.0 码值为拟定值,L1-5 标定后按工程量死区(点表 8020H 段)复核。 5. 多主站/双链路冗余不做(单连接语义)。 6. 主站侧验证工具与送检环境未就绪——台架只做到"第三方 104 主站可总召"级。 @@ -166,3 +173,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 断言 | diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index e0b66781..a29dce9a 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)上送;**出口记录(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)。 --- @@ -320,7 +320,7 @@ | # | 功能点 | 说明 | 状态 | | --- | --- | --- | --- | -| L5-1 | 定值校验和 | `tagPRS_XXX` 的 `dwTagSum` 自检,定值非法闭锁 | 🔶 2026-10-11:`prot_set.c` 已实现 sum32 正/反码封存 + selfcheck 失配置闭锁(参考 `dwTagSum/dwTagSumN` 模式);元件级 tagPRS 常量表校验随板端接线并入 | +| L5-1 | 定值校验和 | `tagPRS_XXX` 的 `dwTagSum` 自检,定值非法闭锁 | 🔶 2026-10-11:`prot_set.c` 已实现 sum32 正/反码封存 + selfcheck 失配置闭锁(参考 `dwTagSum/dwTagSumN` 模式);**B7(2026-10-12)竞态收口**:104 定值写改 `prot_set_set_sealed`(影子区写+封存后单字交换)+ selfcheck seqlock 式复核(提交撞见 = 本轮跳过),B5 登记的 µs 级误锁窗口消除;定值持久化 `/prot_set.bin`(blob 带 sum32 正/反码对,整表原子装载);元件级 tagPRS 常量表校验仍待补 | | L5-2 | 采样通道自检 | 通道码值越界/静默检出 | 🔶 静默/丢帧/序号倒退/错误增量已由 L1-6 `adc_health` 检出(2026-10-11);码值越界待做 | | L5-3 | 硬件自检 | 出口回路、电源、时钟 | ⬜ | | L5-4 | 自检失败闭锁 | 任一项失败 → 闭锁相关保护并告警 | 🔶 定值闭锁 → 全元件复位已联动(`prot_elm_eval` 读 `prot_set_locked()`,单测覆盖);**采样故障闭锁已落地(B5,2026-10-12)**:protectTask 每拍读 `adc_health_flags()` 电平位(TPAFE/STM32 stall + 序号倒退)→ 命中即 `prot_elm_init()` 复位 + 本拍不判据,自愈后自动恢复;锁存类事件位(FRSTDATA/HW_ERR)不构成"当前测量不可信"→ 不闭锁,如实登记 | @@ -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 显示闭环 | +| **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,3 +606,4 @@ 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)待窗口 🔴 | diff --git a/scripts/check_registration.py b/scripts/check_registration.py index bf0afbf1..97d8e33b 100644 --- a/scripts/check_registration.py +++ b/scripts/check_registration.py @@ -81,6 +81,7 @@ SIM_EXEMPT = [ ("App/algo/phasor.c", "L2 相量纯算法,模拟器无消费路径"), ("App/algo/prot_elm.c", "L3 保护元件纯算法,模拟器无消费路径"), ("App/algo/prot_set.c", "L5 保护定值纯算法,模拟器无消费路径"), + ("App/cfg/prot_set_store.c", "定值持久化 MCU 胶水(依赖 prot_set 纯算法),模拟器无消费路径"), ("App/algo/sample_ring.c", "L2 环形缓冲纯算法,模拟器无消费路径"), ("App/app/app_main.c", "固件启动/就绪屏障,MCU 专属"), ("App/fs/vol_lock.c", "FreeRTOS 互斥量卷锁,MCU 专属"), diff --git a/scripts/ram_baseline.tsv b/scripts/ram_baseline.tsv index f8342b91..0fff2549 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 204348 18028 1036 152204 222376 21.2 95816 73.1 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 205500 18044 1036 152484 223544 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 diff --git a/test/host/iec104/iec104_test.c b/test/host/iec104/iec104_test.c index d7cb37e6..504f8f58 100644 --- a/test/host/iec104/iec104_test.c +++ b/test/host/iec104/iec104_test.c @@ -84,6 +84,10 @@ static int f_yk(uint32_t ioa, uint8_t dpc, uint8_t sel) s_f_yk_ioa = ioa; s_f_yk_dpc = dpc; s_f_yk_sel = sel; + if (ioa == 0x600Bu) { + /* YK12 全局软压板(B7):转真实板端源(prot_set_set_sealed 原子路径) */ + return s_src_yk_exec(ioa, dpc, sel); + } return (ioa == 0x600Au) ? 0 : -1; } static int f_set_read(uint32_t addr, float *out) @@ -610,6 +614,48 @@ static void tc_dc(void) "TC-013 无出口硬件 YK 选择段 PN"); } +/* TC-024(B7):YK12 全局软压板两段式转真(经真实板端源 + 原子封存) */ +static void tc_dc_yk12(void) +{ + uint32_t now = 1000u; + uint8_t a[16]; + uint8_t body[1]; + uint16_t n; + cap_t c; + + reset_all(now); + handshake(now); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 1u, "TC-024 软压板默认投入"); + body[0] = 0x81u; /* S=1, DPC=OFF:选择段 */ + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Bu, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(0, &c) == 0) && (c.cot == IEC104_COT_ACTCON) + && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u), "TC-024 YK12 选择段 actcon"); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 1u, "TC-024 选择段不动作"); + body[0] = 0x01u; /* 执行 OFF */ + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Bu, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(1, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u), + "TC-024 YK12 执行段 actcon"); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-024 执行段软压板转真退出"); + CHECK(prot_set_selfcheck() == 0, "TC-024 set_sealed 原子封存 → selfcheck 通过"); + CHECK(prot_set_dirty_peek() == 1u, "TC-024 置脏待持久化"); + body[0] = 0x82u; /* 再投入:选择 ON */ + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Bu, body, 1u); + feed_i(a, n, now); + body[0] = 0x02u; /* 执行 ON */ + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Bu, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(3, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) == 0u), + "TC-024 投入执行 actcon"); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 1u, "TC-024 软压板转真投入"); + body[0] = 0x80u; /* DPC=00 非法:选择段即 PN */ + n = mk_asdu(a, IEC104_T_C_DC_NA_1, 1u, IEC104_COT_ACT, 0u, 1u, 0x600Bu, body, 1u); + feed_i(a, n, now); + CHECK((cap_i(4, &c) == 0) && ((c.cot_hi & IEC104_COT_BIT_PN) != 0u), + "TC-024 非法 DPC 选择段 PN"); +} + static void tc_se(void) { uint32_t now = 1000u; @@ -635,6 +681,7 @@ static void tc_se(void) "TC-014 定值执行 actcon"); CHECK(prot_set_get_f(PS_OC1_CUR) == 5.0f, "TC-014 定值已写入(真实 prot_set)"); CHECK(prot_set_selfcheck() == 0, "TC-014 执行后 seal → selfcheck 通过"); + CHECK(prot_set_dirty_peek() == 1u, "TC-014 执行段置脏(B7 待落盘)"); iec104_put_float(body, 100000.0f); /* 越上限 */ body[4] = IEC104_QDC_S; n = mk_asdu(a, IEC104_T_C_SE_NC_1, 1u, IEC104_COT_ACT, 0u, 1u, addr, body, 5u); @@ -666,6 +713,10 @@ static void tc_rd(void) CHECK((cap_i(2, &c) == 0) && (c.type == 102u) && (c.cot == IEC104_COT_UNK_IOA) && ((c.oa & 0x80u) != 0u), "TC-015 未知 IOA COT14+EVI"); + n = mk_asdu(a, IEC104_T_C_RD_NA_1, 1u, IEC104_COT_REQ, 0u, 1u, 0u, NULL, 0u); + feed_i(a, n, now); + CHECK((cap_i(3, &c) == 0) && (c.cot == IEC104_COT_UNK_IOA), + "TC-015 本地定值项(comm_addr=0)不可寻址(B7)"); } static void tc_cs(void) @@ -852,6 +903,7 @@ int main(void) tc_t2(); tc_t3_t1(); tc_dc(); + tc_dc_yk12(); tc_se(); tc_rd(); tc_cs(); diff --git a/test/host/prot_set/prot_set_test.c b/test/host/prot_set/prot_set_test.c index f2c8cbe4..c40907ec 100644 --- a/test/host/prot_set/prot_set_test.c +++ b/test/host/prot_set/prot_set_test.c @@ -14,6 +14,12 @@ * TC-PS-005 Q10 往返精度(±1 LSB) * TC-PS-006 元数据表自检:min<=max、投退项 0..1、非零通讯地址不重复 * TC-PS-007 越界编号守卫(get/set) + * TC-PS-008 全局软压板 PS_GLOBAL_EN(B7):默认投入、set_sealed 原子写 + * 不破坏 selfcheck、脏标志三件套(peek/take/mark) + * TC-PS-009 持久化 blob 往返:serialize → init 清场 → parse 恢复 + * (位精确 + 封存自洽 + parse 不置脏) + * TC-PS-010 损坏 blob 整表拒绝(all-or-nothing):值区位翻转/坏 magic/ + * 截断/超长/坏版本/伪造自洽越界 → 全部拒绝且活跃值区一字不动 * * 通过:全部 TC PASS(main 返回 0)。 * 创建日期:2026-10-11 @@ -138,6 +144,100 @@ static void tc_id_guard(void) { prot_set_init(); CHECK(prot_set_get(PS_ID_COUNT) == 0, "TC-PS-007 get out-of-range id -> 0"); CHECK(prot_set_set(PS_ID_COUNT, 0) == -1, "TC-PS-007 set out-of-range id -> -1"); + CHECK(prot_set_set_sealed(PS_ID_COUNT, 0) == -1, "TC-PS-007 set_sealed id guard"); +} + +/* TC-PS-008(B7:全局软压板 + 原子写 + 脏标志) */ +static void tc_global_plate_dirty(void) { + prot_set_init(); + CHECK(prot_set_dirty_peek() == 0u, "TC-PS-008 init not dirty"); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 1u, "TC-PS-008 global plate default IN"); + CHECK(prot_set_set(PS_GLOBAL_EN, PROT_SET_Q10(2)) == -1, "TC-PS-008 plate rejects 2"); + CHECK(prot_set_set_sealed(PS_GLOBAL_EN, 0) == 0, "TC-PS-008 plate OUT via set_sealed"); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PS-008 plate OUT readable"); + CHECK(prot_set_selfcheck() == 0, "TC-PS-008 set_sealed leaves selfcheck PASS (no unsealed window)"); + CHECK(prot_set_locked() == 0u, "TC-PS-008 set_sealed no lock"); + CHECK(prot_set_dirty_peek() == 1u, "TC-PS-008 set_sealed marks dirty"); + CHECK(prot_set_dirty_take() == 1u, "TC-PS-008 dirty take consumes"); + CHECK(prot_set_dirty_peek() == 0u, "TC-PS-008 dirty cleared after take"); + prot_set_dirty_mark(); + CHECK(prot_set_dirty_peek() == 1u, "TC-PS-008 dirty mark re-arms (write-fail retry)"); + CHECK(prot_set_set_sealed(PS_GLOBAL_EN, PROT_SET_Q10(2)) == -1, "TC-PS-008 set_sealed range check"); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PS-008 rejected set_sealed keeps value"); +} + +/* TC-PS-009(B7:blob 往返) */ +static void tc_store_roundtrip(void) { + uint8_t blob[PROT_SET_BLOB_SZ]; + uint32_t len = 0u; + int32_t cur; + + prot_set_init(); + (void)prot_set_set_sealed(PS_OC1_CUR, PROT_SET_Q10(12.5)); + (void)prot_set_set_sealed(PS_GLOBAL_EN, 0); + (void)prot_set_dirty_take(); + cur = prot_set_get(PS_OC1_CUR); + CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PS-009 serialize ok"); + CHECK(len == (uint32_t)PROT_SET_BLOB_SZ, "TC-PS-009 blob exact size"); + prot_set_init(); + CHECK(prot_set_get(PS_OC1_CUR) != cur, "TC-PS-009 init wiped to defaults"); + CHECK(prot_set_store_parse(blob, len) == 0, "TC-PS-009 parse ok"); + CHECK(prot_set_get(PS_OC1_CUR) == cur, "TC-PS-009 value round-trip bit-exact"); + CHECK(prot_set_get_ctl(PS_GLOBAL_EN) == 0u, "TC-PS-009 plate state round-trip"); + CHECK(prot_set_selfcheck() == 0, "TC-PS-009 parsed table sealed"); + CHECK(prot_set_dirty_peek() == 0u, "TC-PS-009 parse does not mark dirty"); +} + +/* 伪造辅助:按 blob 值区重算尾部 sum/sumn(构造"自洽但越界"的对抗样本) */ +static void s_forge_tail(uint8_t *b, uint32_t len) { + uint32_t sum = 0u; + uint32_t inv; + uint32_t i; + + for (i = 0u; i < (uint32_t)PS_ID_COUNT; i++) { + sum += s_get32(b + PROT_SET_BLOB_HDR_SZ + 4u * i); + } + inv = ~sum; + s_put32(b + len - 8u, sum); + s_put32(b + len - 4u, inv); +} + +/* TC-PS-010(B7:损坏 blob 整表拒绝,all-or-nothing) */ +static void tc_store_corrupt(void) { + uint8_t blob[PROT_SET_BLOB_SZ]; + uint32_t len = 0u; + int32_t keep; + + prot_set_init(); + (void)prot_set_set_sealed(PS_OC2_CUR, PROT_SET_Q10(6.0)); + keep = prot_set_get(PS_OC2_CUR); + CHECK(prot_set_store_serialize(blob, sizeof(blob), &len) == 0, "TC-PS-010 serialize ok"); + + blob[PROT_SET_BLOB_HDR_SZ] ^= 0x01u; /* 值区一位翻转:sum 对不符 */ + CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 flipped value byte rejected (sum pair)"); + CHECK(prot_set_get(PS_OC2_CUR) == keep, "TC-PS-010 reject leaves values untouched"); + + (void)prot_set_store_serialize(blob, sizeof(blob), &len); + blob[0] ^= 0xFFu; /* magic 破坏 */ + CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 bad magic rejected"); + + (void)prot_set_store_serialize(blob, sizeof(blob), &len); + CHECK(prot_set_store_parse(blob, len - 4u) == -1, "TC-PS-010 truncated blob rejected"); + CHECK(prot_set_store_parse(blob, len + 4u) == -1, "TC-PS-010 oversized blob rejected"); + + (void)prot_set_store_serialize(blob, sizeof(blob), &len); + blob[5] ^= 0x02u; /* version 高字节:1 -> 0x200 */ + CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 version mismatch rejected"); + + /* 对抗样本:越限定值 + 重算 sum 对(校验全过、范围必拦) */ + (void)prot_set_store_serialize(blob, sizeof(blob), &len); + s_put32(blob + PROT_SET_BLOB_HDR_SZ + 4u * (uint32_t)PS_OC1_CUR, + (uint32_t)(g_prot_set_meta[PS_OC1_CUR].max + 1)); + s_forge_tail(blob, len); + CHECK(prot_set_store_parse(blob, len) == -1, "TC-PS-010 forged consistent out-of-range rejected"); + CHECK(prot_set_bad_mask() == (1uL << PS_OC1_CUR), "TC-PS-010 bad_mask points at item"); + CHECK(prot_set_get(PS_OC1_CUR) == PROT_SET_Q10(10.0), "TC-PS-010 defaults still intact"); + CHECK(prot_set_selfcheck() == 0, "TC-PS-010 active table still self-consistent after all rejects"); } int main(void) { @@ -149,6 +249,9 @@ int main(void) { tc_q10_roundtrip(); tc_meta_sanity(); tc_id_guard(); + tc_global_plate_dirty(); + tc_store_roundtrip(); + tc_store_corrupt(); printf("\n=== Prot Set Tests: %d/%d PASSED (failed=%d) ===\n", s_passed, s_total, s_failed); From dafcf8098b7eecf16363e5df8ba8bcba1ac0b182 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 12 Oct 2026 16:31:33 +0800 Subject: [PATCH 4/6] =?UTF-8?q?test(b6):=20=E5=8F=B0=E6=9E=B6=20@test=20?= =?UTF-8?q?=E9=97=AD=E7=8E=AF=E5=A4=8D=E6=B5=8B=E6=94=B6=E5=8F=A3=20+=20?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E8=A1=8C=E9=97=A8=E6=8E=A7=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20+=20PC=20104=20=E4=B8=BB=E7=AB=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit B6 台架 @test 闭环复测(B4/B5 验收窗口)完成,DoD 全判据过。 门控修复(首跑 FAIL 实锤的 B5 遗留竞态): - 现象:protect task start 锚点行字节级交错损坏 (st[art: cycle=220ms elm=70,两次开机同形复现) - 根因:启动行在控制台写者注册前打印走无锁裸发,与 defaultTask 启动日志交错——违反 2026-10-10 门控纪律 (控制台单写者日志设计说明.md §3.4,adcTask 同款先例) - 修复:启动锚点行改 dbg_console_writer_ready() 首拍补打 台架与工具: - .serialtest/config.json:Required 增 protect task start / i104 listening on 2404 / [STACK] protect|iec104|heap - test/host/iec104_master.py:纯标准库 104 主站客户端 (STARTDT→总召四组+actterm→C_SE 两段写触发 YX15/16 变位 COT=3→恢复复归→YK11 两段正答→C_RD 读回),往返 18/18 PASS(d3107f3 与 B7+fix 两版固件) - 复测 @test PASS:锚点完好 +577ms、9/9 Required、零 [ERR]、 回读一致;protect free_min 1220(59%)、iec104 2136(83%)、 新 56KB 堆 min_ever=10000(N-33 抬栈背书就绪) 证据与文档回填: - boot_log_data 四份快照(含缺陷复现 MISS 件)+ README 登记 - 保护规划 §7 B6 行(B5 台架遗留闭环);控制台单写者 §3.4 纪律示例 + §11 变更记录;IEC104 §7/§8 主站工具就绪; W1 卡 B6 ✅ + N-33 背书 + B7 台架腿注;登记簿 N-33 - 内存台账:+16 B 构建后 ram_baseline/check_mem_numbers 回填 验证:@build 0 错 0 警(Code=205516);ci_local 全绿 (L0 30 钩子 + L0.5 13 套件 826 断言)。 --- .serialtest/config.json | 2 +- App/task/protect_task.c | 16 +- docs/任务规划/W1-采集保护收尾.md | 6 +- docs/任务规划/登记簿.md | 2 +- docs/内存管理/RAM使用分析与优化方案.md | 4 +- docs/内存管理/RAM预算台账.md | 2 +- docs/子系统设计/IEC104上行设计说明.md | 4 +- docs/子系统设计/控制台单写者日志设计说明.md | 3 +- .../20261012_B6_iec104_roundtrip_log.txt | Bin 0 -> 9007 bytes ...261012_B6_iec104_roundtrip_pre-fix_log.txt | Bin 0 -> 8143 bytes .../20261012_B6_prod_boot_log.txt | 134 ++++++ ...20261012_B6_prod_boot_log_PROTECT_MISS.txt | 134 ++++++ docs/测试说明/boot_log_data/README.md | 4 + docs/算法/继电保护功能复现规划.md | 1 + scripts/ram_baseline.tsv | 2 +- test/host/README.md | 1 + test/host/iec104_master.py | 406 ++++++++++++++++++ 17 files changed, 706 insertions(+), 15 deletions(-) create mode 100644 docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt create mode 100644 docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_pre-fix_log.txt create mode 100644 docs/测试说明/boot_log_data/20261012_B6_prod_boot_log.txt create mode 100644 docs/测试说明/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt create mode 100644 test/host/iec104_master.py diff --git a/.serialtest/config.json b/.serialtest/config.json index 4f89d139..59a7b3ef 100644 --- a/.serialtest/config.json +++ b/.serialtest/config.json @@ -7,7 +7,7 @@ "fw_marker": "fw build: ", "readback_cmd": ".venv\\Scripts\\python.exe .dsh\\skills\\stlink-flash\\scripts\\stlink_flash.py cmp {hex}", - "required": "App init OK;Network Init;net init: OK", + "required": "App init OK;Network Init;net init: OK;protect task start;i104: listening on 2404;[STACK] protect;[STACK] iec104;[STACK] heap", "forbidden": "FAIL;ERROR;HardFault;[ERR]", "boot_marker": "reset cause:", "max_boot_count": 1, diff --git a/App/task/protect_task.c b/App/task/protect_task.c index 22a22a98..62d8c2c6 100644 --- a/App/task/protect_task.c +++ b/App/task/protect_task.c @@ -22,6 +22,7 @@ #include "dbg_log.h" #include "adc_health.h" +#include "console_log.h" /* dbg_console_writer_ready():启动锚点行门控(B6) */ #include "prot_elm.h" #include "prot_set.h" #include "task_watchdog.h" @@ -69,15 +70,24 @@ static void s_log_active_edge(uint32_t active) { * 每拍喂看门狗(TASK_WD_PROTECT,产品 required_mask 0x1F7)。 */ void protect_task(void *argument) { - (void)argument; + uint8_t start_logged = 0u; /* 启动锚点行留痕(writer-ready 门控,B6) */ - DBG_INFO("protect task start: cycle=%ums elm=%u", - (unsigned)PROTECT_TASK_CYCLE_MS, (unsigned)PE_COUNT); + (void)argument; for (;;) { uint32_t now = osKernelGetTickCount(); uint32_t hf = adc_health_flags(); + /* 启动锚点行:控制台写者注册后首拍补打(2026-10-10 门控纪律,adcTask + * 首帧同款)。写者注册前 con_append 走无锁裸发,与 defaultTask 启动日志 + * 逐字节交错——B6 台架实证:本行曾损坏为 "st[art: cycle=220ms elm=70" + * 致 @test 锚点 MISS(控制台单写者日志设计说明.md §3.4)。 */ + if ((start_logged == 0u) && (dbg_console_writer_ready() != 0u)) { + DBG_INFO("protect task start: cycle=%ums elm=%u", + (unsigned)PROTECT_TASK_CYCLE_MS, (unsigned)PE_COUNT); + start_logged = 1u; + } + if ((hf & PROT_HF_LOCK_MASK) != 0u) { /* L5-4:测量链不可信 → 复位元件(本任务上下文,直接 init 合法) * 并跳过判据;stall 自愈后下一拍自动恢复 */ diff --git a/docs/任务规划/W1-采集保护收尾.md b/docs/任务规划/W1-采集保护收尾.md index 0df64fa8..45fa8ff5 100644 --- a/docs/任务规划/W1-采集保护收尾.md +++ b/docs/任务规划/W1-采集保护收尾.md @@ -52,9 +52,9 @@ graph LR | 序 | 任务 | 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`(无新固件代码) | 🟦 | 保护规划 §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 背书,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 转真 + 竞态收口已落地);**台架腿待窗口 🔴**(与 B6 同窗跑:C_SE 写→断电重启→定值保持 + YK12→YX 联动) | 保护规划 §3.5 L5-1、§5;`../子系统设计/IEC104上行设计说明.md` §3.3 | +| **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/任务规划/登记簿.md b/docs/任务规划/登记簿.md index 3a871a13..54c35574 100644 --- a/docs/任务规划/登记簿.md +++ b/docs/任务规划/登记簿.md @@ -49,5 +49,5 @@ | N-27 | **内存优化簇**:LVGL 池 + UI 两份缓冲 54,146 B 仍在 SRAM1,CCM 只剩 ≈8,160 B(2026-10-12 B5 堆扩容 48→56 KB 后) | R-2 后半段(迁 CCM)被堵死 → 后续功能预算看不清 | **三件套 ✅ 2026-10-12 落地**(`ram_baseline.py` 四模式 + `ram_baseline.tsv` 趋势 + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子 92% 门禁)→ **W3** 再做 R-9(`LV_MEM_SIZE` 40→16 KB,池水位门禁数据已具备)→ R-2 后半;R-3/R-4/R-5/R-6 逐项评估(R-6 前置已满足) | **W3** | 报告 R-2 剩余/R-3~R-6/R-9/§5.5 | | N-28 | Flash 死代码评估簇:剩余 ≈10 KB(`box_shadow` 3,246 / `draw_sw_img` 2,960 / `bin_decoder` 1,972 / `image_decoder` 952 / `triangle` 930)+ 双精度 `dadd` 等 ≈1 KB;uvprojx 仍挂 201 个空 LVGL TU(F-1/F-2/F-3 已闭环,省的是编译时长) | 编译时长 + 文档噪音 | 逐项实测再关;⚠ `mask`/`mask_rect`/`grad` 是文字与矩形绘制必经路径,**不可盲关** | W4 | 报告 F-4/F-5/F-6 | | N-29 | **仓库膨胀**:`.git` 149 MB + 图片 36.3 MB | clone/备份慢,且持续恶化 | 降采样 / 拆 submodule / LFS 三选一 **+ 一次 `git filter-repo` 历史重写**。**已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(届时未推送提交更少、重写代价最低) | **W7** | 报告 D-1 | -| N-33 | **栈余量收口:defaultTask / timeSyncTask `stack_report` FAIL**(2026-10-12 复测:defaultTask 静态 3016 B/余 1080 B < 30% 线,链含 dhara GC→控制台回显→`(Cycle)`;timeSyncTask 静态 1264 B/余 784 B < ISR 底线 1024 B)——**既有债,非 B4/B5 引入** | 深链 + ISR 嵌套场景栈溢出风险(保护链稳定性相关) | 抬栈(需 B6 min_ever 背书)或瘦链(控制台回显尾 / Error_Handler 环),详表见 `W1-采集保护收尾.md` | **W1** | 2026-10-12 `stack_report.py` 实测 | +| N-33 | **栈余量收口:defaultTask / timeSyncTask `stack_report` FAIL**(2026-10-12 复测:defaultTask 静态 3016 B/余 1080 B < 30% 线,链含 dhara GC→控制台回显→`(Cycle)`;timeSyncTask 静态 1264 B/余 784 B < ISR 底线 1024 B)——**既有债,非 B4/B5 引入** | 深链 + ISR 嵌套场景栈溢出风险(保护链稳定性相关) | 抬栈(**B6 min_ever 已背书 2026-10-12**:台架实测 heap free=17936 / min_ever=10000 > 3072 告警线,证据 `../测试说明/boot_log_data/20261012_B6_prod_boot_log.txt`)或瘦链(控制台回显尾 / Error_Handler 环),详表见 `W1-采集保护收尾.md` | **W1** | 2026-10-12 `stack_report.py` 实测 | | U 簇 | UI 标准化:无令牌层/组件库/页注册表(手写 `case` 仍在),**27 页**未落地;golden 未挂 pre-commit、字符集差集检查仍是约定 | 新增一页成本仍是 8 处手工改动 | 按 `../问题记录/项目审查与优化建议报告.md` §6.5:U4 残余(两脚本入门禁,可逢窗口顺带)→ U1 令牌层 → U2/U3 → 页面落地;U4 golden 可直接当 U1 验收工具。**已确认(2026-10-11):本轮不排期**,等功能主线出结果后按产品需求启动 | W6 | 报告 U1~U5 | diff --git a/docs/内存管理/RAM使用分析与优化方案.md b/docs/内存管理/RAM使用分析与优化方案.md index 7c7d57ed..4a2ca0ca 100644 --- a/docs/内存管理/RAM使用分析与优化方案.md +++ b/docs/内存管理/RAM使用分析与优化方案.md @@ -36,10 +36,10 @@ | 区域 | 用量 | 容量 | 占比 | |---|---|---|---| -| ER_IROM1 | 223,544 B (218.30 KB) | 1,048,576 B (1024 KB) | 21.3% | +| ER_IROM1 | 223,560 B (218.32 KB) | 1,048,576 B (1024 KB) | 21.3% | | RW_IRAM1 | 96,096 B (93.84 KB) | 131,072 B (128 KB) | 73.3% | | RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% | -| **Flash (ROM 合计)** | **224,580 B (219.3 KB)** | 1,048,576 B (1024 KB) | **21.4%** | +| **Flash (ROM 合计)** | **224,596 B (219.3 KB)** | 1,048,576 B (1024 KB) | **21.4%** | 各区的容量与常量来源: diff --git a/docs/内存管理/RAM预算台账.md b/docs/内存管理/RAM预算台账.md index 3a06ba13..fea41a60 100644 --- a/docs/内存管理/RAM预算台账.md +++ b/docs/内存管理/RAM预算台账.md @@ -15,7 +15,7 @@ | 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) | |---|---|---|---|---| -| ER_IROM1 (Flash) | 223,544 B | 1,048,576 B | 21.3% | 参考 | +| ER_IROM1 (Flash) | 223,560 B | 1,048,576 B | 21.3% | 参考 | | RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS | | UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 | | RW_IRAM1 | 96,096 B | 131,072 B | 73.3% | PASS | diff --git a/docs/子系统设计/IEC104上行设计说明.md b/docs/子系统设计/IEC104上行设计说明.md index bb646a0b..7d6af784 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 服务启动/监听行);主站工具(lib60870 或等效)总召+遥测+遥控往返,随 B4 收尾 | +| 台架 | `@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 | ## 8. V0.1 限制与待办(如实登记) @@ -161,7 +161,7 @@ 3. YK1~4/13/14 否定确认——出口硬件确认后(R7)转真执行(YK12 已于 B7 转真)。 4. 遥测死区 10.0 码值为拟定值,L1-5 标定后按工程量死区(点表 8020H 段)复核。 5. 多主站/双链路冗余不做(单连接语义)。 -6. 主站侧验证工具与送检环境未就绪——台架只做到"第三方 104 主站可总召"级。 +6. 主站侧验证工具 = `test/host/iec104_master.py`(B6 2026-10-12 就绪,台架往返 18/18,覆盖总召/变位/遥控/定值);**第三方送检环境仍未就绪**——lib60870 级第三方全流程归 B10。 7. **后连优先未实现**(V0.1 = 首到优先):单连接 socket 连接态无法 accept, 旧会话结束前新主站接入被拒;后连优先需 net 层(CH395F 单连接模型)支持, 真需要冗余切换时随 net 扩展立项。 diff --git a/docs/子系统设计/控制台单写者日志设计说明.md b/docs/子系统设计/控制台单写者日志设计说明.md index 2983ca8d..da95515b 100644 --- a/docs/子系统设计/控制台单写者日志设计说明.md +++ b/docs/子系统设计/控制台单写者日志设计说明.md @@ -114,7 +114,7 @@ flowchart LR | 写者未注册(内核启动 → attach) | **约定只有 `defaultTask` 记日志** | 遵守约定 → 无并发;**其他任务此时记日志 → 逐字节交错**(裸发无互斥) | | 写者已注册(稳态) | 任务上下文唯一调用者 = 写者 | 任务上下文零竞争;残余窗口 = ISR 直发撞写者发送中(丢失、不挂死,§7) | -**纪律(2026-10-10 固化)**:周期 / 常驻任务**不得**在写者注册前记日志——用 `dbg_console_writer_ready()`(§5)门控自身日志(`adcTask` 的首帧与 10 s 心跳即按此门控)。内核前代码仍可直接裸发(单线程,无并发)。 +**纪律(2026-10-10 固化)**:周期 / 常驻任务**不得**在写者注册前记日志——用 `dbg_console_writer_ready()`(§5)门控自身日志(`adcTask` 的首帧与 10 s 心跳、`protectTask` 的启动锚点行即按此门控——后者 2026-10-12 B6 台架实证:B5 接线时启动行未门控,注册前裸发被交错损坏致 `@test` 锚点 MISS,见 §11 变更记录)。内核前代码仍可直接裸发(单线程,无并发)。 ## 4. 详细设计 @@ -307,6 +307,7 @@ sequenceDiagram | 2026-10-02 | **ORE 僵尸通道喂狗节奏保护**(台架 gen-288):round-3 的"单次 drain 预算 250ms"只限单次调用——ORE 锁存在外设软复位后**毫秒级重锁**(PA10 悬空 + RX 使能),背靠背 drain 每轮再耗 100ms 块超时 → 主循环周期拉到 450~500ms → 100ms 节流的喂狗抽样间隙超过 IWDG 最坏容限 1.7s → 停喂 → 误复位(且心跳位全员健康、无 stall 日志,纯**节奏性饥饿**,非死等)。修复:发送故障后立即结束本轮 drain 并进入 300ms 发送冷却(冷却期内 drain 直接让位主循环),保证喂狗节奏 ≤ ~300ms | | 2026-10-02 | **round 8b 加固**:发送超时判据改用 DWT `CYCCNT`(时间源无关)。原 `HAL_UART_Transmit` 的 `HAL_GetTick() - Tickstart` 依赖 TIM7 的 `uwTick`,TIM7 一旦停摆超时永不成立 → 写者死等 TXE → 唯一喂狗者停摆 → IWDG 复位。裸发送与缓冲满等待两处均换成 DWT 周期计数硬上界(DWT 使能失败时退回旧 HAL 行为);另加 `huart1.Instance == NULL` 短路,防早期/断言路径解引用 NULL | | 2026-10-10 | **新增 `dbg_console_writer_ready()` + 未注册期纪律固化**:裸发为寄存器级轮询(无 `gState`)→ 未注册期多任务并发**逐字节交错**(台架 `adcTask` 首帧日志与 `[NAND_FTL]` 行交错实证)。新增 `dbg_console_writer_ready()` 供周期任务门控;`adcTask` 首帧/心跳日志据此门控(§3.4 / §4.4) | +| 2026-10-12 | **纪律盲区台架实证(B6)**:`protectTask`(B5 接线,台架腿当时未跑)启动锚点行在写者注册前裸发 → 与 defaultTask 启动日志**逐字节交错**(`st[art: cycle=220ms elm=70`,两次开机同形复现 = 启动调度确定性的竞态,非 USB 噪声)→ `@test` 锚点 MISS。修复 = 启动行改 `dbg_console_writer_ready()` 首拍补打(adcTask 首帧同款),`@build` 0/0 + `@test` PASS 复验(锚点完好 +577 ms)。§3.4 纪律示例更新 | ## 12. ORE 僵尸通道(2026-10-02 台架实证) diff --git a/docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt b/docs/测试说明/boot_log_data/20261012_B6_iec104_roundtrip_log.txt new file mode 100644 index 0000000000000000000000000000000000000000..fef4976953986e2481a36ad9c679b2d382443469 GIT binary patch literal 9007 zcmc&)Yj4{&6uqAd>_6yZ0_n~jRpF;l-D@e>qE5sXIdzw z!1H(LXMphx%rB0vXWse;_pfnvgZ~`UTXV$`D29FcP98{zt&RH@+cWtK?-%liIgjO; zJd!hCE6N3=)on8feLZIk&uXQ%(uAD(5UKXNHkq2O}+w=BO__(vkckkD;+& zA(dFCz`Brg{7o=QzOVMn{eKF4V;sd2X{wiF)9VN_jv>3&$e#QT+a1f$VB9xP(c09` zV{`Vk!*;gxD-D+BnZEO+ZHd2C;w@jl)J_{mS!qZ0Ysb5gkMa&aF|7QKe)<-g8XC*J z#PvCz7*=DlBeUn_l2kL)VIjZ4i_c`=NaAnRf%Ov?Q@g?%$I%Y_G3=dh=X$sDS_v(6 zqFOqERmbua{a!*NQ-gtVb&KmOqaEJ4t*%sqlvE(1T;wmdmP=2#54nuw`;f~>`Sx<# z(zzG89mL_+z?+IiqRd5$=AC#fYQ|0VZX+Na={5_dVo|GVs&__UZtRb6m$|Ar_73vl zAR6iEe8{n`pATJ0DIC;s4hO4A69;)i2iacppn(HN&rM^knDYV`u(q6(x=3p9R!Poe2y@eK=pr*dU5lYeDwKVz{-xxwKE%_dA zJVCElrr(gih90ZYXL%2K+Su?fJ0|k>1^V+D^w6|e7EQjTQA)nbXO*e&dSqJo6l0z( zIp$^=I=MQZ+e7T>JW?$gdL<(+?UkGl+lXxXNgut(XHm=M z2lV>p{J?TAcYe^pDnedv3f18fRGO*sz56zcp>k&*+oMwMl0s#zk+YUYmXE8898zv< zEqcIa)(YjOaZz_UTyfs5{j1*Av)A^xRBjp<{Vaz|>s`}coN@J|xg+L>?(BPWKcqfg zxoKSac~XhBqFB}l`(Mvq+v7T@^qIz$pP`k8hct6-&*+T|I98+IfzNT3(`9(4SOuYH zUhS;G&Wx2!YRvQ9ZP}#dl=jTE zRdP!DQc{rcGBtSqPB4l=1mzMpaG z)s6L7*m~aN%2)e_EUYy961hsDJlU@l^w#b-!xy(EPZq2F`}SK_ z30JM~y#~*uUR}9qT=`iYcN$`q(Dq-iRxQWnGR;kXocUB!+}jd_k; zveHxrzn*c|icbttG1}NqbL*APVU_a~ctW+qS*^WhwP}ITS*`JGTWHIc;Y)q|*SnO` zM8G|;_>PR5$>?$MRgO*MsHU13D?i6-f5GbGIDm)r5nIY_-F4cJ@~_eUYBkmMk=jG@ z(iBbF?tZl)Q&G!veJgJHnw`|BH?=&adSeOdHwR6s_R0pny``2}bAb+2tAG^nIzgP*^l*2KM p@twyB4u0eD+14xj>ooS;VGB(>9`K@kXw?4(8xI4{L!2h= zrvIN~q>%6AN1RL9l`iHeWhi6)<~3)0gz*e8Q+bDjvp&Me-#S7m z1@6DbJY%e9tiQOrfj;#o{y)dn1-`kak9x%w7>0-PjXaPxwsD2+rTmWP3;9*gNAgl0 z%OTEt_!L08P+Wx~;Y!FrM@D+?1n0J#uCCK@c$k&5z{<}XD=ooXSGjaEOywte0>*xZ zRAQY2>r#&KnPHWD-t?FIegS+(IEoe0jF)|#bqX2#kXMdnv7hCGvPm-rcah)%xsH zMB-jl;%%h)R^qDE4-p-0i^(^zkxNt>tb)(+?W~0wn<1yZ#SxRlu^Jogi%(3zOGm!N ze@`*%naNhp z)p)LQa}_#kb?4g!p5MduROjjIxu+vz%pFEwA{&5*UKM@ATBWY&26!@6&uvq_G25)f zSTPu5wjc28Jga^~bUj7KS~*tD({6l?ty|I8Hk6lUSejOH0?VU~e1?^@cUr6L#A;6J z+E8!XPTCn_HIpH#^|;J2Is9r?8At2OH%&IJk{*|~N>&}tBinW|0=jztiXp zxvIuh?w0LrFTiJw_uED>`mbd^#`;2Q*#a7CX1hGQ%m-mlYrXuit}avThLLkS{MNO= zm*ck`H#g@u#2(KYIey2mAM^Y$;@q}&+02@J`KI4ymMF2te4a3GXh)u1JZq8X%i@b` z)0dydm+zAiK`ajrG-jmm#WKd~K3O{t4qADzDL0MF&6espl<4ZFaSanSbqtrE2^qiE z$?qv#wcIo=M%-K`wEahDk3-eh=%#M*GohdTo?<7J%6skc+PklSdyXgTtjbQn2{P3JnLKolpVwlg^Rp%WO*l8F2em`GXjcuA{zA|>0uUzhO zI}!6@+JqZ%d5O;sy&Od;Z3N7WwogfWIz7#L!rT-2U8K$B7*p+tmG6g@H#?6I#|Rd} zy`=3XLkoGY?5~$oeLJZwBrna-r1c(V8&)c&dG5dCnyDbJ5+p7sNUD<(S>Hy?}^n^uDhX zy{k3bd6QnizD+l|zdL~c%&<$KZP{C(kaO$Whn4jw^g}Q8&CqqluEl~u#IF1`q%r0@ zD@5Tm+16DL8gJGnO%BJ6b@9z~5BsUziW}eFFM!TPho$bT*xTdI$~f>XJiM+W1nc)X z=5g;JZBG)ey}5=XyoWx(!FSNF^gTFhk{=+Kb<0BdzI!3>H3!v_+*^11O$iVF2hXUP A5dZ)H literal 0 HcmV?d00001 diff --git a/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log.txt b/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log.txt new file mode 100644 index 00000000..b0106715 --- /dev/null +++ b/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log.txt @@ -0,0 +1,134 @@ +[+0ms] [----/--/-- --:--:--][APP] boot: syslog init OK +[+0ms] [----/--/-- --:--:--][APP] fw build: Oct 12 2026 14:02:47 suite=NONE dstr=off +[+0ms] [----/--/-- --:--:--][APP] reset cause: software (NVIC_SystemReset) (CSR=0x14000000) +[+0ms] PREVRUN seg=2 seq=1933208002 t=1832883 +[+14ms] TICKRUN uw=1832923 n=1832923 duw=40 +[+14ms] [----/--/-- --:--:--][RTC] sd2506_init: OK +[+14ms] [----/--/-- --:--:--][APP] SD2506 init: OK (ret=0) +[+25ms] [2026-10-12 07:21:28][CLK] sys_clock_init: RTC initial time 2026-10-12 07:21:28 +[+35ms] [2026-10-12 07:21:28][CLK] sys_clock_init: wall clock base = unix 1791789688, base_tick=139 +[+35ms] [2026-10-12 07:21:28][APP] RS485 init: OK (UART4, DE=PA15) +[+57ms] [2026-10-12 07:21:28][NAND] Resetting NAND... +[+77ms] [2026-10-12 07:21:28][NAND] Reading NAND ID... +[+77ms] [2026-10-12 07:21:28][NAND] NAND ID: MID=0xC8, DID=0x52 +[+77ms] [2026-10-12 07:21:28][NAND] Scanning bad blocks... +[+212ms] [2026-10-12 07:21:28][NAND] BBT scan: 0 bad blocks found +[+223ms] [2026-10-12 07:21:28][NAND] Enabling ECC... +[+223ms] [2026-10-12 07:21:28][NAND] Unlocking block protection... +[+233ms] [2026-10-12 07:21:28][NAND] Locating BBT pool... +[+233ms] [2026-10-12 07:21:28][NAND] Loading persisted BBT... +[+244ms] [2026-10-12 07:21:28][NAND] NAND init OK +[+244ms] [2026-10-12 07:21:28][APP] NAND init: OK +[+244ms] [2026-10-12 07:21:28][ADC] Init OK +[+254ms] [2026-10-12 07:21:28][APP] ADC init: OK +[+254ms] [2026-10-12 07:21:28][APP] ADC input layer init: OK +[+264ms] [2026-10-12 07:21:28][APP] phasor layer init: OK (inst=5) +[+264ms] [2026-10-12 07:21:28][APP] protection init: OK (set=32 elm=7) +[+275ms] [2026-10-12 07:21:28][APP] SD2506 ID: 2512153425482405 +[+285ms] [2026-10-12 07:21:28][APP] SD2506 time: 2026-10-12 07:21:28 (week 4) +[+285ms] [2026-10-12 07:21:28][APP] SD2506 temp: 31 C +[+285ms] [2026-10-12 07:21:28][APP] SD2506 battery: 3.07 V +[+296ms] [2026-10-12 07:21:28][APP] App init OK +[+307ms] [2026-10-12 07:21:28][NAND_FTL] Initializing NAND FTL... +[+327ms] [2026-10-12 07:21:28][NAND_FTL] Map resumed: 14094/97504 sectors used +[+338ms] [2026-10-12 07:21:28][NAND_FTL] Map head=17696 tail=130306 epoch=2 +[+338ms] [2026-10-12 07:21:28][NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB) +[+410ms] [2026-10-12 07:21:28] [FS] FATFS mounted +[+473ms] [2026-10-12 07:21:28][SYSLOG] runlog boot entry: power on +[+483ms] [2026-10-12 07:21:28][CFG] register: section 'network' (4 keys) +[+483ms] [2026-10-12 07:21:28][CFG] register: section 'ftp' (3 keys) +[+493ms] [2026-10-12 07:21:28][CFG] load: OK (523B, heap free 18088B) +[+493ms] [2026-10-12 07:21:28][NET_CFG] load: OK ip=192.168.1.100 +[+525ms] [2026-10-12 07:21:28][ADC_TASK] first: UA=11428 UB=983 UC=827 UN=11453 IA=11451 IB=902 IC=975 IN=880 T=880 +[+535ms] [2026-10-12 07:21:28][ADC_TASK] phasor(first) C01-IA-F1: Re=-1 Im=-1 rms=1 (x0.1) +[+535ms] [2026-10-12 07:21:28][ADC_TASK] phasor(first) C02-UA-F1: Re=-1 Im=0 rms=1 (x0.1) +[+545ms] [2026-10-12 07:21:28][ADC_TASK] phasor(first) C03-UN-F1: Re=0 Im=-1 rms=1 (x0.1) +[+556ms] [2026-10-12 07:21:28][ADC_TASK] phasor(first) C04-IA-F2: Re=1 Im=-1 rms=1 (x0.1) +[+556ms] [2026-10-12 07:21:28][ADC_TASK] phasor(first) C05-IA-F5: Re=2 Im=2 rms=3 (x0.1) +[+567ms] [2026-10-12 07:21:28][NET_TASK] === Network Init === +[+577ms] [2026-10-12 07:21:28][PROT] protect task start: cycle=20ms elm=7 +[+577ms] [2026-10-12 07:21:28][NET] ch395f ver=0x4A fun_para=0x08 +[+588ms] [2026-10-12 07:21:28][NET_TASK] net init: OK +[+588ms] [2026-10-12 07:21:28][NET_TASK] MAC: 3C:AB:72:53:2B:12 +[+588ms] [2026-10-12 07:21:28][NET_TASK] IP_INF: IP=192.168.1.100 GW=192.168.1.1 MASK=255.255.255.0 +[+598ms] MISS start snap=0x000001E7 req=0x000001F7 t=717 +[+609ms] [2026-10-12 07:21:28][WD] [WD] armed: timeout ~2498ms (worst ~1701ms), miss_tol=800ms +[+619ms] [2026-10-12 07:21:28][UI_TASK] UI task: started, wait net ready +[+2551ms] [2026-10-12 07:21:30][NET_TASK] PHY: 100M FULL +[+2561ms] [2026-10-12 07:21:30][NET_TASK] netTask: started (single-socket mode) +[+2602ms] [2026-10-12 07:21:30] [FTP] using factory default password +[+2633ms] [2026-10-12 07:21:30][TIME_SYNC] time_sync: TCP listen on :8888 (sock=0) +[+2665ms] [2026-10-12 07:21:30][I104] i104: listening on 2404 +[+2665ms] [2026-10-12 07:21:30] [FTP] waiting for connection... +[+2675ms] [2026-10-12 07:21:30][UI_TASK] UI task: net ready, init port +[+2675ms] [2026-10-12 07:21:30][UI_TASK] UI task: ui_port_init enter +[+2686ms] [2026-10-12 07:21:30][UI_PORT] theme: mono dark_bg=true applied +[+2697ms] [2026-10-12 07:21:30][UI_TASK] UI port init: OK +[+2697ms] [2026-10-12 07:21:30][UI_TASK] UI task: ui_menu_init enter +[+2697ms] [2026-10-12 07:21:30][UI_MENU] menu build start: total=39448 free=37004 big=37004 +[+2707ms] [2026-10-12 07:21:30][UI_MENU_VIEW] view init: root frame w=66 h=107 +[+2717ms] [2026-10-12 07:21:30][UI_MENU] menu build done: total=39332 free=36140 big=36128 used=3192 +[+2728ms] [2026-10-12 07:21:30][UI_TASK] UI menu init: OK +[+2728ms] [2026-10-12 07:21:30][UI_STANDBY] standby: ready (idle=60000ms) +[+2738ms] [2026-10-12 07:21:30][UI_TASK] UI standby: ready (idle=60s) +[+2791ms] [2026-10-12 07:21:30][UI_TASK] UI net sink: started (port 7003) +[+2791ms] MISS start snap=0x000001E7 req=0x000001F7 t=2906 +[+2791ms] [PROF] t=2911 uic=0 uip=0 uipn=0 uil=0 uiw=0 uis=0 uisn=0 adc=2496 adcm=2006 adcn=0 gl=0 +[+2801ms] [PROF2] t=2911 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+4911ms] [PROF] t=5025 uic=208 uip=19870 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=4610 adcm=2006 adcn=0 gl=0 +[+4921ms] [PROF2] t=5025 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+5324ms] [2026-10-12 07:21:33] [STACK] default peak_used=2152/4096 free_min=1944 (47%) +[+5335ms] [2026-10-12 07:21:33] [STACK] net peak_used=1092/3840 free_min=2748 (71%) +[+5346ms] [2026-10-12 07:21:33] [STACK] ftp peak_used=740/4096 free_min=3356 (81%) +[+5346ms] [2026-10-12 07:21:33] [STACK] ui peak_used=4016/16384 free_min=12368 (75%) +[+5356ms] [2026-10-12 07:21:33] [STACK] timesync peak_used=616/2048 free_min=1432 (69%) +[+5356ms] [2026-10-12 07:21:33] [STACK] adc peak_used=952/2560 free_min=1608 (62%) +[+5366ms] [2026-10-12 07:21:33] [STACK] iec104 peak_used=424/2560 free_min=2136 (83%) +[+5377ms] [2026-10-12 07:21:33] [STACK] protect peak_used=596/2048 free_min=1452 (70%) +[+5387ms] [2026-10-12 07:21:33] [STACK] heap free=17936 min_ever=10000 +[+6935ms] [PROF] t=7053 uic=403 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=6638 adcm=2006 adcn=0 gl=0 +[+6946ms] [PROF2] t=7053 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+8951ms] [PROF] t=9069 uic=603 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=8654 adcm=2006 adcn=0 gl=0 +[+8961ms] [PROF2] t=9069 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+10306ms] [2026-10-12 07:21:38][ADC_TASK] frames=10001 idle=0 skip=32 seq=10006 frst_err=0 ring=9969 adc1_rc=0 adc1_err=0 adc1_seq=10004 adc1_gap=32 adc1_hw=0 tgap=1 +[+10317ms] [2026-10-12 07:21:38][ADC_TASK] phasor(hb) C01-IA-F1: Re=0 Im=0 rms=1 (x0.1) +[+10327ms] [2026-10-12 07:21:38][ADC_TASK] phasor(hb) C02-UA-F1: Re=0 Im=1 rms=1 (x0.1) +[+10327ms] [2026-10-12 07:21:38][ADC_TASK] phasor(hb) C03-UN-F1: Re=2 Im=2 rms=3 (x0.1) +[+10337ms] [2026-10-12 07:21:38][ADC_TASK] phasor(hb) C04-IA-F2: Re=-2 Im=-2 rms=3 (x0.1) +[+10337ms] [2026-10-12 07:21:38][ADC_TASK] phasor(hb) C05-IA-F5: Re=0 Im=-1 rms=1 (x0.1) +[+10348ms] [2026-10-12 07:21:38][PROT] elm UV-UA asserted=1 picked=1 +[+10957ms] [PROF] t=11070 uic=797 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=10655 adcm=2006 adcn=0 gl=0 +[+10968ms] [PROF2] t=11070 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+11371ms] [2026-10-12 07:21:39] [STACK] default peak_used=2152/4096 free_min=1944 (47%) +[+11382ms] [2026-10-12 07:21:39] [STACK] net peak_used=1092/3840 free_min=2748 (71%) +[+11382ms] [2026-10-12 07:21:39] [STACK] ftp peak_used=740/4096 free_min=3356 (81%) +[+11392ms] [2026-10-12 07:21:39] [STACK] ui peak_used=4016/16384 free_min=12368 (75%) +[+11403ms] [2026-10-12 07:21:39] [STACK] timesync peak_used=616/2048 free_min=1432 (69%) +[+11403ms] [2026-10-12 07:21:39] [STACK] adc peak_used=952/2560 free_min=1608 (62%) +[+11413ms] [2026-10-12 07:21:39] [STACK] iec104 peak_used=424/2560 free_min=2136 (83%) +[+11424ms] [2026-10-12 07:21:39] [STACK] protect peak_used=828/2048 free_min=1220 (59%) +[+11434ms] [2026-10-12 07:21:39] [STACK] heap free=17936 min_ever=10000 +[+12987ms] [PROF] t=13099 uic=992 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=12684 adcm=2006 adcn=0 gl=0 +[+12997ms] [PROF2] t=13099 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+15001ms] [PROF] t=15116 uic=1192 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=14701 adcm=2006 adcn=0 gl=0 +[+15012ms] [PROF2] t=15116 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+17022ms] [PROF] t=17133 uic=1392 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=16718 adcm=2006 adcn=0 gl=0 +[+17032ms] [PROF2] t=17133 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+19034ms] [PROF] t=19150 uic=1592 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=18735 adcm=2006 adcn=0 gl=0 +[+19044ms] [PROF2] t=19150 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+20307ms] [2026-10-12 07:21:48][ADC_TASK] frames=20001 idle=0 skip=35 seq=20006 frst_err=0 ring=19966 adc1_rc=0 adc1_err=0 adc1_seq=20004 adc1_gap=35 adc1_hw=0 tgap=1 +[+20318ms] [2026-10-12 07:21:48][ADC_TASK] phasor(hb) C01-IA-F1: Re=0 Im=-1 rms=2 (x0.1) +[+20318ms] [2026-10-12 07:21:48][ADC_TASK] phasor(hb) C02-UA-F1: Re=1 Im=-2 rms=2 (x0.1) +[+20328ms] [2026-10-12 07:21:48][ADC_TASK] phasor(hb) C03-UN-F1: Re=2 Im=-1 rms=2 (x0.1) +[+20339ms] [2026-10-12 07:21:48][ADC_TASK] phasor(hb) C04-IA-F2: Re=0 Im=1 rms=1 (x0.1) +[+20339ms] [2026-10-12 07:21:48][ADC_TASK] phasor(hb) C05-IA-F5: Re=2 Im=0 rms=2 (x0.1) +[+21054ms] [PROF] t=21164 uic=1787 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=1 uisn=0 adc=20749 adcm=2006 adcn=0 gl=0 +[+21064ms] [PROF2] t=21164 defd=135261 defs=7 netp=16 netn=0 adcp=9 adcq=0 gl=0 +[+23067ms] [PROF] t=23181 uic=1987 uip=73696 uipn=9997 uil=9950 uiw=10351 uis=64 uisn=0 adc=22766 adcm=2006 adcn=0 gl=0 +[+23077ms] [PROF2] t=23181 defd=135261 defs=7 netp=63 netn=0 adcp=9 adcq=0 gl=0 +[+25080ms] [PROF] t=25198 uic=2187 uip=73696 uipn=9996 uil=9958 uiw=10351 uis=64 uisn=0 adc=24783 adcm=2006 adcn=0 gl=0 +[+25091ms] [PROF2] t=25198 defd=135261 defs=7 netp=63 netn=0 adcp=9 adcq=0 gl=0 +[+27100ms] [PROF] t=27215 uic=2387 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=64 uisn=0 adc=26800 adcm=2006 adcn=0 gl=0 +[+27110ms] [PROF2] t=27215 defd=135261 defs=7 netp=63 netn=0 adcp=9 adcq=0 gl=0 +[+29114ms] [PROF] t=29232 uic=2587 uip=73696 uipn=9996 uil=9999 uiw=10351 uis=64 uisn=0 adc=28817 adcm=2006 adcn=0 gl=0 +[+29125ms] [PROF2] t=29232 defd=135261 defs=7 netp=63 netn=0 adcp=9 adcq=0 gl=0 diff --git a/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt b/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt new file mode 100644 index 00000000..ba042d21 --- /dev/null +++ b/docs/测试说明/boot_log_data/20261012_B6_prod_boot_log_PROTECT_MISS.txt @@ -0,0 +1,134 @@ +[+0ms] [----/--/-- --:--:--][APP] boot: syslog init OK +[+0ms] [----/--/-- --:--:--][APP] fw build: Oct 12 2026 14:49:47 suite=NONE dstr=off +[+11ms] [----/--/-- --:--:--][APP] reset cause: software (NVIC_SystemReset) (CSR=0x14000000) +[+11ms] PREVRUN seg=2 seq=1932941145 t=2452628 +[+26ms] TICKRUN uw=2452643 n=2452643 duw=15 +[+26ms] [----/--/-- --:--:--][RTC] sd2506_init: OK +[+26ms] [----/--/-- --:--:--][APP] SD2506 init: OK (ret=0) +[+37ms] [2026-10-12 06:50:17][CLK] sys_clock_init: RTC initial time 2026-10-12 06:50:17 +[+47ms] [2026-10-12 06:50:17][CLK] sys_clock_init: wall clock base = unix 1791787817, base_tick=139 +[+47ms] [2026-10-12 06:50:17][APP] RS485 init: OK (UART4, DE=PA15) +[+68ms] [2026-10-12 06:50:17][NAND] Resetting NAND... +[+79ms] [2026-10-12 06:50:17][NAND] Reading NAND ID... +[+89ms] [2026-10-12 06:50:17][NAND] NAND ID: MID=0xC8, DID=0x52 +[+89ms] [2026-10-12 06:50:17][NAND] Scanning bad blocks... +[+224ms] [2026-10-12 06:50:17][NAND] BBT scan: 0 bad blocks found +[+224ms] [2026-10-12 06:50:17][NAND] Enabling ECC... +[+235ms] [2026-10-12 06:50:17][NAND] Unlocking block protection... +[+245ms] [2026-10-12 06:50:17][NAND] Locating BBT pool... +[+245ms] [2026-10-12 06:50:17][NAND] Loading persisted BBT... +[+256ms] [2026-10-12 06:50:17][NAND] NAND init OK +[+256ms] [2026-10-12 06:50:17][APP] NAND init: OK +[+256ms] [2026-10-12 06:50:17][ADC] Init OK +[+256ms] [2026-10-12 06:50:17][APP] ADC init: OK +[+266ms] [2026-10-12 06:50:17][APP] ADC input layer init: OK +[+266ms] [2026-10-12 06:50:17][APP] phasor layer init: OK (inst=5) +[+277ms] [2026-10-12 06:50:17][APP] protection init: OK (set=31 elm=7) +[+287ms] [2026-10-12 06:50:17][APP] SD2506 ID: 2512153425482405 +[+287ms] [2026-10-12 06:50:17][APP] SD2506 time: 2026-10-12 06:50:17 (week 4) +[+298ms] [2026-10-12 06:50:17][APP] SD2506 temp: 29 C +[+298ms] [2026-10-12 06:50:17][APP] SD2506 battery: 3.09 V +[+308ms] [2026-10-12 06:50:17][APP] App init OK +[+308ms] [2026-10-12 06:50:17][PROT] protect task st[art: cycle=220ms elm=70 +[+319ms] 26-10-12 06:50:17][NAND_FTL] Initializing NAND FTL... +[+340ms] [2026-10-12 06:50:17][NAND_FTL] Map resumed: 14094/97504 sectors used +[+350ms] [2026-10-12 06:50:17][NAND_FTL] Map head=17600 tail=130216 epoch=2 +[+350ms] [2026-10-12 06:50:17][NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB) +[+433ms] [2026-10-12 06:50:17] [FS] FATFS mounted +[+485ms] [2026-10-12 06:50:17][SYSLOG] runlog boot entry: power on +[+485ms] [2026-10-12 06:50:17][CFG] register: section 'network' (4 keys) +[+495ms] [2026-10-12 06:50:17][CFG] register: section 'ftp' (3 keys) +[+506ms] [2026-10-12 06:50:17][CFG] load: OK (523B, heap free 18088B) +[+506ms] [2026-10-12 06:50:17][NET_CFG] load: OK ip=192.168.1.100 +[+537ms] [2026-10-12 06:50:17][ADC_TASK] first: UA=11428 UB=972 UC=825 UN=11454 IA=11451 IB=927 IC=971 IN=878 T=889 +[+537ms] [2026-10-12 06:50:17][ADC_TASK] phasor(first) C01-IA-F1: Re=-1 Im=-2 rms=2 (x0.1) +[+548ms] [2026-10-12 06:50:17][ADC_TASK] phasor(first) C02-UA-F1: Re=2 Im=-1 rms=2 (x0.1) +[+559ms] [2026-10-12 06:50:17][ADC_TASK] phasor(first) C03-UN-F1: Re=-1 Im=1 rms=1 (x0.1) +[+569ms] [2026-10-12 06:50:17][ADC_TASK] phasor(first) C04-IA-F2: Re=3 Im=0 rms=3 (x0.1) +[+569ms] [2026-10-12 06:50:17][ADC_TASK] phasor(first) C05-IA-F5: Re=1 Im=-2 rms=2 (x0.1) +[+579ms] [2026-10-12 06:50:17][NET_TASK] === Network Init === +[+579ms] [2026-10-12 06:50:17][NET] ch395f ver=0x4A fun_para=0x08 +[+590ms] [2026-10-12 06:50:17][NET_TASK] net init: OK +[+590ms] [2026-10-12 06:50:17][NET_TASK] MAC: 3C:AB:72:53:2B:12 +[+600ms] [2026-10-12 06:50:17][NET_TASK] IP_INF: IP=192.168.1.100 GW=192.168.1.1 MASK=255.255.255.0 +[+600ms] MISS start snap=0x000001E7 req=0x000001F7 t=710 +[+611ms] [2026-10-12 06:50:17][WD] [WD] armed: timeout ~2498ms (worst ~1701ms), miss_tol=800ms +[+621ms] [2026-10-12 06:50:17][UI_TASK] UI task: started, wait net ready +[+2605ms] [2026-10-12 06:50:19][NET_TASK] PHY: 100M FULL +[+2625ms] [2026-10-12 06:50:19][NET_TASK] netTask: started (single-socket mode) +[+2657ms] [2026-10-12 06:50:19] [FTP] using factory default password +[+2689ms] [2026-10-12 06:50:19][TIME_SYNC] time_sync: TCP listen on :8888 (sock=0) +[+2720ms] [2026-10-12 06:50:19][I104] i104: listening on 2404 +[+2731ms] [2026-10-12 06:50:19] [FTP] waiting for connection... +[+2731ms] [2026-10-12 06:50:19][UI_TASK] UI task: net ready, init port +[+2741ms] [2026-10-12 06:50:19][UI_TASK] UI task: ui_port_init enter +[+2741ms] [2026-10-12 06:50:19][UI_PORT] theme: mono dark_bg=true applied +[+2752ms] [2026-10-12 06:50:19][UI_TASK] UI port init: OK +[+2752ms] [2026-10-12 06:50:19][UI_TASK] UI task: ui_menu_init enter +[+2762ms] [2026-10-12 06:50:19][UI_MENU] menu build start: total=39448 free=37004 big=37004 +[+2772ms] [2026-10-12 06:50:19][UI_MENU_VIEW] view init: root frame w=66 h=107 +[+2783ms] [2026-10-12 06:50:19][UI_MENU] menu build done: total=39332 free=36140 big=36128 used=3192 +[+2783ms] [2026-10-12 06:50:19][UI_TASK] UI menu init: OK +[+2793ms] [2026-10-12 06:50:19][UI_STANDBY] standby: ready (idle=60000ms) +[+2793ms] [2026-10-12 06:50:19][UI_TASK] UI standby: ready (idle=60s) +[+2845ms] [2026-10-12 06:50:19][UI_TASK] UI net sink: started (port 7003) +[+2855ms] MISS start snap=0x000001E7 req=0x000001F7 t=2954 +[+2855ms] [PROF] t=2959 uic=0 uip=0 uipn=0 uil=0 uiw=0 uis=0 uisn=0 adc=2545 adcm=2017 adcn=0 gl=0 +[+2866ms] [PROF2] t=2959 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+4920ms] [PROF] t=5022 uic=203 uip=20322 uipn=8996 uil=9999 uiw=10487 uis=1 uisn=0 adc=4608 adcm=2017 adcn=0 gl=0 +[+4930ms] [PROF2] t=5022 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+5334ms] [2026-10-12 06:50:22] [STACK] default peak_used=2164/4096 free_min=1932 (47%) +[+5345ms] [2026-10-12 06:50:22] [STACK] net peak_used=1092/3840 free_min=2748 (71%) +[+5345ms] [2026-10-12 06:50:22] [STACK] ftp peak_used=740/4096 free_min=3356 (81%) +[+5355ms] [2026-10-12 06:50:22] [STACK] ui peak_used=4052/16384 free_min=12332 (75%) +[+5365ms] [2026-10-12 06:50:22] [STACK] timesync peak_used=616/2048 free_min=1432 (69%) +[+5365ms] [2026-10-12 06:50:22] [STACK] adc peak_used=952/2560 free_min=1608 (62%) +[+5376ms] [2026-10-12 06:50:22] [STACK] iec104 peak_used=424/2560 free_min=2136 (83%) +[+5387ms] [2026-10-12 06:50:22] [STACK] protect peak_used=456/2048 free_min=1592 (77%) +[+5387ms] [2026-10-12 06:50:22] [STACK] heap free=17936 min_ever=10000 +[+6946ms] [PROF] t=7050 uic=398 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=6636 adcm=2017 adcn=0 gl=0 +[+6956ms] [PROF2] t=7050 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+8965ms] [PROF] t=9066 uic=598 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=8652 adcm=2017 adcn=0 gl=0 +[+8976ms] [PROF2] t=9066 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+10311ms] [2026-10-12 06:50:27][ADC_TASK] frames=10001 idle=0 skip=32 seq=10006 frst_err=0 ring=9969 adc1_rc=0 adc1_err=0 adc1_seq=10004 adc1_gap=32 adc1_hw=0 tgap=1 +[+10322ms] [2026-10-12 06:50:27][ADC_TASK] phasor(hb) C01-IA-F1: Re=2 Im=2 rms=3 (x0.1) +[+10332ms] [2026-10-12 06:50:27][ADC_TASK] phasor(hb) C02-UA-F1: Re=0 Im=1 rms=1 (x0.1) +[+10343ms] [2026-10-12 06:50:27][ADC_TASK] phasor(hb) C03-UN-F1: Re=-1 Im=0 rms=2 (x0.1) +[+10343ms] [2026-10-12 06:50:27][ADC_TASK] phasor(hb) C04-IA-F2: Re=0 Im=2 rms=2 (x0.1) +[+10353ms] [2026-10-12 06:50:27][ADC_TASK] phasor(hb) C05-IA-F5: Re=1 Im=3 rms=3 (x0.1) +[+10364ms] [2026-10-12 06:50:27][PROT] elm UV-UA asserted=1 picked=1 +[+10962ms] [PROF] t=11068 uic=792 uip=73724 uipn=9995 uil=9958 uiw=10487 uis=1 uisn=0 adc=10654 adcm=2017 adcn=0 gl=0 +[+10972ms] [PROF2] t=11068 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+11384ms] [2026-10-12 06:50:28] [STACK] default peak_used=2164/4096 free_min=1932 (47%) +[+11384ms] [2026-10-12 06:50:28] [STACK] net peak_used=1092/3840 free_min=2748 (71%) +[+11394ms] [2026-10-12 06:50:28] [STACK] ftp peak_used=740/4096 free_min=3356 (81%) +[+11405ms] [2026-10-12 06:50:28] [STACK] ui peak_used=4052/16384 free_min=12332 (75%) +[+11405ms] [2026-10-12 06:50:28] [STACK] timesync peak_used=616/2048 free_min=1432 (69%) +[+11415ms] [2026-10-12 06:50:28] [STACK] adc peak_used=952/2560 free_min=1608 (62%) +[+11425ms] [2026-10-12 06:50:28] [STACK] iec104 peak_used=424/2560 free_min=2136 (83%) +[+11425ms] [2026-10-12 06:50:28] [STACK] protect peak_used=828/2048 free_min=1220 (59%) +[+11436ms] [2026-10-12 06:50:28] [STACK] heap free=17936 min_ever=10000 +[+12998ms] [PROF] t=13097 uic=987 uip=73724 uipn=9995 uil=9995 uiw=10487 uis=1 uisn=0 adc=12683 adcm=2017 adcn=0 gl=0 +[+12998ms] [PROF2] t=13097 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+15007ms] [PROF] t=15114 uic=1187 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=14700 adcm=2017 adcn=0 gl=0 +[+15017ms] [PROF2] t=15114 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+17033ms] [PROF] t=17131 uic=1387 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=16717 adcm=2017 adcn=0 gl=0 +[+17033ms] [PROF2] t=17131 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+19048ms] [PROF] t=19148 uic=1587 uip=73724 uipn=10003 uil=9999 uiw=10487 uis=1 uisn=0 adc=18734 adcm=2017 adcn=0 gl=0 +[+19058ms] [PROF2] t=19148 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+20309ms] [2026-10-12 06:50:37][ADC_TASK] frames=20001 idle=0 skip=42 seq=20006 frst_err=0 ring=19959 adc1_rc=0 adc1_err=0 adc1_seq=20004 adc1_gap=42 adc1_hw=0 tgap=1 +[+20320ms] [2026-10-12 06:50:37][ADC_TASK] phasor(hb) C01-IA-F1: Re=0 Im=1 rms=1 (x0.1) +[+20330ms] [2026-10-12 06:50:37][ADC_TASK] phasor(hb) C02-UA-F1: Re=3 Im=0 rms=3 (x0.1) +[+20340ms] [2026-10-12 06:50:37][ADC_TASK] phasor(hb) C03-UN-F1: Re=-1 Im=0 rms=1 (x0.1) +[+20351ms] [2026-10-12 06:50:37][ADC_TASK] phasor(hb) C04-IA-F2: Re=-2 Im=-1 rms=2 (x0.1) +[+20351ms] [2026-10-12 06:50:37][ADC_TASK] phasor(hb) C05-IA-F5: Re=0 Im=0 rms=0 (x0.1) +[+21065ms] [PROF] t=21163 uic=1782 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=20749 adcm=2017 adcn=0 gl=0 +[+21065ms] [PROF2] t=21163 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+23076ms] [PROF] t=23180 uic=1982 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=22766 adcm=2017 adcn=0 gl=0 +[+23086ms] [PROF2] t=23180 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+25093ms] [PROF] t=25197 uic=2182 uip=73724 uipn=9995 uil=9995 uiw=10487 uis=1 uisn=0 adc=24783 adcm=2017 adcn=0 gl=0 +[+25104ms] [PROF2] t=25197 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+27113ms] [PROF] t=27214 uic=2382 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=26800 adcm=2017 adcn=0 gl=0 +[+27123ms] [PROF2] t=27214 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 +[+29129ms] [PROF] t=29231 uic=2582 uip=73724 uipn=9995 uil=9999 uiw=10487 uis=1 uisn=0 adc=28817 adcm=2017 adcn=0 gl=0 +[+29140ms] [PROF2] t=29231 defd=135841 defs=7 netp=0 netn=0 adcp=9 adcq=0 gl=0 diff --git a/docs/测试说明/boot_log_data/README.md b/docs/测试说明/boot_log_data/README.md index ea5880cb..d9c27727 100644 --- a/docs/测试说明/boot_log_data/README.md +++ b/docs/测试说明/boot_log_data/README.md @@ -29,6 +29,10 @@ | 2026-10-10 | `prod_adc_l1` / 开机 + 30 s 空载 | `adc` **584/2048(71%)**(+56 B,L1 层 adc_input_poll/raw 上链);`default` 2164/4096(47%);heap free=15088 min_ever=7152 | `20261010_prod_adc_l1_boot_log.txt` | | 2026-10-11 | `prod_phasor` / 开机 + 30 s 空载(L2 台架闭环) | `adc` **928/2048(54%)**(+344 B,压环 + `phasor_run` + `log_phasors` 上链);`default` 2152/4096(47%);heap free=15088 min_ever=7152 | `20261011_prod_phasor_boot_log.txt` | | 2026-10-11 | `prod_adc_health` / 开机 + 30 s 空载(L1-6 + 抬栈 640 words) | `adc` **952/2560(62%)**(静态最坏链 1080 B,`adc_health_report`→`syslog_post` 回显尾);`default` 2152/4096(47%);heap free=14576 **min_ever=6640**(抬栈 -512 B,符合预算) | `20261011_prod_adc_health_boot_log.txt` | +| 2026-10-12 | `prod`(HEAD d3107f3,B4/B5 验收窗口 B6)/ 开机 + 30 s 空载 | **首采**:`iec104` 424/2560(83%);`protect` 828/2048(59%,free_min 1220);新 56 KB 堆 heap free=17936 **min_ever=10000**(>3072 告警线,无 `[HEAP]` 告警);⚠ **@test FAIL(缺陷证据快照)**:`protect task start` 锚点行字节级交错损坏(`st[art: cycle=220ms elm=70`,两次开机同形复现)= protectTask 违反控制台写者注册前门控纪律(`控制台单写者日志设计说明.md` §3.4),其余 8 Required / 零 `[ERR]` / 锚点×1 / 回读一致全过;**缺陷已修**(启动行改 writer-ready 首拍补打),修复后 PASS 见下行 | `20261012_B6_prod_boot_log_PROTECT_MISS.txt` | +| 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` | ## 4. 关联 diff --git a/docs/算法/继电保护功能复现规划.md b/docs/算法/继电保护功能复现规划.md index a29dce9a..e91a102a 100644 --- a/docs/算法/继电保护功能复现规划.md +++ b/docs/算法/继电保护功能复现规划.md @@ -607,3 +607,4 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5) | 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 | **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/scripts/ram_baseline.tsv b/scripts/ram_baseline.tsv index 0fff2549..3a6276e7 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 205500 18044 1036 152484 223544 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 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 diff --git a/test/host/README.md b/test/host/README.md index 7ccb3923..871eb4e9 100644 --- a/test/host/README.md +++ b/test/host/README.md @@ -22,6 +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) | ### 时间 / 时延 diff --git a/test/host/iec104_master.py b/test/host/iec104_master.py new file mode 100644 index 00000000..f236fdbb --- /dev/null +++ b/test/host/iec104_master.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""B6 bench leg: IEC 60870-5-104 master client (GI + COV round-trip). + +Task card: docs/任务规划/W1-采集保护收尾.md (B6 DoD); protocol baseline: +docs/子系统设计/IEC104上行设计说明.md §3/§4. Constants mirror +App/protocol/iec104/iec104_asdu.h / iec104_link.h. + +Flow: + 1. TCP connect device :2404, STARTDT act/con (enter RUN). + 2. General interrogation C_IC_NA_1 (QOI=20): expect actcon, background + scan (YX double-point group SQ=1 -> YX single-point group SQ=1 -> + YC group SQ=1 -> frequency single point), actterm. + 3. Deterministic COV trigger: bench analog inputs are floating (phasor + rms is 0..0.3 raw-code noise only; the standard source belongs to + B10), so we use the two-step C_SE_NC_1 write to temporarily lower + the OC1 current setting (comm addr 0x8858, default 10.0 A) to + 0.05 A -> protectTask (20 ms cadence) asserts OC1 -> YX16/YX15 + spontaneous (COT=3) uplink. This is exactly the "104 YX linkage" + leg left open by B5. Then restore 10.0 A -> YX16 returns. + 4. YK11 (0x600A) two-step select/execute -> positive actcon (reset + request consumed asynchronously by protectTask, B5 contract). + 5. C_RD read back 0x8858 ~= 10.0 (restore confirmation). + +Exit codes: 0 = all checks PASS; 1 = any check FAIL; 2 = connect or +protocol error. Output is pure ASCII (redirect stdout to archive the +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] +""" +import argparse +import collections +import socket +import struct +import sys +import time + +# ---- constants (mirror iec104_asdu.h / iec104_link.h) ----------------------- +U_STARTDT_ACT, U_STARTDT_CON = 0x07, 0x0B +U_TESTFR_ACT, U_TESTFR_CON = 0x43, 0x83 + +T_M_SP_NA_1, T_M_DP_NA_1, T_M_ME_NC_1 = 1, 3, 13 +T_C_SE_NC_1, T_C_DC_NA_1 = 50, 52 +T_C_IC_NA_1, T_C_RD_NA_1 = 100, 102 + +COT_BG, COT_SPONT, COT_INIT, COT_REQ = 2, 3, 4, 5 +COT_ACT, COT_ACTCON, COT_ACTTERM = 6, 7, 8 +COT_PN = 0x40 # COT high byte bit6: negative confirm +RQT_GROUP1 = 20 +CA = 1 # common address fixed to 1 in V0.1 +SCAN_COTS = (COT_BG, COT_INIT) + +YX_NAMES = {15: "YX15 fault-total", 16: "YX16 OC-I", 17: "YX17 OC-II", + 18: "YX18 OC-III", 23: "YX23 overload", 31: "YX31 prot-block"} + +T0 = time.time() + + +def log(msg): + print("[%9.3fs] %s" % (time.time() - T0, msg), flush=True) + + +def hexs(b): + return " ".join("%02X" % x for x in b) + + +# ---- APCI / ASDU builders ---------------------------------------------------- +def u_frame(code): + return bytes([0x68, 0x04, code, 0x00, 0x00, 0x00]) + + +def s_frame(vr): + return bytes([0x68, 0x04, 0x01, 0x00, (vr << 1) & 0xFE, (vr >> 7) & 0x7F]) + + +def i_frame(vs, vr, body): + ctrl = bytes([(vs << 1) & 0xFE, (vs >> 7) & 0x7F, + (vr << 1) & 0xFE, (vr >> 7) & 0x7F]) + return bytes([0x68, len(body) + 4]) + ctrl + body + + +def put_ioa(ioa): + return bytes([ioa & 0xFF, (ioa >> 8) & 0xFF, (ioa >> 16) & 0xFF]) + + +def get_ioa(b, off=0): + return b[off] | (b[off + 1] << 8) | (b[off + 2] << 16) + + +def asdu(type_id, vsq, cot, cot_hi, ioa=None, payload=b""): + h = bytes([type_id, vsq, cot & 0x3F, cot_hi, CA & 0xFF, (CA >> 8) & 0xFF]) + if ioa is not None: + h += put_ioa(ioa) + return h + payload + + +class Master(object): + """Minimal 104 master. k/w/t are covered by "S after every recv batch" + (far faster than t1=15s / t2=10s), so no timers are needed here.""" + + def __init__(self, ip, port): + self.sock = socket.create_connection((ip, port), timeout=10) + self.sock.settimeout(1.0) + self.rx = b"" + self.vs = 0 + self.vr = 0 + self.vr_dirty = False + self.events = collections.deque() # (kind, detail) tuples + self.yx = {} # ioa -> (val, iv) + self.yc = {} # ioa -> (val, qds) + + # ---- send ---- + def _send(self, data, tag): + log("TX %s %s" % (tag, hexs(data))) + self.sock.sendall(data) + + def send_i(self, body, tag): + self._send(i_frame(self.vs, self.vr, body), tag) + self.vs = (self.vs + 1) & 0x7FFF + + def _send_s(self): + if self.vr_dirty: + self._send(s_frame(self.vr), "S N(R)=%d" % self.vr) + self.vr_dirty = False + + # ---- receive pump ---- + def pump_until(self, deadline): + """Pump RX until deadline (non-blocking semantics for wait_event).""" + while time.time() < deadline: + try: + chunk = self.sock.recv(512) + except socket.timeout: + self._send_s() + continue + if not chunk: + raise RuntimeError("peer closed (EOF)") + self.rx += chunk + while len(self.rx) >= 2 and self.rx[0] == 0x68: + ln = self.rx[1] + if ln < 4 or ln > 253: + raise RuntimeError("bad APDU length %d" % ln) + if len(self.rx) < 2 + ln: + break + apdu, self.rx = self.rx[:2 + ln], self.rx[2 + ln:] + self._handle(apdu) + if self.rx and self.rx[0] != 0x68: + raise RuntimeError("stream desync at 0x%02X" % self.rx[0]) + self._send_s() + + def wait_event(self, pred, timeout): + deadline = time.time() + timeout + while True: + for i, e in enumerate(self.events): + if pred(e): + return self.events[i] + if time.time() >= deadline: + return None + self.pump_until(min(deadline, time.time() + 1.0)) + + # ---- frame handling ---- + def _handle(self, apdu): + c = apdu[2:6] + b0, b1, b2, b3 = c[0], c[1], c[2], c[3] + if (b0 & 0x01) == 0: # I format + ns = (b0 >> 1) | ((b1 & 0x7F) << 7) + nr = (b2 >> 1) | ((b3 & 0x7F) << 7) + if ns != self.vr: + raise RuntimeError("N(S)=%d out of order (expect %d)" + % (ns, self.vr)) + self.vr = (self.vr + 1) & 0x7FFF + self.vr_dirty = True + self._asdu(apdu[6:], nr) + elif (b0 & 0x03) == 0x01: # S format + nr = (b2 >> 1) | ((b3 & 0x7F) << 7) + log("RX S N(R)=%d" % nr) + else: # U format + if b0 == U_STARTDT_CON: + log("RX U STARTDT con") + self.events.append(("startdt_con", None)) + elif b0 == U_TESTFR_ACT: + self._send(u_frame(U_TESTFR_CON), "U TESTFR con") + elif b0 == U_TESTFR_CON: + log("RX U TESTFR con") + else: + log("RX U code=0x%02X" % b0) + + def _asdu(self, a, nr): + if len(a) < 6: + raise RuntimeError("short ASDU") + type_id, vsq, cot, cot_hi = a[0], a[1], a[2], a[3] + pn = (cot_hi & COT_PN) != 0 + sq = (vsq & 0x80) != 0 + n = vsq & 0x7F + obj = a[6:] + + if type_id in (T_M_SP_NA_1, T_M_DP_NA_1): + pts = [] + if sq: + base = get_ioa(obj) + for i in range(n): + pts.append((base + i, obj[3 + i])) + else: + off = 0 + for _ in range(n): + pts.append((get_ioa(obj, off), obj[off + 3])) + off += 4 + for ioa, raw in pts: + val = (raw & 0x03) if type_id == T_M_DP_NA_1 else (raw & 0x01) + iv = (raw & 0x80) != 0 + self.yx[ioa] = (val, iv) + self.events.append(("yx", (ioa, val, iv, cot))) + if ioa in YX_NAMES or cot == COT_SPONT: + log("RX I %s ioa=%d val=%d iv=%d cot=%d [N(R)=%d]" + % ("M_DP" if type_id == T_M_DP_NA_1 else "M_SP", + ioa, val, 1 if iv else 0, cot, nr)) + elif type_id == T_M_ME_NC_1: + pts = [] + if sq: + base = get_ioa(obj) + for i in range(n): + v = struct.unpack_from(" %s:%d (COV trigger: write 0x%X %.2f then " + "restore %.2f)" % (args.ip, args.port, addr, args.low, args.restore)) + + try: + m = Master(args.ip, args.port) + except Exception as e: + log("CONNECT FAIL: %r" % (e,)) + return 2 + + rc = 2 + try: + # 1. STARTDT + m._send(u_frame(U_STARTDT_ACT), "U STARTDT act") + ck.add("startdt_con", m.wait_event( + lambda e: e[0] == "startdt_con", 5.0) is not None) + + # 2. first general interrogation + m.send_i(asdu(T_C_IC_NA_1, 1, COT_ACT, 0, ioa=0, + payload=bytes([RQT_GROUP1])), + "I C_IC act (QOI=20)") + ck.add("gi_actcon", m.wait_event(actcon_of(T_C_IC_NA_1, False), + 5.0) is not None) + + def scan_yx(ioa): + return lambda e: (e[0] == "yx" and e[1][0] == ioa + and e[1][3] in SCAN_COTS) + + ck.add("scan_yx_dp(ioa4)", m.wait_event(scan_yx(4), 10.0) is not None) + ck.add("scan_yx_sp(ioa16)", m.wait_event(scan_yx(16), 10.0) is not None) + ck.add("scan_yc(ioa0x4018)", m.wait_event( + lambda e: (e[0] == "yc" and e[1][0] == 0x4018 + and e[1][3] in SCAN_COTS), 10.0) is not None) + ck.add("scan_freq(ioa0x401D)", m.wait_event( + lambda e: (e[0] == "yc" and e[1][0] == 0x401D + and e[1][3] in SCAN_COTS), 10.0) is not None) + ck.add("gi_actterm", m.wait_event( + lambda e: (e[0] == "asdu" and e[1][0] == T_C_IC_NA_1 + and e[1][1] == COT_ACTTERM), 10.0) is not None) + + v16 = m.yx.get(16) + ck.add("baseline_yx16_off", v16 is not None and v16 == (0, False), + "yx16=%r" % (v16,)) + + # 3. COV up: lower OC1 setting (two-step C_SE_NC_1) + def se(select): + pl = struct.pack(" second GI background scan") + m.send_i(asdu(T_C_IC_NA_1, 1, COT_ACT, 0, ioa=0, + payload=bytes([RQT_GROUP1])), + "I C_IC act #2 (QOI=20)") + ok_term = 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 + ck.add("yx16_OFF", ok_term and m.yx.get(16) == (0, False), + "via 2nd GI scan, yx16=%r" % (m.yx.get(16),)) + + # 5. YK11 two-step (positive confirm; reset consumed by protectTask) + m.send_i(asdu(T_C_DC_NA_1, 1, COT_ACT, 0, ioa=0x600A, + payload=bytes([0x82])), "I C_DC YK11 select (QDC=82H)") + ck.add("yk11_select_con", m.wait_event(actcon_of(T_C_DC_NA_1, False), + 5.0) is not None) + m.send_i(asdu(T_C_DC_NA_1, 1, COT_ACT, 0, ioa=0x600A, + payload=bytes([0x02])), "I C_DC YK11 execute (QDC=02H)") + ck.add("yk11_execute_con", m.wait_event(actcon_of(T_C_DC_NA_1, False), + 5.0) is not None) + + # 6. C_RD read back the restored setpoint + m.send_i(asdu(T_C_RD_NA_1, 1, COT_REQ, 0, ioa=addr), + "I C_RD 0x%X" % addr) + e = m.wait_event(lambda e: (e[0] == "yc" and e[1][0] == addr + and e[1][3] == COT_REQ), 5.0) + ck.add("rd_setpoint_10.0", + e is not None and abs(e[1][1] - args.restore) < 0.1, + "read=%.3f" % (e[1][1],) if e else "no response") + + m.close() + rc = 0 if all(ok for _, ok, _ in ck.items) else 1 + except Exception as e: + log("PROTOCOL ERROR: %r" % (e,)) + rc = 2 + + 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" if rc == 1 else "ERROR"))) + return rc + + +if __name__ == "__main__": + sys.exit(main()) 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 5/6] =?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])), From 4262bf61466c4b485ce635a19fa36901445247e7 Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Mon, 12 Oct 2026 16:56:00 +0800 Subject: [PATCH 6/6] =?UTF-8?q?docs(=E4=BB=BB=E5=8A=A1=E8=A7=84=E5=88=92):?= =?UTF-8?q?=20W1=20=E5=B9=B6=E8=A1=8C=E9=81=93=E5=9B=BE=E9=94=80=E9=A1=B9?= =?UTF-8?q?=E6=AE=8B=E7=95=99=E6=B8=85=E7=90=86=EF=BC=88B6=20=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E9=9A=8F=E9=94=80=E9=A1=B9=E7=A7=BB=E9=99=A4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - §3 mermaid 台架道删 B6 节点(销项已随 6215bb6 完成,图为唯一残留), 台架道现直接从 N-33 起步;与 B7 节点处理一致 - doc-links 全绿(141 文档) --- docs/任务规划/W1-采集保护收尾.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/任务规划/W1-采集保护收尾.md b/docs/任务规划/W1-采集保护收尾.md index 3978c6f9..6aaf51af 100644 --- a/docs/任务规划/W1-采集保护收尾.md +++ b/docs/任务规划/W1-采集保护收尾.md @@ -35,7 +35,7 @@ B7 证据 = `../子系统设计/IEC104上行设计说明.md` §3.4 + boot_log_da ```mermaid graph LR subgraph BL[台架道 🔴 串行独占 bench.lock] - B6[B6 @test 复测] --> N33[N-33 栈收口+复测] + N33[N-33 栈收口+复测] end subgraph CL[代码道 🟢 worktree 并行 绿即合] B8[B8 频率保护]