测试套件增设破坏性用例总开关(默认只读),GD5F/存储/RTC 破坏性用例改为按需开启
This commit is contained in:
+91
-61
@@ -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();
|
||||
|
||||
+65
-35
@@ -49,28 +49,36 @@ static void sd2506_phase_basic(void)
|
||||
(unsigned int)r.second, (unsigned int)r.week);
|
||||
}
|
||||
|
||||
/* TC-RTC-002: 写固定时间,立即回读比对。
|
||||
/* TC-RTC-002: 写固定时间,立即回读比对(破坏性:改设备 RTC 时间,套件结束会复原)。
|
||||
* 若 FAIL -> 先查 sd2506.h 寄存器宏后缀是否为 H(曾因 0x0FH 被 KEIL 编译为 0
|
||||
* 导致 SD2506_REG_CTR1 指向秒寄存器、WRTC 写错地址)。详见 docs/SD2506_Trap_Records.md。 */
|
||||
sd2506_time_t t;
|
||||
t.year = 2026; t.month = 8; t.day = 28; t.hour = 12; t.minute = 0; t.second = 0; t.week = 4;
|
||||
ret = sd2506_set_time(&t);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_set_time() ret=%d (expect 0)", ret);
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
{
|
||||
sd2506_time_t t;
|
||||
int match;
|
||||
|
||||
ret = sd2506_get_time(&r);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_time() after set ret=%d (expect 0)", ret);
|
||||
if (ret == SD2506_OK) {
|
||||
DBG_INFO(" set : %04u-%02u-%02u %02u:%02u:%02u",
|
||||
(unsigned int)t.year, (unsigned int)t.month, (unsigned int)t.day,
|
||||
(unsigned int)t.hour, (unsigned int)t.minute, (unsigned int)t.second);
|
||||
DBG_INFO(" readback: %04u-%02u-%02u %02u:%02u:%02u",
|
||||
(unsigned int)r.year, (unsigned int)r.month, (unsigned int)r.day,
|
||||
(unsigned int)r.hour, (unsigned int)r.minute, (unsigned int)r.second);
|
||||
t.year = 2026; t.month = 8; t.day = 28; t.hour = 12; t.minute = 0; t.second = 0; t.week = 4;
|
||||
ret = sd2506_set_time(&t);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_set_time() ret=%d (expect 0)", ret);
|
||||
|
||||
ret = sd2506_get_time(&r);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_time() after set ret=%d (expect 0)", ret);
|
||||
if (ret == SD2506_OK) {
|
||||
DBG_INFO(" set : %04u-%02u-%02u %02u:%02u:%02u",
|
||||
(unsigned int)t.year, (unsigned int)t.month, (unsigned int)t.day,
|
||||
(unsigned int)t.hour, (unsigned int)t.minute, (unsigned int)t.second);
|
||||
DBG_INFO(" readback: %04u-%02u-%02u %02u:%02u:%02u",
|
||||
(unsigned int)r.year, (unsigned int)r.month, (unsigned int)r.day,
|
||||
(unsigned int)r.hour, (unsigned int)r.minute, (unsigned int)r.second);
|
||||
}
|
||||
match = (r.year == t.year && r.month == t.month && r.day == t.day &&
|
||||
r.hour == t.hour && r.minute == t.minute &&
|
||||
(r.second == t.second || r.second == ((t.second + 1U) % 60U)));
|
||||
SD2506_TEST_CHECK(match, "set==readback (in-session write takes effect)");
|
||||
}
|
||||
int match = (r.year == t.year && r.month == t.month && r.day == t.day &&
|
||||
r.hour == t.hour && r.minute == t.minute &&
|
||||
(r.second == t.second || r.second == ((t.second + 1U) % 60U)));
|
||||
SD2506_TEST_CHECK(match, "set==readback (in-session write takes effect)");
|
||||
#else
|
||||
DBG_INFO("TC-RTC-002 skipped: destructive tests disabled (RTC time write)");
|
||||
#endif
|
||||
|
||||
/* TC-RTC-003: 走时。写后等 3s,应前进约 3 秒 */
|
||||
if (ret == SD2506_OK) {
|
||||
@@ -147,25 +155,37 @@ static void sd2506_phase_api(void)
|
||||
id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
|
||||
}
|
||||
|
||||
/* TC-RTC-014: 用户 SRAM 读写回环(addr=0, len=8) */
|
||||
uint8_t wbuf[8] = {0xA1U, 0xB2U, 0xC3U, 0xD4U, 0xE5U, 0xF6U, 0x07U, 0x18U};
|
||||
uint8_t rbuf[8] = {0};
|
||||
ret = sd2506_write_sram(0U, wbuf, 8U);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_write_sram() ret=%d (expect 0)", ret);
|
||||
if (ret == SD2506_OK) {
|
||||
ret = sd2506_read_sram(0U, rbuf, 8U);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_read_sram() ret=%d (expect 0)", ret);
|
||||
int sram_ok = (memcmp(wbuf, rbuf, 8U) == 0);
|
||||
SD2506_TEST_CHECK(sram_ok, "SRAM write==readback");
|
||||
/* TC-RTC-014: 用户 SRAM 读写回环(addr=0, len=8;破坏性:写芯片 SRAM) */
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
{
|
||||
uint8_t wbuf[8] = {0xA1U, 0xB2U, 0xC3U, 0xD4U, 0xE5U, 0xF6U, 0x07U, 0x18U};
|
||||
uint8_t rbuf[8] = {0};
|
||||
ret = sd2506_write_sram(0U, wbuf, 8U);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_write_sram() ret=%d (expect 0)", ret);
|
||||
if (ret == SD2506_OK) {
|
||||
ret = sd2506_read_sram(0U, rbuf, 8U);
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_read_sram() ret=%d (expect 0)", ret);
|
||||
int sram_ok = (memcmp(wbuf, rbuf, 8U) == 0);
|
||||
SD2506_TEST_CHECK(sram_ok, "SRAM write==readback");
|
||||
}
|
||||
}
|
||||
#else
|
||||
DBG_INFO("TC-RTC-014 skipped: destructive tests disabled (RTC SRAM write)");
|
||||
#endif
|
||||
|
||||
/* TC-RTC-015: 报警设置 + 清除(验证 API 通路,不影响时间寄存器) */
|
||||
sd2506_time_t at;
|
||||
at.year = 2026; at.month = 8; at.day = 28; at.hour = 12; at.minute = 0; at.second = 30; at.week = 4;
|
||||
ret = sd2506_set_alarm(&at, (uint8_t)(SD2506_AL_EN_EAS | SD2506_AL_EN_EAMN));
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_set_alarm() ret=%d (expect 0)", ret);
|
||||
ret = sd2506_clear_alarm();
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_clear_alarm() ret=%d (expect 0)", ret);
|
||||
/* TC-RTC-015: 报警设置 + 清除(破坏性:写报警寄存器;验证 API 通路,不影响时间寄存器) */
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
{
|
||||
sd2506_time_t at;
|
||||
at.year = 2026; at.month = 8; at.day = 28; at.hour = 12; at.minute = 0; at.second = 30; at.week = 4;
|
||||
ret = sd2506_set_alarm(&at, (uint8_t)(SD2506_AL_EN_EAS | SD2506_AL_EN_EAMN));
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_set_alarm() ret=%d (expect 0)", ret);
|
||||
ret = sd2506_clear_alarm();
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_clear_alarm() ret=%d (expect 0)", ret);
|
||||
}
|
||||
#else
|
||||
DBG_INFO("TC-RTC-015 skipped: destructive tests disabled (RTC alarm write)");
|
||||
#endif
|
||||
|
||||
SD2506_TEST_REPORT("Phase 2 API");
|
||||
}
|
||||
@@ -175,6 +195,12 @@ static void sd2506_phase_api(void)
|
||||
void sd2506_test_run(void)
|
||||
{
|
||||
DBG_INFO("SD2506 test suite started");
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
DBG_INFO("mode: DESTRUCTIVE (RTC time / SRAM / alarm writes enabled)");
|
||||
#else
|
||||
DBG_INFO("mode: READ-ONLY (destructive cases skipped; set "
|
||||
"ENABLE_DESTRUCTIVE_TESTS in test_config.h to run them)");
|
||||
#endif
|
||||
|
||||
int ret = sd2506_init();
|
||||
SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_init() ret=%d (expect 0)", ret);
|
||||
@@ -188,12 +214,14 @@ void sd2506_test_run(void)
|
||||
(unsigned int)((c1 >> 7) & 1U));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
/* 记录原始时间,测试结束恢复,避免把板子时间留在测试值 */
|
||||
sd2506_time_t orig;
|
||||
int have_orig = (sd2506_get_time(&orig) == SD2506_OK);
|
||||
if (!have_orig) {
|
||||
DBG_INFO(" WARN: cannot read original time; restore step will be skipped");
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&g_sd2506_test_stats, 0, sizeof(g_sd2506_test_stats));
|
||||
|
||||
@@ -205,11 +233,13 @@ void sd2506_test_run(void)
|
||||
sd2506_phase_api();
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
/* 恢复原始时间(用公共 API,写保护逻辑已由 sd2506.c 正确处理) */
|
||||
if (have_orig) {
|
||||
int r = sd2506_set_time(&orig);
|
||||
DBG_INFO(" restored original time (ret=%d)", r);
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG_INFO("SD2506 test suite done");
|
||||
for (;;) {
|
||||
|
||||
+52
-26
@@ -12,6 +12,7 @@
|
||||
|
||||
#define DBG_TAG "[STORAGE-TEST]"
|
||||
#include "dbg_log.h"
|
||||
#include "test_config.h" /* 破坏性用例开关 ENABLE_DESTRUCTIVE_TESTS 的唯一来源 */
|
||||
#include "storage_test.h"
|
||||
#include "nand_ftl.h"
|
||||
#include "diskio.h"
|
||||
@@ -26,6 +27,7 @@ storage_test_stats_t g_storage_stats;
|
||||
static FATFS fs;
|
||||
static FIL fil;
|
||||
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
/* 性能缓冲 2048B = 恰好一个 NAND 页(RAM 预算:4096 时套件链接溢出 0x604,
|
||||
* L6406E 实测;2048 分块仍覆盖整页写路径,128KB 总量不变) */
|
||||
static uint8_t s_perf_buf[2048];
|
||||
@@ -252,6 +254,8 @@ static void storage_test_badblock(void)
|
||||
* 后跑一次套件,即可清除运行时注入坏块 + 清 dhara map 回出厂态) */
|
||||
}
|
||||
|
||||
#endif /* ENABLE_DESTRUCTIVE_TESTS: s_perf_buf + TC-STO-01/02/03(写、擦、坏块注入) */
|
||||
|
||||
/* TC-STO-05: 文件名/路径合法性校验(守护 ".fschk 无限重格式化" 真根因)
|
||||
* 本移植 FF_USE_LFN=0,只支持严格 8.3 短名(主名≤8、扩展≤3、不以点开头)。
|
||||
* 非法名字 f_open 必返 FR_INVALID_NAME(纯 RAM 名字判定、不碰盘);合法但
|
||||
@@ -324,6 +328,7 @@ static void storage_test_name_validation(void)
|
||||
STORAGE_TEST_CHECK(bok, "TC-STO-05 invalid names rejected (FR_INVALID_NAME)");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
/* TC-STO-06: 打开模式与写回字节数语义(守护 FA_OPEN_APPEND / 短写陷阱)
|
||||
* 本移植 FA_OPEN_APPEND 不含 FA_WRITE → 不带写位打开 f_write 必返 FR_DENIED;
|
||||
* 追加写必须 FA_WRITE|FA_OPEN_APPEND。另 f_write 簇耗尽返 FR_OK+短写(无错误
|
||||
@@ -381,6 +386,7 @@ static void storage_test_open_modes(void)
|
||||
|
||||
(void)f_unlink("mode.tmp");
|
||||
}
|
||||
#endif /* ENABLE_DESTRUCTIVE_TESTS: TC-STO-06 */
|
||||
#endif /* !ENABLE_STORAGE_RECOVERY_TESTS: 共享缓冲 + 正常测试函数 */
|
||||
|
||||
#ifdef ENABLE_STORAGE_RECOVERY_TESTS
|
||||
@@ -391,45 +397,65 @@ static void storage_test_recover(void);
|
||||
/* 正常存储测试套件主体(恢复模式见文件末尾 storage_test_run 分发) */
|
||||
static void storage_test_run_normal(void)
|
||||
{
|
||||
static uint8_t work[FF_MAX_SS];
|
||||
char read_buf[64];
|
||||
const char *test_str = "Hello FatFS + dhara FTL!";
|
||||
FRESULT res;
|
||||
|
||||
memset(&g_storage_stats, 0, sizeof(g_storage_stats));
|
||||
|
||||
/* ==================== FTL + FatFS 文件系统测试 ==================== */
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
DBG_INFO("mode: DESTRUCTIVE (write/erase/format/badblock-inject enabled)");
|
||||
#else
|
||||
DBG_INFO("mode: READ-ONLY (destructive cases skipped; set "
|
||||
"ENABLE_DESTRUCTIVE_TESTS in test_config.h to run them)");
|
||||
#endif
|
||||
|
||||
FRESULT res = f_mount(&fs, "", 1);
|
||||
/* ==================== 挂载 ==================== */
|
||||
|
||||
res = f_mount(&fs, "", 1);
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
if (res == FR_NO_FILESYSTEM) {
|
||||
static uint8_t work[FF_MAX_SS];
|
||||
MKFS_PARM opts = { FM_FAT32, 0, 0, 0, 0 };
|
||||
res = f_mkfs("", &opts, work, sizeof(work));
|
||||
STORAGE_TEST_CHECK(res == FR_OK, "f_mkfs");
|
||||
res = f_mount(&fs, "", 1);
|
||||
}
|
||||
#else
|
||||
if (res == FR_NO_FILESYSTEM) {
|
||||
DBG_INFO("read-only mode: no filesystem on volume, skip write cases "
|
||||
"(mkfs self-heal disabled)");
|
||||
}
|
||||
#endif
|
||||
STORAGE_TEST_CHECK(res == FR_OK, "f_mount");
|
||||
|
||||
if (res == FR_OK) {
|
||||
UINT bw, br;
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
/* ==================== FTL + FatFS 文件系统测试 ==================== */
|
||||
{
|
||||
char read_buf[64];
|
||||
const char *test_str = "Hello FatFS + dhara FTL!";
|
||||
|
||||
res = f_open(&fil, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);
|
||||
STORAGE_TEST_CHECK(res == FR_OK, "f_open(write)");
|
||||
if (res == FR_OK) {
|
||||
f_write(&fil, test_str, (UINT)strlen(test_str), &bw);
|
||||
STORAGE_TEST_CHECK(bw == (UINT)strlen(test_str), "f_write (%u bytes)", bw);
|
||||
f_close(&fil);
|
||||
UINT bw, br;
|
||||
|
||||
res = f_open(&fil, "test.txt", FA_READ);
|
||||
STORAGE_TEST_CHECK(res == FR_OK, "f_open(read)");
|
||||
res = f_open(&fil, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);
|
||||
STORAGE_TEST_CHECK(res == FR_OK, "f_open(write)");
|
||||
if (res == FR_OK) {
|
||||
f_read(&fil, read_buf, (UINT)(sizeof(read_buf) - 1), &br);
|
||||
f_write(&fil, test_str, (UINT)strlen(test_str), &bw);
|
||||
STORAGE_TEST_CHECK(bw == (UINT)strlen(test_str), "f_write (%u bytes)", bw);
|
||||
f_close(&fil);
|
||||
read_buf[br] = '\0';
|
||||
STORAGE_TEST_CHECK(br == (UINT)strlen(test_str) &&
|
||||
memcmp(test_str, read_buf, br) == 0,
|
||||
"data verify \"%s\"", read_buf);
|
||||
|
||||
res = f_open(&fil, "test.txt", FA_READ);
|
||||
STORAGE_TEST_CHECK(res == FR_OK, "f_open(read)");
|
||||
if (res == FR_OK) {
|
||||
f_read(&fil, read_buf, (UINT)(sizeof(read_buf) - 1), &br);
|
||||
f_close(&fil);
|
||||
read_buf[br] = '\0';
|
||||
STORAGE_TEST_CHECK(br == (UINT)strlen(test_str) &&
|
||||
memcmp(test_str, read_buf, br) == 0,
|
||||
"data verify \"%s\"", read_buf);
|
||||
}
|
||||
}
|
||||
f_unlink("test.txt");
|
||||
}
|
||||
f_unlink("test.txt");
|
||||
}
|
||||
|
||||
/* ==================== FTL + FatFS 性能测试 ==================== */
|
||||
@@ -478,19 +504,19 @@ static void storage_test_run_normal(void)
|
||||
total_kb, tr, (total_kb * 1000) / tr);
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_DESTRUCTIVE_TESTS: 文件系统写读 + 性能压测 */
|
||||
|
||||
/* ==================== 存储集成测试(TC-STO-05~06 契约 + 01~03 集成) ========== */
|
||||
/* ==================== 存储集成测试(TC-STO-05 契约 + 01~03 集成) ========== */
|
||||
|
||||
/* 纯语义契约测试(非破坏性,先跑):名字合法性 + 打开模式 */
|
||||
/* 纯语义契约测试(非破坏性):文件名合法性 */
|
||||
storage_test_name_validation();
|
||||
storage_test_open_modes();
|
||||
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
/* 破坏性用例:打开模式契约 + 掉电恢复 / 大文件 / 坏块注入集成 */
|
||||
storage_test_open_modes();
|
||||
storage_test_powerloss();
|
||||
storage_test_largefile();
|
||||
storage_test_badblock();
|
||||
|
||||
#ifdef ENABLE_STORAGE_RECOVERY_TESTS
|
||||
storage_test_recover();
|
||||
#endif
|
||||
|
||||
/* ==================== 汇总报告 ==================== */
|
||||
|
||||
+29
-11
@@ -28,6 +28,16 @@ extern "C" {
|
||||
//#define TEST_SUITE_GD5F
|
||||
//#define TEST_SUITE_RTC
|
||||
|
||||
/* === 破坏性测试总开关(默认关闭)===
|
||||
* 破坏性用例会改变设备的**持久状态**,跑一次即有代价(2026-09-21 实测:GD5F 整轮
|
||||
* 破坏性用例跑一次即消耗一个 NAND 块,容量 95248 → 95200,且 TC-STO-04 恢复不回来):
|
||||
* - 向 BBT 持久化坏块标记 / 注入坏块(永久减少可用容量)
|
||||
* - 写、擦 NAND 块(覆盖卷数据);格式化卷(nand_ftl_format / f_mkfs)
|
||||
* - FatFS 建文件、写文件、性能压测
|
||||
* 默认关闭:套件只跑**只读与参数校验**类用例,可随时在在用设备上执行。
|
||||
* 仅在**产品首次上电/产线首启**或明确需要时打开;打开跑完建议做一次恢复。 */
|
||||
//#define ENABLE_DESTRUCTIVE_TESTS
|
||||
|
||||
#if defined(TEST_SUITE_CH395F) + defined(TEST_SUITE_STORAGE) + defined(TEST_SUITE_GD5F) + defined(TEST_SUITE_RTC) > 1
|
||||
#error "测试套件互斥:一次构建只能启用一个 TEST_SUITE_*"
|
||||
#endif
|
||||
@@ -47,18 +57,26 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef TEST_SUITE_GD5F
|
||||
/* 选中 GD5F 套件时,自动开启 gd5f 测试总开关与全部阶段 */
|
||||
/* 选中 GD5F 套件时,自动开启 gd5f 测试总开关;
|
||||
* 只读阶段无条件启用,破坏性阶段(写/擦/格式化/BBT 落盘)受 ENABLE_DESTRUCTIVE_TESTS 门控 */
|
||||
#define ENABLE_GD5F_TESTS
|
||||
#define ENABLE_GD5F_PHASE1_TESTS
|
||||
#define ENABLE_GD5F_PHASE2_TESTS
|
||||
#define ENABLE_GD5F_PHASE3_TESTS
|
||||
#define ENABLE_GD5F_PHASE4_TESTS
|
||||
#define ENABLE_GD5F_PHASE5_TESTS
|
||||
#define ENABLE_GD5F_PHASE6_TESTS
|
||||
#define ENABLE_GD5F_PHASE7_TESTS
|
||||
#define ENABLE_GD5F_PHASE8_TESTS
|
||||
#define ENABLE_GD5F_PHASE9_TESTS
|
||||
#define ENABLE_GD5F_PHASE10_TESTS
|
||||
|
||||
/* --- 只读阶段:随时可跑,不改设备状态 --- */
|
||||
#define ENABLE_GD5F_PHASE1_TESTS /* init / read_id / reset */
|
||||
#define ENABLE_GD5F_PHASE2_TESTS /* BBT 读取与 RAM 内标记(206/207 落盘另受门控) */
|
||||
#define ENABLE_GD5F_PHASE7_TESTS /* DMA 边界与守卫(701~703/705 写擦受门控;704 只读,日常回归亦跑) */
|
||||
#define ENABLE_GD5F_PHASE10_TESTS /* 越界与 size=0 参数校验(1003/1004 写入另受门控) */
|
||||
|
||||
#ifdef ENABLE_DESTRUCTIVE_TESTS
|
||||
/* --- 破坏性阶段:写/擦页与块、格式化、FatFS 写入 --- */
|
||||
#define ENABLE_GD5F_PHASE3_TESTS /* 页/跨页/多页读写 */
|
||||
#define ENABLE_GD5F_PHASE4_TESTS /* 块擦除 */
|
||||
#define ENABLE_GD5F_PHASE5_TESTS /* ECC 写读 */
|
||||
#define ENABLE_GD5F_PHASE6_TESTS /* SPI 原语(块擦除 + 编程) */
|
||||
#define ENABLE_GD5F_PHASE8_TESTS /* FTL init + nand_ftl_format(格式化清卷) */
|
||||
#define ENABLE_GD5F_PHASE9_TESTS /* FatFS 挂载 + 写文件 */
|
||||
#endif
|
||||
|
||||
#include "gd5f_test.h"
|
||||
#define TEST_SUITE_NAME "GD5F"
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user