台架板 NAND 存储卷写回死锁:LPN=211 恒 TOO_BAD 致 f_mount(fr=1)、整卷禁用(挡掉配置持久化类真机验证) #79

Open
opened 2026-11-04 17:13:10 +08:00 by super_agent_bot · 3 comments
Collaborator

本单由 #73 线程上 wandering1 的指示建立(「板子的 NAND 存储卷故障,我怎么不知道,创建一个工单,解决这个问题」,见评论 303)。建单人是 UDP 队列化工单的执行代理,只做取证与登记,未在本单动手修;修的理由与处方留给受理本单的人/工单。

一句话结论

台架板(192.168.31.100,GD5F2GQ5UE SPI NAND + dhara FTL + FatFs)的存储卷在 本地 2026-11-03 20:55 还正常挂载、2026-11-04 08:16 起进入不可自愈的写回死锁(串口行首有两个时间戳:[...]T..+08:00 是采集机本地时间,中括号里是板上钟面——这台板当时慢 8 小时,正是 #57 SNTP 要修的那件事;下表一律用本地时间):dhara 每次把脏页写回 LPN=211 都报 TOO_BAD,FatFs 因此拿不到卷、f_mount 失败,重试 3 轮后整卷在本轮启动里被禁用。断电重启、换固件都不恢复——同一份 map 状态被原样读回,卡住的那一页永远写不出去。

真机证据(三次捕获,同一块板、同一条串口链路)

本地时刻 板上镜像 FTL 恢复 结果
11-03 20:54:52 阶段 16 台架镜像(11-03 20:53 构建) Map resumed: 14094/97504 sectors used [FS] FATFS mounted ✅ 0 条 flush 失败
11-04 08:16:36 phase16c.hex(fw build Nov 4 2026 01:06:04) 同上,Map head=65024 tail=27662 epoch=7 ❌ 15 条 Cache flush FAIL,卷被禁用
11-04 08:42:11 phase16d.hex(fw build Nov 4 2026 08:40:28) 同上,head/tail/epoch 一字不变 ❌ 同上,序列完全一致

失败序列原文(board_serial_run5.log L61–L94,捕获于 2026-11-04 08:42,本工单留存):

[NAND_FTL] Initializing NAND FTL...
[NAND_FTL] Map resumed: 14094/97504 sectors used
[NAND_FTL] Map head=65024 tail=27662 epoch=7
[NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB)
[ERR][NAND_FTL] Cache flush FAIL: LPN=211 dhara=TOO_BAD class=-7      ← 共 15 条,全在 00:42:11→00:42:22 这 11 秒内
[ERR] [FS] volume FAT invalid (fr=1), reformatting...
[ERR] [FS] volume repair failed (fr=1)
[ERR] [FS] f_mount failed (fr=1)                                      ← 3 轮重试
[ERR] [FS] storage retries exhausted (fr=1), storage disabled          ← 本轮启动内存储彻底不可用

要点:capacity: 97504 pages 与 map 占用在故障前后完全一致 ⇒ 不是块池/容量耗尽(不是 MAP_FULL/JOURNAL_FULL),是单个 LPN 的重定位被 dhara 判定为「坏到救不回来」。class=-7 是 ftl_class_from_dhara() 把 DHARA_E_TOO_BAD 归成 BSP_ERR_CRC(介质/位翻转类),而这条归类本身来自本仓尚未还的 C4 债(见下面指针)。

影响(谁被挡住)

  1. 配置持久化链路在板上整条不可用:config.ini 读不到也存不进、FTP 起不来、/log 写不下去,配置一律回落出厂默认。
  2. 已登记的直接代价:#57 SNTP 真机闭环里,「UI 保存 → config.ini → 重启加载」与「拔线退避 / 主备切换」两条判据因此没能真机验,当时是靠临时未提交构建把 [sntp] 默认值改写进固件才跑通对时闭环(PR #77 正文「真机台架」与「限制与后续」两节已记,登记簿 §7 保留该行)。
  3. 同类被挡的还有任何依赖板上级落盘的真机判据(#68 坏段/空态画面、#53 记录 5 页等按 docs 口径需要落盘对照的那些)。
  4. 故障是每轮启动必现,不是偶发;重启不恢复。

不是本因(已排除)

  • 不是 SNTP 改动引入:SNTP 工单已确认改动前固件与旧日志同样复现。
  • 不是 UDP 队列化改造引入:本工单的三次捕获里,11-03 20:54 那份已经是含阶段 16 台架用例的镜像并且挂载正常;故障出现在其后,且 map 占用没有变化。UDP 侧改动不碰存储路径。
  • 结论:「与本 PR 无关」这个说法成立,但「一直就是坏的」不成立——上面表格给出明确的时间分界。请受理人按"某次台架操作把它打进去的"来查,而不是当成出厂既有缺陷。

候选机理(以下是假设,未验证,按取证成本从低到高排)

  1. 写回被打断:11-03 21:0x 至 11-04 01:1x 之间这块板经历过两次断电(10-pin 杜邦线断裂)与多次 ST-LINK reset/hard。若 journal 正处 recovery 队列中、或 LPN=211 的脏页恰在落盘中途被切,try_recover() 会在 pad_queue/raw_gc 上反复拿 E_RECOVER,超过 DHARA_MAX_RETRIES(=8,Lib/dhara/journal.h:41)后直接判 DHARA_E_TOO_BAD(Lib/dhara/map.c:296)——之后 ftl_flush_cache() 的 s_cache_dirty 永远清不掉,于是每次访问都重试同一页、每轮启动都重来。这与「两次独立启动里 head/tail/epoch 一字不变、sector 占用三次都停在 14094」高度吻合。
  2. 该 PPA 真的坏了且映射无法换页:需要读 LPN=211 当前映射的 PPA、该块在 BBT 里的状态、以及坏块计数(bb_current/bb_last)才能定性;BBT scan: 0 bad blocks found 与「TOO_BAD」并列出现本身可疑(持久化 BBT 与运行时状态可能不同源)。
  3. 归类/自愈策略问题(产品侧):TOO_BAD 被 nand_ftl 当 BSP_ERR_CRC 处理,而 App/task/default_task.c:151 的注释说明「只有真空白的 TOO_BAD 才当新卷」;当前没有跨调用存活的失败类快照(nand_ftl.c:170 自陈的 C4 待还),所以「卷级故障」与「单页故障」在处置上分不开。这可能是为什么它无法自愈的设计面原因,值得和 #45(dhara 重试自旋与卷锁评估)并案看。

建议的第一步(都是可逆性最差放最后,动卷内容前需人明确同意)

  1. 先取证:跑只读存储套件 + 打印 LPN=211 的映射 PPA、该块 BBT 状态、bb_current/bb_last、journal head/tail/epoch/recovery 标志;确认假设 1 还是 2。
  2. 按 docs/测试说明/专项验证/存储维护与容量恢复.md 动作 A(重建 BBT + nand_ftl_format())试一次——文档 §2 已实测说明 A 不恢复容量,但足以判断「map 清掉后能否解开这一页」。
  3. 解不开再上动作 B(STORAGE_RECOVERY_FULL_WIPE,擦净 dhara 可见区 2044 块 + 重建 BBT + 断电重启)。代价:卷内容全失(/log 历史与 /config.ini 回落工厂默认),必须先跟人确认可以丢。
  4. 恢复后按文档 §3 第 7 步验收 [FS] FATFS mounted,并跑一次只读套件;随后补做被挡的真机判据(#57 的两条 + 登记簿 §7 那行)。
  5. 若最终定性为「一次断电就能把卷打死且无法自愈」,请把它当产品可靠性问题处理(上电时的 journal 恢复策略 / 单页写死的降级路径 / C4 快照),而不是只当台架维修:这台设备的现场是要断电的。

指针

  • Drivers/BSP/GD5F2GQ5UE/nand_ftl.c:189-204 ftl_flush_cache()(失败点、s_cache_dirty 永不清零)、:146-156 ftl_err_name()、:158-185 ftl_class_from_dhara()(-7 = BSP_ERR_CRC,内含 C4 待还说明)、:437 TOO_BAD 分支
  • App/task/default_task.c:532(volume FAT invalid (fr=%d), reformatting...)、:588(f_mount failed (fr=%d))、:151(TOO_BAD 只在真空白时当新卷的既有约定)
  • App/fs/vol_idle_sync.c:68(Cache flush FAIL / Map sync failed 由 nand_ftl 就地打点的口径)
  • Lib/dhara/map.c:269-302 try_recover()(E_RECOVER 重启超过 DHARA_MAX_RETRIES → TOO_BAD)、Lib/dhara/journal.h:41 DHARA_MAX_RETRIES=8、Lib/dhara/journal.c:222(E-31:TOO_BAD 被上层当空白的契约)
  • 维护流程:docs/测试说明/专项验证/存储维护与容量恢复.md §1 动作 A/B、§2 根因、§3 步骤、§4 注意事项;破坏性用例清单 docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md
  • 关联工单:#45 dhara 重试自旋与卷锁评估(同一条失败路径的自愈策略)、#57 SNTP 设置(其「限制与后续」两条真机判据等本单解)、#68 / #53(落盘类真机判据)
  • 本单证据原始文件(不在仓内,台架留存):board_serial.log(11-03 20:54,挂载正常)、board_serial_manual.log(11-04 00:16)、board_serial_run5.log(11-04 08:42)

一个附带对不上的数,请受理人顺手核

文档 §2 写「健康满容量 = 96064 pages(187 MB)」,而本单三次捕获都打 capacity: 97504 pages = 190 MB(比文档基线还大 1440 页)。两者口径不同还是文档陈旧?如果 97504 才是满值,建议把 §2 的基线数一并改掉——这个数将来是判断「容量有没有被扣掉」的唯一尺子。

复现

产品构建或台架构建烧录后上电,采 25 s 串口即可:[NAND_FTL] Map resumed: ... 之后紧跟 [ERR][NAND_FTL] Cache flush FAIL: LPN=211 dhara=TOO_BAD class=-7,约 11 s 内出现 [ERR] [FS] storage retries exhausted (fr=1), storage disabled。

> 本单由 #73 线程上 wandering1 的指示建立(「板子的 NAND 存储卷故障,我怎么不知道,创建一个工单,解决这个问题」,见评论 303)。建单人是 UDP 队列化工单的执行代理,**只做取证与登记,未在本单动手修**;修的理由与处方留给受理本单的人/工单。 ## 一句话结论 台架板(192.168.31.100,GD5F2GQ5UE SPI NAND + dhara FTL + FatFs)的存储卷在 **本地 2026-11-03 20:55 还正常挂载、2026-11-04 08:16 起**进入**不可自愈的写回死锁**(串口行首有两个时间戳:`[...]T..+08:00` 是采集机本地时间,中括号里是板上钟面——这台板当时慢 8 小时,正是 #57 SNTP 要修的那件事;下表一律用本地时间):dhara 每次把脏页写回 LPN=211 都报 `TOO_BAD`,FatFs 因此拿不到卷、`f_mount` 失败,重试 3 轮后**整卷在本轮启动里被禁用**。断电重启、换固件都不恢复——**同一份 map 状态被原样读回,卡住的那一页永远写不出去**。 ## 真机证据(三次捕获,同一块板、同一条串口链路) | 本地时刻 | 板上镜像 | FTL 恢复 | 结果 | |---|---|---|---| | 11-03 20:54:52 | 阶段 16 台架镜像(11-03 20:53 构建) | `Map resumed: 14094/97504 sectors used` | **`[FS] FATFS mounted`** ✅ 0 条 flush 失败 | | 11-04 08:16:36 | `phase16c.hex`(fw build Nov 4 2026 01:06:04) | 同上,`Map head=65024 tail=27662 epoch=7` | ❌ 15 条 `Cache flush FAIL`,卷被禁用 | | 11-04 08:42:11 | `phase16d.hex`(fw build Nov 4 2026 08:40:28) | 同上,**head/tail/epoch 一字不变** | ❌ 同上,序列完全一致 | 失败序列原文(`board_serial_run5.log` L61–L94,捕获于 2026-11-04 08:42,本工单留存): ```text [NAND_FTL] Initializing NAND FTL... [NAND_FTL] Map resumed: 14094/97504 sectors used [NAND_FTL] Map head=65024 tail=27662 epoch=7 [NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB) [ERR][NAND_FTL] Cache flush FAIL: LPN=211 dhara=TOO_BAD class=-7 ← 共 15 条,全在 00:42:11→00:42:22 这 11 秒内 [ERR] [FS] volume FAT invalid (fr=1), reformatting... [ERR] [FS] volume repair failed (fr=1) [ERR] [FS] f_mount failed (fr=1) ← 3 轮重试 [ERR] [FS] storage retries exhausted (fr=1), storage disabled ← 本轮启动内存储彻底不可用 ``` 要点:`capacity: 97504 pages` 与 map 占用在故障前后完全一致 ⇒ **不是块池/容量耗尽**(不是 `MAP_FULL`/`JOURNAL_FULL`),是**单个 LPN 的重定位被 dhara 判定为「坏到救不回来」**。`class=-7` 是 `ftl_class_from_dhara()` 把 `DHARA_E_TOO_BAD` 归成 `BSP_ERR_CRC`(介质/位翻转类),而这条归类本身来自本仓尚未还的 C4 债(见下面指针)。 ## 影响(谁被挡住) 1. **配置持久化链路在板上整条不可用**:`config.ini` 读不到也存不进、FTP 起不来、`/log` 写不下去,配置一律回落出厂默认。 2. 已登记的直接代价:#57 SNTP 真机闭环里,「UI 保存 → `config.ini` → 重启加载」与「拔线退避 / 主备切换」两条判据因此**没能真机验**,当时是靠**临时未提交构建**把 `[sntp]` 默认值改写进固件才跑通对时闭环(PR #77 正文「真机台架」与「限制与后续」两节已记,登记簿 §7 保留该行)。 3. 同类被挡的还有任何依赖板上级落盘的真机判据(#68 坏段/空态画面、#53 记录 5 页等按 `docs` 口径需要落盘对照的那些)。 4. 故障是**每轮启动必现**,不是偶发;重启不恢复。 ## 不是本因(已排除) - **不是 SNTP 改动引入**:SNTP 工单已确认改动前固件与旧日志同样复现。 - **不是 UDP 队列化改造引入**:本工单的三次捕获里,11-03 20:54 那份已经是含阶段 16 台架用例的镜像并且**挂载正常**;故障出现在其后,且 map 占用没有变化。UDP 侧改动不碰存储路径。 - 结论:**「与本 PR 无关」这个说法成立,但「一直就是坏的」不成立**——上面表格给出明确的时间分界。请受理人按"某次台架操作把它打进去的"来查,而不是当成出厂既有缺陷。 ## 候选机理(**以下是假设,未验证**,按取证成本从低到高排) 1. **写回被打断**:11-03 21:0x 至 11-04 01:1x 之间这块板经历过两次断电(10-pin 杜邦线断裂)与多次 ST-LINK `reset`/`hard`。若 journal 正处 recovery 队列中、或 LPN=211 的脏页恰在落盘中途被切,`try_recover()` 会在 `pad_queue`/`raw_gc` 上反复拿 `E_RECOVER`,超过 `DHARA_MAX_RETRIES`(=8,`Lib/dhara/journal.h:41`)后直接判 `DHARA_E_TOO_BAD`(`Lib/dhara/map.c:296`)——之后 `ftl_flush_cache()` 的 `s_cache_dirty` 永远清不掉,于是**每次访问都重试同一页、每轮启动都重来**。这与「两次独立启动里 head/tail/epoch 一字不变、sector 占用三次都停在 14094」高度吻合。 2. **该 PPA 真的坏了且映射无法换页**:需要读 LPN=211 当前映射的 PPA、该块在 BBT 里的状态、以及坏块计数(`bb_current`/`bb_last`)才能定性;`BBT scan: 0 bad blocks found` 与「TOO_BAD」并列出现本身可疑(持久化 BBT 与运行时状态可能不同源)。 3. **归类/自愈策略问题(产品侧)**:`TOO_BAD` 被 `nand_ftl` 当 `BSP_ERR_CRC` 处理,而 `App/task/default_task.c:151` 的注释说明「只有真空白的 TOO_BAD 才当新卷」;当前没有跨调用存活的失败类快照(`nand_ftl.c:170` 自陈的 **C4 待还**),所以「卷级故障」与「单页故障」在处置上分不开。这可能是**为什么它无法自愈**的设计面原因,值得和 #45(dhara 重试自旋与卷锁评估)并案看。 ## 建议的第一步(都是可逆性最差放最后,动卷内容前需人明确同意) 1. 先**取证**:跑只读存储套件 + 打印 LPN=211 的映射 PPA、该块 BBT 状态、`bb_current/bb_last`、journal head/tail/epoch/recovery 标志;确认假设 1 还是 2。 2. 按 `docs/测试说明/专项验证/存储维护与容量恢复.md` **动作 A**(重建 BBT + `nand_ftl_format()`)试一次——文档 §2 已实测说明 A **不恢复容量**,但足以判断「map 清掉后能否解开这一页」。 3. 解不开再上**动作 B**(`STORAGE_RECOVERY_FULL_WIPE`,擦净 dhara 可见区 2044 块 + 重建 BBT + **断电重启**)。**代价:卷内容全失**(`/log` 历史与 `/config.ini` 回落工厂默认),必须先跟人确认可以丢。 4. 恢复后按文档 §3 第 7 步验收 `[FS] FATFS mounted`,并跑一次只读套件;随后**补做被挡的真机判据**(#57 的两条 + 登记簿 §7 那行)。 5. 若最终定性为「一次断电就能把卷打死且无法自愈」,请把它当**产品可靠性问题**处理(上电时的 journal 恢复策略 / 单页写死的降级路径 / C4 快照),而不是只当台架维修:这台设备的现场是要断电的。 ## 指针 - `Drivers/BSP/GD5F2GQ5UE/nand_ftl.c:189-204` `ftl_flush_cache()`(失败点、`s_cache_dirty` 永不清零)、`:146-156` `ftl_err_name()`、`:158-185` `ftl_class_from_dhara()`(`-7 = BSP_ERR_CRC`,内含 C4 待还说明)、`:437` TOO_BAD 分支 - `App/task/default_task.c:532`(`volume FAT invalid (fr=%d), reformatting...`)、`:588`(`f_mount failed (fr=%d)`)、`:151`(TOO_BAD 只在真空白时当新卷的既有约定) - `App/fs/vol_idle_sync.c:68`(`Cache flush FAIL` / `Map sync failed` 由 nand_ftl 就地打点的口径) - `Lib/dhara/map.c:269-302` `try_recover()`(`E_RECOVER` 重启超过 `DHARA_MAX_RETRIES` → `TOO_BAD`)、`Lib/dhara/journal.h:41` `DHARA_MAX_RETRIES=8`、`Lib/dhara/journal.c:222`(E-31:TOO_BAD 被上层当空白的契约) - 维护流程:`docs/测试说明/专项验证/存储维护与容量恢复.md` §1 动作 A/B、§2 根因、§3 步骤、§4 注意事项;破坏性用例清单 `docs/测试说明/板级测试/GD5F2GQ5UE_Test_Guide.md` - 关联工单:**#45** dhara 重试自旋与卷锁评估(同一条失败路径的自愈策略)、**#57** SNTP 设置(其「限制与后续」两条真机判据等本单解)、**#68 / #53**(落盘类真机判据) - 本单证据原始文件(不在仓内,台架留存):`board_serial.log`(11-03 20:54,挂载正常)、`board_serial_manual.log`(11-04 00:16)、`board_serial_run5.log`(11-04 08:42) ## 一个附带对不上的数,请受理人顺手核 文档 §2 写「健康满容量 = **96064 pages(187 MB)**」,而本单三次捕获都打 `capacity: 97504 pages = 190 MB`(**比文档基线还大 1440 页**)。两者口径不同还是文档陈旧?如果 97504 才是满值,建议把 §2 的基线数一并改掉——这个数将来是判断「容量有没有被扣掉」的唯一尺子。 ## 复现 产品构建或台架构建烧录后上电,采 25 s 串口即可:`[NAND_FTL] Map resumed: ...` 之后紧跟 `[ERR][NAND_FTL] Cache flush FAIL: LPN=211 dhara=TOO_BAD class=-7`,约 11 s 内出现 `[ERR] [FS] storage retries exhausted (fr=1), storage disabled`。
super_agent_bot added the 下一顺位 label 2026-11-04 17:13:11 +08:00
Author
Collaborator

补一条与本单直接冲突的文档口径,受理人请一并核:

docs/架构设计/STM32F4-Base存储架构说明.md:646 的错误码表现写着——

| ECC / TOO_BAD | BSP_ERR_CRC | 位翻转不可纠或页太坏:是页级问题,读重试 / 由 dhara 换页,不代表卷坏 |

本单的真机捕获正是这条口径的反例:一个页级 TOO_BAD(LPN=211 写回)最终让整卷被禁用(f_mount(fr=1) × 3 轮 → storage disabled),而且看不出换页发生过——两次独立启动(本地 11-04 08:16 与 08:42)里 Map head=65024 tail=27662 epoch=7 一字不变。另要注意 ftl_flush_cache()(Drivers/BSP/GD5F2GQ5UE/nand_ftl.c:189-204)的失败分支不清 s_cache_dirty,此后每次存储访问都会重试同一页——本单两次捕获各刷出 15 条 Cache flush FAIL 就是这么来的。

所以有两种可能,本单要用取证把它们分开:

  1. 文档那句「不代表卷坏」在写回路径上站不住(journal 恢复失败被判 TOO_BAD,Lib/dhara/map.c:296-297,DHARA_MAX_RETRIES=8 见 Lib/dhara/journal.h:41)——那就属于产品可靠性问题,卷级/页级失败的归类与降级要重做(顺带能还掉 nand_ftl.c:158-185 自陈的 C4 债:跨调用存活的失败类快照)。
  2. 或者这块颗粒的这个块确实坏到无法换页——那就先按 docs/测试说明/专项验证/存储维护与容量恢复.md 动作 A/B 处置,本单收尾。

哪一条成立都请把结论回写到上面那句文档口径里:别留着「TOO_BAD 只是页级问题、不影响卷」这句话当判据,下一个读到它的排障人会把整卷禁用的现场误判成"不用管"。

(另:docs/测试说明/板级测试/FTP_Test_Guide.md:187 已经写了「非首次挂载仍 f_mount 失败 → 跑一次存储套件确认磁盘健康」,与本单第 1 步取证一致,可以直接照它做。)

补一条与本单直接冲突的文档口径,受理人请一并核: `docs/架构设计/STM32F4-Base存储架构说明.md:646` 的错误码表现写着—— > | `ECC` / `TOO_BAD` | `BSP_ERR_CRC` | 位翻转不可纠或页太坏:**是页级问题**,读重试 / 由 dhara 换页,不代表卷坏 | 本单的真机捕获正是这条口径的反例:**一个页级 TOO_BAD(LPN=211 写回)最终让整卷被禁用**(`f_mount(fr=1)` × 3 轮 → `storage disabled`),而且**看不出换页发生过**——两次独立启动(本地 11-04 08:16 与 08:42)里 `Map head=65024 tail=27662 epoch=7` 一字不变。另要注意 `ftl_flush_cache()`(`Drivers/BSP/GD5F2GQ5UE/nand_ftl.c:189-204`)的失败分支不清 `s_cache_dirty`,此后每次存储访问都会重试同一页——本单两次捕获各刷出 15 条 `Cache flush FAIL` 就是这么来的。 所以有两种可能,本单要用取证把它们分开: 1. 文档那句「不代表卷坏」在**写回路径**上站不住(journal 恢复失败被判 TOO_BAD,`Lib/dhara/map.c:296-297`,`DHARA_MAX_RETRIES=8` 见 `Lib/dhara/journal.h:41`)——那就属于产品可靠性问题,卷级/页级失败的归类与降级要重做(顺带能还掉 `nand_ftl.c:158-185` 自陈的 C4 债:跨调用存活的失败类快照)。 2. 或者这块颗粒的这个块确实坏到无法换页——那就先按 `docs/测试说明/专项验证/存储维护与容量恢复.md` 动作 A/B 处置,本单收尾。 哪一条成立都请把结论回写到上面那句文档口径里:**别留着「TOO_BAD 只是页级问题、不影响卷」这句话当判据**,下一个读到它的排障人会把整卷禁用的现场误判成"不用管"。 (另:`docs/测试说明/板级测试/FTP_Test_Guide.md:187` 已经写了「非首次挂载仍 `f_mount` 失败 → 跑一次存储套件确认磁盘健康」,与本单第 1 步取证一致,可以直接照它做。)
Owner

@super_agent_bot 开始修复

@super_agent_bot 开始修复
Author
Collaborator

#79 修复完成:PR #81 已开(分支 fix/nand-ftl-format-deadlock,f979b394 + 4681e547 台账随修),已真机闭环。

根因定案(比工单正文更进一层)

工单登记的两条放大机制成立(脏缓存不清 → format 被同一页挡死),但不是本板故障
的第一推动
。真机逐层取证(临时诊断构建:prog/erase 原语失败打印 → is_bad 命中
打印 → BBT 合并打印)后定案:

  1. 出厂扫描 0 坏块;诊断构建里 prog/erase 零失败——TOO_BAD 不来自当次 I/O;
  2. 合并持久化 BBT 后 129/2048 块坏,全部是 1016–1142 连续段;
    Map head=65024 >> 6 = 1016 正中段首 → prepare_head() 连续 8 次 is_bad
    → DHARA_E_TOO_BAD(journal.c:820-832)→ 写头永世不得前进;
  3. 误标来源:旧 dhara_nand_erase/prog() 把一切失败(含传输层/等忙超时,芯片
    根本没回 E_FAIL/P_FAIL)一律 dhara_nand_mark_bad(),而
    gd5f2gq5ue_mark_block_bad() 每次立即持久化 BBT(不可撤销)。
    11-03 21:0x–11-04 01:1x 的断电/reset 打中写窗口即固化一批——这解释了
    「11-03 20:54 还好、之后每轮必现、重启不恢复、容量读数不变」全部特征。
  4. 曾怀疑的写保护已排除:init 补了 A0h 回读校验哨兵,实测本板 A0h=0。
    「TOO_BAD 归类 CRC」不假(§10.4.1 判据修正保留),但本案连"页级坏"都不是——
    是误标固化。

修复(PR 内容)

  • dhara_nand_erase/prog():只有芯片明确回 E_FAIL/P_FAIL 才标坏;
    传输/超时只报 BAD_BLOCK 重试,不标坏(杜绝误标再进 BBT)
  • nand_ftl_format():脏缓存 flush 失败不再挡死恢复动作(尽力刷一次后丢弃继续
    dhara_map_clear();丢弃权限只在 format 内)
  • C4 还清:nand_ftl_fault_get/clear() 跨调用失败类快照(20 B)+ defaultTask
    探针按类分流(NO_SPACE 跳过重格式化)——本轮排障就是靠它一眼定位
  • 哨兵/诊断:A0h 回读校验;gd5f_bbt_load() 合并后坏块增量 > 出厂扫描时打
    「BBT after merge」,现场可秒判真坏 vs 误标
  • 单测 149 → 178 全绿(format 死锁 21 条 + 传输失败不标坏 207/208/505;
    牙齿检查:回退修复即见红)
  • 文档:架构说明 §10.4/10.4.1/10.4.2、维护与容量恢复 §2/2.1、登记簿 C4 销项

存量误标处置(动作 A,卷内容已弃)

恢复构建(TEST_SUITE_STORAGE + ENABLE_STORAGE_RECOVERY_TESTS,未开 FULL_WIPE)
Storage Recovery: 3/3 PASSED → BBT rebuilt and persisted(version=71)→
format 成功。产品镜像复烧后真机判据全中(2026-11-04 18:05):

[NAND] BBT scan: 0 bad blocks found        ← 无 BBT after merge 行
[NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB)
[FS] no FAT volume, formatting NAND...
[FS] FATFS mounted                          ← ★
[CFG] load: file missing, factory template generated
[NET_CFG] load: OK ip=192.168.31.100

0 条 Cache flush FAIL / 0 条 TOO_BAD / 0 条 storage disabled。
#57 SNTP 被挡的两条真机判据、#68/#53 的落盘验证自此解锁。

遗留(不在本 PR)

  • 97504 vs 96064 pages 基线口径:恢复后仍报 97504;改判需跑动作 B(FULL_WIPE),
    已按工单注记留在维护文档 §2。
  • 旧卷内容(11-03 前的 config.ini/日志)随 map clear 作废——台架卷为可弃数据,
    出厂模板已重建。
#79 修复完成:[PR #81](http://100.123.83.113:3001/wandering1/STM32F4-Base/pulls/81) 已开(分支 fix/nand-ftl-format-deadlock,f979b394 + 4681e547 台账随修),已真机闭环。 ## 根因定案(比工单正文更进一层) 工单登记的两条放大机制成立(脏缓存不清 → format 被同一页挡死),但**不是本板故障 的第一推动**。真机逐层取证(临时诊断构建:prog/erase 原语失败打印 → is_bad 命中 打印 → BBT 合并打印)后定案: 1. 出厂扫描 **0 坏块**;诊断构建里 prog/erase **零失败**——TOO_BAD 不来自当次 I/O; 2. 合并持久化 BBT 后 **129/2048 块坏**,全部是 1016–1142 **连续段**; `Map head=65024 >> 6 = 1016` 正中段首 → `prepare_head()` 连续 8 次 `is_bad` → `DHARA_E_TOO_BAD`(journal.c:820-832)→ 写头永世不得前进; 3. 误标来源:旧 `dhara_nand_erase/prog()` 把**一切失败**(含传输层/等忙超时,芯片 根本没回 E_FAIL/P_FAIL)一律 `dhara_nand_mark_bad()`,而 `gd5f2gq5ue_mark_block_bad()` **每次立即持久化 BBT(不可撤销)**。 11-03 21:0x–11-04 01:1x 的断电/reset 打中写窗口即固化一批——这解释了 「11-03 20:54 还好、之后每轮必现、重启不恢复、容量读数不变」全部特征。 4. 曾怀疑的写保护已排除:init 补了 A0h 回读校验哨兵,实测本板 A0h=0。 「TOO_BAD 归类 CRC」不假(§10.4.1 判据修正保留),但本案连"页级坏"都不是—— 是**误标固化**。 ## 修复(PR 内容) - `dhara_nand_erase/prog()`:只有芯片明确回 E_FAIL/P_FAIL 才标坏; 传输/超时只报 BAD_BLOCK 重试,不标坏(杜绝误标再进 BBT) - `nand_ftl_format()`:脏缓存 flush 失败不再挡死恢复动作(尽力刷一次后丢弃继续 `dhara_map_clear()`;丢弃权限只在 format 内) - C4 还清:`nand_ftl_fault_get/clear()` 跨调用失败类快照(20 B)+ defaultTask 探针按类分流(NO_SPACE 跳过重格式化)——本轮排障就是靠它一眼定位 - 哨兵/诊断:A0h 回读校验;`gd5f_bbt_load()` 合并后坏块增量 > 出厂扫描时打 「BBT after merge」,现场可秒判真坏 vs 误标 - 单测 149 → 178 全绿(format 死锁 21 条 + 传输失败不标坏 207/208/505; 牙齿检查:回退修复即见红) - 文档:架构说明 §10.4/10.4.1/10.4.2、维护与容量恢复 §2/2.1、登记簿 C4 销项 ## 存量误标处置(动作 A,卷内容已弃) 恢复构建(TEST_SUITE_STORAGE + ENABLE_STORAGE_RECOVERY_TESTS,未开 FULL_WIPE) `Storage Recovery: 3/3 PASSED` → `BBT rebuilt and persisted`(version=71)→ format 成功。产品镜像复烧后真机判据全中(2026-11-04 18:05): ``` [NAND] BBT scan: 0 bad blocks found ← 无 BBT after merge 行 [NAND_FTL] NAND FTL ready (capacity: 97504 pages = 190 MB) [FS] no FAT volume, formatting NAND... [FS] FATFS mounted ← ★ [CFG] load: file missing, factory template generated [NET_CFG] load: OK ip=192.168.31.100 ``` 0 条 Cache flush FAIL / 0 条 TOO_BAD / 0 条 storage disabled。 #57 SNTP 被挡的两条真机判据、#68/#53 的落盘验证自此解锁。 ## 遗留(不在本 PR) - 97504 vs 96064 pages 基线口径:恢复后仍报 97504;改判需跑动作 B(FULL_WIPE), 已按工单注记留在维护文档 §2。 - 旧卷内容(11-03 前的 config.ini/日志)随 map clear 作废——台架卷为可弃数据, 出厂模板已重建。
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wandering1/STM32F4-Base#79