merge: N32 并入 v2-on-ui 主干(解 RAM 快照冲突并重生成)

N32 的 8 个提交与主干 v2-on-ui 的 6 个新提交合并。唯一冲突是
`docs/内存管理/RAM使用分析与优化方案.md` 的 mem-numbers 快照数字表:
- N32 侧基于旧基线(e4134a4)刷新
- v2-on-ui 侧含其他任务(B4/IEC104 等)的新代码

**两边都不能直接选**,故解冲突后按合并后的**实际构建**重新生成:
@build(合并后代码,0 错 0 警)→ check_mem_numbers.py --write
→ ram_baseline.py --write(同步 RAM 台账受管区)。

合并后内存水位:ER_IROM1 223,724 / RW_IRAM1 96,144 (73.4%) /
RW_CCM 57,376 (**87.9%**) / Flash 224,772;mem-budget 92% 门禁 PASS。
(RW_CCM 87.9% 已接近红线,后续加缓冲需注意。)

其余文件自动合并成功(uvprojx / check_registration.py)。
This commit is contained in:
2026-10-12 17:43:11 +08:00
101 changed files with 13312 additions and 4539 deletions
+7 -5
View File
@@ -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`)
---
@@ -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 问题记录(**改驱动前必读**)
@@ -211,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 环境与部署
@@ -224,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/` 生成) |
@@ -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) |
+1 -1
View File
@@ -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)
+203
View File
@@ -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];
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 474 KiB

+33 -27
View File
@@ -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"];
}
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 106 KiB

@@ -24,7 +24,7 @@
3. **产品当前做到哪一步**——已实现、已验收、待实现的**明确边界**。
**不含**:具体代码实现细节(见各模块设计文档)、测试用例步骤(见 `docs/测试说明/`)、
未闭环事项的逐条跟踪(见 [`docs/待处理内容.md`](../../docs/待处理内容.md))。
未闭环事项的逐条跟踪(见 [`docs/任务规划/README.md`](../任务规划/README.md))。
### 1.2 术语与缩写
@@ -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)**。
> **顺序唯一权威 → [`../任务规划/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`)。
> 功能缺口口径见 §9.1;B0 产品定义结论见 `../算法/继电保护功能复现规划.md` §1.5。
@@ -861,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) |
+27 -2
View File
@@ -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 检测脚本 |
+137
View File
@@ -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 ✅ / B6 台架复测 ✅ / B7 定值持久化+软压板 ✅ 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`(执行流程)——三者均不在本文件夹合并范围。
@@ -0,0 +1,70 @@
# 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 用例);
**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)**:把"采集→相量→保护→上送"链路从"代码落地"收口到
**"台架闭环 + 功能面完整 + 可送检"**。规划方式 = **里程碑(时间驱动、判据退出)×
并行道(按资源约束切分)× 任务卡(五字段)**。
## 2. 里程碑(时间驱动:功能可顺延,里程碑不拖延)
| 里程碑 | 退出判据(全部满足才算完成,随后销项) | 服务分类 |
|---|---|---|
| **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 并行、绿即合)
```mermaid
graph LR
subgraph BL[台架道 🔴 串行独占 bench.lock]
N33[N-33 栈收口+复测]
end
subgraph CL[代码道 🟢 worktree 并行 绿即合]
B8[B8 频率保护]
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 已先合入(2026-10-12,`App/algo/prot_set.*` 与 `App/protocol/iec104/iec104_pts.c` 定值段已释放);B8∥B9 写范围互不相交,可直接并行。
| 序 | 任务 | DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 | 出处 |
|---|---|---|---|---|---|---|---|
| **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` 实测 |
| **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)。
+93
View File
@@ -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`。
**旧栈表/旧余量数字作废,勿引用。**
+26
View File
@@ -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 已过) |
+12
View File
@@ -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 |
@@ -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`),本项仍是**门禁缺口**。
+53
View File
@@ -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 已背书 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 |
@@ -9,7 +9,7 @@
## 1. 背景与目标
`待处理内容.md` 已提出:"所有任务的内存都是往大的给的,导致内存不够用,要仔细排查内存的预算情况"。
登记簿(原 `待处理内容.md`,现 `docs/任务规划/`)已提出:"所有任务的内存都是往大的给的,导致内存不够用,要仔细排查内存的预算情况"。
分析起点(2026-09-11 快照,逐符号见 `data/ram_report_20260911.md`):
@@ -36,10 +36,10 @@
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ER_IROM1 | 214,228 B (209.21 KB) | 1,048,576 B (1024 KB) | 20.4% |
| RW_IRAM1 | 94,808 B (92.59 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,208 B (210.2 KB)** | 1,048,576 B (1024 KB) | **20.5%** |
| ER_IROM1 | 223,724 B (218.48 KB) | 1,048,576 B (1024 KB) | 21.3% |
| RW_IRAM1 | 96,144 B (93.89 KB) | 131,072 B (128 KB) | 73.4% |
| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
| **Flash (ROM 合计)** | **224,772 B (219.5 KB)** | 1,048,576 B (1024 KB) | **21.4%** |
<!-- MEM_SNAPSHOT:END -->
各区的容量与常量来源:
@@ -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** |
+96
View File
@@ -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. 区域预算与门禁(受管区)
<!-- MEM_BUDGET:BEGIN generated by scripts/ram_baseline.py -->
| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |
|---|---|---|---|---|
| ER_IROM1 (Flash) | 223,724 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,144 B | 131,072 B | 73.4% | PASS |
| 子系统(静态 RW+ZI;除 RTOS 堆在 CCM 外均在 SRAM1) | 现值 | 配额 | 状态 |
|---|---|---|---|
| 网络 | 13,410 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 | 堆=配额 |
| 应用 | 13,119 B | 8 KB | ⚠ 超 4.8 KB |
| 其它 | 7,596 B | — | 参考 |
<!-- MEM_BUDGET:END -->
- **门禁**: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/任务规划/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
(静态 +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 后半链注记 |
@@ -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。
@@ -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 更新中断提供"。
@@ -0,0 +1,177 @@
# IEC 60870-5-104 上行设计说明(B4)
> **定位**:DTU 上行规约 IEC 60870-5-104(DL/T 634.5104-2009)的设计基线——
> 范围、点表、链路流程、板端接入、预算与测试。规格来源
> `docs/算法/继电保护功能复现规划.md` §1.5(B0 产品定义,验收 = 省电科院点表);
> 代码落点 `App/protocol/iec104/`;登记项 `docs/任务规划/W1-采集保护收尾.md`(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/任务规划/暂缓-RS485.md`) | ❌ IV |
| 31 | 保护闭锁 | `prot_set_locked()` | ✅ |
| 32~33 | 预留 | — | ❌ IV |
> **点存在性优先**:无效点照常入总召/周期表并置 IV——点表是验收口径,缺行比
> 置 IV 更糟(主站侧无法区分"没做"与"接线错")。
>
> **保护类 YX(15/16~18/23/31)自 B5(2026-10-12)起为活数据**:protectTask
> 20 ms 判据节拍驱动 `prot_elm` 状态 → pts COV 变位上送(≤120 ms 端到端)。
### 3.3 遥控 YK(IOA 0x6000+,双点两段式)
| IOA | 点 | V0.1 行为 |
|---|---|---|
| 0x6000~0x6003 | YK1~4 开关 | **否定确认**(无出口硬件,`docs/算法/继电保护功能复现规划.md` R7) |
| 0x600A | YK11 信号复归 | ✅ 执行段 → `prot_elm_request_reset()`(B5 起跨上下文安全:请求由 protectTask 下一拍 eval 头部消费,不当拍直接复位) |
| 0x600B | YK12 遥控软压板 | ✅ 两段式转真(B7):选择段校验 DPC(ON/OFF,非法即 PN);执行段 → `prot_set_set_sealed(PS_GLOBAL_EN)` 原子写+封存;protectTask 下一拍读到退出态即复位元件并停判据(`App/task/protect_task.c`) |
| 0x600C | YK13 电池活化 | 否定确认(无对应硬件) |
| 0x600D | YK14 解除闭锁 | 否定确认(闭锁源于定值校验和,只能重写定值解除) |
### 3.4 定值(IOA = 通讯地址)
- 地址 = `App/algo/prot_set.h` 元数据 `comm_addr`(0x8820 基址 + 告警段 0x8027~0x802A,
逐项对照参考项目 `Const_CommSetPara.c`,见 `docs/算法/继电保护功能复现规划.md` §5.4)——
**点表不另立地址表**,prot_set 即单一事实源。`comm_addr = 0` 的本地项(投退/返回系数/
全局软压板)不可经 C_RD/C_SE 寻址(B7 起显式排除,防 IOA=0 误命中首个本地项)。
- 写两段式:选择 = 范围校验;执行 = `prot_set_set_sealed`(**原子写+封存**:影子区
写好后单字交换活跃区,protectTask 的 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. 链路与流程
- 参数: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、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`);**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 限制与待办(如实登记)
1. 固有参数 8001H~800AH 未实现(字符串类无法短浮点上送)→ 未知 IOA 应答;随送检需求再设计。
2. SOE 带时标(M_SP_TB_1)随 L4-4 SOE 记录落地;现突发只发 COT=3。
3. YK1~4/13/14 否定确认——出口硬件确认后(R7)转真执行(YK12 已于 B7 转真)。
4. 遥测死区 10.0 码值为拟定值,L1-5 标定后按工程量死区(点表 8020H 段)复核。
5. 多主站/双链路冗余不做(单连接语义)。
6. 主站侧验证工具 = `test/host/iec104_master.py`(B6 2026-10-12 就绪,台架往返 18/18,覆盖总召/变位/遥控/定值);**第三方送检环境仍未就绪**——lib60870 级第三方全流程归 B10。
7. **后连优先未实现**(V0.1 = 首到优先):单连接 socket 连接态无法 accept,
旧会话结束前新主站接入被拒;后连优先需 net 层(CH395F 单连接模型)支持,
真需要冗余切换时随 net 扩展立项。
8. 公共地址固定 1、监听端口固定 2404:可配置化(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) |
| 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_*` |
@@ -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 台架实证)
@@ -323,7 +324,7 @@ sequenceDiagram
**未做(根治)**:让 USART1 为 **TX-only**(.ioc 中不再使能 RX / PA10 不作 USART1_RX),
从机制上消除 ORE。属 `.ioc` 结构性改动 + CubeMX 重生成,需单开一轮并复跑台架闭环
→ 已登记为 `待处理内容.md` **S-3**。
→ 已登记为 `docs/任务规划/登记簿.md` **S-3**。
## 13. 开放问题
@@ -332,7 +333,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. 相关文档
@@ -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)(故障注入台架流程)、
@@ -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 任何构建不入掩码,口径不变) |
-384
View File
@@ -1,384 +0,0 @@
# 待处理内容(统一待办登记簿)
> **用途**:**全项目唯一的未闭环事项登记簿**——汇总"审计发现 / 台架观察 / 测试充分性与架构
> 专项 / 任务排序"四类待办。原 `审查记录/项目审计改进清单.md`(P-x)、`审查记录/下一步任务规划.md`
> (阶段与基线)、`审查记录/测试与架构改进建议.md`(S1x / A-x)、`docs/待处理内容.md`(N-x / S-x / T-x)
> 于 2026-10-04 合并入本文件,**编号一律沿用,不回收**。
>
> **只保留待办**:**已完成条目直接删除,不留变更记录**(历史见 `git log` 与各模块文档);
> 已闭环项的**结论与证据沉淀进对应模块文档/问题记录**,本文件不再重复。
> **消化即销项**:事项修复/关闭后,直接删除对应条目,并同步清理其它文档对本编号的引用。
>
> **不在本文件范围**:`问题记录/错误码传播审计.md`(E-xx,审计报告,非待办池)、
> `问题记录/项目审查与优化建议报告.md`(体系层评审报告)、`测试说明/实机测试实施指南.md`(执行流程)。
>
> **创建**:2026-09-22(L3 pending 台架收尾);**合并重写**:2026-10-04;**统一排序 + 审查报告并轨**:2026-10-11。
---
## 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 = 确认功能 bug|P1 = 疑似 bug 或健壮性风险|P2 = 改进|P3 = 卫生。
**置信度**:high = 代码级确证|medium = 依赖外部条件(手册/硬件/产品定义)。
---
## 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) |
> **网络侧另有 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.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。
4. **验证债仅剩窗口性事项**(D2/D5/D6/D7 + P1-10 收尾),不单独排期、逢窗口顺手做。
---
## 2. 统一推进顺序(全项目唯一权威)
> **本节是全项目所有工作流唯一的权威顺序**:`产品需求设计文档.md` §9.2、`算法/继电保护功能复现规划.md`、
> `项目审查与优化建议报告.md` §0.3 中的路线图均为局部视图,**顺序变更只改本节,其它文档只留指针**。
> 排序原则:**安全风险 > 产品功能主线 > 数据正确性 > 预算/结构债 > 验证常态 > 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` 历史重写影响未推送提交与协作者 → **需用户决策** |
| **硬件改版** | N-18 8 路电气量全接 TPAFE(V0.2) | 下一版硬件;固件侧已用语义映射隔离,改版只动映射表 |
### 2.1 W2 功能主线详述
> **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)。
| 序 | 任务 | 前置 | 说明 |
|---|---|---|---|
| **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 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 |
### 2.3 W6 验证常态详述
| 序 | 任务 | 说明 |
|---|---|---|
| **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 顺序一图
```
W2 功能 E-50/E-49 → B2 RS485(ModBus) ∥ B4 IEC104 上行 → B5 protectTask
↓
W3 数据 N-21 dhara is_free/copy(配主机侧移植层测试)
↓
W4 预算 内存台账三件套 → R-9 池瘦身 → R-2 后半(54KB→CCM)
↓
W5 结构 C1 pending 二期 · C3 日志(N-2/N-24) · C5 · C6(S-3) · N-20 · N-23 · N-22/25/26/28
↓
W6 验证 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
```
---
## 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(非阻塞日志)合并评估 | `错误码传播审计.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` |
**存储 / 日志管线**
| # | 事项 | 发现 | 证据与现状 | 出处 |
|---|---|---|---|---|
| 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 兜底),无自检日志 | 统一降级策略:记自检 + 禁用该子系统 + 其余照常 | 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 |
### 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 | 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 已完成)的设计约束**——应在动手前明确,否则后续无法补测。
**约束**(建议纳入 B1 / 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 削链闭环销项**
> (defaultTask 静态最坏链 5312 → 2776 B、实测 3392 → 2152 B,**未抬栈**),本项仍是**门禁缺口**。
---
## 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 的半双工方向语义需硬件实测确认(本次仅静态审查)。
---
## 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-04 曾升到 defaultTask **3664 B**(登记 S-1);2026-10-10 削链
> (删旧档迁移 + `FIL` 静态化 + 日志行缓冲按模块收紧 + 钩子脱离 HAL)后实测 **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);`错误码传播审计.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(登记簿)。
- 上游引用关系:`问题记录/项目审查与优化建议报告.md`(体系层评审)、`问题记录/错误码传播审计.md`(E-xx)、
`测试说明/实机测试实施指南.md`(执行流程)——三者均不在本文件合并范围。
+1 -1
View File
@@ -300,7 +300,7 @@
| 项目级铁律、构建/烧录/测试命令、平台约束 | `AGENTS.md`(AI 协作上下文,**精简优先**) |
| 开发者入门、架构速览、目录导航 | `README.md` |
| 详细设计、专项说明、测试指南 | `docs/` 下对应子目录 |
| 跨文档待办登记 | `docs/待处理内容.md`(统一登记簿) |
| 跨文档待办登记 | `docs/任务规划/README.md`(统一登记簿) |
| 评审报告与专项审计 | `docs/问题记录/` |
> **避免重复**:同一事实只在一处详述,其它位置用链接指向。典型如 FreeRTOS 任务表——`Src/freertos.c` 是唯一事实源,`README.md`/`AGENTS.md` 的表由脚本生成,不在别处再抄一份。
@@ -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
@@ -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
@@ -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
@@ -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
+7 -2
View File
@@ -29,10 +29,15 @@
| 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` |
| 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. 关联
- 沉淀约定:`../测试开发标准流程.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 固化为本节流程后销项)
@@ -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 决策规则 | 本文为"需回真机"项的执行面 |
@@ -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** 头阻塞)
---
+1 -1
View File
@@ -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 门禁在测试分层中的位置)。
@@ -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 总线 |
@@ -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 跟踪 |
@@ -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 重锁**
+1 -1
View File
@@ -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` 的部署前置警示块)。
---
@@ -14,7 +14,7 @@
## 1. 目的与范围
**要解决的问题**:多个任务同时推进时,若共用同一个工作目录,会互相踩——构建产物、日志目录、
Python 环境、以及 `docs/待处理内容.md` 这类**全局唯一登记簿**都会被并发写坏。
Python 环境、以及 `docs/任务规划/` 这类**全局唯一登记簿**都会被并发写坏。
**做法**:每个任务一棵 `git worktree` + 一条任务分支,任务之间物理隔离;干完由固定命令合回主干。
@@ -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/<ID>-<slug>`,从主干当前 HEAD 切出 |
| `<ID>` | **沿用 `docs/待处理内容.md` 的编号空间**(`P0-x`/`N-x`/`S-x`/`T-x`/`B-x`/`C-x`/`D-x`);无对应条目的临时任务用 `X-<日期>-<slug>` |
| 合并方式 | `git merge --no-ff` 合入主干 |
| 并发上限 | **同时最多 3 棵工作树** |
| 项 | 取值 |
| -------- | ---------------------------------------------------------------------------------------------------- |
| 集成分支(主干) | `v2-on-ui` |
| 任务分支 | `task/<ID>-<slug>`,从主干当前 HEAD 切出 |
| `<ID>` | **沿用 `docs/任务规划/README.md` 的编号空间**(`P0-x`/`N-x`/`S-x`/`T-x`/`B-x`/`C-x`/`D-x`);无对应条目的临时任务用 `X-<日期>-<slug>` |
| 合并方式 | `git merge --no-ff` 合入主干 |
| 并发上限 | **同时最多 3 棵工作树** |
**`<ID>` 复用登记簿编号**是为了可追溯:任务分支名直接对应待办条目,回收时销项有据可查。
@@ -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 <UTF-8 无 BOM 文件>`) | 可并行 |
| `sync` | `rebase` 追平主干,把冲突控制在任务分支上 | 可并行 |
| `done` | 预演 → 合入主干 → 残留审计 → 重生成产物 → 门禁 → 清理工作树 | **必须串行** |
| `push` | 推送主干/任务分支 | **需用户明确许可** |
| 阶段 | 动作 | 并行性 |
| ------ | -------------------------------------------- | ----------- |
| `new` | 建分支 + 工作树 + junction + 台账 | 可并行 |
| 编码 | 在新空间里改代码 | 可并行 |
| 门禁 | `scripts/ci_local.py`(L0 + L0.5,纯软件) | **可并行** |
| 构建 | `@build`(UV4 增量,需持 `build` 锁) | **必须串行** |
| 台架 | `@test` / 板级套件(需先持台架锁,见 §7) | **必须串行** |
| 提交 | 本地 `git commit`(多行正文用 `-F <UTF-8 无 BOM 文件>`) | 可并行 |
| `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 自动改写 | 手工并 `<File>` 条目 → 重跑 `registration-check` → `@build` |
| `.pre-commit-config.yaml` | 新增主机单测要加钩子 | 并集处理 |
| `docs/内存管理/RAM使用分析与优化方案.md`(及其 `mem-numbers` 快照) | `mem-numbers` 快照 | **绝不手工合数字**,合并后 `scripts/check_mem_numbers.py --write` 重生成 |
| 文件 | 冲突原因 | 回收时的处理 |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `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 自动改写 | 手工并 `<File>` 条目 → 重跑 `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/<ID>-<slug>`。
- `rc=0`(无冲突)→ 继续合并
- `rc≠0` → **在任务分支上** `git merge v2-on-ui` 解决冲突并提交,再重跑 `done`
@@ -196,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 设计
@@ -205,15 +231,15 @@ D:/Code/DTU Code/
**执行体**:`.dsh/skills/task-worktree/scripts/task_worktree.py`(纯标准库,
照 `keil_build.py` 的写法,整目录可拷到别的项目复用)。**已落地并端到端实测**(见 §11)。
| 子命令 | 作用 |
|---|---|
| 子命令 | 作用 |
| ----------------------------------------------------- | ----------------------------------------------------------- |
| `new <ID> <slug> [--base B] [--lean] [--needs-bench]` | 建分支 `task/<ID>-<slug>` + `_wt/<ID>-<slug>/` 工作树 + 共享联接 + 台账 |
| `list` | 所有任务一览:分支 / 落后领先 / 脏文件数 / 台架状态 + 两个锁的归属 |
| `status <ID>` | 单任务详情:未提交清单、相对基线漂移、台架记录、已建联接 |
| `sync <ID>` | `rebase` 追平主干,把冲突控制在任务分支上 |
| `lock acquire\|release\|status <build\|bench>` | 独占资源锁(`--task` / `--wait` / `--force` / `--bench-pass`) |
| `done <ID> [--dry-run] [--skip-build] [--skip-gates]` | 预演 → 合入主干 → 残留审计 → 重生成产物 → 门禁 → 清场 |
| `abort <ID> [--force]` | 放弃任务(有未提交/未合并内容时不加 `--force` 会拒绝) |
| `list` | 所有任务一览:分支 / 落后领先 / 脏文件数 / 台架状态 + 两个锁的归属 |
| `status <ID>` | 单任务详情:未提交清单、相对基线漂移、台架记录、已建联接 |
| `sync <ID>` | `rebase` 追平主干,把冲突控制在任务分支上 |
| `lock acquire\|release\|status <build\|bench>` | 独占资源锁(`--task` / `--wait` / `--force` / `--bench-pass`) |
| `done <ID> [--dry-run] [--skip-build] [--skip-gates]` | 预演 → 合入主干 → 残留审计 → 重生成产物 → 门禁 → 清场 |
| `abort <ID> [--force]` | 放弃任务(有未提交/未合并内容时不加 `--force` 会拒绝) |
**环境变量**:`DTU_WT_ROOT`(任务容器位置)· `DTU_TASK_BASE`(默认基线)·
`DTU_INTEGRATION_WORKTREE`(集成点,默认主工作树;用于隔离演练/测试)。
@@ -231,35 +257,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 +314,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 +342,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,隔离集成点演练)
@@ -352,4 +394,4 @@ docs\内存管理\RAM使用分析与优化方案.md:585 [路径引用] docs/内
| 自动化测试与台架流程 | `docs/测试说明/自动化测试流程.md` |
| 文档写作规范(编码/链接/登记) | `docs/文档规范.md` |
| 工具路径环境变量(换机) | `docs/环境与部署/本地工具路径环境变量方案.md` |
| 待办与排序登记簿 | `docs/待处理内容.md` |
| 待办与排序登记簿 | `docs/任务规划/README.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);全注释 = 正常产品固件 |
---
+15 -13
View File
@@ -3,8 +3,8 @@
> **定位**:把参考系统(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`。
> **状态**:**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)。
> **相关文档**:`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)。
---
@@ -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 限制) |
@@ -320,10 +320,10 @@
| # | 功能点 | 说明 | 状态 |
| --- | --- | --- | --- |
| 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()`,单测覆盖);采样故障闭锁(`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,10 +466,10 @@
| 阶段 | 名称 | 内容 | 前置 | 里程碑 |
| --- | --- | --- | --- | --- |
| **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 显示闭环 |
| **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 修复 + 中点偏置),本期**建接口不使能**。
@@ -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 待确认项) |
---
@@ -585,7 +585,6 @@ B0 产品定义 ✅(2026-10-10 已确认,见 §1.5)
2. 出口硬件形态(继电器/回读)——依硬件(R7)。
3. 等周波调频范围与精度目标——依产品定义(R4)。
4. 是否保留遥测谐波轨(k=1~9)——依 UI/上送需求。
5. 遥测/遥信/遥控的 104 上送实现范围与排期——依产品定义。
---
@@ -606,3 +605,6 @@ 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 里程碑更新 |
| 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 仍待窗) |
@@ -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:修订记录
+1 -1
View File
@@ -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(生产固件确定性复现 + 当日修复闭环)。
+2 -2
View File
@@ -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),保持既有正确做法
---
@@ -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 负向台架)→ 引用带文档名。
| 类别 | 编号 | 未闭环内容 | 下一步 |
@@ -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 小时工作量"的一条 |
@@ -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` 闭环"两步) |
---
@@ -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` 未扩展,注册表不存在) |
@@ -688,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` **仍未创建**(见 §5.5)。
> - 本报告按 `docs/README.md` 的定位是**体系层评审报告,不是待办池**——待办一律以 `../待处理内容.md` 为准;本报告只保留**未闭环问题的发现 + 证据**,修复即销项。
> - ✅ `docs/内存管理/RAM预算台账.md` 与 `scripts/ram_baseline.tsv` **已于 2026-10-12 创建**(见 §5.5 各条闭环标注)。
> - 本报告按 `docs/README.md` 的定位是**体系层评审报告,不是待办池**——待办一律以 `../任务规划/README.md` 为准;本报告只保留**未闭环问题的发现 + 证据**,修复即销项。
---