CCM扩容FreeRTOS堆+DMA阈值1024防栈缓冲进CCM+HardFault现场报告与栈/内存钩子+修defaultTask栈溢出+LVGL绘制缓冲护栏+存储套件05/06与恢复模式

This commit is contained in:
2026-09-21 00:47:58 +08:00
parent 9bb5a8dcae
commit a7d4339e6f
9 changed files with 357 additions and 36 deletions
+1 -1
View File
@@ -48,7 +48,7 @@ void storage_test_run(void);
/* 存储套件恢复测试(默认关闭):取消注释并编译 STORAGE 套件运行一次,
* 即可重建 BBT(清除 TC-STO-03 等注入的坏块)并重新格式化,恢复设备干净态。
* 恢复完成后建议重新注释并编译正常构建。 */
//#define ENABLE_STORAGE_RECOVERY_TESTS
//#define ENABLE_STORAGE_RECOVERY_TESTS /* 台架已跑过一次恢复(2026-09-20 BBT 回出厂态),保持注释 */
#ifdef __cplusplus
}
+174 -14
View File
@@ -19,15 +19,22 @@
storage_test_stats_t g_storage_stats;
static uint8_t s_perf_buf[4096];
#ifndef ENABLE_STORAGE_RECOVERY_TESTS
/* 全套件共享的 FATFS/FIL(RAM 预算紧张:每个 static FATFS≈560B、FIL≈600B,
* 各测试函数独立持有会撑爆 .bss。测试在单任务 testTask 内串行执行、从不并发,
* 共用一组安全,且比"每函数一份"省下约 5KB。见产品级 RAM 溢出 L6406E) */
static FATFS fs;
static FIL fil;
/* 性能缓冲 2048B = 恰好一个 NAND 页(RAM 预算:4096 时套件链接溢出 0x604,
* L6406E 实测;2048 分块仍覆盖整页写路径,128KB 总量不变) */
static uint8_t s_perf_buf[2048];
/* TC-STO-01: FTL 掉电恢复(journal 持久化)
* 写文件并同步落盘,随后模拟掉电(卸载 + 复位 FTL + 重新 resume),再挂载校验内容一致。
*/
static void storage_test_powerloss(void)
{
static FATFS fs;
static FIL fil;
const uint32_t len = 4096;
uint8_t wbuf[512];
uint8_t rbuf[512];
@@ -90,14 +97,14 @@ static void storage_test_powerloss(void)
/* TC-STO-02: 大文件 / 多扇区 / 随机 seek
* 写 256KB 位置相关模式文件,顺序读回比对 + 随机偏移 seek 读比对。
* 栈预算:testTask 栈 4KB,局部缓冲 4096 必然溢出栈(8 月侥幸未爆是堆使用
* 低),改 2048 = 恰好一个 NAND 整页,覆盖度等价。
*/
static void storage_test_largefile(void)
{
static FATFS fs;
static FIL fil;
const uint32_t total = 256 * 1024;
const uint32_t chunk = 4096;
uint8_t buf[4096];
const uint32_t chunk = 2048;
uint8_t buf[2048];
UINT bw, br;
uint32_t off, i;
int ok = 1;
@@ -162,8 +169,6 @@ static void storage_test_largefile(void)
*/
static void storage_test_badblock(void)
{
static FATFS fs;
static FIL fil;
uint8_t wbuf[512], rbuf[512];
UINT bw, br;
uint32_t bad[3];
@@ -242,17 +247,150 @@ static void storage_test_badblock(void)
STORAGE_TEST_CHECK(badok, "TC-STO-03 injected blocks still reported bad");
f_unlink("bbt.dat");
/* 注意:注入的坏块已持久化,测试设备专用;如需恢复需重建 BBT / 重新格式化 */
/* 注意:注入的坏块已持久化,测试设备专用;如需恢复需重建 BBT / 重新格式化
* (配套 TC-STO-04 恢复测试:storage_test.h 启用 ENABLE_STORAGE_RECOVERY_TESTS
* 后跑一次套件,即可清除运行时注入坏块 + 清 dhara map 回出厂态) */
}
/* TC-STO-05: 文件名/路径合法性校验(守护 ".fschk 无限重格式化" 真根因)
* 本移植 FF_USE_LFN=0,只支持严格 8.3 短名(主名≤8、扩展≤3、不以点开头)。
* 非法名字 f_open 必返 FR_INVALID_NAME(纯 RAM 名字判定、不碰盘);合法但
* 不存在的名字返 FR_NO_FILE。本测试断言两类严格可区分——一旦哪天有人把
* FR_INVALID_NAME 误归入"卷损坏"自愈集合,这条测试就是最后的机械防线。
* (详见 docs/问题记录/GD5F2GQ5UE_Trap_Records.md Trap 05 / AGENTS.md)
*/
static void storage_test_name_validation(void)
{
uint32_t i;
int gok = 1;
int bok = 1;
/* 合法 8.3:FA_READ 打开 → FR_OK(存在) 或 FR_NO_FILE(不存在),均非 INVALID */
static const char *good[] = {
"fschk.tmp", /* 修复后的探针名(名5+扩展3) */
"config.ini", /* 名6+扩展3 */
"12345678.txt", /* 主名 8 / 扩展 3 上限 */
"A.TXT", /* 最小合法名 */
"NOEXT", /* 无扩展 */
"1.23", /* 数字名 */
"run.log"
};
/* 非法:FF_USE_LFN=0 下 create_short 必拒 → FR_INVALID_NAME */
static const char *bad[] = {
".fschk", /* 事故根因:点开头(点后当扩展域,超 3 上限) */
".hidden", /* 点开头隐藏名风格 */
"123456789", /* 主名 9 > 8 */
"toolongname.txt", /* 主名 > 8 */
"a.toolongext", /* 扩展 > 3 */
"bad?char.txt", /* 非法字符 ? */
"star*name", /* * */
"col:on", /* : */
"lt<gt>val", /* < > */
"pipe|name" /* | */
};
DBG_INFO("=== Storage Test: TC-STO-05 Filename validation ===");
if (f_mount(&fs, "", 1) != FR_OK) {
STORAGE_TEST_CHECK(0, "TC-STO-05 mount");
return;
}
for (i = 0; i < (uint32_t)(sizeof(good) / sizeof(good[0])); i++) {
FRESULT r = f_open(&fil, good[i], FA_READ);
if (r == FR_OK) {
f_close(&fil);
}
if (r == FR_INVALID_NAME) {
gok = 0;
DBG_ERROR(" valid name wrongly rejected: '%s'", good[i]);
}
}
STORAGE_TEST_CHECK(gok, "TC-STO-05 valid 8.3 names accepted");
for (i = 0; i < (uint32_t)(sizeof(bad) / sizeof(bad[0])); i++) {
FRESULT r = f_open(&fil, bad[i], FA_READ);
if (r == FR_OK) {
f_close(&fil);
}
/* 含 ':' 的名字被 FatFs 先解析为盘符前缀 → FR_INVALID_DRIVE(11)
* 同样属合法拒绝(台架实测 'col:on' fr=11),与 INVALID 同等待遇 */
if ((r != FR_INVALID_NAME) &&
!((r == FR_INVALID_DRIVE) && (strchr(bad[i], ':') != NULL))) {
bok = 0;
DBG_ERROR(" invalid name NOT rejected: '%s' -> fr=%d", bad[i], (int)r);
}
}
STORAGE_TEST_CHECK(bok, "TC-STO-05 invalid names rejected (FR_INVALID_NAME)");
}
/* TC-STO-06: 打开模式与写回字节数语义(守护 FA_OPEN_APPEND / 短写陷阱)
* 本移植 FA_OPEN_APPEND 不含 FA_WRITE → 不带写位打开 f_write 必返 FR_DENIED;
* 追加写必须 FA_WRITE|FA_OPEN_APPEND。另 f_write 簇耗尽返 FR_OK+短写(无错误
* 码),判成败必须校验写回字节数。锁定这两条移植专有语义防回归。
*/
static void storage_test_open_modes(void)
{
UINT bw;
FRESULT r;
DBG_INFO("=== Storage Test: TC-STO-06 Open-mode semantics ===");
if (f_mount(&fs, "", 1) != FR_OK) {
STORAGE_TEST_CHECK(0, "TC-STO-06 mount");
return;
}
(void)f_unlink("mode.tmp");
/* 1) 建一个含初始内容的文件 */
r = f_open(&fil, "mode.tmp", FA_CREATE_ALWAYS | FA_WRITE);
STORAGE_TEST_CHECK(r == FR_OK, "TC-STO-06 create base file");
if (r == FR_OK) {
f_write(&fil, "abc", 3, &bw);
f_close(&fil);
}
/* 2) FA_OPEN_APPEND(无 FA_WRITE)→ 写必返 FR_DENIED */
r = f_open(&fil, "mode.tmp", FA_OPEN_APPEND);
STORAGE_TEST_CHECK(r == FR_OK, "TC-STO-06 open append(no write)");
if (r == FR_OK) {
FRESULT wr = f_write(&fil, "xyz", 3, &bw);
STORAGE_TEST_CHECK(wr == FR_DENIED,
"TC-STO-06 append-no-write must DENY (fr=%d)", (int)wr);
f_close(&fil);
}
/* 3) FA_WRITE|FA_OPEN_APPEND → 追加成功且字节数正确 */
r = f_open(&fil, "mode.tmp", FA_WRITE | FA_OPEN_APPEND);
STORAGE_TEST_CHECK(r == FR_OK, "TC-STO-06 open write|append");
if (r == FR_OK) {
(void)f_write(&fil, "xyz", 3, &bw);
STORAGE_TEST_CHECK(bw == 3, "TC-STO-06 append byte-count (%u)", bw);
f_close(&fil);
}
/* 4) 只读打开后写 → 必返 FR_DENIED(读句柄不可写) */
r = f_open(&fil, "mode.tmp", FA_READ);
STORAGE_TEST_CHECK(r == FR_OK, "TC-STO-06 open read-only");
if (r == FR_OK) {
FRESULT wr = f_write(&fil, "q", 1, &bw);
STORAGE_TEST_CHECK(wr == FR_DENIED,
"TC-STO-06 read-only write must DENY (fr=%d)", (int)wr);
f_close(&fil);
}
(void)f_unlink("mode.tmp");
}
#endif /* !ENABLE_STORAGE_RECOVERY_TESTS: 共享缓冲 + 正常测试函数 */
#ifdef ENABLE_STORAGE_RECOVERY_TESTS
static void storage_test_recover(void);
#endif
void storage_test_run(void)
#ifndef ENABLE_STORAGE_RECOVERY_TESTS
/* 正常存储测试套件主体(恢复模式见文件末尾 storage_test_run 分发) */
static void storage_test_run_normal(void)
{
static FATFS fs;
static FIL fil;
static uint8_t work[FF_MAX_SS];
char read_buf[64];
const char *test_str = "Hello FatFS + dhara FTL!";
@@ -341,7 +479,11 @@ void storage_test_run(void)
}
}
/* ==================== 存储集成测试(TC-STO-01~03) ==================== */
/* ==================== 存储集成测试(TC-STO-05~06 契约 + 01~03 集成) ========== */
/* 纯语义契约测试(非破坏性,先跑):名字合法性 + 打开模式 */
storage_test_name_validation();
storage_test_open_modes();
storage_test_powerloss();
storage_test_largefile();
@@ -355,6 +497,24 @@ void storage_test_run(void)
STORAGE_TEST_REPORT("Storage Tests");
}
#endif /* !ENABLE_STORAGE_RECOVERY_TESTS */
/*
* 套件总入口分发。恢复模式(storage_test.h 打开 ENABLE_STORAGE_RECOVERY_TESTS)
* = 专用维护构建:重建 BBT(清除运行时误标坏块)+ 清 dhara map 后直接返回,
* 不在受污染介质上继续跑其余测试(2026-09-20:CCM 首轮实验中 DMA 够不到栈上
* 小缓冲,随机块被误标坏并持久化,journal 引用到即静默卡死——恢复模式即为其
* 清账手段)。恢复完成后重新注释该宏、编译正常套件即可。
*/
void storage_test_run(void)
{
#ifdef ENABLE_STORAGE_RECOVERY_TESTS
storage_test_recover();
STORAGE_TEST_REPORT("Storage Recovery");
#else
storage_test_run_normal();
#endif
}
#ifdef ENABLE_STORAGE_RECOVERY_TESTS
/* TC-STO-04: 重建 BBT + 重新格式化(恢复 TC-STO-03 注入的坏块)