GD5F页读回归主线单发令(settle与二次发令移除、3.1V误判更正归一Trap05)、新增Phase11复现用例(16轮零复现)、附台架环境与审计文档
This commit is contained in:
@@ -785,6 +785,151 @@ static void gd5f_phase10(void)
|
||||
}
|
||||
#endif /* ENABLE_GD5F_PHASE10_TESTS */
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
* Phase 11 — 13h 锁存 / WIP 提前清零对照复现(2026-09-21 台架实验)
|
||||
*
|
||||
* 复现对象 = 09-20 两项读异常(归因/证伪史实见 GD5F Trap_Records
|
||||
* Trap 05,本用例只承担复现职能):
|
||||
* H1: 编程/擦除风暴后 13h 命令未被锁存(空操作)→ 0Bh 读残留缓存
|
||||
* H2: WIP 早于 array→cache 整页装载完成而清零 → 0Bh 读混合页
|
||||
* 设计:
|
||||
* 每轮:擦块 → 64 页背靠背编程(风暴,每页唯一图案)→ 立即(零间隔,
|
||||
* 最坏时序)13h 读 3 个非相邻页并逐字节比对。
|
||||
* 读目标刻意避开最后编程的页(页 63):若 13h 为空操作,残留缓存即
|
||||
* 最后一次编程的数据,读页 63 会巧合一致而掩盖故障;读其他页时,
|
||||
* 空操作(整页陈旧 = 页 63 图案)与提前清零(前段新后段旧)都会
|
||||
* 表现为不一致。
|
||||
* 对照组:延迟 50ms 后重读同 3 页——立即读失败而延迟读成功 = 时间窗型故障。
|
||||
* 首次失败时记录页头/尾 4B,用于区分 H1 / H2 签名。
|
||||
* 影响面:仅擦写最高一块(gd5f_find_run(1) 取最高好块,远离 FTL 活跃区);
|
||||
* 不写 BBT、不格式化卷。
|
||||
* ------------------------------------------------------------------- */
|
||||
#ifdef ENABLE_GD5F_PHASE11_TESTS
|
||||
|
||||
#define GD5F_P11_ROUNDS 16
|
||||
static const uint32_t s_p11_probe[3] = {0, 21, 43};
|
||||
|
||||
static void gd5f_phase11(void)
|
||||
{
|
||||
uint32_t blk;
|
||||
uint32_t page0;
|
||||
int32_t round, pi, p, i;
|
||||
int32_t ret;
|
||||
int32_t storm_fail = 0;
|
||||
int32_t imm_fail = 0, ctl_fail = 0;
|
||||
int32_t imm_bad = 0, ctl_bad = 0;
|
||||
int32_t first_bad = -1;
|
||||
|
||||
blk = gd5f_find_run(1);
|
||||
if (blk >= GD5F_TOTAL_BLOCKS) {
|
||||
GD5F_TEST_CHECK(0, "TC-GD5F-1100 no usable block for repro");
|
||||
GD5F_TEST_REPORT("GD5F Phase 11");
|
||||
return;
|
||||
}
|
||||
page0 = blk * GD5F_PAGES_PER_BLOCK;
|
||||
|
||||
DBG_INFO("=== GD5F Phase 11: 13h latch / WIP repro (%d rounds, block %u) ===",
|
||||
GD5F_P11_ROUNDS, (unsigned)blk);
|
||||
|
||||
for (round = 1; round <= GD5F_P11_ROUNDS; round++) {
|
||||
int32_t round_bad = 0;
|
||||
|
||||
/* 风暴:擦除 + 64 页背靠背编程(图案 = i ^ p*0x11 ^ round*0x37) */
|
||||
if (gd5f_block_erase(blk) != GD5F_OK) {
|
||||
storm_fail++;
|
||||
}
|
||||
for (p = 0; p < GD5F_PAGES_PER_BLOCK; p++) {
|
||||
for (i = 0; i < GD5F_PAGE_SIZE; i++) {
|
||||
s_wbuf[i] = (uint8_t)(i ^ (p * 0x11) ^ (round * 0x37));
|
||||
}
|
||||
gd5f_write_enable();
|
||||
if (gd5f_program_load(0, s_wbuf, GD5F_PAGE_SIZE) != GD5F_OK ||
|
||||
gd5f_program_exec(page0 + (uint32_t)p) != GD5F_OK) {
|
||||
storm_fail++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 立即读(零间隔、最坏时序):3 个非相邻页逐字节比对 */
|
||||
for (pi = 0; pi < 3; pi++) {
|
||||
int32_t ok = 1;
|
||||
uint8_t want;
|
||||
|
||||
ret = gd5f_page_read(page0 + s_p11_probe[pi]);
|
||||
if (ret != GD5F_OK) {
|
||||
ok = 0;
|
||||
}
|
||||
memset(s_rbuf, 0, GD5F_PAGE_SIZE);
|
||||
if (gd5f_read_from_cache(0, s_rbuf, GD5F_PAGE_SIZE) != GD5F_OK) {
|
||||
ok = 0;
|
||||
}
|
||||
for (i = 0; ok && i < GD5F_PAGE_SIZE; i++) {
|
||||
want = (uint8_t)(i ^ (s_p11_probe[pi] * 0x11) ^ (round * 0x37));
|
||||
if (s_rbuf[i] != want) {
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
imm_fail++;
|
||||
round_bad = 1;
|
||||
if (first_bad < 0) {
|
||||
first_bad = round;
|
||||
DBG_INFO("TC-GD5F-1101 r=%d p=%u IMM mismatch head=%02X %02X %02X %02X "
|
||||
"tail=%02X %02X %02X %02X",
|
||||
round, (unsigned)s_p11_probe[pi],
|
||||
s_rbuf[0], s_rbuf[1], s_rbuf[2], s_rbuf[3],
|
||||
s_rbuf[GD5F_PAGE_SIZE - 4], s_rbuf[GD5F_PAGE_SIZE - 3],
|
||||
s_rbuf[GD5F_PAGE_SIZE - 2], s_rbuf[GD5F_PAGE_SIZE - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 对照组:延迟 50ms 后重读同 3 页(区分时间窗型故障) */
|
||||
HAL_Delay(50);
|
||||
for (pi = 0; pi < 3; pi++) {
|
||||
int32_t ok = 1;
|
||||
uint8_t want;
|
||||
|
||||
ret = gd5f_page_read(page0 + s_p11_probe[pi]);
|
||||
if (ret != GD5F_OK) {
|
||||
ok = 0;
|
||||
}
|
||||
memset(s_rbuf, 0, GD5F_PAGE_SIZE);
|
||||
if (gd5f_read_from_cache(0, s_rbuf, GD5F_PAGE_SIZE) != GD5F_OK) {
|
||||
ok = 0;
|
||||
}
|
||||
for (i = 0; ok && i < GD5F_PAGE_SIZE; i++) {
|
||||
want = (uint8_t)(i ^ (s_p11_probe[pi] * 0x11) ^ (round * 0x37));
|
||||
if (s_rbuf[i] != want) {
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
ctl_fail++;
|
||||
ctl_bad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (round_bad) {
|
||||
imm_bad++;
|
||||
}
|
||||
if (round == 1 || (round & 3) == 0) {
|
||||
DBG_INFO("TC-GD5F-1101 progress r=%d/%d storm_fail=%d imm_fail=%d ctl_fail=%d",
|
||||
round, GD5F_P11_ROUNDS, storm_fail, imm_fail, ctl_fail);
|
||||
}
|
||||
}
|
||||
|
||||
GD5F_TEST_CHECK(storm_fail == 0,
|
||||
"TC-GD5F-1100 storm ops: erase/program all OK (fail=%d)", storm_fail);
|
||||
GD5F_TEST_CHECK(imm_bad == 0,
|
||||
"TC-GD5F-1101 immediate read after storm: %d/%d bad rounds (pages=%d first=%d)",
|
||||
imm_bad, GD5F_P11_ROUNDS, imm_fail, first_bad);
|
||||
GD5F_TEST_CHECK(ctl_fail == 0,
|
||||
"TC-GD5F-1102 delayed(50ms) read: %d/%d bad rounds (pages=%d)",
|
||||
ctl_bad, GD5F_P11_ROUNDS, ctl_fail);
|
||||
GD5F_TEST_REPORT("GD5F Phase 11");
|
||||
}
|
||||
#endif /* ENABLE_GD5F_PHASE11_TESTS */
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
* 入口:按启用的阶段顺序执行并汇总
|
||||
* ------------------------------------------------------------------- */
|
||||
@@ -829,6 +974,9 @@ void gd5f_test_run(void)
|
||||
#ifdef ENABLE_GD5F_PHASE10_TESTS
|
||||
gd5f_phase10();
|
||||
#endif
|
||||
#ifdef ENABLE_GD5F_PHASE11_TESTS
|
||||
gd5f_phase11();
|
||||
#endif
|
||||
|
||||
GD5F_TEST_REPORT("GD5F2GQ5UE Tests");
|
||||
DBG_INFO("########## GD5F2GQ5UE Test Done ##########");
|
||||
|
||||
Reference in New Issue
Block a user