refactor(结构债): S-4 删零消费点占位宏;S-2 消两处与 Inc 重复的 extern

用户批准「先只跑 1+2」(报告 §0.4 结构债三项 S-1/S-2/S-4 的评估结论)。

**S-4 闭环**:删除 `App/app/app_cfg.h` 里 4 个**全库零消费点**的宏
(`APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` /
`APP_SYS_TIME_SRC`),文件降格为「决策占位说明」——修改记录 v1.2 写明为什么删、
将来在真实初始化点接入门控时怎么接回;同时去掉 `app_main.c` 里只为它存在的
include。留「看着能裁剪、其实不生效」的宏比不留更糟:它不产生任何编译期效果,
却会让评审误信模块可裁剪——此前为了对冲这个误解,AGENTS 之外还得在 6 处文档各
写一句「未接线占位,别当开关用」。

**文档口径同步 17 处**:`App/app/README.md`、`App/README.md`、根 `README.md`、
`项目架构总览.md`、`项目部署环境要求.md`(§3.2 两行 + 配置表一行)、`产品需求
设计文档.md`(B0 结论 + 配置表)、`基线与待确认.md`、`排期详述.md` C5、`登记簿
.md` N-23 残余、`RAM使用分析与优化方案.md` 三处。

**顺带纠出另一个「文档里有、代码里从来没有」的东西**:`RAM使用分析与优化方案
.md` 把 `APP_CCM_ENABLE` 写成「加在 `App/app/app_cfg.h`」,全库只有那篇文档提
到它,从未落地——已就地标注「未实现,重开本簇时一起落地」,免得下一个读者以为
CCM 有回退开关。

**S-2 第一步**:删 `gd5f2gq5ue.c:47`、`sd2506.c:20` 两处与 `Inc/spi.h` /
`Inc/i2c.h` 重复的 `extern`;GD5F 改 `#include "spi.h"`(沿用 `ch395f.c:22`
的既有做法)。

**镜像体积逐项不变**:`Code=213,188 RO-data=18,580 RW-data=1,184
ZI-data=131,504` 与改动前完全相同,`@build` 0 错 0 警告 → 两步均为行为中性。

报告 §0.4/§9 同步为实测口径并**认错**:S-2 不是旧写的「4 处」而是 **25 处**
(`App/task/default_task.c:52-69` 一次就 18 行任务句柄/属性 extern;
`stm32f4xx_it.c` 的 `fault_entry_hard` 属 ARMCC `__asm` 合法例外,不该「
修」);S-1 不是「语义层错位」而是**真实的 BSP→App 反向依赖**(NETCFG 10 处
include `App/cfg/cfg_file.h` + UI 3 个文件)。这两个旧数字是 v3.0 重写时沿用
未测所致。

途中被自家门禁正确拦下一次:在 .c 注释里写「S-2a」→ `+1 [校验1] 未登记编号
`,改成平实语言后转绿(正合既有纪律「代码注释禁用不可检索的内部编号」)。

门禁:`@build` 0/0;`check_ids.py --strict` 增量拦截通过、存量债 650 → 640、
可判定比例 82.83%(地板 82.6%+0.1pp);`check_doc_links.py --all
--sections-strict` 146 文档 0 问题;`pre-commit` 相关文件全 Passed;字节卫生 15
个文件 BOM/CR/U+FFFD/行尾空格全清(`end-of-file-fixer` 修掉 app_cfg.h 的一个
多余空行)。未推送。
This commit is contained in:
2026-10-22 18:22:58 +08:00
parent 538c44c1cc
commit 67fbdd9897
15 changed files with 35 additions and 55 deletions
@@ -448,7 +448,7 @@ sequenceDiagram
- **需求(B0 已确认,2026-10-10)**:**持续采集** 8 路电气量(Ua/Ub/Uc/U0、Ia/Ib/Ic/I0,**1000 Hz / 20 点/周波**),经保护/遥测算法后**上送 IEC 60870-5-104**(以太网 TCP 2404;遥测上送短浮点、采集上传系数 = 1)。
- **现状(采集链路 B1 + L1 已实现,2026-10-10)**:启动序列调用一次 `tpafe5160_init()`;**运行期周期 CONVST 重触发已由 TIM6 更新中断(1 kHz)接管**(`Src/main.c` 的 `HAL_TIM_PeriodElapsedCallback`,2026-10-10)+ `adcTask` 经 L1 层 `adc_input_poll()` 消费(`tpafe5160_snapshot()` 8 通道 + STM32 ADC1 9 通道扫描)+ 帧统计,台架 `@test` 确认 `frame_seq` 严格 1000 Hz 递增、`frst_err=0`、`adc1_rc=0` / `adc1_err=0`;STM32 侧 ADC1 **消费者已落地**(`App/algo/adc_input.c` 的 `stm32_scan()`,L1-3/L1-4,2026-10-10),按 N-18 仅逐通道独立监视。
- **后果**:上电后仅采集 1 个样本,此后数据永久陈旧。
- **B0 结论**(2026-10-10,详见 `docs/算法/继电保护功能复现规划.md` §1.5):① 持续采集 ② 1000 Hz(20 点/周波),通道 = 4U+4I(点表 `4011~4018`)③ 上行 **IEC 60870-5-104**(2404,非 ModBus RTU 上行)④ `APP_ADC_ENABLE` 语义 = 门控 ADC 采集链路(ADC 为遥测/保护必需来源;是否接线或删除占位宏待定)。
- **B0 结论**(2026-10-10,详见 `docs/算法/继电保护功能复现规划.md` §1.5):① 持续采集 ② 1000 Hz(20 点/周波),通道 = 4U+4I(点表 `4011~4018`)③ 上行 **IEC 60870-5-104**(2404,非 ModBus RTU 上行)④ ADC 采集链路为遥测/保护的必需来源 → **常驻编译**;原 `APP_ADC_ENABLE` 占位宏零消费点,已于 2026-10-22 删除(将来若要裁剪,需在真实初始化点接入门控并登记进 `App/app/app_cfg.h`)。
- **实现约束**(见 §9):周期 CONVST 重触发 + `adc_task` 消费 `tpafe5160_snapshot()`;**原子快照 API 已就位**(2026-10-10 修 E-44 / E-45 / E-58,旧的 `get_buf` / `data_ready` / `clear_ready` 已删 → 取数不再撕裂、重触发不再丢帧、芯片不驱动总线会被 `init()` 首帧自检抓到);栈预算核算;V0.1 通道映射已固化 → `docs/硬件平台/ADC通道映射说明.md`(13/17 路置换;语义 UA/UB/UC/UN、IA/IB/IC/IN、V_ZL2=温度,其余备用;网名 ADC17 = PC4 用 `ADC_CHANNEL_14`,**不是** `ADC_CHANNEL_12`)。⚠ **8 路电气量分属 TPAFE / STM32 两片转换器属 V0.1 硬件缺陷**(跨转换器无同一时刻性、精度与量程不一致,登记簿 N-18,V0.2 改版要求全部走 TPAFE)→ 在 V0.1 上主板侧只做**逐通道独立监视**,功率 / 功率因数 / 相角 / 矢量类量一律取子板计量模块结果,不得由主板混算。
### 5.10 RS-485 采集(FR-RS485)⬜ 待实现
@@ -790,7 +790,7 @@ cfg-file-unit-test、test-suite-switch、gitlint。
| 开关 | 位置 | 现状 |
|---|---|---|
| `APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` | `App/app/app_cfg.h` | **未接线占位,不门控任何代码**——三宏全库零消费点,各模块一律编译进产品;B0 已确认 ADC / RS-485 均为必需链路(ADC=遥测/保护来源,RS-485=对下 ModBus RTU 采集)→ 建议在后续落地时接线为真实门控(或删除占位宏)。**在接线前不要把它们当开关用** |
| 功能裁剪开关 | `App/app/app_cfg.h`(当前无宏) | **没有任何生效的裁剪开关**:原三个 `APP_*_ENABLE` 占位宏因全库零消费点已于 2026-10-22 删除(报告 S-4),各模块一律编译进产品——B0 已确认 ADC / RS-485 均为必需链路(ADC=遥测/保护来源,RS-485=对下 ModBus RTU 采集)。将来确需裁剪时在真实初始化点接入门控,并同步登记回该文件 |
| `TEST_SUITE_*` | `test/board/test_config.h` | 测试套件**互斥**,一次构建只开一个;全注释 = 正常产品固件 |
---
+1 -1
View File
@@ -6,7 +6,7 @@
## 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`**)。
2. 要不要引入**真实**的功能裁剪门控——原 `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 占位宏已于 2026-10-22 删除(零消费点),当前没有开关;此处要确认的是**是否需要在真实初始化点接入门控**(B1 取数不依赖它;**RS-485 侧随 B2 暂缓,见 `暂缓-RS485.md`**)。
3. RS-485 PD0 DE 的半双工方向语义需硬件实测确认(本次仅静态审查)——**随 B2 暂缓(`暂缓-RS485.md`)**。
## 2. 设计基线(供后续接入参考)
+1 -1
View File
@@ -12,7 +12,7 @@
| **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)** | 丢弃可观测性**代码已具备**(`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(非阻塞日志)合并评估。⚠ 原挂本卡的 **N-24**(日志逐条 `f_open/f_write/f_close`)已于 2026-10-15 修复销项(写侧一次排空合并成每文件一次开关、读侧 8 条滑动窗口)→ 实施记录 `../子系统设计/运行与自检记录设计说明.md` §4.4 / §4.5 | N-2 |
| **C1** | **net 层跨上下文收口** | 消化 E-25(`net_select` 语义)、E-27/E-28(裸指针收口为状态查询 API)。原 ACCEPT + SEND pending 化已收口:SEND 2026-10-14 落地、ACCEPT 决定不实施(2026-10-15) | E-25 / E-27 / E-28 |
| **C5** | 一档剩余 | **N-23 残余**(`KNOWN_GAPS` 白名单清理 + `app_cfg.h` 未接线开关,见 `登记簿.md`)。**RS-485 DE 收尾已移入 `暂缓-RS485.md`** | 一档/二档 |
| **C5** | 一档剩余 | **N-23 残余**(`KNOWN_GAPS` 白名单清理,见 `登记簿.md`);~~`app_cfg.h` 未接线开关~~ ✅ **已闭环**(2026-10-22 删除零消费点占位宏,报告 S-4)。**RS-485 DE 收尾已移入 `暂缓-RS485.md`** | 一档/二档 |
| **N-22/25/28** | 评估簇 | 写回 flush / 性能与语义一致性 / Flash 死代码——逐项见 `登记簿.md` 对应行,随窗口评估 | 报告各条 |
## 2. W5 验证常态详述
+1 -1
View File
@@ -42,7 +42,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` 一条**刻意**缺口(E-59 门禁下随 B2 暂缓,见 `暂缓-RS485.md`);`app_cfg.h` 未接线开关(C5)。⚠ `lftpd_log.c` 已随 N-19 删除并入 `lftpd_auth.c`(2026-10-11),不再是缺口 | 白名单不清 = "写了不编译"盲区仍在 | 随 B2 一并出白名单(`--strict` 供审计复跑);开关随 C5 处置 | W4(C5) | 报告 N-06 残余 + 报告 S-3 |
| N-23 残余 | **钩子已落地**(2026-10-12 `registration-check` 挂 pre-commit,存量缺口走 `KNOWN_GAPS` 白名单只 WARN);**残余** = 白名单只剩 `rs485_task.c` 一条**刻意**缺口(E-59 门禁下随 B2 暂缓,见 `暂缓-RS485.md`)。⚠ `lftpd_log.c` 已随 N-19 删除并入 `lftpd_auth.c`(2026-10-11),不再是缺口 | 白名单不清 = "写了不编译"盲区仍在 | 随 B2 一并出白名单(`--strict` 供审计复跑) | W4(C5) | 报告 N-06 残余 + 报告 S-3 |
| N-25 | 性能/资源建议簇:PASV 每次新建监听;PHY 强制 100M 无自协商回退;`NET_MAX_SOCKETS 8` 与单连接语义不符;`HAL_Delay(1)` 阻塞 DE(**DE 项随 B2 暂缓,见 `暂缓-RS485.md`**)。⚠ 原列的 `NET_RECV_TIMEOUT_MS 30000` 已随 2026-10-13「recv 语义主流化」删除(挂起 recv 模型),不再是待办 | 次级性能/语义一致性 | 逐项见 `../问题记录/项目审查与优化建议报告.md` §4.2/§4.7,随窗口评估 | W4 | 报告 N-09/PHY/P3-x/rs485 |
| N-27 | **内存优化簇**:**R-9 ✅ 已落地(2026-10-15)**——`LV_MEM_SIZE` 40→16 KB → SRAM1 由 74.9% 降到 **56.1%(余 57,504 B)**;待迁 CCM 体量随之由 54,146 B 降到 **29,570 B**,而 CCM 只剩 **7,904 B**(`RW_CCM` 上限 65,280 − 57,376) | ⏸ **整簇暂缓(用户裁定 2026-10-15)**:R-2 后半(缩堆 56→32 KB → 迁 CCM)与 R-3 / R-4 / R-6 **不再排期**——没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测,收益不抵风险与工时。⚠ 代价落在"以后加任务 / 抬栈 / 加堆"那一刻:CCM 只剩 7,904 B、FreeRTOS 堆实测 `min_ever` 8,464 B,届时 `mem-budget` 会先报警 → 按报告 §5.3 重开条件评估 | **三件套 ✅ 2026-10-12 落地**(`ram_baseline.py` 四模式 + `ram_baseline.tsv` 趋势 + `docs/内存管理/RAM预算台账.md` + `mem-budget` 钩子 92% 门禁)→ **R-9 ✅ 2026-10-15**(实测峰值 6,568 B = 池的 40%,水位表见 `../内存管理/RAM使用分析与优化方案.md` §2.6.2)→ **⏸ 其余整簇暂缓**(2026-10-15 裁定;理由与重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3)。⚠ **R-5 已判定不可行、从本簇剔除**:CMSIS-RTOS2 `freertos_os2.h` 有 `#if (configMAX_PRIORITIES != 56) #error`,改小直接编译失败(为 480 B 改第三方包装层不划算) | **暂缓** | 报告 R-2 剩余/R-3/R-4/R-6/§5.5 |
| N-28 | **本簇三项已全部判定(2026-10-22)**:**报告 F-6 ✅ 落地**(`App/algo/prot_set.h` 两个 Q10 宏去显式 `(double)` → `@build` 0 错 0 警、Code −332 B、保护判据路径不再走软件双精度;剩余 `dadd`/`dmul`/`ddiv`/`depilogue`/`dfixul` 1,018 B 锁在 MicroLIB `printfa.o` 的 `_printf_core → _fp_digits`,**与 `%f` 无关——全库 0 处 `%f`,报告原归因错**);**报告 F-4 ❌ 判定不做**(五项字节数仍准、合计 10,060 B,但**无一项有开关**:根因是 `lv_draw_sw.c` 的 `execute_drawing()` 无条件 switch 引用全部 task 类型;唯一总开关 `LV_DRAW_SW_COMPLEX` 被主界面"浅 V"3 px 粗斜腿锁死,2026-09-03 已实测失败并两端固化 =1;报告原"mask 是文字必经路径"的理由亦证伪——字形走 blend 层 `mask_buf`) | 仅剩 **报告 F-5 🟡 观察项**:uvprojx 201 个 LVGL `.c` 里 **127 个是空 TU**(`.map` 零产出);增量构建实测 4~5 s、远程 CI 刻意不跑 `@build` → **非产品指标**,报告原"编译时长 −40%"无基线记录 | 有实测的全量构建耗时痛点时再做:用 Keil 原生 `<IncludeInBuild>0</IncludeInBuild>`(可逆)而非删条目,且排在任何 `lv_conf.h` 改动之后;动手前先补一次全量构建计时做基线 | W4 | 报告 F-4/F-5/F-6 |
@@ -473,7 +473,7 @@ FreeRTOS 堆不变(`free=17248 / min_ever=9312`)。验证链:`@build` 0/0
}
```
**风险门禁**:scatter 注释已提示"clone MCU 可能缺 SRAM3",同理 CCM 在克隆芯片上不可靠 → 加编译开关 `APP_CCM_ENABLE`(`App/app/app_cfg.h`),关闭时 `LV_MEM_ATTR` 等定义退化为空,缓冲全部落回主 SRAM(阶段 1.1 池缩到 16KB 后主 SRAM 也放得下)。真 ST 芯片默认开。
**风险门禁**:scatter 注释已提示"clone MCU 可能缺 SRAM3",同理 CCM 在克隆芯片上不可靠 → 加编译开关 `APP_CCM_ENABLE`(**未实现**——2026-10-22 复核:`App/app/app_cfg.h` 里没有这个宏,重开本簇时要连它一起落地),关闭时 `LV_MEM_ATTR` 等定义退化为空,缓冲全部落回主 SRAM(§4.1.1 池缩到 16KB 后主 SRAM 也放得下)。真 ST 芯片默认开。
验证:map 中出现 `RW_CCM` 且 `*(CCM_DATA)` 各对象地址落在 0x10000000~0x100FFFF;`ram_report.py` 同时输出两个 Region 水位。
@@ -593,7 +593,7 @@ ISR 余量:该任务运行期间可能被中断打断的最深中断链(SPI/
| LVGL 池缩小 → 分配失败 | 复杂界面/长字符串吃池 | 分步降(40→16→8)+ 每步全 UI 回归 + `LV_USE_MEM_MONITOR` 观测 |
| 高水位低估 | 启动后未触发的路径(如格式化失败分支)没算进去 | 测试套件覆盖异常分支;保留 ≥30% free_min 底线 |
| 第三方代码改动 | lftpd 被 pre-commit 排除,改动不受检查 | 最小侵入、台账登记、升级 lftpd 时需重放补丁 |
| CubeMX 重生成 | `freertos.c`/`FreeRTOSConfig.h` 的 USER CODE 区受保护,但 CubeMX 改配置会覆盖部分生成区 | 所有内核宏改动集中在 USER CODE 区或 `app_cfg.h`;`.ioc` 与代码双向核对 |
| CubeMX 重生成 | `freertos.c`/`FreeRTOSConfig.h` 的 USER CODE 区受保护,但 CubeMX 改配置会覆盖部分生成区 | 所有内核宏改动只集中在 USER CODE 区与 `Inc/FreeRTOSConfig.h`(`App/app/app_cfg.h` 已无任何宏,不是宏的落点);`.ioc` 与代码双向核对 |
| 编码安全 | 新增 .c/.h 为 UTF-8 无 BOM;`Drivers/BSP/UI/*` 为 UTF-8 带 BOM | 遵守 AGENTS.md"源码编辑与编码安全"铁律:只用 Edit 工具改,不整文件重写 |
## 8. 附录
@@ -662,7 +662,7 @@ V1 链接视图(map:Grand Totals / Image component sizes / Symbol Table)
V4 逐项相加须与 V1 的 `Image component sizes` 逐 .o 吻合;不等则以 V1 为准并记录差异原因。
**数据来源清单**:`STM32F407-Demo.sct`(区域)、`Inc/FreeRTOSConfig.h`(堆/优先级/静态分配开关)、`cmsis_os2.c:472-476`(**栈大小单位 = 字节**:内部 `/ sizeof(StackType_t)`)、`Src/freertos.c`(任务/队列/事件组属性)、`Lib/lv_conf.h`、`Lib/FatFs/ffconf.h`、`App/app/app_cfg.h` + `test/board/test_config.h`(构建口径)、`Drivers/BSP/**` + `App/**`(缓冲语义/用途/DMA 归属);**权威数据 = `@build` 重建后的 `.map`**(历史 map 不得用于结论)。
**数据来源清单**:`STM32F407-Demo.sct`(区域)、`Inc/FreeRTOSConfig.h`(堆/优先级/静态分配开关)、`cmsis_os2.c:472-476`(**栈大小单位 = 字节**:内部 `/ sizeof(StackType_t)`)、`Src/freertos.c`(任务/队列/事件组属性)、`Lib/lv_conf.h`、`Lib/FatFs/ffconf.h`、`test/board/test_config.h`(构建口径;`App/app/app_cfg.h` 自 2026-10-22 起无宏,不再是口径来源)、`Drivers/BSP/**` + `App/**`(缓冲语义/用途/DMA 归属);**权威数据 = `@build` 重建后的 `.map`**(历史 map 不得用于结论)。
### 8.5 图表与台账重生成
+1 -1
View File
@@ -317,7 +317,7 @@ flowchart LR
| MCU 固件 | Keil MDK-ARM v5(`@build` = `keil-build` skill) | `@build` 0 错 0 警 → `@test` 串口闭环 |
| PC 模拟器 | CMake + SDL2 + MSVC(`simulator/build/`) | `check_menu_rows.py` + `check_content_pages.py`(文本断言 + 像素黄金参考) |
**功能编译开关**:`App/app/app_cfg.h`(网络/ADC/RS485);`test/board/test_config.h` 测试套件互斥选择(产品构建全注释)。
**功能编译开关**:当前**不存在**——`App/app/app_cfg.h` 自 2026-10-22 起不含任何宏(原 `APP_NET/ADC/RS485_ENABLE` 三个零消费点占位宏已删,接回方法记在该文件 v1.2),各模块一律编译进产品;裁剪测试套件的唯一开关是 `test/board/test_config.h` 互斥选择(产品构建全注释)。
---
@@ -492,9 +492,9 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级
|---|---|---|---|
| CH395F 以太网 | SPI2 | PB12 CS / PB13 SCK / PB14 SDO / PB15 SDI | PHY 强制 100M 全双工;SPI 分频系数必须为 8(PCB 设计约束,速度受限) |
| GD5F2GQ5UE NAND(2 Gbit) | SPI1 | PE0 CS / PB3 SCK / PB4 MISO / PB5 MOSI / PB8 WP / PE1 HOLD | FatFS(FAT32)+ dhara FTL;上电无卷自动 `f_mkfs` |
| TPAFE5160 ADC | 并行 16 位 | PG0~PG15 数据 / PD3 RD / PD4 CONVST / PD7 BUSY | 编译期常驻(`app_cfg.h` 的 `APP_ADC_ENABLE` 为**未接线占位**,不门控本模块) |
| TPAFE5160 ADC | 并行 16 位 | PG0~PG15 数据 / PD3 RD / PD4 CONVST / PD7 BUSY | **编译期常驻**(无裁剪开关;原 `APP_ADC_ENABLE` 未接线占位宏已于 2026-10-22 删除) |
| USART1(调试串口) | UART | PA9 TX / PA10 RX | 115200 8N1;printf 日志 + `@test` 采集通道 |
| UART5(RS-485) | UART | PC12 TX / PD2 RX / PD0 DE | 半双工;编译期常驻(`APP_RS485_ENABLE` 为**未接线占位**) |
| UART5(RS-485) | UART | PC12 TX / PD2 RX / PD0 DE | 半双工;**编译期常驻**(无裁剪开关;原 `APP_RS485_ENABLE` 占位宏已删) |
| 状态 LED ×6 | GPIO | PC4 / PC5 / PB1 / PB2 / PF11 / PF12 | **低电平点亮** |
### 3.3 资源预算(部署红线)
@@ -534,7 +534,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 核实):三个宏全库零消费点,各模块一律编译进产品;"能否裁剪"取决于产品定义(docs/任务规划/README.md §2 阶段 B0),落定后再接入真实门控。**不要把它们当开关** |
| 功能裁剪开关 | — | 无 | **当前没有任何可裁剪的编译开关**(2026-10-22):原 `APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE` 三个宏全库零消费点,已按报告 S-4 删除,`App/app/app_cfg.h` 只留决策占位说明。要不要真实门控取决于产品定义(`docs/任务规划/README.md` §2 阶段 B0);在此之前各模块一律编译进产品 |
| `TEST_SUITE_*` | `test/board/test_config.h` | 全注释(产品构建) | 测试套件**互斥**:一次构建只开一个(CH395F / 存储 / GD5F / RTC);全注释 = 正常产品固件 |
---
@@ -48,7 +48,8 @@
| 内存 RAM | R-2 剩余 / R-3 / R-4 / R-6 ⏸(N-27) | 待迁体量 29,570 B,而 CCM 只剩 7,904 B → 搬迁已无空间收益 | 暂缓;重开条件 §5.3 |
| 内存 RAM | N-14 🟡(N-22) | FTL 单页写回缓存无空闲/掉电强制 flush(整页写与换页已 flush,`f_close` 经 `CTRL_SYNC` 已落盘) | 用户裁定 2026-10-22 暂不做;残余窗口只是"单条记录" |
| Flash | **F-5 🟡 观察项**(N-28) | uvprojx 201 个 LVGL `.c` 里 **127 个空 TU**;增量构建 4~5 s、CI 不跑 `@build` | 有实测全量耗时痛点再做,用 `<IncludeInBuild>` |
| 结构 | S-1 / S-2 / S-4 ❌ | `NETCFG`/`UI` 语义层错位;裸 `extern` 仍在;`app_cfg.h` 三个 `APP_*_ENABLE` 里两个是未接线占位(未删) | 随登记簿 C5 处置 |
| 结构 | **S-1 ❌**(口径已按实测更正) | **不是"命名错位",是真实的 BSP→App 反向依赖**:`Drivers/BSP/NETCFG/{net_cfg,ftp_cfg}.c` include `App/cfg/cfg_file.h`(10 处调用点:`cfg_file_load/save/poll/register`),`Drivers/BSP/UI` 另有 3 个文件 include App 层头(`ui_page_runlog.c`、`ui_page_selftest.c`、`ui_w_records.h`);21 个 BSP 文件用 `dbg_log.h`(横切,待显式豁免) | **反转依赖**(约 7 文件 / 15 处;NETCFG 去掉 `cfg_file.h` 后还能进主机侧单测)+ 加一条「`Drivers/BSP/**` 不得 include `App/**`」的门禁;**目录搬迁暂缓**(远程 CI 仍不跑 `@build`,兜底未成立) |
| 结构 | **S-2 ❌**(实测 **25 处**,旧写「4 处」低估) | 原 4 处全部仍在,其中 `ch395f.c:177` 最危险:CH395F 裸写 GD5F 的 `g_spi1_dma_done`,并在 `HAL_SPI_ErrorCallback` 的 SPI1 分支里**替 GD5F 释放等待者**——谁清理那两行「看着无关」的分支,编译零报错,GD5F 的 DMA 出错就退化成干等 `GD5F_SPI_TIMEOUT`;`HAL_SPI_AbortCpltCallback`(`HAL_SPI_DMAStop` 会触发)无人实现。新增实测面:`App/task/default_task.c:52-69` 18 行任务句柄/属性 extern(看门狗用的任务清单表)、`adc_task.c:125`、`Src/main.c:115`、`Src/stm32f4xx_it.c` 2 处;其中 `fault_entry_hard` 属 ARMCC `__asm` **合法例外** | 四步:① ~~删冗余 extern~~ ✅ 已做 2 处(2026-10-22)② SPI 完成/错误/中止回调**归属拆清**(GD5F 导出 `gd5f_spi1_notify_*`,CH395F 只转发)③ 建 `App/task/task_registry.h` 集中消掉 19 行 ④ `netMsgQueueHandle` 收口 |
| 驱动规范 | S-5 ❌ | `bsp_err_t` 至今只出现在本报告里(无统一错误码/超时/重试约定) | 定义后进 `docs/代码规范/` |
| 网络 | N-09 / PHY ❌(N-25) | `NET_MAX_SOCKETS` 仍为 8(与单连接复用语义不符);PHY 强制 100M 无自协商回退;PASV 每次新建监听 | 见 §4.2;随 N-25 一并处置 |
| 存储 | N-15 🟡(N-25) | `nand_ftl.o` 静态 6,216 B——三块 2 KB 级页缓冲并存未合并 | 与 R-3 同批评估 |
@@ -373,7 +374,8 @@ W6 簇按 U4 → U1 → U3 → U2 的顺序执行完毕(U2 停在"够用即止
| **D-1** | 外部资料与工程文档同仓同树 | ❌ 暂不处理 | 本文 §3.3、登记簿 N-29 |
| D-2 ~ D-7 | 文档治理条目(链接/同源/编号/BOM 等) | ✅ 多数已制度化为钩子 | 本文 §3.2、`../文档规范.md` |
| D-9 | 文档面残余观察 | 🟡 观察 | 本节即定义位 |
| **S-1 / S-2 / S-4** | 语义层错位 / 裸 `extern` / `app_cfg.h` 占位开关 | ❌ 在策 | 本文 §0.4、登记簿 C5 |
| **S-1 / S-2** | 分层反向依赖 / 跨模块裸 `extern` | ❌ 在策(2026-10-22 实测:S-1 = NETCFG+UI 共 7 文件 15 处;S-2 = 25 处,含 1 处合法例外) | 本文 §0.4、登记簿 C5 |
| **S-4** | `app_cfg.h` 未接线占位开关 | ✅ **已闭环 2026-10-22**(4 个零消费点宏删除) | `App/app/app_cfg.h` 修改记录 v1.2;口径同步见 `../环境与部署/项目部署环境要求.md` §3.2/§3.5、`../产品需求/产品需求设计文档.md`、`../任务规划/排期详述.md` C5 |
| **S-3** | `.ioc` 侧 USART1 配置 | ❌ 在策 | 登记簿 S-3 |
| **S-5** | 统一 `bsp_err_t` 错误码约定 | ❌ 未做 | 本文 §0.4、`docs/代码规范/`(待建) |
| R-1 ~ R-9 | 内存优化项(R-9 已落地、R-5 判定不可行、其余随簇暂缓) | 见 §5.3 | 本文 §5.3、`../内存管理/RAM预算台账.md` |
@@ -407,6 +409,9 @@ W6 簇按 U4 → U1 → U3 → U2 的顺序执行完毕(U2 停在"够用即止
**改判的三条旧结论**:① §6 的 U1/U3/U4 原写「❌ 未建」,实际已落地(`ui_tokens.h` 69 行、`ui_page_registry.c` 描述符注册表、`ui-golden`+`font-charset` 两枚钩子);U2 只有 `ui_w_records` 一个组件;"27 页未落地"实为 7 页。② "新增一页 ≤30 行"目标**未达**(最省 40 行),如实记为未达项。③ §0.4 与登记簿已漂开 → 本版把待办清单降级为**快照 + 指向登记簿**,权威只留一处。
**刻意保留的三层**(删了会出事):§9 **编号族登记处**——本文是 `id_registry.json` 里 `N-RPT`/`D-RPT`/`S-RPT`/`R-RPT`(游标 R-9)/`F-RPT`/`U-RPT`(游标 U5) 六族的属主登记处,且外部存在「报告 N-14」「报告 F-4/F-5/F-6」「报告 D-1」「报告 R-2/R-3」式紧邻引用与 `check_dangling`,删定义位即触发编号门禁;§1.2/§1.3 方法与口径(数字可重跑);文末**变更记录 + 已销项去处表**原样冻结保留(52 行)。被外部点名的锚点(`§0.3`/`§3.1`/`§4.1`/`§4.2`/`§4.3`/`§5.3`×9/`§5.4`/`§5.5`×4/`§6.2`/`§6.3`/`§6.5`)逐个保留,**68 处入站引用零改动**。
**门禁**:`check_doc_links.py --all --sections-strict` → 146 文档 0 问题(章节引用 2,499、可判定 1,483);`check_ids.py --strict` 增量拦截通过、**存量债 650 → 641(−9)**、可判定比例 82.98% → **82.79%**(仍高于基线 82.6%,但缓冲从 0.38pp 缩到 0.19pp——删掉的那批引用 99% 是可判定的,属预期副作用);`mem-numbers` / `ram_baseline --gate` / `task-table` / `cubemx-survival` 全 0。字节卫生:BOM 无 / CR 0 / U+FFFD 0 / 无行尾空格 / LF 结尾。 |
| **2026-10-22** | **结构债 S-4 闭环 + S-2 第一步(用户批准「先只跑 1+2」)** | **S-4**:删除 `App/app/app_cfg.h` 里 4 个**零消费点**宏(`APP_NET_ENABLE`/`APP_ADC_ENABLE`/`APP_RS485_ENABLE`/`APP_SYS_TIME_SRC`),文件降格为「决策占位说明」——修改记录 v1.2 写明为什么删与将来怎么接回;并去掉 `app_main.c` 里只为它存在的 include。留「看着能裁剪、其实不生效」的宏比不留更糟:它不产生任何编译期效果,却让评审误信模块可裁剪;此前为了说明它,AGENTS 之外还得在 6 处文档各写一句「未接线占位,别当开关用」。同步改口径 **17 处**:`App/app/README.md`、`App/README.md`、根 `README.md`、`项目架构总览.md`、`项目部署环境要求.md`(§3.2 两行 + 配置表一行)、`产品需求设计文档.md`(B0 结论 + 配置表)、`基线与待确认.md`、`排期详述.md` C5、`登记簿.md` N-23 残余、`RAM使用分析与优化方案.md` 三处。
| | **顺带纠出另一个不存在的宏**:`RAM使用分析与优化方案.md` 把 `APP_CCM_ENABLE` 写成「加在 `App/app/app_cfg.h`」,实际从来没有落地(全库仅该文档提及)——已就地标注「未实现,重开本簇时一起落地」,避免下一个读者以为 CCM 有回退开关。
| | **S-2 第一步(实测纠偏)**:删掉 `gd5f2gq5ue.c:47`、`sd2506.c:20` 两处与 `Inc/spi.h`/`Inc/i2c.h` 重复的 `extern`,GD5F 改 `#include "spi.h"`(沿用 `ch395f.c:22` 的既有做法)。**镜像逐字节不变**:`Code=213,188 RO=18,580 RW=1,184 ZI=131,504` 与改动前完全相同,`@build` 0 错 0 警告 → 证明这两步是行为中性的。同时把 §0.4/§9 的旧口径换成实测值:**S-2 不是 4 处而是 25 处**(`App/task/default_task.c:52-69` 一次就有 18 行;`stm32f4xx_it.c` 的 `fault_entry_hard` 属 ARMCC `__asm` 合法例外,不该「修」),**S-1 不是语义错位而是真实反向依赖**(NETCFG include `App/cfg/cfg_file.h` 10 处 + UI 3 个文件)。**这两个旧数字是我 v3.0 重写时沿用未测,一并认错。** SPI 回调归属这条隐患(CH395F 替 GD5F 释放错误路径)目前只在本文 §0.4 留了痕,**尚未进登记簿**——要不要立项等你定。 |
| **2026-10-22** | **执行 §5.4:F-6 落地、F-4 判定不做、F-5 降级观察项**(登记簿 N-28 同步改写) | 动手前逐条对 `.map` 与源码核(本报告"建议栏不可照抄"总口径的又一次复现——三处误判全部出在**建议栏**,"发现"栏字节数全对)。**F-6 ✅**:`App/algo/prot_set.h` 两个 Q10 宏去掉显式 `(double)`、`1024.0`→`1024.0f` → `@build` 0 错 0 警、Code 213,520→**213,188(−332 B)**;`.map` 中 `dflti`、`d2f`、`f2d`、`dfixi`、`fepilogue` 共 300 B 消失,自研侧不再引用任何双精度 helper。**原报告"来自 `printf` 的 `%f`"是误判**:全库 0 处 `%f`,剩余 `dadd`+`dmul`+`ddiv`+`depilogue`+`dfixul` = 1,018 B 由 `mc_w.l(printfa.o)` 的 `_printf_core → _fp_digits` 无条件引用,MicroLIB 层面删不掉。**数值等价用穷举证明**(宏内 42 个字面量 + `int32` 全域 ÷1024 往返 4.49×10⁶ 例零差异;×1024 方向 2×10⁵ 例零差异);回归 = `prot_set` 90/90、`prot_elm` 47/47、`iec104` 97/97 主机单测全过。**F-4 ❌ 判定不做**:五项字节数逐字节仍准(合计 10,060 B)但**无一项有开关**,根因是 `lv_draw_sw.c` 的 `execute_drawing()` 无条件 switch 引用全部 task 类型;唯一总开关 `LV_DRAW_SW_COMPLEX` 被 `ui_deco.c` 的"浅 V"3 px 粗斜腿锁死(**2026-09-03 已实测失败并两端固化 =1**);**原"mask/grad 是文字必经路径"的理由同时证伪**(字形走 blend 层 `mask_buf`,不经 `lv_draw_sw_mask_*`)。**F-5 🟡 降级观察项**:uvprojx 实测 326 个 `.c` / LVGL 201 个 / `.map` 零产出 **127 个**,但增量构建实测 4~5 s、远程 CI 刻意不跑 `@build`,原"−40%"无基线记录。同步更正 §0.1 Flash 行、§0.4 Flash 行、注册表 uvprojx 行、§1 口径行、§5.1 快照注与要点行、§6.4 LVGL 占比分母、W4 波次行;台账受管区与内存快照已 `--write` 回填(`mem-budget` / `mem-numbers` 转绿)。**`@test` 台架 PASS**(固件戳 `fw build: Oct 22 2026 10:36:15 suite=NONE dstr=off`;无 `[ERR]`/`ERROR`/`FAIL`/Fault,708 ms 到 `net init: OK`,`protect task start`、`i104: listening on 2404`、`[STACK]` 三面水位齐;`adc`/`phasor`/`freq` 心跳持续) |
| **2026-10-14** | **清理:删除已完成与过时内容** | ① **已修复项按销项删除**(去处见下表):N-02(FTP 鉴权)、N-03c(`Error_Handler` 降级)、**N-11(DMA 可达性三层防线 + 规则族 R1~R4)**、S-3(注册反向校验)、P2-5/P2-6(SD2506 负温度与 WRTC)、P2-8(`NET_RECV_TIMEOUT_MS` 已删)、P2-9(`mkdir` 幂等重试)、§5.5 前三条(内存治理三件套)、交付物清单已建项。② **删除过时层**:2026-09-16 / 2026-10-11 双列基线表与"复核期间未提交改动"口径说明、旧"组合结果预估"表、逐条"2026-10-11 复核"批注、历史变更记录行——内存数字改由 `../内存管理/RAM预算台账.md` 与 `scripts/ram_baseline.tsv` 持有。③ **按 2026-10-14 `.map` 与代码重测**全部保留结论的数字(含 `lftpd_log.c` 已删除并入 `lftpd_auth.c`,N-06 残余只剩 `rs485_task.c` 一条刻意缺口)。④ **修正三处错误**:R-5(`configMAX_PRIORITIES` 56→32)**判定不可行**(CMSIS-RTOS2 `#error`);原 §7 把报告 S-5(驱动统一错误码)与登记簿 S-5(卷锁覆盖面)混为一谈;原 §5.5 第 4 条建议的 `_Static_assert` 形态在 AC5 上取不到链接期地址,已被"窗口断言 + 启动自检 + 运行时守卫"三层取代。⑤ 报告自有编号**不回改、不重排**(`../编号规范.md`) |