diff --git a/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c b/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c index 82a78b1a..7aa2c5c8 100644 --- a/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c +++ b/Drivers/BSP/GD5F2GQ5UE/nand_ftl.c @@ -143,6 +143,10 @@ static uint8_t s_cache_dirty; /* 拷贝临时缓冲区 */ static uint8_t s_copy_buf[FTL_PAGE_SIZE]; +/* 【#85 P0 台架实证】写提交回读探针缓冲 + 计数 */ +static uint8_t s_prog_verify_buf[FTL_PAGE_SIZE]; +static volatile uint32_t s_prog_verify_mismatch; + /* 初始化状态 */ static uint8_t s_initialized; @@ -276,6 +280,15 @@ static bsp_err_t ftl_flush_cache(void) { return cls; } + /* 【#85 P0 台架实证】map 状态日志:每次写后打 root/head/tail/epoch/count, + * 对照台架打回时刻的 map 状态,确认 root 是否回退。仅台架实证用,量产前移除。 */ + DBG_INFO("map_write: root=%lu head=%lu tail=%lu epoch=%u count=%lu", + (unsigned long)s_map.journal.root, + (unsigned long)s_map.journal.head, + (unsigned long)s_map.journal.tail, + (unsigned)s_map.journal.epoch, + (unsigned long)s_map.count); + s_cache_dirty = 0; return BSP_OK; } @@ -381,10 +394,29 @@ int dhara_nand_prog(const struct dhara_nand *n, dhara_page_t p, const uint8_t *d return -1; } - /* 编程正确性以 P_FAIL 状态位(gd5f_program_exec 内检查)+ 读时 ECC + - * journal 读时门(magic/CRC)为准;数据路径不做整页回读比对—— - * 2026-09-20 曾加回读校验(GD5F_PROG_VERIFY),2026-09-21 经评估整体 - * 移除(依据见 docs/内存管理/存储栈RAM优化调研.md 与 GD5F Trap Records TRAP-GD5F-05) */ + /* 【#85 P0 台架实证】写提交回读探针:编程成功后立即回读同 PPN 做字节比对。 + * 2026-09-20 曾加回读校验(GD5F_PROG_VERIFY),2026-09-21 经评估整体移除。 + * 现以低频探针形式恢复:仅台架实证用,量产前移除。 + * 目的:在 FTL 层直接抓到"编程成功但回读不一致"的窗口, + * 区分"NAND 编程未落地" vs "map 指旧 PPN"。 */ + { + int32_t vret; + vret = gd5f_page_read(phy_pg); + if (vret == GD5F_OK) { + vret = gd5f_read_from_cache(0, s_prog_verify_buf, FTL_PAGE_SIZE); + if (vret == GD5F_OK) { + if (gd5f_check_ecc() == GD5F_ECC_ERROR) { + DBG_ERROR("Prog verify: ECC error on readback page=%lu", + (unsigned long)phy_pg); + s_prog_verify_mismatch++; + } else if (memcmp(data, s_prog_verify_buf, FTL_PAGE_SIZE) != 0) { + DBG_ERROR("Prog verify: MISMATCH page=%lu (data differs after prog)", + (unsigned long)phy_pg); + s_prog_verify_mismatch++; + } + } + } + } return 0; }