feat(S-5 R4): 返回值不得裸丢弃成为机械检查,并修掉照出的第一处 ECC 静默降级
B 的第一步(加规则)与第二步(修最小最值的那处)。用户裁定"B 按你说的进行"。 **为什么只能项目侧自己做**(两条实测负结果,已写进 §2.27 与 bsp_err.h 边界纪律 4): · ARMCC v5 对 __attribute__((warn_unused_result)) 不生效(凌晨在 rs485_transmit 上实测:属性 在位、调用点裸调不接返回值,构建仍 0 错 0 警告); · cppcheck 也照不出来——按本仓自己的 --enable=warning,style,performance,portability 跑 gd5f2gq5ue.c,对 14 处丢弃 HAL_SPI_* 返回值、以及"未初始化局部量直接进 P_FAIL 判定" **一条不报**(它假定 gd5f_read_status(&status) 会写出参,而失败路径根本不写)。 结论:**丢弃底层传输的返回值,今天没有任何工具会响**。 **R4 上线即照出 37 条存量丢弃**:gd5f2gq5ue.c 29(14 处 HAL + 15 处自家原语)、net_socket.c 8、 ui_net_sink.c 4(net_close)、rs485.c 2、nand_ftl.c 1。按增量拦截老规矩入基线、只减不增—— 这是覆盖面扩大新暴露的历史债,不是新增违规;基线 19 → 1 → **38**。 **R4 自己被修三次(逐条记下,都是"规则比我想的更脆")**: ① 首版漏判"裸调用行尾带注释"这种写法(正则的 \s*$ 卡死),而那恰是最常见的"带说明的丢弃" → 补可选注释分支,并做 6 条正/反例自检; ② 把 net_set_errno 八处误判成丢弃(它是 setter,返回 int 是状态回声不是调用成败)→ **按真实 反例把规则收窄**(谓词 + setter 两类豁免),而不是塞进基线洗掉假阳性; ③ must-use 名单只从**头文件**取,gd5f_set_feature 这类 static 原语整个在视野外——而下面那处 真窟窿恰恰是 static、靠人工才发现 → 名单扩到 .c 内 static 定义(同一套启发式),补完立刻 又照出 gd5f_bbt_save#1:**运行时标坏后 BBT 落盘结果被丢弃 = 坏块记账可能没持久化**,已入 基线记为待还,本步不动行为。 另修一处自己的排版误判:R3 原本要求注释块出现字面"返回值",规范 V1.0 允许列对齐写法 「返 回 值:」→ 改为忽略空格匹配(门禁不该规定排版)。 **修掉的第一处真窟窿**:bbt_rebuild 的注释写着"无论扫描成败都须恢复 ECC,否则后续 I/O 在无 ECC 下运行",而它下面 gd5f_set_feature(0xB0,…) + gd5f_wait_busy(100) **返回值全丢**:SPI 一抖 ECC 就保持关闭,且 gd5f_check_ecc() 在 ECC 关闭时恒读"无 ECC 错"——整条链再没有任何信号。 补法复用 init 路径的 E-10(写完回读 B0h 验 ECC_EN 位真生效,"写了但没生效"与写失败同罪), 并把"关 ECC 失败"改成**立即中止**(此时 ECC 仍开着,是安全侧;带着 ECC 去扫 spare 反而会把 厂标好块误判成坏块,"重建 BBT"变成制造坏块)。恢复失败时按 (void)gd5f_bbt_load() 回读盘上 副本,避免 RAM 留着"比盘上更新"的表而下次上电又退回旧表。 **一条定位纠正(差点把修复记大)**:查链接映射发现 Removing gd5f2gq5ue.o (i.gd5f2gq5ue_bbt_rebuild), (604 bytes)——该函数在产品镜像里**根本没被链接**(产品构建无调用 者),只由 ENABLE_STORAGE_RECOVERY_TESTS 的恢复构建经 testTask 调用。所以本次修的是**恢复流程 自身的安全**(跑恢复时若 ECC 没恢复,设备会带着"已恢复"的结论在无保护状态下继续跑),不是 现场日常路径;相应地镜像 Code 的 +28 B 也不是它带来的(未逐字节追,线索是 gd5f_private_get_feature 由单调用点变多调用点、内联决策可能变化)。验证因此不能只跑产品构建: 临时打开 TEST_SUITE_STORAGE + ENABLE_STORAGE_RECOVERY_TESTS 编一次(0 错 0 警告且该函数不再 出现在 Removing 列表),随即还原两处开关并重编产品构建核对(test/board 无残留差异)。 **编号门禁把我自己的自造编号拦下了**:我起初用 B-1/B2/B3/B4 标记这批缺陷,id-check 报"未登记 前缀"13 处(且 B2/B3/B4 会与真实里程碑号撞号)→ 全部改写成平实语言。这是那条"注释与文档里 不许用没人检索得到的内部阶段编号"的规则第一次在提交前拦住我,规则是对的。 验证:@build 0 错 0 警告,Code 213,648 → **213,676**、RO 18,860、ER_IROM1 **232,536 B / 22.2%** (ROM 合计 233,724 B;RAM 逐字段不变);ram_report 重生成 + ram_baseline.py --update + 配图常量 同步(mem-numbers Passed);@test **PASS**(到 net init: OK 682 ms、[ERR] 0);R4 两处**探针 实证**(临时加一条裸调用 → 立刻成为新增并 RC=1;还原 → 38/38/0);--prune 点名本次还掉的 2 条 已删;pre-commit run 全绿 15 Passed;check_doc_links --all --sections-strict 147 篇 0 问题; id-check --strict 增量拦截通过。 文档:AGENTS.md 与 .pre-commit-config.yaml 的 bsp-err 口径(四条规则、基线 38); pre-commit使用说明.md §2.27(R4 全量口径 + 两条负结果 + 名单来源与豁免形状 + 单行限度); bsp_err.h 边界纪律 4;报告 §0.4 / §5.1 / §9 / 附录 A + 变更记录;存储维护与容量恢复.md 新增 §4.3(运维判据:出现 ECC restore FAILED / ECC not enabled 即本次恢复**不算完成**,须断电重启 重走 init,不许接着 nand_ftl_format() 当作已修好;并记明该函数产品镜像不链接)——顺带修该文 结构缺陷:原 ## 5. 变更记录 误插在 §4.1 与 §4.2 之间,会让 §4.2 变成 §5 的子节。
This commit is contained in:
+13
-13
@@ -7,29 +7,29 @@
|
||||
.bar-seg { stroke:#fff; stroke-width:0.5; }
|
||||
</style>
|
||||
</defs>
|
||||
<text x="410.0" y="24" text-anchor="middle" class="title">Flash (1MB) 使用布局 — 2026-10-22 @build</text>
|
||||
<text x="410.0" y="24" text-anchor="middle" class="title">Flash (1MB) 使用布局 — 2026-10-23 @build</text>
|
||||
<rect class="bar-seg" x="60" y="50" width="150.8" height="40" fill="#2196F3" rx="2"/>
|
||||
<text x="135.4" y="70.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">代码段 (Code) 208.6KB</text>
|
||||
<rect class="bar-seg" x="210.77545166015625" y="50" width="13.3" height="40" fill="#4CAF50" rx="2"/>
|
||||
<text x="135.4" y="70.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">代码段 (Code) 208.7KB</text>
|
||||
<rect class="bar-seg" x="210.7952117919922" y="50" width="13.3" height="40" fill="#4CAF50" rx="2"/>
|
||||
<text x="228.1" y="70.0" text-anchor="start" dominant-baseline="central" class="legend-text" fill="#333">只读数据 (RO) 18.4KB</text>
|
||||
<rect class="bar-seg" x="224.08531188964844" y="50" width="575.1" height="40" fill="#E0E0E0" rx="2"/>
|
||||
<rect class="bar-seg" x="224.10507202148438" y="50" width="575.1" height="40" fill="#E0E0E0" rx="2"/>
|
||||
<text x="511.6" y="70.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">Flash 空闲 795.8KB</text>
|
||||
<text x="60" y="108" class="label" fill="#333">已用: 228.2KB (22.3%) 空闲: 795.8KB (77.7%) ER_IROM1(Code+RO): 227.1KB (22.2%) 总量: 1MB (= ROM 合计口径)</text>
|
||||
<text x="60" y="124" class="label" fill="#555">Code + RO 分布(ER_IROM1 227.1KB,按 .map 对象归类)</text>
|
||||
<rect class="bar-seg" x="60" y="130" width="279.1" height="24" fill="#4CAF50" rx="2"/>
|
||||
<text x="199.6" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">85.7KB</text>
|
||||
<rect class="bar-seg" x="339.1406747294717" y="130" width="181.6" height="24" fill="#2196F3" rx="2"/>
|
||||
<rect class="bar-seg" x="339.1070629923969" y="130" width="181.5" height="24" fill="#2196F3" rx="2"/>
|
||||
<text x="429.9" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">55.7KB</text>
|
||||
<rect class="bar-seg" x="520.7033736473584" y="130" width="82.5" height="24" fill="#F44336" rx="2"/>
|
||||
<rect class="bar-seg" x="520.6478996800496" y="130" width="82.5" height="24" fill="#F44336" rx="2"/>
|
||||
<text x="561.9" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">25.3KB</text>
|
||||
<rect class="bar-seg" x="603.1858688733291" y="130" width="56.9" height="24" fill="#607D8B" rx="2"/>
|
||||
<rect class="bar-seg" x="603.1204630680842" y="130" width="56.9" height="24" fill="#607D8B" rx="2"/>
|
||||
<text x="631.6" y="142.0" text-anchor="middle" dominant-baseline="central" class="label" fill="#000">17.5KB</text>
|
||||
<rect class="bar-seg" x="660.0795671546786" y="130" width="35.7" height="24" fill="#FF9800" rx="2"/>
|
||||
<rect class="bar-seg" x="695.7956715467855" y="130" width="34.3" height="24" fill="#00BCD4" rx="2"/>
|
||||
<rect class="bar-seg" x="730.0477402928071" y="130" width="27.0" height="24" fill="#9C27B0" rx="2"/>
|
||||
<rect class="bar-seg" x="756.9987269255251" y="130" width="17.5" height="24" fill="#795548" rx="2"/>
|
||||
<rect class="bar-seg" x="774.4589433481859" y="130" width="1.5" height="24" fill="#B0BEC5" rx="2"/>
|
||||
<rect class="bar-seg" x="775.9484404837683" y="130" width="24.1" height="24" fill="#E0E0E0" rx="2"/>
|
||||
<rect class="bar-seg" x="660.0073106959784" y="130" width="35.7" height="24" fill="#FF9800" rx="2"/>
|
||||
<rect class="bar-seg" x="695.7191144596967" y="130" width="34.2" height="24" fill="#00BCD4" rx="2"/>
|
||||
<rect class="bar-seg" x="729.967058864004" y="130" width="26.9" height="24" fill="#9C27B0" rx="2"/>
|
||||
<rect class="bar-seg" x="756.9148002889876" y="130" width="17.5" height="24" fill="#795548" rx="2"/>
|
||||
<rect class="bar-seg" x="774.3729143014416" y="130" width="1.5" height="24" fill="#B0BEC5" rx="2"/>
|
||||
<rect class="bar-seg" x="775.8622320844945" y="130" width="24.1" height="24" fill="#E0E0E0" rx="2"/>
|
||||
<rect x="60" y="167" width="10" height="10" fill="#4CAF50" rx="2"/>
|
||||
<text x="74" y="176" class="legend-text" fill="#333">LVGL 库 85.7KB</text>
|
||||
<rect x="255" y="167" width="10" height="10" fill="#2196F3" rx="2"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
@@ -478,7 +478,7 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **为什么需要** | 报告原文说"无统一错误码",实测更准的说法是**六套并存**:0/−1(SD2506、NETCFG、nand_ftl)、`int32_t`;
|
||||
| **为什么需要** | 报告原文说"无统一错误码",实测更准的说法是**六套并存**:0/−1(SD2506、NETCFG、nand_ftl)、
|
||||
自研枚举(`CH395F_STATUS_*`)、芯片寄存器原生码(`CH395F_ERR_*`,与前一套同模块并存)、
|
||||
`HAL_StatusTypeDef`(`rs485.h` 曾直接暴露)、`bool`,外加第三方 dhara 的出参 `dhara_error_t`
|
||||
与 FatFs 的 `FRESULT`。超时侧更乱:**同名形状装三种东西**——真毫秒但带不带 `_MS` 后缀不统一(`SD2506_I2C_TIMEOUT_MS` vs
|
||||
@@ -487,22 +487,38 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法
|
||||
| **约定正文在哪** | `Drivers/BSP/bsp_err.h`(**header-only,无 `.c`** → 不占体积、不需双端注册)。
|
||||
`0 = BSP_OK`、负值失败、`BSP_ERR_CAN_RETRY(e)` 把"能不能重试"变成跨模块可判定(这是本契约
|
||||
真正值钱的一条:以前"可重试"只写在个别注释里) |
|
||||
| **三条规则** | **R1** 公开 API 不得用 `HAL_StatusTypeDef` / `bool` 当错误通道(`is_/has_/can_/valid`
|
||||
| **四条规则** | **R1** 公开 API 不得用 `HAL_StatusTypeDef` / `bool` 当错误通道(`is_/has_/can_/valid`
|
||||
这类**谓词**白名单放行——第一版误判了 7 个正当谓词,我们把规则改窄,**不拿基线去洗规则**);
|
||||
**R2** `*_TIMEOUT` 宏不得取负值(名字叫 TIMEOUT 却是返回码 → 一律改 `BSP_ERR_TIMEOUT`);
|
||||
**R3** 非 void 的公开 API 必须有「返回值:」注释(约定要能被读到才谈得上审查) |
|
||||
**R3** 非 void 的公开 API 必须有「返回值:」注释(约定要能被读到才谈得上审查;匹配时**忽略空格**,
|
||||
因为规范 V1.0 允许列对齐写法「返 回 值:」——门禁去规定排版会把合规注释判成违规,实测就有两条因为
|
||||
**函数说明**里顺口出现"返回值"三个字而误判通过);
|
||||
**R4** 返回错误码的函数,调用点必须**接住返回值**或**显式 `(void)` 丢弃**(裸调用即违规)。must-use
|
||||
名单**自动取**、不手写:① 返回 `bsp_err_t` 的公开 API;② 返回 `int`/`int32_t` 且文档块出现"错误码 /
|
||||
失败 / BSP_ERR / `_FAIL`"的函数;③ 已知返回 `HAL_StatusTypeDef` 的 HAL 传输/读写族。**名单必须同时
|
||||
覆盖 `.c` 里的 static 定义**——只扫头文件时 `gd5f_set_feature` 这类 static 原语在名单之外,等于只守
|
||||
跨编译单元的边界、看不见编译单元内部的丢弃(实测漏掉后靠人工才发现一处 ECC 丢弃)。豁免两类形状:
|
||||
**谓词**(`is_/has_/can_/should_/need_/valid_`)与 **setter**(`xxx_set_yyy`,实跑误判出 `net_set_errno`
|
||||
八处)——同 R1 的原则:**规则按真实反例收窄,不拿基线洗假阳性**。已知限度:只认**单行整句**的裸调用
|
||||
(`foo(...);` 一行写完,行尾注释允许),跨行写的调用暂测不到 |
|
||||
| **范围** | 只扫 `git ls-files` 里 `Drivers/BSP/**/*.h`(对外 API 面);**lftpd 按第三方排除**——
|
||||
它的 `226/425/450/550` 是 FTP 协议码不是内部错误码;**`net_*` BSD 兼容层不纳入**(用户裁定
|
||||
2026-10-23):调用方要的就是"返回字节数 + 每任务 errno 槽"那个形状,模拟器的 Winsock
|
||||
后端也照同一形状实现 |
|
||||
| **增量拦截** | 存量 **1 条**(首清点 19,2026-10-23 已还 18)钉 `BASELINE`(首清点 19 条:2 个 `*_BUSY_TIMEOUT = -2` + 16 个缺「返回值:」+ 1 个 bool;**现仅剩
|
||||
`bool ui_content_page_open()` 一条**——它需要改签名并处理 3 个调用点,与"还注释"不是一档事),**只减不增**、脚本没有 `--write`;修完跑 `--prune` 会点名"这条已消失,
|
||||
| **增量拦截** | 存量 **38 条**钉 `BASELINE`(首清点 19,已还 18(首清点 19 条:2 个 `*_BUSY_TIMEOUT = -2` + 16 个缺「返回值:」+ 1 个 bool;**现仅剩
|
||||
`bool ui_content_page_open()` 一条**——它需要改签名并处理 3 个调用点,与"还注释"不是一档事)。**R4 是同日新加的一条,上线即暴露 37 条存量丢弃**(`gd5f2gq5ue.c` 29 处:14 处
|
||||
丢弃 `HAL_SPI_*` 状态 + 15 处丢弃自家原语;`NET/net_socket.c` 8、`UI/ui_net_sink.c` 4 处 `net_close`、
|
||||
`RS485/rs485.c` 2、`nand_ftl.c` 1)——这些是**覆盖面扩大而新暴露的历史债**,按增量拦截的老规矩入基线
|
||||
(不算"新增违规"),修一条删一行。**只减不增**、脚本没有 `--write`;修完跑 `--prune` 会点名"这条已消失,
|
||||
请从基线删除" |
|
||||
| **配置** | `files: ^Drivers/BSP/\|^scripts/check_bsp_err\.py$\|^\.pre-commit-config\.yaml$`、
|
||||
`pass_filenames: false`(恒扫全库,要按 git 清单建公开头索引) |
|
||||
| **实测负结果(顺手记一条)** | `__attribute__((warn_unused_result))` **在 ARMCC v5 上不生效**:
|
||||
属性挂上、调用点裸调不接返回值,构建仍 0 错 0 警告。所以"返回值必须被消费"只能靠
|
||||
本脚本 + 书写约定"故意丢弃必须写 `(void)`",评审时看到既没 `(void)` 也没接住的调用就是漏判嫌疑 |
|
||||
| **为什么 R4 只能自己做**(两条实测负结果) | ① `__attribute__((warn_unused_result))` **在 ARMCC v5 上
|
||||
不生效**:属性挂上、调用点裸调不接返回值,构建仍 0 错 0 警告。② **cppcheck 也照不出来**:按本仓自己的
|
||||
`--enable=warning,style,performance,portability` 跑 `gd5f2gq5ue.c`,对 14 处丢弃 `HAL_SPI_*` 返回值、以及
|
||||
"未初始化局部量直接进 `P_FAIL` 判定"都**一条不报**(它假定 `gd5f_read_status(&status)` 会写出参,而失败
|
||||
路径根本不写)。**所以"丢弃底层传输的返回值"今天没有任何工具会响**,只能靠本脚本 + 书写约定"故意丢弃
|
||||
必须写 `(void)`";评审时看到既没 `(void)` 也没接住的调用就是漏判嫌疑 |
|
||||
| **踩坑提醒** | pre-commit 会 **stash 未暂存改动**再跑钩子。所以"改代码 + 同时更新基线"要在
|
||||
一次提交里**把改动 `git add` 了再跑**,否则钩子看到的是没有你改动的树,会假报警 |
|
||||
| **运行器** | `scripts/check_bsp_err.py`(纯标准库;`--verbose` 列全部命中归类、`--prune` 只报
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
> `data/ram_report_20261022.md` / `data/stack_report_20261022.md` 两份新快照。
|
||||
> 变更:2026-10-23 补 `data/ram_report_20261023.md` 快照(S-5 试点:RS485 改报 `bsp_err_t`,
|
||||
> `Code` 213,436 → **213,648**(S-5 全波 +212:契约试点 +48、C3 SD2506 +44、C1 GD5F/TPAFE +36、
|
||||
C2 dhara 失败类 +84;RO 另 +208,全是 C2 的失败类名表)→ `ER_IROM1` **232,508 B / 22.2%**;
|
||||
C2 dhara 失败类 +84;RO 另 +208,全是 C2 的失败类名表)→ `ER_IROM1` **232,536 B / 22.2%**;
|
||||
> **RAM 全部字段零增量**;受管表已由
|
||||
> `check_mem_numbers.py --write` 同步,配图常量同步)。
|
||||
> 变更:v1.2 数据现状全量同步——§2.1/§2.2/§5/§6/§8.6 等"现状"数据全部更新为 2026-09-21 lftpd 静态化后的最新 map 与实测值;清除 2026-09-11 历史口径残留(历史快照保留于 `data/`)
|
||||
@@ -43,10 +43,10 @@ C2 dhara 失败类 +84;RO 另 +208,全是 C2 的失败类名表)→ `ER_IR
|
||||
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
|
||||
| 区域 | 用量 | 容量 | 占比 |
|
||||
|---|---|---|---|
|
||||
| ER_IROM1 | 232,508 B (227.06 KB) | 1,048,576 B (1024 KB) | 22.2% |
|
||||
| ER_IROM1 | 232,536 B (227.09 KB) | 1,048,576 B (1024 KB) | 22.2% |
|
||||
| RW_IRAM1 | 75,264 B (73.50 KB) | 131,072 B (128 KB) | 57.4% |
|
||||
| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
|
||||
| **Flash (ROM 合计)** | **233,696 B (228.2 KB)** | 1,048,576 B (1024 KB) | **22.3%** |
|
||||
| **Flash (ROM 合计)** | **233,724 B (228.2 KB)** | 1,048,576 B (1024 KB) | **22.3%** |
|
||||
<!-- MEM_SNAPSHOT:END -->
|
||||
|
||||
各区的容量与常量来源:
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- MEM_BUDGET:BEGIN generated by scripts/ram_baseline.py -->
|
||||
| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |
|
||||
|---|---|---|---|---|
|
||||
| ER_IROM1 (Flash) | 232,508 B | 1,048,576 B | 22.2% | 参考 |
|
||||
| ER_IROM1 (Flash) | 232,536 B | 1,048,576 B | 22.2% | 参考 |
|
||||
| RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS |
|
||||
| UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 |
|
||||
| RW_IRAM1 | 75,264 B | 131,072 B | 57.4% | PASS |
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# STM32F4-Base RAM/Flash Usage Report
|
||||
|
||||
> Generated: 2026-10-23 01:35 Map: `STM32F407-Demo.map`
|
||||
> Generated: 2026-10-23 08:53 Map: `STM32F407-Demo.map`
|
||||
|
||||
## 1. Grand Totals (全局总量)
|
||||
|
||||
| Metric | Value |
|
||||
|---|---|
|
||||
| Code (inc. data) | 213,648 B (208.6 KB) |
|
||||
| Code (inc. data) | 213,676 B (208.7 KB) |
|
||||
| RO Data | 18,860 B (18.4 KB) |
|
||||
| RW Data (initialized) | 1,188 B (1.16 KB) |
|
||||
| ZI Data (zero-init) | 131,500 B (128.4 KB) |
|
||||
| **Total RO (Code + RO)** | **232,508 B (227.1 KB)** |
|
||||
| **Total RO (Code + RO)** | **232,536 B (227.1 KB)** |
|
||||
| **Total RW (RW + ZI) = SRAM used** | **132,688 B (129.58 KB)** |
|
||||
| **Total ROM (Code + RO + RW init)** | **233,696 B (228.2 KB)** |
|
||||
| **Total ROM (Code + RO + RW init)** | **233,724 B (228.2 KB)** |
|
||||
|
||||
## 2. 执行区水位 (Execution Regions)
|
||||
|
||||
| Region | Base | Size | Max | Util% |
|
||||
|---|---|---|---|---|
|
||||
| ER_IROM1 | 0x08000000 | 232,508 B (227.06 KB) | 1,048,576 B (1024 KB) | 22.2% |
|
||||
| ER_IROM1 | 0x08000000 | 232,536 B (227.09 KB) | 1,048,576 B (1024 KB) | 22.2% |
|
||||
| RW_CCM | 0x10000000 | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
|
||||
| UNINIT_CCM | 0x1000FF00 | 48 B (0.05 KB) | 256 B (0 KB) | 18.8% |
|
||||
| RW_IRAM1 | 0x20000000 | 75,264 B (73.50 KB) | 131,072 B (128 KB) | 57.4% |
|
||||
@@ -150,7 +150,7 @@
|
||||
| 14 | cfg_file_store_mcu.o | 380 | 24 | 0 | 1,104 | 1,104 |
|
||||
| 15 | soe_store.o | 816 | 28 | 20 | 1,064 | 1,084 |
|
||||
| 16 | startup_stm32f407xx.o | 36 | 392 | 0 | 1,024 | 1,024 |
|
||||
| 17 | gd5f2gq5ue.o | 3,954 | 478 | 20 | 800 | 820 |
|
||||
| 17 | gd5f2gq5ue.o | 3,982 | 478 | 20 | 800 | 820 |
|
||||
| 18 | iec104_serv.o | 1,188 | 16 | 16 | 712 | 728 |
|
||||
| 19 | cfg_file.o | 5,970 | 810 | 20 | 704 | 724 |
|
||||
| 20 | spi.o | 584 | 0 | 0 | 560 | 560 |
|
||||
@@ -204,7 +204,7 @@
|
||||
| 68 | vol_lock.o | 92 | 0 | 4 | 0 | 4 |
|
||||
| 69 | errno.o | 20 | 0 | 4 | 0 | 4 |
|
||||
| 70 | ui_page_net_cfg.o | 1,004 | 105 | 2 | 0 | 2 |
|
||||
| | **All .o files** | **213,648** | **18,860** | **1,188** | **131,500** | **132,688** |
|
||||
| | **All .o files** | **213,676** | **18,860** | **1,188** | **131,500** | **132,688** |
|
||||
|
||||
## 5. Flash (Code + RO Data) Top-30(按大小降序)
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
| 7 | ui_font_cn_12.o | 0 | 4,545 | 4,545 |
|
||||
| 8 | lv_obj_pos.o | 4,526 | 16 | 4,542 |
|
||||
| 9 | lv_refr.o | 4,486 | 0 | 4,486 |
|
||||
| 10 | gd5f2gq5ue.o | 3,954 | 478 | 4,432 |
|
||||
| 10 | gd5f2gq5ue.o | 3,982 | 478 | 4,460 |
|
||||
| 11 | tasks.o | 4,342 | 0 | 4,342 |
|
||||
| 12 | lv_obj_scroll.o | 4,126 | 0 | 4,126 |
|
||||
| 13 | lv_obj_style.o | 4,106 | 0 | 4,106 |
|
||||
@@ -240,6 +240,6 @@
|
||||
| 28 | printfa.o | 2,312 | 0 | 2,312 |
|
||||
| 29 | stm32f4xx_hal_i2c.o | 2,294 | 0 | 2,294 |
|
||||
| 30 | lv_display.o | 2,284 | 0 | 2,284 |
|
||||
| | **All .o files** | **213,648** | **18,860** | **232,508** |
|
||||
| | **All .o files** | **213,676** | **18,860** | **232,536** |
|
||||
|
||||
> 自洽校验:per-file 213,648/18,860/1,188/131,500 vs Grand Totals 213,648/18,860/1,188/131,500(CodeΔ=+0 / ROΔ=+0 / RWΔ=+0 / ZIΔ=+0;精确一致(含 '('incl. Generated)'-'(incl. Padding)' 台账行))→ **PASS**
|
||||
> 自洽校验:per-file 213,676/18,860/1,188/131,500 vs Grand Totals 213,676/18,860/1,188/131,500(CodeΔ=+0 / ROΔ=+0 / RWΔ=+0 / ZIΔ=+0;精确一致(含 '('incl. Generated)'-'(incl. Padding)' 台账行))→ **PASS**
|
||||
|
||||
+21
-2
@@ -79,8 +79,6 @@
|
||||
- 这属于**动作 D(清文件)**,与本文 §1 的 A(重建 BBT + 格式化)/ B(全片擦除)/ C(容量恢复)
|
||||
都不同:A/B 会丢卷内容,D 不动文件系统结构。
|
||||
|
||||
## 5. 变更记录
|
||||
|
||||
### 4.2 自检台账清零,重建 S7 审计基线(2026-10-22 实测)
|
||||
|
||||
`@test --require-selftest-pass --selftest-scope all`(累计口径)在台架上**永远 FAIL**:
|
||||
@@ -106,8 +104,29 @@
|
||||
(清零前这条是 `29 fault record(s)` FAIL)。设备侧无此文件时 lftpd 回 450,被按"台账干净"
|
||||
处理,这条映射见 `../架构设计/STM32F4-Base存储架构说明.md` §10.3 与 S7 判定表。
|
||||
|
||||
### 4.3 恢复流程里的 ECC 开关:不能只看"跑完了"(2026-10-23)
|
||||
|
||||
动作 A/B 的第一步是 `gd5f2gq5ue_bbt_rebuild()`:临时**关掉 ECC** 才能读原始出厂坏块标记,扫完
|
||||
必须**重新打开并验证真的生效**。这一"关—开"以前是两条**裸调用**(返回值全丢),于是存在一条
|
||||
静默路径:**SPI 抖一下 → ECC 没能重新打开 → 设备以为恢复完成,之后所有 NAND 读写都在无位翻转
|
||||
保护下运行**,而且 `gd5f_check_ecc()` 在 ECC 关闭时恒读"无 ECC 错误",整条链不会再有任何信号。
|
||||
|
||||
- 现在(2026-10-23 改)关 ECC 失败会**立即中止**(此刻 ECC 仍开着,是安全侧;带着 ECC 去扫 spare 反而会把
|
||||
厂标好块误判成坏块,"重建 BBT"变成制造坏块),重开失败则复用 init 的 **E-10** 做法**回读 B0h 校验
|
||||
`ECC_EN` 位**,"写了但没生效"与写失败同罪,一律返回错误。
|
||||
- **运维判据**:串口/`run.log` 里出现 `BBT rebuild: ECC restore FAILED` 或 `ECC not enabled (B0h=…)`
|
||||
→ 本次恢复**不算完成**,设备处于无 ECC 保护态,必须**断电重启**让 init 重走一遍并使回读校验通过,
|
||||
不要接着跑 `nand_ftl_format()` 当作已修好。反之 `BBT rebuilt and persisted` 才代表扫描 + 使能 +
|
||||
持久化三件事都成了。
|
||||
- 另记一条定位事实:`gd5f2gq5ue_bbt_rebuild()` 在产品镜像里**不被链接**(map 明写 `Removing …
|
||||
(604 bytes)`,产品构建无调用者),只有本动作 A/B 的恢复构建会把它链进去——所以这条坑只在
|
||||
**做恢复的时候**才存在,也正因如此平时不会有迹象。
|
||||
|
||||
## 5. 变更记录
|
||||
|
||||
| 日期 | 变更 |
|
||||
|---|---|
|
||||
| 2026-09-21 | 新建:A/B/C 三个维护动作;容量恢复原理(dhara checkpoint 坏块计数不清零)与全片擦除恢复路径(实测 95200 → 96064) |
|
||||
| 2026-10-22 | 加 §4.1「根目录残留文件清理」(动作 D,与 A/B/C 区分):台架实测 27 个探针残留文件 / 262 KB 已清;判据 = 只删显式点名、保留 `/config.ini`、`/PROT_SET.BIN`、`/log`;清后 `@test` PASS + LIST 完整性回归 PASS |
|
||||
| 2026-10-22 | 加 §4.2「自检台账清零,重建 S7 审计基线」:29 条历史记录(16 × `watchdog reset` + 13 × `heap low water`,10-10 → 10-14,两案均已结案)按用户决定删除;安全判据 = `sys_log_mcu.c` 每条记录开-写-关、不持常驻句柄;`run.log`/`wdev.log`/`soe.log` 属产品数据不动;顺带删掉孤儿 `/log/flushchk.bin`(32 KB、0..255 图案的写盘校验填充、全库零引用,删前留档);清后 `this-run` 与 `all` 两条判定路径都 PASS(清零前 `all` 是 29 条 FAIL) |
|
||||
| 2026-10-23 | 加 §4.3:恢复流程的 ECC 开关改为"失败即中止 + 回读 B0h 验生效"——S-5 R4 上线照出来的第一处静默降级;给出运维判据——出现 `ECC restore FAILED` / `ECC not enabled` 即本次恢复不算完成,须断电重启重走 init;并记明该函数在产品镜像中不被链接(`Removing … 604 bytes`),只有恢复构建才有这条路径。顺带修正本文结构:`## 5. 变更记录` 原先误插在 §4.1 与 §4.2 之间,已移到文末(原位置会让 §4.2 变成 §5 的子节) |
|
||||
|
||||
@@ -504,7 +504,7 @@ $env:DTU_KEIL_UV4 = 'D:\NotExist\UV4.exe' # 仅当前会话,不动用户级
|
||||
|
||||
| 资源 | 已用 | 总量 | 利用率 | 余量 | 红线说明 |
|
||||
|---|---|---|---|---|---|
|
||||
| Flash(`ER_IROM1` = Code + RO) | 232,508 B(227.06 KB) | 1 MB | 22.2% | ≈804 KB | **充裕**:产品需求无 OTA / 双镜像预算,Flash 不是卡点;死代码裁剪簇已收口 → `docs/问题记录/项目审查与优化建议报告.md` §5.4 |
|
||||
| Flash(`ER_IROM1` = Code + RO) | 232,536 B(227.09 KB) | 1 MB | 22.2% | ≈804 KB | **充裕**:产品需求无 OTA / 双镜像预算,Flash 不是卡点;死代码裁剪簇已收口 → `docs/问题记录/项目审查与优化建议报告.md` §5.4 |
|
||||
| 主 SRAM1(静态区;FreeRTOS 堆已迁 CCM) | 75,264 B(73.5 KB) | 128 KB | 57.4% | 55,808 B | 已不紧张——2026-10-11 堆迁 CCM 与 2026-10-15 `LV_MEM_SIZE` 40→16 KB 两步的结果 |
|
||||
| CCM(`RW_CCM` 段) | 57,376 B(56.0 KB) | 65,280 B | **87.9%** | **7,904 B** | **当前真正的红线**:加任务 / 抬栈 / 加堆会先在这里撞墙;`mem-budget` 钩子在 92% 拦提交 |
|
||||
|
||||
|
||||
@@ -55,7 +55,13 @@
|
||||
`net_msg_queue_adopt()` 绑定(创建点不能外移——`osKernelInitialize()` 之前的创建类 API 会杀死启动;**故意不新建第二个队列**:那会白占 CCM 里 8×`net_msg_t`
|
||||
的堆空间,而 CCM 正是当前红线)。**两类从来不算债**:`stm32f4xx_it.c:241-256` 是 CubeMX「External variables」生成块;`:183/195/207/220` 是 `__asm` Handler
|
||||
里的汇编标签引用(ARMCC `__asm` 取不到 C 数据符号)。 | 无(后续由 `layer-deps` 与 `cubemx-survival` 两条门禁守着不回退:新增 `net-msgq-adopt` 存活项) |
|
||||
| 驱动规范 | **S-5 🟡 主体已落地**(2026-10-23:契约 + 门禁 + RS485/SD2506/TPAFE 收编 + GD5F 改名 + dhara 三类码) | 我原先写的"无统一错误码"**不准**,实测是 **六套并存**:0/−1(SD2506、NETCFG、nand_ftl)、自研枚举 `CH395F_STATUS_*`、**芯片寄存器原生码** `CH395F_ERR_*`(与前一套同模块并存)、`HAL_StatusTypeDef`(`rs485.h` 曾直接暴露)、`bool`,外加第三方 dhara 出参 `dhara_error_t` 与 FatFs `FRESULT`。超时侧是**同形两义**:`SD2506_I2C_TIMEOUT_MS` 带单位后缀而 `GD5F_SPI_TIMEOUT 100` 不带(**逐行核过:它也是毫秒**,我先前记成"自旋圈数"是错的)、`GD5F/TPAFE5160_BUSY_TIMEOUT = -2` 其实是**返回码**;`osWaitForever` 与 `HAL_MAX_DELAY` **同为 0xFFFFFFFFU**(值同域不同,跨层转手不报错也不变慢)。真正值钱的不是码名,是"**能不能重试**"以前只写在个别注释里 | `Drivers/BSP/bsp_err.h`(header-only,含 `BSP_ERR_CAN_RETRY`)+ `bsp-err` 钩子(三条规则,基线 **19 → 1**);已收编 **RS485(HAL 枚举不再外泄)/ SD2506(11 个公共 API,I2C 超时终于归成可重试)/ TPAFE5160(含 E-44 的 FRSTDATA → `BSP_ERR_NO_DEVICE`)**,GD5F 的 `GD5F_BUSY_TIMEOUT` 改名 `GD5F_WAIT_EXPIRED` 消掉同形两义,FTL 坍缩点按 **ECC / 预算耗尽 / 完整性** 三类就地分类并打可读日志(§10.4)。`net_*` BSD 层与 `tpafe5160_snapshot()` 三态按裁定**不纳入**。**待还**:GD5F 私有码集整体收编(169 处、含板级套件 48 处,需真机 + 套件回归)、C4 失败类快照(让卷健康探针按类分支)、仅 `bool ui_content_page_open()` 一条(需改签名 + 处理 3 个调用点,与还注释不是一档事) |
|
||||
| 驱动规范 | **S-5 🟡 主体已落地**(2026-10-23:契约 + 门禁 + RS485/SD2506/TPAFE 收编 + GD5F 改名 + dhara 三类码) | 我原先写的"无统一错误码"**不准**,实测是 **六套并存**:0/−1(SD2506、NETCFG、nand_ftl)、自研枚举 `CH395F_STATUS_*`、**芯片寄存器原生码** `CH395F_ERR_*`(与前一套同模块并存)、`HAL_StatusTypeDef`(`rs485.h` 曾直接暴露)、`bool`,外加第三方 dhara 出参 `dhara_error_t` 与 FatFs `FRESULT`。超时侧是**同形两义**:`SD2506_I2C_TIMEOUT_MS` 带单位后缀而 `GD5F_SPI_TIMEOUT 100` 不带(**逐行核过:它也是毫秒**,我先前记成"自旋圈数"是错的)、`GD5F/TPAFE5160_BUSY_TIMEOUT = -2` 其实是**返回码**;`osWaitForever` 与 `HAL_MAX_DELAY` **同为 0xFFFFFFFFU**(值同域不同,跨层转手不报错也不变慢)。真正值钱的不是码名,是"**能不能重试**"以前只写在个别注释里 | `Drivers/BSP/bsp_err.h`(header-only,含 `BSP_ERR_CAN_RETRY`)+ `bsp-err` 钩子(**四条规则**,基线 19 → 1 → **38**:R4 上线又暴露 37 条存量丢弃);已收编 **RS485(HAL 枚举不再外泄)/ SD2506(11 个公共 API,I2C 超时终于归成可重试)/ TPAFE5160(含 E-44 的 FRSTDATA → `BSP_ERR_NO_DEVICE`)**,GD5F 的 `GD5F_BUSY_TIMEOUT` 改名 `GD5F_WAIT_EXPIRED` 消掉同形两义,FTL 坍缩点按 **ECC / 预算耗尽 / 完整性** 三类就地分类并打可读日志(§10.4)。`net_*` BSD 层与 `tpafe5160_snapshot()` 三态按裁定**不纳入**。**已修第一处静默降级**(2026-10-23):`gd5f2gq5ue_bbt_rebuild()` 的 ECC 关闭/恢复不再裸丢弃,并补 E-10 同款**回读
|
||||
B0h 验 `ECC_EN`**——原先那两行的注释自己写着"否则后续 I/O 在无 ECC 下运行",风险却正落在它下面那行。
|
||||
**待还**:GD5F 私有码集整体收编(169 处、含板级套件 48 处,需真机 + 套件回归)、C4 失败类快照(让卷
|
||||
健康探针按类分支)、`bool ui_content_page_open()` 一条(需改签名 + 处理 3 个调用点,与还注释不是一档事)、
|
||||
**37 条丢弃点的收编**(已入基线只减不增)、**"host 侧失败也标坏块"的策略修正**(`dhara_nand_erase`/`dhara_nand_prog`
|
||||
把 host 侧 SPI 失败与 DMA 等待超时也标成坏块,而 dhara 只在 `DHARA_E_BAD_BLOCK` 才 retire;改它得先定
|
||||
"host 侧失败给哪个码",见变更记录) |
|
||||
| 网络 | 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 同批评估 |
|
||||
| 存储/日志 | P2-10 ❌(N-25) | 卷锁现有 5 个使用者(配置原子写 / 日志 / SOE / lftpd_io / defaultTask),容量轮转删除与 UI 读并发仍未全覆盖 | 登记簿 S-5 面(卷锁覆盖面) |
|
||||
@@ -93,7 +99,7 @@ git ls-files -z | xargs -0 stat -c '%s'
|
||||
|
||||
| 名词 | 口径 |
|
||||
|---|---|
|
||||
| Flash 占用 | `Code + RO-data` = `ER_IROM1` = **232,508 B(22.2%)**;`ROM 合计` 再加 `RW` 初始化表 = 233,696 B(22.3%) |
|
||||
| Flash 占用 | `Code + RO-data` = `ER_IROM1` = **232,536 B(22.2%)**;`ROM 合计` 再加 `RW` 初始化表 = 233,724 B(22.3%) |
|
||||
| SRAM 占用 | `RW_IRAM1`(DMA 可达区)与 `RW_CCM`(仅 CPU)分开计,二者不可互换(规则 R2/R3) |
|
||||
| 最坏栈 | `max(armlink 静态调用图深度, 真机 [STACK] 高水位)`;判定线 `余量 ≥ max(1024 B ISR, 配置×30%)` |
|
||||
| 编译单元 | uvprojx 的 `<FilePath>` 计数(今日 **326 个 `.c`**,其中 LVGL 201);"自研 `.c`" 另按目录口径 114 个 |
|
||||
@@ -230,7 +236,7 @@ defaultTask 单属主;原子写经卷锁;旧档迁移已删除。**仍列为
|
||||
|
||||
| 指标 | 2026-10-23 | 2026-10-15 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `Code` | 213,648 B | 213,520 B | 10-23 S-5 全波 +212:契约试点 +48、C3 SD2506 迁移 +44、C1 GD5F/TPAFE 收编 +36、C2 dhara 失败类 +84(RO 另 +208 = 失败类名表);10-22 当日累计:F-6 −332、SPI 回调 +16、消息队列 +32、FTP 日志级别 +28(RO 另 +72)、LIST 满块续发 +172 |
|
||||
| `Code` | 213,676 B | 213,520 B | 10-23 S-5 全波 +212:契约试点 +48、C3 SD2506 迁移 +44、C1 GD5F/TPAFE 收编 +36、C2 dhara 失败类 +84(RO 另 +208 = 失败类名表);ECC 回读校验(恢复构建路径)+28(见变更记录:该函数在产品镜像里被链接器 Removing,28 B 非它带来);10-22 当日累计:F-6 −332、SPI 回调 +16、消息队列 +32、FTP 日志级别 +28(RO 另 +72)、LIST 满块续发 +172 |
|
||||
| `ER_IROM1`(Code+RO) | **232,508 B / 22.2%** | 232,280 B / 22.2% | 余 ≈803 KB;**RAM 三项 10-23 零增量** |
|
||||
| `RW_IRAM1` | **75,264 B / 57.4%**(余 55,808) | 73,568 B / 56.1% | 增量来自 B5/B8 功能码 |
|
||||
| `RW_CCM` | **57,376 B / 87.9%**(余 7,904) | 57,376 B / 87.9% | **当前唯一红线** |
|
||||
@@ -271,7 +277,7 @@ defaultTask 单属主;原子写经卷锁;旧档迁移已删除。**仍列为
|
||||
| **F-6** 双精度软浮点 | ≈1 KB | **归因错**:全库 0 处 `%f`;剩余 `dadd/dmul/ddiv/depilogue/dfixul` 1,018 B 锁在 MicroLIB `printfa.o` 的 `_printf_core → _fp_digits`,只要用 `snprintf` 就删不掉。但**根因侧确有可修点**:`App/algo/prot_set.h` 两个 Q10 宏写成 `double` | ✅ **已落地 2026-10-22**:改单精度 → `@build` −332 B、5 个 helper(300 B)消失;数值逐位等价(穷举 42 个字面量 + int32 全域 ÷1024 往返 4.49×10⁶ 例零差异);真机 `@test` PASS |
|
||||
|
||||
**当前可回收 Flash = 0 B**(F-4/F-6 已定论,图片链同理不打补丁)。LVGL 仍占镜像 **37.8%**
|
||||
(87,706 / 232,508 B)——这是"用 LVGL 画单色菜单"的结构性代价,F-1/F-2/F-3 已省掉 64,576 B。
|
||||
(87,706 / 232,536 B)——这是"用 LVGL 画单色菜单"的结构性代价,F-1/F-2/F-3 已省掉 64,576 B。
|
||||
|
||||
### 5.5 内存治理长效机制(常开,不受暂缓影响)
|
||||
|
||||
@@ -324,7 +330,7 @@ W6 簇按 U4 → U1 → U3 → U2 的顺序执行完毕(U2 停在"够用即止
|
||||
| 波次 | 本报告条目(今天状态) | 备注 |
|
||||
|---|---|---|
|
||||
| ~~W3 预算与内存~~ ⏸ | R-9 ✅ / R-2 后半、R-3、R-4、R-6 暂缓 | 暂缓期间无验收动作,观测照常 |
|
||||
| W4 结构债 | N-14 ⏸、F-5 🟡、S-1/S-2/S-4/S-5、N-25 | `--strict` 已默认;S-5 契约/门禁已落地并收编三模块(基线 19→1,剩 GD5F 码集收编与 C4 快照——均经论证暂不做) |
|
||||
| W4 结构债 | N-14 ⏸、F-5 🟡、S-1/S-2/S-4/S-5、N-25 | `--strict` 已默认;S-5 契约/门禁已落地并收编三模块,R4 已把"丢弃返回值"纳入机械检查(基线 19→1→38;剩 GD5F 码集收编、C4 快照、37 条丢弃点、标坏策略) |
|
||||
| W5 验证常态 | 覆盖率、`malloc` 正则、TC 差异 13 处升门禁 | 逢窗口顺手做 |
|
||||
| W6 UI 扩展 | U2 残余、U5 页量 | 随产品需求,不再单列专项 |
|
||||
| W7 仓库决策 | D-1(N-29) | 已决策暂不处理;对外交付前重评 |
|
||||
@@ -383,7 +389,7 @@ W6 簇按 U4 → U1 → U3 → U2 的顺序执行完毕(U2 停在"够用即止
|
||||
| **S-2** | 跨模块裸 `extern` | ✅ **已闭环 2026-10-22**(24 处手写全消;两类本就不算债见 §0.4) | 本文变更记录 2026-10-22 三行;契约见 `App/task/task_handles.h`、`gd5f_spi1_notify_*`、`net_msg_queue_adopt` |
|
||||
| **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` 错误码与超时命名约定 | 🟡 主体已落地(2026-10-23:契约 + `bsp-err` 钩子 + RS485/SD2506/TPAFE 收编 + GD5F 改名 + dhara 三类码;基线 19 → 1) | 本文 §0.4、`pre-commit使用说明.md` §2.27、`STM32F4-Base存储架构说明.md` §10.4、`Drivers/BSP/bsp_err.h` |
|
||||
| **S-5** | 统一 `bsp_err_t` 错误码与超时命名约定 + **返回值不得裸丢弃** | 🟡 主体已落地(2026-10-23:契约 + `bsp-err` 四规则 + RS485/SD2506/TPAFE 收编 + GD5F 改名 + dhara 三类码 + R4 照出 37 条丢弃 + ECC 回读校验;基线 19 → 1 → 38) | 本文 §0.4、`pre-commit使用说明.md` §2.27、`STM32F4-Base存储架构说明.md` §10.4、`Drivers/BSP/bsp_err.h` |
|
||||
| R-1 ~ R-9 | 内存优化项(R-9 已落地、R-5 判定不可行、其余随簇暂缓) | 见 §5.3 | 本文 §5.3、`../内存管理/RAM预算台账.md` |
|
||||
| F-1 / F-2 / F-3 | LVGL 死代码裁剪,省 64,576 B | ✅ 已落地 2026-10-11 | `../内存管理/RAM使用分析与优化方案.md` §2.6.4 |
|
||||
| **F-4 / F-5 / F-6** | Flash 双精度与死代码簇 | ✅/🟡/❌ 见 §5.4 | 本文 §5.4、`App/algo/prot_set.h` 注释 |
|
||||
@@ -442,6 +448,34 @@ admin/admin(SHA-256 `pwd_hash`)→ 该脚本**必然登录失败**;它是
|
||||
| | 数字联动照做:两份 `data/` 快照重跑、`ram_baseline --update/--write`、`check_mem_numbers --write`、FLASH 与
|
||||
任务栈两张配图重算重生成(逐文本复查越界 = 0)、本文 §1.3/§5.1/§5.4 与部署文档 §3.3 同步;§0.4 的 S-2 行按
|
||||
「完成即销项」改写、§9 拆出 S-2 行标 ✅。 |
|
||||
| **2026-10-23** | **S-5 第三波**:给 `bsp-err` 加 **R4(返回值不得裸丢弃)**,并修掉它照出来的第一处
|
||||
| | ECC 静默降级 | 用户裁定"B 按你说的进行"(先上 R4,再修最小最值的那处)。R4 之所以必须自己做,是两条实测
|
||||
| | 负结果:`warn_unused_result` 在 ARMCC v5 不生效;cppcheck 按本仓 `--enable` 跑同一文件,对 14 处丢弃
|
||||
| | `HAL_SPI_*` **一条不报**(它还假定 `gd5f_read_status(&status)` 会写出参,而失败路径根本不写)。上线即照出
|
||||
| | **37 条存量丢弃**:`gd5f2gq5ue.c` 29(14 处 HAL + 15 处自家原语)、`net_socket.c` 8、`ui_net_sink.c` 4(`net_close`)、
|
||||
| | `rs485.c` 2、`nand_ftl.c` 1——按增量拦截老规矩**入基线只减不增**(覆盖面扩大新暴露的历史债,不是新增违规)。
|
||||
| | **R4 自身被修三次**:① 首版漏判 `foo(); /* 注释 */` 这种**行尾带注释**的裸调用(正则 `\s*$` 卡死),而那
|
||||
| | 恰是最常见的"带说明的丢弃"→ 补可选注释分支并做 6 条自检;② 把 `net_set_errno` 八处误判成丢弃(它是 setter,
|
||||
| | 返回的 int 是状态回声不是调用成败)→ **按真实反例收窄规则**(谓词 + setter 豁免),不塞基线洗掉;③ 名单
|
||||
| | 只从**头文件**取,`gd5f_set_feature` 这类 **static** 原语整个在视野外——而上面那处 ECC 丢弃恰恰是 static、靠人工才发现
|
||||
| | → 名单扩到 `.c` 内 static 定义,补完立刻又照出 `gd5f_bbt_save#1`(运行时标坏后 BBT 落盘结果被丢弃 = 记账
|
||||
| | 可能没持久化;已入基线记为待还,本步不动行为)。
|
||||
| | **这处为什么值得修**:`bbt_rebuild` 注释写着"无论扫描成败都须恢复 ECC,否则后续 I/O 在无 ECC 下运行",
|
||||
| | 而它下面 `gd5f_set_feature(0xB0,…)` + `gd5f_wait_busy(100)` **返回值全丢**:SPI 一抖 ECC 就保持关闭,且
|
||||
| | `gd5f_check_ecc()` 在 ECC 关闭时恒读"无错"——整条链再无信号。补法复用 init 路径的 **E-10**(写完回读 B0h 验
|
||||
| | `ECC_EN`,"写了但没生效"与写失败同罪),并把"关 ECC 失败"改成**立即中止**(此时 ECC 仍开着,是安全侧;
|
||||
| | 继续扫反而会在 ECC 语义下读 spare、把厂标好块误判成坏块,"重建 BBT"变成制造坏块)。
|
||||
| | **一条定位纠正(差点把修复记大)**:查链接映射发现 `Removing gd5f2gq5ue.o(i.gd5f2gq5ue_bbt_rebuild),
|
||||
| | (604 bytes)`——**该函数在产品镜像里根本没被链接**(产品构建无调用者),只由 `ENABLE_STORAGE_RECOVERY_TESTS`
|
||||
| | 的**恢复构建**经 testTask 调用。所以本次修的是**恢复流程自身的安全**(跑恢复时若 ECC 没恢复,设备会带着
|
||||
| | "已恢复"的结论在无保护状态下继续跑),不是现场日常路径;相应地镜像 `Code` 的 +28 B 也**不是**它带来的(未逐字节
|
||||
| | 追,线索是 `gd5f_private_get_feature` 由单调用点变多调用点、内联决策可能变化)。因此验证不能只跑产品构建:
|
||||
| | 临时打开 `TEST_SUITE_STORAGE` + `ENABLE_STORAGE_RECOVERY_TESTS` 编一次(**0 错 0 警告且该函数不再出现在
|
||||
| | Removing 列表**),随即还原两处开关并重编产品构建核对(`test/board` 无残留差异)。
|
||||
| | 验证:`@build` 0 错 0 警告,`Code` 213,648 → **213,676**、RO 18,860、`ER_IROM1` **232,536 B / 22.2%**(ROM
|
||||
| | 合计 233,724 B);`ram_report` 重生成 + `ram_baseline.py --update` + 配图常量同步(`mem-numbers` Passed);
|
||||
| | `@test` **PASS**(到 `net init: OK` 682 ms、`[ERR]` 0);R4 两处**探针实证**(临时加一条裸调用 → 立刻成为
|
||||
| | 新增并 RC=1;还原 → 38/38/0);`--prune` 点名本次还掉的 2 条已删;受影响文件钩子全 Passed。
|
||||
| **2026-10-23** | **S-5 还债:`bsp-err` 基线 19 → 1**,并修掉门禁自己的一处误判口径 | 用户裁定先还 A(清存量)再调查 B。**16 条缺「返回值:」全部补齐**:`gd5f2gq5ue.h` 九个 SPI 原语
|
||||
(`wait_busy`/`write_enable`/`read_status`/`page_read`/`read_from_cache`/`program_load`/`program_exec`/
|
||||
`block_erase`/`check_ecc`)逐条写全 函数功能/入口参数/返回值/限定条件/函数说明,**并把每个函数
|
||||
|
||||
Reference in New Issue
Block a user