5 Commits

Author SHA1 Message Date
wandering1 829c2580bb Merge pull request 'build(mdk): Keil 可逆排除 126 个零产出 LVGL 编译单元,全量重建 21.5→18.3 s(-14.6%,#46)' (#87) from execute-issue-46-214251580469 into master
CI / 静态门禁 (pre-commit) (push) Failing after 4m36s
CI / 主机侧单测 (MSVC) (push) Successful in 32s
Reviewed-on: http://100.123.83.113:3001/wandering1/STM32F4-Base/pulls/87
2026-11-06 01:04:31 +08:00
wandering1 0f2aec8850 Merge pull request 'docs(storage): #45 复核结论——卷锁无第二写者,全序列卷锁项关闭(销项)' (#86) from execute-issue-45-262ec492e96a into master
Reviewed-on: #86
2026-11-06 00:05:47 +08:00
super_agent_bot 488f6fbf21 build(mdk): Keil 可逆排除 126 个零产出 LVGL 编译单元,全量重建 21.5→18.3 s(-14.6%,#46)
CI / 静态门禁 (pre-commit) (push) Failing after 44s
CI / 主机侧单测 (MSVC) (push) Failing after 44s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 45s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 45s
按 #46 判据「有实测收益才保留改动」执行,证据(同机同基线 c487ce42,UV4 -r 墙钟):

- 基线 4 次全量重建均值 21.46 s → 排除态 4 次均值 18.33 s,-3.13 s(-14.6%);
  增量最坏对照(touch lvgl.h 后 -b)9.66 s/83 单元 → 8.06 s/45 单元(-16.6%)。
- 影像等价:Program Size 四项全同(Code=254820 RO=30896 RW=2072 ZI=150104);
  .hex 286,084 字节两两比对仅差 0x08007C6B–6F 的 fw 时间戳横幅(基线之间同差);
  .map 符号表逐行比对,基线独有 126 行恰为被排除单元的 ABSOLUTE 文件记录。
- 零产出认定:3 次基线 .map 的 Image component sizes 中 Code/RO/RW/ZI 全 0,
  名单一致(121 空 TU + 6 仅调试记录)。Cross Reference Table 不动点收敛得可安全
  排除集:lv_circle_buf.c 因被保留的 lv_iter.o 静态引用而保留(armlink 先解析
  后死删,127 全排实测 L6218E×9);净排除 126 个。
- 形态:仅加每文件 <FileOption><IncludeInBuild>0</IncludeInBuild>,不删条目,
  GUI 可逐项恢复,revert 单笔整体回滚;FilePath 集合不变(registration-check 过)。
- 本机构建对工程文件零抖动;最终一次全量构建(18.20 s,0E0W)跑在提交字节上。
- sim/CMake 不涉及;LVGL 源码零改动。台架回归不需要:镜像与已验收基线逐字节
  等价(除时间戳)。

Issue: http://100.123.83.113:3001/wandering1/STM32F4-Base/issues/46
2026-11-06 00:03:33 +08:00
super_agent_bot 84f46b5660 docs(storage): #45 复核结论——卷锁无第二写者,全序列卷锁项关闭(销项)
登记簿 §2「可选全序列卷锁」按其判据(无第二写者则关闭)销项:
master c487ce4 枚举全部生产卷访问点——写者 syslog/soe/cfg/prot_set、
录波段、lftpd,读者 UI 两径,空闲 sync——全部持卷锁或走屏障;
启动期卷写由 STORAGE_READY 屏障门控(default_task.c bring-up)。
「存储侧喂狗饥饿」2026-10-02 后无新台架证据:F2/F3(10-25)、
录波枚举(11-02)、PR #82 补验 soak(11-05)均无该签名;dhara
try_recover 自旋有界(8 次 restart 定案 TOO_BAD)且 FTL 入口
nand_ftl_wd_feed() 直接喂 IWDG,观察行留存并更新现状字段。

覆盖面审计沉淀进 存储架构说明 §10.5;登记簿 §6 第 3 项销项、
uvprojx 观察行升 3;项目架构总览 fs/ 行旧「三条路径」口径更正。

评估过程与逐条证据:Gitea issue #45。
2026-11-05 23:51:23 +08:00
wandering1 c487ce4225 Merge pull request 'fix(cfg): 热重载读侧三点一致性校验——掐断打回出厂与保存吞段(#73)' (#82) from fix-config-reload-03ecc431fc5e into master
CI / 静态门禁 (pre-commit) (push) Failing after 5m15s
CI / 主机侧单测 (MSVC) (push) Failing after 45s
Reviewed-on: #82
2026-11-05 18:26:56 +08:00
4 changed files with 674 additions and 5 deletions
File diff suppressed because it is too large Load Diff
+2 -4
View File
@@ -20,8 +20,7 @@
| # | 事项 | 发现 | 证据与现状 | 出处 | | # | 事项 | 发现 | 证据与现状 | 出处 |
|---|---|---|---|---| |---|---|---|---|---|
| dhara 重试自旋残留 | **dhara 重试自旋残留**——`try_recover()` 的 `DHARA_MAX_RETRIES`(8) 自旋在坏块密集时仍可能长时间占用 defaultTask(喂狗点) | 2026-10-02 | 低优先:现有 `vol_lock` + 喂狗节奏缓解;若台架再出"存储侧喂狗饥饿"再排期 | `Lib/dhara/map.c` | | dhara 重试自旋残留 | **dhara 重试自旋残留**——`try_recover()` 的 `DHARA_MAX_RETRIES`(8) 自旋在坏块密集时仍可能长时间占用 defaultTask(喂狗点) | 2026-10-02;2026-11-05 复核未复发 | 低优先:现有 `vol_lock` + 喂狗节奏缓解,自旋另有 FTL 入口直接喂狗兜底(`../架构设计/STM32F4-Base存储架构说明.md` §10.5);若台架再出"存储侧喂狗饥饿"再排期 | `Lib/dhara/map.c` |
| 可选全序列卷锁 | **可选全序列卷锁**——现卷锁仅覆盖 `syslog` / `cfg` / `lftpd` 三条路径(`vol_lock_wait(0)` try 语义),其它潜在访问点(如 UI 读日志)未纳入。⚠ 原本挂在本题下的「dhara 失败类快照(C4)」待还项**已于 2026-11-04 由问题 #79 还清**(`nand_ftl_fault_get/clear` + 探针按类分流,见 `../架构设计/STM32F4-Base存储架构说明.md` §10.4 已闭环段)——本题现只剩**卷锁覆盖面**本身,不再被 C4 阻塞 | 2026-10-02;C4 拆分 2026-11-04 | 待评估:先确认是否真有第二写者;无则关闭本项 | `App/fs/vol_lock.{c,h}` |
## 3. 硬件(V0.1 缺陷 → V0.2 改版项) ## 3. 硬件(V0.1 缺陷 → V0.2 改版项)
@@ -53,8 +52,7 @@
|---|---|---|---| |---|---|---|---|
| 1 | **net 层跨上下文收口** | 同批处理两件事:裸指针收口为状态查询 API;对时 reconcile/relisten 突发导致 uiTask 800 ms 以上连续缺席,评估优先级矩阵与突发分片让路 | 同类台架负载下不再出现目标饿死签名;网络与 UI 回归通过;证据写入网络与看门狗模块文档 | | 1 | **net 层跨上下文收口** | 同批处理两件事:裸指针收口为状态查询 API;对时 reconcile/relisten 突发导致 uiTask 800 ms 以上连续缺席,评估优先级矩阵与突发分片让路 | 同类台架负载下不再出现目标饿死签名;网络与 UI 回归通过;证据写入网络与看门狗模块文档 |
| 2 | **网络性能资源建议簇** | 分别评估 PASV 重复建监听、PHY 强制 100M 无回退、`NET_MAX_SOCKETS` 与单连接语义不一致;DE 项随 RS-485,不在本项做。机理见 `../网络/Net层阻塞模型架构设计.md` 与 `Drivers/BSP/NET/README.md` | 每项形成“修改并验证”或“有理由不做”的结论;不为了清清单做无收益重构 | | 2 | **网络性能资源建议簇** | 分别评估 PASV 重复建监听、PHY 强制 100M 无回退、`NET_MAX_SOCKETS` 与单连接语义不一致;DE 项随 RS-485,不在本项做。机理见 `../网络/Net层阻塞模型架构设计.md` 与 `Drivers/BSP/NET/README.md` | 每项形成“修改并验证”或“有理由不做”的结论;不为了清清单做无收益重构 |
| 3 | **dhara 重试自旋与卷锁评估** | 先确认是否仍出现存储侧喂狗饥饿、是否确有第二写者,再决定是否修改 | 有新证据才排修改;无第二写者则关闭全序列卷锁项 | | 3 | **uvprojx 空 TU 观察** | 201 个 LVGL `.c` 中 127 个在 `.map` 零产出,但当前增量构建仅 4~5 秒;有全量构建耗时痛点时先补计时基线,再用 Keil 原生 `<IncludeInBuild>0</IncludeInBuild>` 可逆排除 | 有实测收益才保留改动;否则继续观察 |
| 4 | **uvprojx 空 TU 观察** | 201 个 LVGL `.c` 中 127 个在 `.map` 零产出,但当前增量构建仅 4~5 秒;有全量构建耗时痛点时先补计时基线,再用 Keil 原生 `<IncludeInBuild>0</IncludeInBuild>` 可逆排除 | 有实测收益才保留改动;否则继续观察 |
> RS-485 白名单随 `暂缓-RS485.md` 整簇处理,不列为 UI 后的独立编码任务。 > RS-485 白名单随 `暂缓-RS485.md` 整簇处理,不列为 UI 后的独立编码任务。
> 并行写域、工作树与合并纪律统一见 `docs/环境与部署/并行任务工作树方案.md`。 > 并行写域、工作树与合并纪律统一见 `docs/环境与部署/并行任务工作树方案.md`。
@@ -728,3 +728,44 @@ LPN 与原始码的位置**就地分类并打印(`ftl_err_name()` 给可读名
`[CFG] load: file missing, factory template generated`,0 条 flush FAIL。 `[CFG] load: file missing, factory template generated`,0 条 flush FAIL。
⚠ 动作 A 语义 = 卷内容全失(旧卷随 map clear 作废),本次台架卷为可弃数据。 ⚠ 动作 A 语义 = 卷内容全失(旧卷随 map clear 作废),本次台架卷为可弃数据。
### 10.5 卷锁覆盖面审计与 dhara 重试自旋复核(2026-11-05,问题 #45 评估结论)
**结论先行:卷锁之外没有第二写者,登记簿「可选全序列卷锁」项就此关闭;
「存储侧喂狗饥饿」无 2026-10-02 之后的新证据,dhara 重试自旋保留为长期观察。**
判据 = 对 master `c487ce4` 的调用点枚举(判据:`App/` 与 `Drivers/BSP/` 下全部带
`FA_WRITE` 的 `f_open` 与 `f_unlink`/`f_rename`/`f_mkdir`/`f_opendir` 调用点)
+ 2026-11-05 之前的全部台架留档。评估过程与逐条证据见 Gitea 问题 #45。
**覆盖面清单(生产构建的全部卷访问序列):**
| 访问道 | 任务上下文 | 串行化纪律 |
|---|---|---|
| `/log` 七本 + `wdev.log`(追加写 / 清除 / `f_mkdir /log`) | defaultTask | `vol_lock_wait(0)` try,锁跨 open…close 完整序列(`App/log/sys_log_mcu.c`) |
| `/log/soe.log` | defaultTask | 同上(`App/log/soe_store.c`) |
| `/config.ini` 原子写 tmp+rename / unlink;`/prot_set.bin` 同后端 | defaultTask | 同上,store 后端四函数全覆盖(`App/cfg/cfg_file_store_mcu.c` v1.3;`App/cfg/prot_set_store.c` 走 `cfg_store_read`/`cfg_store_write_atomic`,无独立盘触点) |
| `/wave` 录波段(mkdir / 追加写 ≤21×`f_write` / unlink) | defaultTask | 同上,锁跨完整序列(`App/task/default_task.c` 录波段) |
| FTP RETR/STOR/LIST/DELE/MKD | ftpTask | 100 ms 分片阻塞 + 每片 `lftpd_task_wd_beat()`,锁跨 open…close / opendir…closedir 全程(`Drivers/BSP/NET/lftpd/lftpd_io.c`) |
| 回放页段表/段窗读、UI 记录页读 | uiTask | try(0) 锁跨完整序列(`App/task/ui_task.c`、`App/log/sys_log_mcu.c` 读径) |
| 空闲 flush 兜底(`CTRL_SYNC`) | defaultTask | try(0) 闸门,卷忙跳过(§5.5;`App/fs/vol_idle_sync.c`) |
| `f_mount`/`f_mkfs`/`/fschk.tmp` 探针/`nand_ftl_format` | defaultTask 启动段 | **就绪屏障门控**:`STORAGE_READY` 在 `storage_bring_up()` 末尾才置位,netTask/ftpTask/uiTask 的卷入口全部等屏障(`App/task/default_task.c` 卷锁创建处注释),启动期卷写无并发使用者 |
LVGL 的 FatFs 驱动桥(`Lib/lvgl/src/libs/fsdrv/lv_fs_fatfs.c`)`LV_USE_FS_FATFS`
默认关闭、本仓未接线,不是卷使用者;`test/board/` 的存储测试任务仅存在于互斥测试
构建(`test-suite-switch` 门禁),不在产品镜像。**登记簿原口径「卷锁仅覆盖
syslog/cfg/lftpd 三条路径」是 2026-10-02 建档快照,已被本表取代**——SOE、录波段写、
`/prot_set.bin`、UI 读径与空闲 sync 随后都进了同一把锁。
**dhara 重试自旋**:`try_recover()` 的自旋有界——`DHARA_MAX_RETRIES`(8) 次 restart
后以 `DHARA_E_TOO_BAD` 定案(`Lib/dhara/map.c:270-306`),journal 层六处重试环同为
有界;且 NAND 长操作在驱动入口与 `gd5f_wait_busy` 每 100 ms 经 `nand_ftl_wd_feed()`
**直接喂 IWDG**(`Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c`)——自旋即便落在
defaultTask(喂狗点)内也不饿狗,残留形态收敛为「有界时长的存储服务延迟」。
真 NAND 卡死 = 持续喂狗、设备存活但存储冻结,属已声明边界
(`../子系统设计/看门狗设计说明.md` §9 R4;要改成"NAND 死也复位"需给
`nand_ftl_wd_feed()` 加上限,非本单判据)。**复发复核**:「存储侧喂狗饥饿」唯一
实证 = 2026-10-02 台架轮(并发 FTL 写 → journal 竞争,另有同日 IWDG 超时被配成
复位默认值的 P0 修复,见 `../子系统设计/看门狗设计说明.md` 变更记录),此后
2026-10-25 F2/F3 探针轮、2026-11-02 录波枚举台架轮(卷锁 try 超时 0 次)、
2026-11-05 PR #82 补验 soak(STOR 密集)均无该签名。重开判据不变:**台架再出
存储侧喂狗饥饿才排期**;观察行留登记簿 §2。
+1 -1
View File
@@ -320,7 +320,7 @@ STM32F4-Base/
│ │ console_log(UART5 控制台单写者)、soe_rec(64B SOE 纯编解码)+ soe_store(投递/落盘胶水) │ │ console_log(UART5 控制台单写者)、soe_rec(64B SOE 纯编解码)+ soe_store(投递/落盘胶水)
│ ├── cfg/ 配置引擎:cfg_file(静态态单任务收敛于 defaultTask)、store(MCU=FreeRTOS 堆)、 │ ├── cfg/ 配置引擎:cfg_file(静态态单任务收敛于 defaultTask)、store(MCU=FreeRTOS 堆)、
│ │ prot_set_store(/prot_set.bin 原子写,保护定值持久化) │ │ prot_set_store(/prot_set.bin 原子写,保护定值持久化)
│ ├── fs/ 卷锁 vol_lock(syslog / cfg / lftpd 三条路径 try 语义)、vol_idle_sync │ ├── fs/ 卷锁 vol_lock(全卷访问点串行化:写者/读者 try、lftpd 分片阻塞)、vol_idle_sync
│ ├── sync/ time_sync(timeSyncTask 载体)、time_sntp(SNTP 校时客户端,UDP) │ ├── sync/ time_sync(timeSyncTask 载体)、time_sntp(SNTP 校时客户端,UDP)
│ └── util/ sys_clock(墙钟)、task_watchdog(IWDG 判定状态机)、boot_stats、sha256、task_prof │ └── util/ sys_clock(墙钟)、task_watchdog(IWDG 判定状态机)、boot_stats、sha256、task_prof
├── Drivers/BSP/ 纯手工驱动/服务(不受 CubeMX 保护) ├── Drivers/BSP/ 纯手工驱动/服务(不受 CubeMX 保护)