FTL诊断增强:resume前裸NAND checkpoint扫描+header十六进制转储(定位编程落盘问题)
This commit is contained in:
@@ -56,6 +56,7 @@ static uint8_t s_initialized;
|
|||||||
|
|
||||||
static int ftl_flush_cache(void);
|
static int ftl_flush_cache(void);
|
||||||
static int ftl_read_page(dhara_sector_t lpn);
|
static int ftl_read_page(dhara_sector_t lpn);
|
||||||
|
static void ftl_scan_checks_raw(void);
|
||||||
|
|
||||||
/* SPI 原语从 gd5f2gq5ue.h 获取 */
|
/* SPI 原语从 gd5f2gq5ue.h 获取 */
|
||||||
|
|
||||||
@@ -205,6 +206,12 @@ DSTATUS disk_initialize(BYTE pdrv) {
|
|||||||
|
|
||||||
dhara_map_init(&s_map, &s_nand, s_page_buf, 4);
|
dhara_map_init(&s_map, &s_nand, s_page_buf, 4);
|
||||||
|
|
||||||
|
/* 诊断:resume 前的裸 NAND checkpoint 扫描(复位后地面真值,
|
||||||
|
* 不经 FTL 缓存)——判定上一开机的 checkpoint 页是否真正写入芯片 */
|
||||||
|
DBG_INFO("Pre-resume raw check scan start: blocks=%lu",
|
||||||
|
(unsigned long)s_nand.num_blocks);
|
||||||
|
ftl_scan_checks_raw();
|
||||||
|
|
||||||
memset(s_cache_buf, 0, FTL_PAGE_SIZE);
|
memset(s_cache_buf, 0, FTL_PAGE_SIZE);
|
||||||
s_cached_lpn = (dhara_sector_t)-1; /* -1 表示缓存未加载;LPN 0 合法,不能用 0 作哨兵 */
|
s_cached_lpn = (dhara_sector_t)-1; /* -1 表示缓存未加载;LPN 0 合法,不能用 0 作哨兵 */
|
||||||
s_cache_dirty = 0;
|
s_cache_dirty = 0;
|
||||||
@@ -421,9 +428,34 @@ void nand_ftl_log_state(const char *tag)
|
|||||||
(unsigned long)dhara_map_size(&s_map));
|
(unsigned long)dhara_map_size(&s_map));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 打印某块 checkpoint 页的 16 字节 header(magic/epoch/tail/bb),
|
||||||
|
* 用于区分"未落盘(全FF)"/"编程失败(花)"/"完整" 三种状态 */
|
||||||
|
static void ftl_dump_checkheader(uint32_t blk)
|
||||||
|
{
|
||||||
|
uint8_t hdr[16];
|
||||||
|
|
||||||
|
const uint32_t pg = ftl_phy_page((blk << s_nand.log2_ppb) |
|
||||||
|
((1u << s_map.journal.log2_ppc) - 1u));
|
||||||
|
if (gd5f_page_read(pg) != GD5F_OK) {
|
||||||
|
DBG_INFO("check hdr blk %lu: read fail", (unsigned long)blk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gd5f_read_from_cache(0, hdr, sizeof(hdr));
|
||||||
|
DBG_INFO("check hdr blk %lu: %02X %02X %02X %02X %02X %02X %02X %02X "
|
||||||
|
"%02X %02X %02X %02X %02X %02X %02X %02X",
|
||||||
|
(unsigned long)blk,
|
||||||
|
(unsigned int)hdr[0], (unsigned int)hdr[1], (unsigned int)hdr[2],
|
||||||
|
(unsigned int)hdr[3], (unsigned int)hdr[4], (unsigned int)hdr[5],
|
||||||
|
(unsigned int)hdr[6], (unsigned int)hdr[7],
|
||||||
|
(unsigned int)hdr[8], (unsigned int)hdr[9], (unsigned int)hdr[10],
|
||||||
|
(unsigned int)hdr[11], (unsigned int)hdr[12], (unsigned int)hdr[13],
|
||||||
|
(unsigned int)hdr[14], (unsigned int)hdr[15]);
|
||||||
|
}
|
||||||
|
|
||||||
/* 全扫每块首组 checkpoint 页(magic+epoch),打印连续区段分布,
|
/* 全扫每块首组 checkpoint 页(magic+epoch),打印连续区段分布,
|
||||||
* 用于识别 journal 环上的 epoch 分界与空洞 */
|
* 用于识别 journal 环上的 epoch 分界与空洞。
|
||||||
void nand_ftl_scan_checks(void)
|
* 裸读(gd5f 页读),不受 FTL 缓存影响 = NAND 真实内容。 */
|
||||||
|
static void ftl_scan_checks_raw(void)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint8_t buf[8];
|
uint8_t buf[8];
|
||||||
@@ -434,12 +466,6 @@ void nand_ftl_scan_checks(void)
|
|||||||
uint8_t run_epoch = 0;
|
uint8_t run_epoch = 0;
|
||||||
uint8_t run_open = 0;
|
uint8_t run_open = 0;
|
||||||
|
|
||||||
if (!s_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_INFO("check scan start: blocks=%lu", (unsigned long)s_nand.num_blocks);
|
|
||||||
|
|
||||||
for (i = 0; i < s_nand.num_blocks; i++) {
|
for (i = 0; i < s_nand.num_blocks; i++) {
|
||||||
const uint32_t pg = ftl_phy_page((i << s_nand.log2_ppb) |
|
const uint32_t pg = ftl_phy_page((i << s_nand.log2_ppb) |
|
||||||
((1u << s_map.journal.log2_ppc) - 1u));
|
((1u << s_map.journal.log2_ppc) - 1u));
|
||||||
@@ -457,6 +483,7 @@ void nand_ftl_scan_checks(void)
|
|||||||
DBG_INFO("check run: blk %lu..%lu epoch=%u (%lu blocks)",
|
DBG_INFO("check run: blk %lu..%lu epoch=%u (%lu blocks)",
|
||||||
(unsigned long)run_start, (unsigned long)run_prev,
|
(unsigned long)run_start, (unsigned long)run_prev,
|
||||||
(unsigned int)run_epoch, (unsigned long)run_len);
|
(unsigned int)run_epoch, (unsigned long)run_len);
|
||||||
|
ftl_dump_checkheader(run_start);
|
||||||
}
|
}
|
||||||
run_start = i;
|
run_start = i;
|
||||||
run_epoch = ep;
|
run_epoch = ep;
|
||||||
@@ -471,6 +498,17 @@ void nand_ftl_scan_checks(void)
|
|||||||
DBG_INFO("check run: blk %lu..%lu epoch=%u (%lu blocks)",
|
DBG_INFO("check run: blk %lu..%lu epoch=%u (%lu blocks)",
|
||||||
(unsigned long)run_start, (unsigned long)run_prev,
|
(unsigned long)run_start, (unsigned long)run_prev,
|
||||||
(unsigned int)run_epoch, (unsigned long)run_len);
|
(unsigned int)run_epoch, (unsigned long)run_len);
|
||||||
|
ftl_dump_checkheader(run_start);
|
||||||
}
|
}
|
||||||
DBG_INFO("check scan done: %lu checkpoint blocks", (unsigned long)total);
|
DBG_INFO("check scan done: %lu checkpoint blocks", (unsigned long)total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nand_ftl_scan_checks(void)
|
||||||
|
{
|
||||||
|
if (!s_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG_INFO("check scan start: blocks=%lu", (unsigned long)s_nand.num_blocks);
|
||||||
|
ftl_scan_checks_raw();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user