diff --git a/Src/freertos.c b/Src/freertos.c index f152c621..69e995a6 100644 --- a/Src/freertos.c +++ b/Src/freertos.c @@ -245,21 +245,26 @@ void StartDefaultTask(void *argument) } } if (fr == FR_OK) { - /* 探针:/.fschk(8.3 合规)小写一次,验证 FAT 链真实可用。本移植 + /* 探针:/fschk.tmp 小写一次,验证 FAT 链真实可用。本移植 * f_write 簇分配失败返回 FR_OK+短写 → 必须校验写回字节数;短写按 - * FR_DENIED 归一化(落入下方结构性集合触发重格式化) */ + * FR_DENIED 归一化(落入下方结构性集合触发重格式化)。 + * ⚠ 事故教训(2026-09-20 台架实证,"无限重格式化"真根因):本移植 + * FF_USE_LFN=0,ff.c create_short 把 ".fschk" 点后的 FSCHK 当扩展域 + * 解析(5 字符 > 3 上限)→ f_open 恒返 FR_INVALID_NAME(6)(纯 RAM + * 判定、不碰盘)→ 曾误入下方结构性错误集合 → 每 boot 假失败 → + * 无限重格式化。探针名必须严格 8.3:名≤8、扩展≤3、不以点开头。 */ #define FS_VOL_PROBE(h) do { \ FIL __chk; \ static const uint8_t __chkbuf[8] = { 0 }; \ UINT __bw = 0u; \ FRESULT __wr; \ - (h) = f_open(&__chk, "/.fschk", FA_WRITE | FA_OPEN_ALWAYS); \ + (h) = f_open(&__chk, "/fschk.tmp", FA_WRITE | FA_OPEN_ALWAYS); \ if ((h) == FR_OK) { \ __wr = f_write(&__chk, __chkbuf, (UINT)sizeof(__chkbuf), &__bw); \ (void)f_close(&__chk); \ if (__wr == FR_OK && __bw == (UINT)sizeof(__chkbuf)) { \ (h) = FR_OK; \ - (void)f_unlink("/.fschk"); \ + (void)f_unlink("/fschk.tmp"); \ } else { \ (h) = (__wr != FR_OK) ? __wr : FR_DENIED; \ } \ @@ -280,10 +285,12 @@ void StartDefaultTask(void *argument) nand_ftl_dump_binding(16, "postreset"); } if (hfr != FR_OK) { - if (hfr == FR_DENIED || hfr == FR_INVALID_OBJECT || + /* ⚠ FR_INVALID_NAME 绝不可入本集合:它是路径名语法错误(纯 RAM 判定、 + * 不碰盘),与卷健康无关(曾误入 → "无限重格式化"事故) */ + if (hfr == FR_DENIED || hfr == FR_INVALID_OBJECT || hfr == FR_INT_ERR || hfr == FR_DISK_ERR || hfr == FR_NO_FILE || hfr == FR_NO_PATH || - hfr == FR_INVALID_NAME || hfr == FR_NO_FILESYSTEM) { + hfr == FR_NO_FILESYSTEM) { DBG_INFO("[FS] volume FAT invalid (fr=%d), reformatting...", (int)hfr); f_mount(NULL, "", 0);