FTL诊断:L0探针窗口绑定路径日志(FAT读LPN→物理页+写目标)+重格式化行带fr码
This commit is contained in:
@@ -54,6 +54,20 @@ static uint8_t s_initialized;
|
|||||||
|
|
||||||
/* resume 搜索探针日志窗口(诊断:逐探测记录判定输入) */
|
/* resume 搜索探针日志窗口(诊断:逐探测记录判定输入) */
|
||||||
static uint8_t s_probe_log;
|
static uint8_t s_probe_log;
|
||||||
|
/* L0 卷健康探针窗口(诊断:记录 FAT 读的 LPN 绑定 → 物理页路径) */
|
||||||
|
static uint8_t s_tree_probe_log;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 函数功能:打开/关闭 L0 卷健康探针日志窗口
|
||||||
|
* 入口参数:on - 1 打开,0 关闭
|
||||||
|
* 返回值:无
|
||||||
|
* 限定条件:FTL 已初始化
|
||||||
|
* 函数说明:窗口内的 dhara_nand_read/is_free/is_bad 调用逐条记录
|
||||||
|
* 物理页(= journal LPN),用于判定 map 绑定指向
|
||||||
|
*/
|
||||||
|
void nand_ftl_set_tree_probe(uint8_t on) {
|
||||||
|
s_tree_probe_log = on;
|
||||||
|
}
|
||||||
|
|
||||||
/* ======================== 私有函数声明 ======================== */
|
/* ======================== 私有函数声明 ======================== */
|
||||||
|
|
||||||
@@ -90,6 +104,10 @@ static int ftl_read_page(dhara_sector_t lpn) {
|
|||||||
|
|
||||||
s_cached_lpn = lpn;
|
s_cached_lpn = lpn;
|
||||||
s_cache_dirty = 0;
|
s_cache_dirty = 0;
|
||||||
|
if (s_tree_probe_log) {
|
||||||
|
DBG_INFO("ftl read LPN=%lu (binding see nand read lines)",
|
||||||
|
(unsigned long)lpn);
|
||||||
|
}
|
||||||
return GD5F_OK;
|
return GD5F_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +116,7 @@ static int ftl_read_page(dhara_sector_t lpn) {
|
|||||||
int dhara_nand_is_bad(const struct dhara_nand *n, dhara_block_t b) {
|
int dhara_nand_is_bad(const struct dhara_nand *n, dhara_block_t b) {
|
||||||
(void)n;
|
(void)n;
|
||||||
const int bad = gd5f2gq5ue_is_block_bad(ftl_phy_block(b));
|
const int bad = gd5f2gq5ue_is_block_bad(ftl_phy_block(b));
|
||||||
if (s_probe_log) {
|
if (s_probe_log || s_tree_probe_log) {
|
||||||
DBG_INFO("probe blk %lu: bbt_bad=%u", (unsigned long)b,
|
DBG_INFO("probe blk %lu: bbt_bad=%u", (unsigned long)b,
|
||||||
(unsigned int)bad);
|
(unsigned int)bad);
|
||||||
}
|
}
|
||||||
@@ -125,6 +143,12 @@ int dhara_nand_prog(const struct dhara_nand *n, dhara_page_t p, const uint8_t *d
|
|||||||
int ret;
|
int ret;
|
||||||
uint32_t phy_pg = ftl_phy_page(p);
|
uint32_t phy_pg = ftl_phy_page(p);
|
||||||
|
|
||||||
|
if (s_probe_log || s_tree_probe_log) {
|
||||||
|
DBG_INFO("probe t %lu prog pg %lu blk %lu g%lu",
|
||||||
|
(unsigned long)HAL_GetTick(), (unsigned long)phy_pg,
|
||||||
|
(unsigned long)(p >> 6), (unsigned long)((p >> 4) & 3u));
|
||||||
|
}
|
||||||
|
|
||||||
gd5f_write_enable();
|
gd5f_write_enable();
|
||||||
ret = gd5f_program_load(0, data, FTL_PAGE_SIZE);
|
ret = gd5f_program_load(0, data, FTL_PAGE_SIZE);
|
||||||
if (ret != GD5F_OK) {
|
if (ret != GD5F_OK) {
|
||||||
@@ -193,7 +217,7 @@ int dhara_nand_is_free(const struct dhara_nand *n, dhara_page_t p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s_probe_log) {
|
if (s_probe_log || s_tree_probe_log) {
|
||||||
DBG_INFO("probe t %lu isfree pg %lu = %u",
|
DBG_INFO("probe t %lu isfree pg %lu = %u",
|
||||||
(unsigned long)HAL_GetTick(), (unsigned long)phy_pg,
|
(unsigned long)HAL_GetTick(), (unsigned long)phy_pg,
|
||||||
(unsigned int)fre);
|
(unsigned int)fre);
|
||||||
@@ -208,7 +232,7 @@ int dhara_nand_read(const struct dhara_nand *n, dhara_page_t p, size_t offset, s
|
|||||||
int eret;
|
int eret;
|
||||||
|
|
||||||
if ((rret = gd5f_page_read(phy_pg)) != GD5F_OK) {
|
if ((rret = gd5f_page_read(phy_pg)) != GD5F_OK) {
|
||||||
if (s_probe_log) {
|
if (s_probe_log || s_tree_probe_log) {
|
||||||
DBG_INFO("probe pg %lu blk %lu: page_read=%d",
|
DBG_INFO("probe pg %lu blk %lu: page_read=%d",
|
||||||
(unsigned long)phy_pg, (unsigned long)(p >> 6),
|
(unsigned long)phy_pg, (unsigned long)(p >> 6),
|
||||||
rret);
|
rret);
|
||||||
@@ -218,7 +242,7 @@ int dhara_nand_read(const struct dhara_nand *n, dhara_page_t p, size_t offset, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((eret = gd5f_check_ecc()) != GD5F_OK) {
|
if ((eret = gd5f_check_ecc()) != GD5F_OK) {
|
||||||
if (s_probe_log) {
|
if (s_probe_log || s_tree_probe_log) {
|
||||||
DBG_INFO("probe pg %lu blk %lu: ecc=%d",
|
DBG_INFO("probe pg %lu blk %lu: ecc=%d",
|
||||||
(unsigned long)phy_pg, (unsigned long)(p >> 6),
|
(unsigned long)phy_pg, (unsigned long)(p >> 6),
|
||||||
eret);
|
eret);
|
||||||
@@ -229,7 +253,8 @@ int dhara_nand_read(const struct dhara_nand *n, dhara_page_t p, size_t offset, s
|
|||||||
|
|
||||||
gd5f_read_from_cache((uint16_t)offset, data, length);
|
gd5f_read_from_cache((uint16_t)offset, data, length);
|
||||||
|
|
||||||
if (s_probe_log && offset == 0 && length == FTL_PAGE_SIZE) {
|
if ((s_probe_log || s_tree_probe_log) &&
|
||||||
|
offset == 0 && length == FTL_PAGE_SIZE) {
|
||||||
/* 组末页(组内偏移 15:页号低 4 位 = 15)= checkpoint 页:
|
/* 组末页(组内偏移 15:页号低 4 位 = 15)= checkpoint 页:
|
||||||
* 记录 header 前 4 字节 + meta 区 4 字节(偏移 944 = 槽 7,
|
* 记录 header 前 4 字节 + meta 区 4 字节(偏移 944 = 槽 7,
|
||||||
* 树根 meta)+ 时间戳。header 新/meta 旧 = 半新半旧混合页
|
* 树根 meta)+ 时间戳。header 新/meta 旧 = 半新半旧混合页
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ void nand_ftl_deinit(void);
|
|||||||
/* 诊断接口:打印 journal 状态 / 全扫 checkpoint 分布(跨复位持久性分析) */
|
/* 诊断接口:打印 journal 状态 / 全扫 checkpoint 分布(跨复位持久性分析) */
|
||||||
void nand_ftl_log_state(const char *tag);
|
void nand_ftl_log_state(const char *tag);
|
||||||
void nand_ftl_scan_checks(void);
|
void nand_ftl_scan_checks(void);
|
||||||
|
void nand_ftl_set_tree_probe(uint8_t on);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -260,9 +260,13 @@ void StartDefaultTask(void *argument)
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
FRESULT hfr;
|
FRESULT hfr;
|
||||||
|
nand_ftl_set_tree_probe(1);
|
||||||
FS_VOL_PROBE(hfr);
|
FS_VOL_PROBE(hfr);
|
||||||
if (hfr != FR_OK) {
|
if (hfr != FR_OK) {
|
||||||
FS_VOL_PROBE(hfr); /* 两击确认 */
|
FS_VOL_PROBE(hfr); /* 两击确认 */
|
||||||
|
}
|
||||||
|
nand_ftl_set_tree_probe(0);
|
||||||
|
if (hfr != FR_OK) {
|
||||||
nand_ftl_scan_checks(); /* 诊断:环上 checkpoint 的 epoch 分布 */
|
nand_ftl_scan_checks(); /* 诊断:环上 checkpoint 的 epoch 分布 */
|
||||||
}
|
}
|
||||||
if (hfr != FR_OK) {
|
if (hfr != FR_OK) {
|
||||||
@@ -270,7 +274,8 @@ void StartDefaultTask(void *argument)
|
|||||||
hfr == FR_INT_ERR || hfr == FR_DISK_ERR ||
|
hfr == FR_INT_ERR || hfr == FR_DISK_ERR ||
|
||||||
hfr == FR_NO_FILE || hfr == FR_NO_PATH ||
|
hfr == FR_NO_FILE || hfr == FR_NO_PATH ||
|
||||||
hfr == FR_INVALID_NAME || hfr == FR_NO_FILESYSTEM) {
|
hfr == FR_INVALID_NAME || hfr == FR_NO_FILESYSTEM) {
|
||||||
DBG_INFO("[FS] volume FAT invalid, reformatting...");
|
DBG_INFO("[FS] volume FAT invalid (fr=%d), reformatting...",
|
||||||
|
(int)hfr);
|
||||||
f_mount(NULL, "", 0);
|
f_mount(NULL, "", 0);
|
||||||
{
|
{
|
||||||
static uint8_t fs_work2[FF_MAX_SS];
|
static uint8_t fs_work2[FF_MAX_SS];
|
||||||
|
|||||||
Reference in New Issue
Block a user