修复IWDG超时未配置与dhara resume回滚:看门狗误复位与复位后写入全部丢失,台架全量自检PASS
This commit is contained in:
@@ -144,11 +144,26 @@ static int gd5f_dma_buf_ok(const void *p_buf, size_t size) {
|
||||
* 限定条件:SPI 已初始化
|
||||
* 函数说明:循环读取状态寄存器直到 OIP 位清零或超时
|
||||
*/
|
||||
/* 看门狗心跳弱钩子:默认空实现(无看门狗/模拟器构建);强符号由
|
||||
* App/util/task_watchdog.c 提供,路由到调用者任务的心跳位 */
|
||||
__weak void nand_ftl_wd_beat(void) {
|
||||
}
|
||||
|
||||
/* 看门狗直接喂狗弱钩子:默认空实现;强符号由 App/util/task_watchdog.c
|
||||
* 提供(IWDG 已启动时写 KR)——覆盖 defaultTask(喂狗点)自身陷于长 FTL
|
||||
* 操作、主循环喂狗停摆的形态(2026-10-02 台架实证) */
|
||||
__weak void nand_ftl_wd_feed(void) {
|
||||
}
|
||||
|
||||
int gd5f_wait_busy(uint32_t timeout_ms) {
|
||||
uint8_t cmd = GD5F_CMD_GET_FEATURE;
|
||||
uint8_t addr = GD5F_REG_STATUS;
|
||||
uint8_t status = 0;
|
||||
uint32_t tick_start = HAL_GetTick();
|
||||
uint32_t last_beat = tick_start;
|
||||
|
||||
nand_ftl_wd_beat(); /* 看门狗:入口心跳(长操作在调用者任务上下文;内核前调用为空操作) */
|
||||
nand_ftl_wd_feed(); /* 看门狗:入口直接喂狗(覆盖 defaultTask 长 I/O 阻塞主循环喂狗点的形态) */
|
||||
|
||||
while (1) {
|
||||
GD5F_CS_LOW();
|
||||
@@ -163,6 +178,11 @@ int gd5f_wait_busy(uint32_t timeout_ms) {
|
||||
if ((HAL_GetTick() - tick_start) >= timeout_ms) {
|
||||
return GD5F_BUSY_TIMEOUT;
|
||||
}
|
||||
if ((uint32_t)(HAL_GetTick() - last_beat) >= 100u) {
|
||||
last_beat = HAL_GetTick();
|
||||
nand_ftl_wd_beat(); /* 看门狗:循环内每 100 ms 心跳(擦除等待最长 5 s) */
|
||||
nand_ftl_wd_feed(); /* 看门狗:同步直接喂狗(同节奏) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -247,6 +247,36 @@ int32_t gd5f_program_exec(uint32_t page_addr);
|
||||
int32_t gd5f_block_erase(uint32_t block_addr);
|
||||
int32_t gd5f_check_ecc(void);
|
||||
|
||||
/*
|
||||
* 函数功能:NAND 长耗时操作看门狗心跳弱钩子
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:任意上下文可调(内核启动前调用为空操作)
|
||||
* 函数说明:gd5f_wait_busy 的长轮询(块擦除等待最长 5 s、GC 页拷贝、
|
||||
* 日志写)都运行在调用者任务上下文(default/ftp/ui/timesync 等);
|
||||
* 本钩子默认空实现,App/util/task_watchdog.c 提供强符号,按调用者
|
||||
* 任务句柄路由到该任务的心跳位,防止长耗时窗口心跳缺席导致 IWDG
|
||||
* 误复位(2026-10-02 台架:0 字节 STOR 截断 → dhara GC > 800 ms
|
||||
* 无心跳 → 停喂 → IWDG 误复位)。
|
||||
*/
|
||||
void nand_ftl_wd_beat(void);
|
||||
|
||||
/*
|
||||
* 函数功能:NAND 长耗时操作看门狗直接喂狗弱钩子
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:任意上下文可调(内核启动前 / IWDG 未启动时为空操作)
|
||||
* 函数说明:心跳钩子(nand_ftl_wd_beat)只能维持"心跳位",喂狗动作本身在
|
||||
* defaultTask 主循环(task_wd_poll)——若长耗时 FTL 操作(GC/整卷
|
||||
* 格式化)发生在 defaultTask 上下文,主循环被阻塞在 FTL 调用里,
|
||||
* 喂狗点停摆 → 心跳位再新也无人喂 → IWDG 误复位(2026-10-02 台架
|
||||
* 实证:console tx fault 条目落盘触发 GC,poller 饥饿 ~2 s → IWDG
|
||||
* 复位、无任何 stall 日志)。本钩子让 FTL 长路径在操作进行中直接
|
||||
* 喂狗,覆盖"喂狗点自身被长 I/O 阻塞"的形态。强符号由
|
||||
* App/util/task_watchdog.c 提供(仅 IWDG 已启动时生效)。
|
||||
*/
|
||||
void nand_ftl_wd_feed(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
* 2026-07-20 王建锋 创建初始版本
|
||||
* 2026-09-21 E-31 resume 失败按错误分类:仅真空白判新卷,其余失败
|
||||
* 返回 mount 层(禁止静默清 map 触发整卷重格式化)
|
||||
* 2026-10-02 王建锋 resume 成功后增打 journal head/tail/epoch:复盘
|
||||
* "复位后所有写入丢失"时 sectors used 不足以判定
|
||||
* journal 回退(覆盖写不改 count),head/tail/epoch 是
|
||||
* 唯一能暴露 resume 锚错 checkpoint 的证据
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
@@ -245,6 +249,15 @@ DSTATUS disk_initialize(BYTE pdrv) {
|
||||
} else {
|
||||
DBG_INFO("Map resumed: %lu/%lu sectors used",
|
||||
dhara_map_size(&s_map), dhara_map_capacity(&s_map));
|
||||
/* journal 头/尾/epoch 一并打印:2026-10-02 台架复盘"复位后写入全部
|
||||
* 丢失"时,只看 sectors used 判断不出 journal 是否回退(覆盖写场景
|
||||
* count 不变),必须看 head/tail/epoch 才能发现 resume 锚错了
|
||||
* checkpoint(详见 Lib/dhara/journal.c 的 2026-10-02 本地修复注释)。
|
||||
* 纯内存字段、零 I/O,保留作长期可观测性。 */
|
||||
DBG_INFO("Map head=%lu tail=%lu epoch=%u",
|
||||
(unsigned long)s_map.journal.head,
|
||||
(unsigned long)s_map.journal.tail,
|
||||
(unsigned)s_map.journal.epoch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user