测试套件增设破坏性用例总开关(默认只读),GD5F/存储/RTC 破坏性用例改为按需开启

This commit is contained in:
2026-09-21 03:22:12 +08:00
parent 23a03a6136
commit 51c5707f49
9 changed files with 287 additions and 149 deletions
+91 -61
View File
@@ -170,10 +170,6 @@ static void gd5f_phase2(void)
{
uint32_t usable = gd5f_get_usable_blocks();
uint32_t X = gd5f_find_run(1); /* 管理区内的一个好块 */
uint8_t flash_bbt[GD5F_TOTAL_BLOCKS / 8];
uint32_t ver = 0;
uint32_t cnt_a, cnt_b;
int32_t marked;
/* TC-GD5F-205: 保留块池已预留,dhara 可用块数 < 总块数;
* 且测试用块 X 落在管理区内(不会擦到 BBT 存储区) */
@@ -182,36 +178,48 @@ static void gd5f_phase2(void)
GD5F_TEST_CHECK(X < usable,
"TC-GD5F-205 test block X=%lu < usable=%lu", X, usable);
/* TC-GD5F-206: 标记坏块后 RAM 生效,且已落盘(闪存副本含该位、版本>=1) */
gd5f2gq5ue_mark_block_bad(X);
marked = gd5f2gq5ue_is_block_bad(X);
GD5F_TEST_CHECK(marked == 1, "TC-GD5F-206 RAM mark X=%lu -> %d", X, marked);
if (GD5F_OK == gd5f_bbt_dump_flash(flash_bbt, &ver)) {
int32_t flash_bit = (flash_bbt[X >> 3] >> (X & 7)) & 1;
GD5F_TEST_CHECK(flash_bit == 1 && ver >= 1,
"TC-GD5F-206 flash persist X bit=%d ver=%lu", flash_bit, ver);
} else {
GD5F_TEST_CHECK(0, "TC-GD5F-206 dump_flash failed");
}
#ifdef ENABLE_DESTRUCTIVE_TESTS
{
uint8_t flash_bbt[GD5F_TOTAL_BLOCKS / 8];
uint32_t ver = 0;
uint32_t cnt_a, cnt_b;
int32_t marked;
/* TC-GD5F-207: 清空 RAM 后从闪存重载,坏块记录被恢复(验证 load 链路) */
cnt_a = gd5f_count_bad();
gd5f2gq5ue_bbt_clear();
gd5f_bbt_reload();
marked = gd5f2gq5ue_is_block_bad(X);
cnt_b = gd5f_count_bad();
GD5F_TEST_CHECK(marked == 1 && cnt_b >= cnt_a,
"TC-GD5F-207 reload X=%lu restored (cnt %lu->%lu)", X, cnt_a, cnt_b);
/* 清理:还原出厂快照(RAM)并擦除保留池(闪存),设备回到干净态,
* 保证测试可重复且不在 NAND 上留下伪坏块 */
gd5f2gq5ue_bbt_clear();
for (blk = 0; blk < GD5F_TOTAL_BLOCKS; blk++) {
if ((orig_bad[blk >> 5] & (1U << (blk & 31))) != 0) {
gd5f2gq5ue_mark_block_bad(blk);
/* TC-GD5F-206: 标记坏块后 RAM 生效,且已落盘(闪存副本含该位、版本>=1) */
gd5f2gq5ue_mark_block_bad(X);
marked = gd5f2gq5ue_is_block_bad(X);
GD5F_TEST_CHECK(marked == 1, "TC-GD5F-206 RAM mark X=%lu -> %d", X, marked);
if (GD5F_OK == gd5f_bbt_dump_flash(flash_bbt, &ver)) {
int32_t flash_bit = (flash_bbt[X >> 3] >> (X & 7)) & 1;
GD5F_TEST_CHECK(flash_bit == 1 && ver >= 1,
"TC-GD5F-206 flash persist X bit=%d ver=%lu", flash_bit, ver);
} else {
GD5F_TEST_CHECK(0, "TC-GD5F-206 dump_flash failed");
}
/* TC-GD5F-207: 清空 RAM 后从闪存重载,坏块记录被恢复(验证 load 链路) */
cnt_a = gd5f_count_bad();
gd5f2gq5ue_bbt_clear();
gd5f_bbt_reload();
marked = gd5f2gq5ue_is_block_bad(X);
cnt_b = gd5f_count_bad();
GD5F_TEST_CHECK(marked == 1 && cnt_b >= cnt_a,
"TC-GD5F-207 reload X=%lu restored (cnt %lu->%lu)", X, cnt_a, cnt_b);
/* 清理:还原出厂快照(RAM)并擦除保留池(闪存),设备回到干净态,
* 保证测试可重复且不在 NAND 上留下伪坏块 */
gd5f2gq5ue_bbt_clear();
for (blk = 0; blk < GD5F_TOTAL_BLOCKS; blk++) {
if ((orig_bad[blk >> 5] & (1U << (blk & 31))) != 0) {
gd5f2gq5ue_mark_block_bad(blk);
}
}
gd5f_bbt_wipe_pool();
}
gd5f_bbt_wipe_pool();
#else
DBG_INFO("TC-GD5F-206/207 skipped: destructive tests disabled "
"(BBT flash persist + pool wipe)");
#endif
}
}
#endif /* ENABLE_GD5F_PHASE2_TESTS */
@@ -536,6 +544,7 @@ static void gd5f_phase7(void)
blk = gd5f_find_run(1);
base = (int32_t)blk * GD5F_BLOCK_SIZE;
#ifdef ENABLE_DESTRUCTIVE_TESTS
/* TC-GD5F-701: 阈值下界(= 阈值,轮询路径) */
gd5f2gq5ue_erase(base, GD5F_BLOCK_SIZE);
for (i = 0; i < (int32_t)GD5F_DMA_THRESHOLD; i++) {
@@ -582,6 +591,9 @@ static void gd5f_phase7(void)
if (s_rbuf[i] != (uint8_t)(i & 0xFF)) { ok = 0; break; }
}
GD5F_TEST_CHECK(ok, "TC-GD5F-703 DMA whole page %s", ok ? "OK" : "MISMATCH");
#else
DBG_INFO("TC-GD5F-701/702/703 skipped: destructive tests disabled (write/erase)");
#endif
/* ================= DMA 可达性守卫(负路径) =================
* 探针缓冲取自 FreeRTOS 堆:堆驻留 CCM(0x10000000),DMA1/DMA2 不可达。
@@ -598,7 +610,7 @@ static void gd5f_phase7(void)
DBG_INFO("TC-GD5F-704/705 SKIP: heap buf not in CCM (p=0x%08lX)",
(unsigned long)p_addr);
} else {
/* TC-GD5F-704: 读方向 —— 目的缓冲在 CCM,应回落轮询 */
/* TC-GD5F-704: 读方向 —— 目的缓冲在 CCM,应回落轮询(只读,日常回归亦运行) */
memset(s_rbuf, 0, GD5F_PAGE_SIZE);
(void)gd5f2gq5ue_read(base, s_rbuf, GD5F_PAGE_SIZE); /* 参考读(SRAM 静态) */
for (i = 0; i < GD5F_PAGE_SIZE; i++) {
@@ -610,7 +622,8 @@ static void gd5f_phase7(void)
GD5F_TEST_CHECK(ok, "TC-GD5F-704 CCM(heap) rx poll fallback %s",
ok ? "OK" : "MISMATCH");
/* TC-GD5F-705: 写方向 —— 源缓冲在 CCM,应回落轮询 */
#ifdef ENABLE_DESTRUCTIVE_TESTS
/* TC-GD5F-705: 写方向 —— 源缓冲在 CCM,应回落轮询(需擦写) */
gd5f2gq5ue_erase(base, GD5F_BLOCK_SIZE);
for (i = 0; i < GD5F_PAGE_SIZE; i++) {
p_heap[i] = (uint8_t)(i ^ 0x5A);
@@ -625,6 +638,9 @@ static void gd5f_phase7(void)
}
GD5F_TEST_CHECK(ok, "TC-GD5F-705 CCM(heap) tx poll fallback %s",
ok ? "OK" : "MISMATCH");
#else
DBG_INFO("TC-GD5F-705 skipped: destructive tests disabled (write/erase)");
#endif
}
vPortFree(p_heap);
}
@@ -709,7 +725,7 @@ static void gd5f_phase10(void)
{
uint32_t blk;
int32_t base;
int32_t ret, i, ne, ok;
int32_t ret;
DBG_INFO("=== GD5F Phase 10: boundary conditions ===");
blk = gd5f_find_run(1);
@@ -729,35 +745,43 @@ static void gd5f_phase10(void)
ret = gd5f2gq5ue_write(base, s_wbuf, 0);
GD5F_TEST_CHECK(ret == GD5F_OK, "TC-GD5F-1002 write size=0 ret=%d", ret);
/* TC-GD5F-1003: 写前未擦除 → 数据不可预期(NAND 不可原地覆盖)
* 先擦除写入全 0x00,再不清擦写入全 0xFF(需要 0→1,物理不可行),
* 读回应仍 != 0xFF。 */
gd5f2gq5ue_erase(base, GD5F_BLOCK_SIZE);
memset(s_wbuf, 0x00, GD5F_PAGE_SIZE);
gd5f2gq5ue_write(base, s_wbuf, GD5F_PAGE_SIZE);
memset(s_wbuf, 0xFF, GD5F_PAGE_SIZE);
gd5f2gq5ue_write(base, s_wbuf, GD5F_PAGE_SIZE); /* 未擦除,0→1 不可能 */
memset(s_rbuf, 0, GD5F_PAGE_SIZE);
gd5f2gq5ue_read(base, s_rbuf, GD5F_PAGE_SIZE);
ne = 0;
for (i = 0; i < GD5F_PAGE_SIZE; i++) {
if (s_rbuf[i] != 0xFF) ne++;
}
GD5F_TEST_CHECK(ne > 0,
"TC-GD5F-1003 write-without-erase not applied (bytes!=0xFF: %d)", ne);
#ifdef ENABLE_DESTRUCTIVE_TESTS
{
int32_t i, ne, ok;
/* TC-GD5F-1004: 写保护解除验证(init 后 Protect=0x00,可正常编程) */
gd5f2gq5ue_erase(base, GD5F_BLOCK_SIZE);
memset(s_wbuf, 0x5A, GD5F_PAGE_SIZE);
ret = gd5f2gq5ue_write(base, s_wbuf, GD5F_PAGE_SIZE);
memset(s_rbuf, 0, GD5F_PAGE_SIZE);
gd5f2gq5ue_read(base, s_rbuf, GD5F_PAGE_SIZE);
ok = 1;
for (i = 0; i < GD5F_PAGE_SIZE; i++) {
if (s_rbuf[i] != 0x5A) { ok = 0; break; }
/* TC-GD5F-1003: 写前未擦除 → 数据不可预期(NAND 不可原地覆盖)
* 先擦除写入全 0x00,再不清擦写入全 0xFF(需要 0→1,物理不可行),
* 读回应仍 != 0xFF。 */
gd5f2gq5ue_erase(base, GD5F_BLOCK_SIZE);
memset(s_wbuf, 0x00, GD5F_PAGE_SIZE);
gd5f2gq5ue_write(base, s_wbuf, GD5F_PAGE_SIZE);
memset(s_wbuf, 0xFF, GD5F_PAGE_SIZE);
gd5f2gq5ue_write(base, s_wbuf, GD5F_PAGE_SIZE); /* 未擦除,0→1 不可能 */
memset(s_rbuf, 0, GD5F_PAGE_SIZE);
gd5f2gq5ue_read(base, s_rbuf, GD5F_PAGE_SIZE);
ne = 0;
for (i = 0; i < GD5F_PAGE_SIZE; i++) {
if (s_rbuf[i] != 0xFF) ne++;
}
GD5F_TEST_CHECK(ne > 0,
"TC-GD5F-1003 write-without-erase not applied (bytes!=0xFF: %d)", ne);
/* TC-GD5F-1004: 写保护解除验证(init 后 Protect=0x00,可正常编程) */
gd5f2gq5ue_erase(base, GD5F_BLOCK_SIZE);
memset(s_wbuf, 0x5A, GD5F_PAGE_SIZE);
ret = gd5f2gq5ue_write(base, s_wbuf, GD5F_PAGE_SIZE);
memset(s_rbuf, 0, GD5F_PAGE_SIZE);
gd5f2gq5ue_read(base, s_rbuf, GD5F_PAGE_SIZE);
ok = 1;
for (i = 0; i < GD5F_PAGE_SIZE; i++) {
if (s_rbuf[i] != 0x5A) { ok = 0; break; }
}
GD5F_TEST_CHECK(ret == GD5F_OK && ok,
"TC-GD5F-1004 write unprotected (ret=%d) %s", ret, ok ? "OK" : "FAIL");
}
GD5F_TEST_CHECK(ret == GD5F_OK && ok,
"TC-GD5F-1004 write unprotected (ret=%d) %s", ret, ok ? "OK" : "FAIL");
#else
DBG_INFO("TC-GD5F-1003/1004 skipped: destructive tests disabled (write/erase)");
#endif
}
#endif /* ENABLE_GD5F_PHASE10_TESTS */
@@ -768,6 +792,12 @@ void gd5f_test_run(void)
{
memset(&g_gd5f_test_stats, 0, sizeof(g_gd5f_test_stats));
DBG_INFO("########## GD5F2GQ5UE Test Start ##########");
#ifdef ENABLE_DESTRUCTIVE_TESTS
DBG_INFO("mode: DESTRUCTIVE (write/erase/format/BBT-persist enabled)");
#else
DBG_INFO("mode: READ-ONLY (destructive cases skipped; set "
"ENABLE_DESTRUCTIVE_TESTS in test_config.h to run them)");
#endif
#ifdef ENABLE_GD5F_PHASE1_TESTS
gd5f_phase1();