Files
STM32F4-Base/docs/GD5F2GQ5UE_Test_Guide.md
2026-08-27 18:22:44 +08:00

31 KiB
Raw Blame History

GD5F2GQ5UE NAND Flash 测试规范

本规范参照 docs/CH395F_Test_Guide.md 结构编写,覆盖 Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c 全部公开/私有函数,并向上延伸到 FTLnand_ftl.c)与 FatFS diskio。 详细芯片行为见 docs/GD5F2GQ5UExxG.md,已知陷阱见 docs/GD5F2GQ5UE_Trap_Records.md

1. 概述

设计原则

  • 同步 SPI 访问GD5F 驱动全部为同步阻塞 SPI 事务CS 拉低 → 命令/地址/数据 → CS 拉高), 由调用任务直接执行,不经过消息队列(与 CH395F 的 netTask 串行化模型不同)。 因此测试代码可在任意任务上下文调用,但要注意调用任务会被 SPI 传输阻塞数毫秒(擦除最久)。
  • 先擦后写NAND 只能将 1 写为 0写操作前目标块必须已擦除,否则数据不可预期(见边界条件 TC-GD5F-1003
  • ECC 默认开启gd5f2gq5ue_init() 会置 Feature(B0h).ECC_EN=1,读/写均走内部 ECC。
  • 坏块以 BBT 管理出厂坏块标记在每块的第一页page 0spare byte 0列地址 0x800见手册 §12.4 / Table 12-6 / Noteinit 阶段扫描构建 RAM 中的 BBT。

芯片参数(关键参数)

参数 说明
制造商/设备 ID 0xC8 / 0x52 gd5f2gq5ue_read_id() 校验依据
页数据大小 2048 B GD5F_PAGE_SIZE
Spare 大小 64 B GD5F_SPARE_SIZEECC 开启时有效)
单页总长 2112 B GD5F_TOTAL_PAGE_SIZEECC 开启)
每块页数 64 GD5F_PAGES_PER_BLOCK
块大小 128 KB GD5F_BLOCK_SIZE = 64×2048
总块数 2048 GD5F_TOTAL_BLOCKS
总容量 256 MB GD5F_TOTAL_SIZE
最小擦除单位 1 块128 KB 不可按页/字节擦除
DMA 阈值 32 B GD5F_DMA_THRESHOLD>32B 走 HAL_SPI_*_DMA

寄存器与状态位

寄存器 地址 关键位
Status 0xC0 OIP(b0) 忙标志、WEL(b1) 写使能、E_FAIL(b2)、P_FAIL(b3)、ECCS1/0(b5/b4) ECC 状态
Feature 0xB0 ECC_EN(b4)、QE(b0)
Protect 0xA0 BP2/1/0 块保护init 后写为 0x00 解除保护

ECC 状态(ECCS1:ECCS000=无错;01/10/11=纠正 1/2/3 bit10ECCS1=1,ECCS0=0= 超出纠正能力(>4bit不可纠正。 驱动 gd5f_check_ecc()(status>>4)&0x03 == 2 时返回 GD5F_ECC_ERROR

测试环境

  • 硬件STM32F407ZGTx + GD5F2GQ5UESPI NAND
  • SPI 接口SPI1CubeMX 初始化),引脚:
    • CS=PE0SCK=PB3MISO=PB4MOSI=PB5WP=PB8HOLD=PE1
  • 调试输出USART1115200bps[NAND] 标签(dbg_log.h
  • 擦除/编程耗时参考驱动超时PAGE_READ 等待 100ms、PROGRAM_EXEC 等待 1000ms、BLOCK_ERASE 等待 5000ms

统一测试调度ch395fTestTask

所有测试套件CH395F / 存储 / GD5F统一收归 ch395fTestTask 线程(test/ch395f_test_task.cStartCh395fTestTask),通过 test/test_config.h 中的 TEST_SUITE_* 宏在编译期选择要跑的套件。 选中 TEST_SUITE_GD5F 时,test_config.h 会自动 #define ENABLE_GD5F_TESTS 及全部 ENABLE_GD5F_PHASE*_TESTS,随后由 gd5f_test_run()test/gd5f_test_task.c)按阶段串行执行。

defaultTask 不再承担任何测试(仅空闲);所有测试都只在 ch395fTestTask 中运行。

test/test_config.h 配置示例(三选一,互斥,多选触发 #error

// #define TEST_SUITE_CH395F
// #define TEST_SUITE_STORAGE
#define TEST_SUITE_GD5F      /* 选中后自动开启 gd5f 全部阶段宏 */

执行顺序(由 gd5f_test_run() 按阶段串行,与函数依赖一致): init/read_id/resetBBT页读写块擦除ECCSPI 原语DMA 边界FTLFatFS边界条件

启用测试

  1. test/test_config.h 取消注释所需的 TEST_SUITE_* 宏(如 TEST_SUITE_GD5F
  2. 编译(@build)确认 0 错误 0 警告;
  3. 烧录后串口观察 [NAND-TEST] 日志与各 TC 的 PASS/FAIL,结尾打印 === GD5F2GQ5UE Tests: X/Y PASSED ===
  4. 不选任何 TEST_SUITE_* 时为正常产品构建(ch395fTestTask 空闲,不跑测试)。

2. 阶段 1初始化与 ID 识别

TC-GD5F-101: gd5f2gq5ue_init 全流程

字段
ID TC-GD5F-101
优先级 P0
类型 功能测试
标题 初始化成功复位→ID 校验→BBT 扫描→ECC 使能→解除块保护)
前置条件 SPI1 与 GPIO 已由 CubeMX 初始化
测试步骤 1. 调用 gd5f2gq5ue_init()
2. 观察日志Resetting / Reading NAND ID / Scanning bad blocks / Enabling ECC / Unlocking block protection / NAND init OK
通过标准 返回 GD5F_OK;日志无 ID mismatch / Reset failedBBT 扫描打印 bad count
覆盖原则 初始化主路径

TC-GD5F-102: gd5f2gq5ue_read_id 返回正确 ID

字段
ID TC-GD5F-102
优先级 P0
类型 功能测试
标题 读取 MID=0xC8、DID=0x52
前置条件 gd5f2gq5ue_init() 已成功(或至少 SPI 已初始化)
测试步骤 调用 gd5f2gq5ue_read_id(&mid, &did) 并比较
通过标准 mid==0xC8 && did==0x52
覆盖原则 gd5f2gq5ue_read_id

TC-GD5F-103: gd5f2gq5ue_reset 成功

字段
ID TC-GD5F-103
优先级 P1
类型 功能测试
标题 软复位后状态寄存器 OIP 清零
前置条件 SPI 已初始化
测试步骤 调用 gd5f2gq5ue_reset();随后 gd5f_read_status(&s) 检查 OIP==0
通过标准 reset 返回 GD5F_OKs & GD5F_STATUS_OIP == 0
覆盖原则 gd5f2gq5ue_reset / gd5f_read_status

3. 阶段 2坏块管理BBT

注:gd5f2gq5ue_mark_block_bad() / gd5f2gq5ue_bbt_clear() 仅修改 RAM 中的 BBT 位图 不会写回 Flash 物理标记(与头注释"尝试物理标记"不符,见陷阱节)。重启后由 init 重新扫描出厂标记。

TC-GD5F-201: 出厂坏块扫描

字段
ID TC-GD5F-201
优先级 P0
类型 功能测试
标题 init 后 BBT 扫描可完成并打印坏块数
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 观察 init 日志 BBT scan: N bad blocks found;调用 gd5f2gq5ue_print_bbt()
通过标准 扫描完成N 为合理值,通常 0~数十);print_bbt 能列出坏块偏移
覆盖原则 BBT 扫描(gd5f_private_bbt_scan

TC-GD5F-202: gd5f2gq5ue_is_block_bad 查询

字段
ID TC-GD5F-202
优先级 P0
类型 功能测试
标题 好块返回 0坏块返回 1
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 1. 对已知好块(如 block 0除非其为坏块is_block_bad 应返回 0
2. 对 print_bbt 列出的坏块 is_block_bad 应返回 1
通过标准 好块返回 0坏块返回 1越界 block 返回 1
覆盖原则 gd5f2gq5ue_is_block_bad

TC-GD5F-203: mark_block_bad 与 is_block_bad 一致性

字段
ID TC-GD5F-203
优先级 P1
类型 功能测试
标题 标记后查询一致RAM BBT
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 取一个好块 Bgd5f2gq5ue_mark_block_bad(B)is_block_bad(B)==1;再 gd5f2gq5ue_bbt_clear()is_block_bad(B)==0
通过标准 mark 后查得 1clear 后查得 0RAM 行为符合预期)
覆盖原则 gd5f2gq5ue_mark_block_bad / gd5f2gq5ue_bbt_clear

TC-GD5F-204: 初始化 BBT 稳定读取(无需 rescan

字段
ID TC-GD5F-204
优先级 P2
类型 一致性测试
标题 初始化 BBT 可直接读取且稳定(无需 rescan
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 记录 print_bbt 坏块数;再次 print_bbt 比较坏块数(验证 init BBT 可直接读取且稳定)
通过标准 两次坏块数一致(出厂标记未变)
覆盖原则 gd5f2gq5ue_is_block_bad / gd5f2gq5ue_bbt_clear / gd5f2gq5ue_mark_block_badinit BBT 读取)

4. 阶段 3页读写跨页

重要:写操作前目标区域必须已擦除(见阶段 4 / 边界条件 TC-GD5F-1003

TC-GD5F-301: 整页写读

字段
ID TC-GD5F-301
优先级 P0
类型 功能测试
标题 offset=0, size=2048 写入递增模式并读回比对
前置条件 目标块已擦除
测试步骤 1. 填 buf[i]=i&0xFF(或 (offset+i)&0xFF
2. gd5f2gq5ue_write(0, buf, 2048)
3. gd5f2gq5ue_read(0, rbuf, 2048) 逐字节比对
通过标准 读回与写入完全一致
覆盖原则 gd5f2gq5ue_write / gd5f2gq5ue_read(单页路径)

TC-GD5F-302: 跨页写读

字段
ID TC-GD5F-302
优先级 P0
类型 功能测试
标题 offset=1000, size=3000 跨越页边界
前置条件 涉及块已擦除
测试步骤 写入 3000 字节offset=1000 起),读回同窗口比对
通过标准 跨页数据连续正确(gd5f2gq5ue_read/write 自动分页)
覆盖原则 跨页拆分逻辑

TC-GD5F-303: 非对齐 offset 写读

字段
ID TC-GD5F-303
优先级 P1
类型 边界测试
标题 offset=1, size=2047
前置条件 目标块已擦除
测试步骤 同 TC-GD5F-301但 offset=1
通过标准 读回与写入一致(列地址 = offset%2048 正确)
覆盖原则 列地址计算

TC-GD5F-304: 多页顺序写读

字段
ID TC-GD5F-304
优先级 P1
类型 压力测试
标题 连续 10 页offset=0, size=20480
前置条件 前 10 页所在块已擦除
测试步骤 写入 20480 字节递增模式,读回全量比对
通过标准 全部一致
覆盖原则 多页循环

TC-GD5F-305: 随机单字节访问

字段
ID TC-GD5F-305
优先级 P2
类型 功能测试
标题 任意 offsetsize=1 写入/读回
前置条件 目标块已擦除
测试步骤 在若干随机 offset 写单字节并读回
通过标准 单字节值正确,且不影响同页其余字节(部分页编程约束内)
覆盖原则 单字节 program_load 列偏移

5. 阶段 4块擦除

TC-GD5F-401: 单块擦除后读全 0xFF

字段
ID TC-GD5F-401
优先级 P0
类型 功能测试
标题 擦除 block 0先确认非坏块读出应全 0xFF
前置条件 block 0 非坏块
测试步骤 gd5f2gq5ue_erase(0, 128*1024);读整块比对全 0xFF
通过标准 返回 GD5F_OK 且整块读回全 0xFF
覆盖原则 gd5f2gq5ue_erase / gd5f_block_erase

TC-GD5F-402: 多块擦除

字段
ID TC-GD5F-402
优先级 P1
类型 功能测试
标题 size=3 块384KB连续擦除
前置条件 对应块非坏块
测试步骤 gd5f2gq5ue_erase(0, 3*128*1024);读回比对全 0xFF
通过标准 返回 GD5F_OK,范围全 0xFF
覆盖原则 多块循环擦除

TC-GD5F-403: 非块对齐应返回错误

字段
ID TC-GD5F-403
优先级 P0
类型 负向测试
标题 offset 或 size 非 128KB 整数倍
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 gd5f2gq5ue_erase(100, 128*1024)offset 不对齐);gd5f2gq5ue_erase(0, 100)size 不对齐)
通过标准 两者均返回 GD5F_ERROR
覆盖原则 对齐校验

TC-GD5F-404: 擦除-写-读 完整循环

字段
ID TC-GD5F-404
优先级 P0
类型 集成测试
标题 erase → write → read 闭环比对
前置条件 目标块非坏块
测试步骤 1. erase 目标块
2. write 已知模式(如 0xAA 填充/递增)
3. read 比对
通过标准 读回 == 写入(验证"先擦后写"链路)
覆盖原则 完整 NAND 写流程

6. 阶段 5ECC 验证

TC-GD5F-501: ECC 开启下写读正确

字段
ID TC-GD5F-501
优先级 P0
类型 功能测试
标题 ECC 使能时数据正确ECC status 无错
前置条件 gd5f2gq5ue_init()(已使能 ECC目标块已擦除
测试步骤 写随机/递增模式;gd5f_page_read(page) + gd5f_read_from_cache 读回;gd5f_check_ecc() 检查
通过标准 数据一致且 gd5f_check_ecc() 返回 GD5F_OKECCS=00 无错)
覆盖原则 ECC 数据路径

TC-GD5F-502: gd5f_check_ecc 干净读

字段
ID TC-GD5F-502
优先级 P1
类型 功能测试
标题 干净页 gd5f_check_ecc() 返回 OK
前置条件 gd5f_page_read 加载页
测试步骤 读后调 gd5f_check_ecc()
通过标准 返回 GD5F_OK(非 GD5F_ECC_ERROR
覆盖原则 gd5f_check_ecc

TC-GD5F-503: ECC 纠错能力(可选)

字段
ID TC-GD5F-503
优先级 P3
类型 可选/深入测试
标题 观察 ECCS 位在纠正场景下的变化
前置条件 已知好块ECC 开启
测试步骤 写入后读回,检查 ECCS00 无错 / 01~11 已纠正 bit人为制造位翻转较困难建议仅读状态位验证逻辑
通过标准 gd5f_check_ecc() 在不可纠正时返回 GD5F_ECC_ERROR,否则 GD5F_OK
覆盖原则 ECC 状态位语义

7. 阶段 6SPI 原语FTL 共享)

下列函数为 gd5f2gq5ue.c 的私有/半公开原语FTL 直接复用;通过组合调用验证。

TC-GD5F-601: page_read + read_from_cache 组合

字段
ID TC-GD5F-601
优先级 P1
类型 功能测试
标题 单页加载到 cache 并读出
前置条件 目标页有已编程数据
测试步骤 gd5f_page_read(page)gd5f_read_from_cache(0, buf, 2048)
通过标准 数据正确,返回 GD5F_OK
覆盖原则 gd5f_page_read / gd5f_read_from_cache

TC-GD5F-602: program_load + program_exec 组合

字段
ID TC-GD5F-602
优先级 P1
类型 功能测试
标题 单页编程load→exec
前置条件 目标块已擦除
测试步骤 gd5f_write_enable()gd5f_program_load(0, buf, 2048)gd5f_program_exec(page);读回比对
通过标准 编程后数据一致,无 P_FAIL
覆盖原则 gd5f_program_load / gd5f_program_exec

TC-GD5F-603: gd5f_block_erase 单块

字段
ID TC-GD5F-603
优先级 P1
类型 功能测试
标题 原语级块擦除(地址=块首页地址)
前置条件 SPI 已初始化
测试步骤 gd5f_block_erase(block)(注意传块编号,内部转块首页地址,见陷阱 01
通过标准 返回 GD5F_OK,无 E_FAIL
覆盖原则 gd5f_block_eraseTrap 01 修复点)

TC-GD5F-604: write_enable / read_statusWEL 位)

字段
ID TC-GD5F-604
优先级 P2
类型 功能测试
标题 写使能后 WEL 位置位
前置条件 SPI 已初始化
测试步骤 gd5f_write_enable()gd5f_read_status(&s) 检查 s & GD5F_STATUS_WEL
通过标准 WEL 位为 1
覆盖原则 gd5f_write_enable / gd5f_read_status

TC-GD5F-605: gd5f_wait_busy 正常返回

字段
ID TC-GD5F-605
优先级 P2
类型 功能测试
标题 操作完成后 wait_busy 在超时内返回 0
前置条件 执行一次读/写操作后
测试步骤 gd5f_wait_busy(1000),检查返回值
通过标准 返回 GD5F_OKOIP 已清零)
覆盖原则 gd5f_wait_busy

8. 阶段 7DMA 边界(阈值 32 字节)

驱动 GD5F_DMA_THRESHOLD=32size>32HAL_SPI_*_DMA,否则轮询。两路径结果必须一致。

TC-GD5F-701: 阈值下界(轮询路径)

字段
ID TC-GD5F-701
优先级 P1
类型 边界测试
标题 size=32 走非 DMA 路径,读写正确
前置条件 目标块已擦除
测试步骤 写/读 32 字节并比对
通过标准 数据一致
覆盖原则 GD5F_DMA_THRESHOLD 下界

TC-GD5F-702: 阈值上界DMA 路径)

字段
ID TC-GD5F-702
优先级 P1
类型 边界测试
标题 size=33 走 DMA 路径,读写正确
前置条件 目标块已擦除
测试步骤 写/读 33 字节并比对
通过标准 数据一致
覆盖原则 GD5F_DMA_THRESHOLD 上界

TC-GD5F-703: 大块 DMA 一致性

字段
ID TC-GD5F-703
优先级 P1
类型 功能测试
标题 size=2048 整页DMA 路径)读写正确
前置条件 目标块已擦除
测试步骤 同 TC-GD5F-301确认 DMA 路径全页正确
通过标准 数据一致
覆盖原则 DMA 大数据路径

9. 阶段 8FTL 层nand_ftl

TC-GD5F-801: nand_ftl_init 成功

字段
ID TC-GD5F-801
优先级 P0
类型 功能测试
标题 FTL 初始化(在 driver init 之上建立映射)
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 调用 nand_ftl_init()
通过标准 返回 0日志无异常
覆盖原则 nand_ftl_init

TC-GD5F-802: nand_ftl_format 成功

字段
ID TC-GD5F-802
优先级 P1
类型 功能测试
标题 格式化后可正常使用
前置条件 nand_ftl_init() 已成功
测试步骤 调用 nand_ftl_format()
通过标准 返回 0
覆盖原则 nand_ftl_format

10. 阶段 9FatFS diskio可选待 FTL 完成)

TC-GD5F-901: 挂载 + 文件写读

字段
ID TC-GD5F-901
优先级 P2
类型 集成测试
标题 FatFS 挂载 /,写文件后读回比对
前置条件 FTL 已 init/formatFatFS diskio 已对接
测试步骤 f_mountf_open 写若干 KB → f_closef_open 读回比对
通过标准 文件内容一致
覆盖原则 FatFS diskio 链路

11. 边界条件

TC-GD5F-1001: offset 越界

字段
ID TC-GD5F-1001
优先级 P1
类型 负向测试
标题 offset >= TOTAL_SIZE 应返回错误
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 gd5f2gq5ue_read(GD5F_TOTAL_SIZE, buf, 1) / write
通过标准 返回错误码(非 GD5F_OK
覆盖原则 边界保护

TC-GD5F-1002: size=0

字段
ID TC-GD5F-1002
优先级 P2
类型 负向测试
标题 零长度读写不崩溃
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 gd5f2gq5ue_read(0, buf, 0) / write(0, buf, 0)
通过标准 返回 GD5F_OK 或合理错误,无 HardFault
覆盖原则 零长度处理

TC-GD5F-1003: 未擦除区域写入

字段
ID TC-GD5F-1003
优先级 P0
类型 注意事项/负向
标题 写前未擦除 → 数据不可预期
前置条件 目标块含旧数据(未擦除)
测试步骤 直接 write 新数据并 read 比对
通过标准 不通过比对(验证 NAND "先擦后写" 特性;测试本身用于确认驱动不会误报成功)
覆盖原则 NAND 写约束

TC-GD5F-1004: 写保护解除验证

字段
ID TC-GD5F-1004
优先级 P1
类型 功能测试
标题 init 后 Protect 寄存器为 0x00可写
前置条件 gd5f2gq5ue_init() 已成功
测试步骤 gd5f_private_set_feature 读 Protect(0xA0);或间接由"可正常 program"推断
通过标准 块保护已解除,编程不返回 GD5F_PROGRAM_FAIL
覆盖原则 块保护解除


12. 存储套件测试TEST_SUITE_STORAGE / storage_test_run

本套件独立于 GD5F 驱动套件,由 test_config.hTEST_SUITE_STORAGE 选择, 入口 storage_test_run()test/storage_test_task.c),统一在 ch395fTestTask 中调度。 当前 storage_test_run() 已覆盖 mkfs/mount/文件写读/性能(与阶段 9 FatFs 同类路径), 并新增下列三项集成测试TC-STO-01~03覆盖 FTL journal 掉电恢复、大文件/随机访问、坏块注入下的存储可用性。 三项均已于 STORAGE 套件实测通过(=== Storage Tests: 11/11 PASSED (failed=0) ===)。

已知陷阱(已修复)FTL 页缓存用 s_cached_lpn = 0 表示"缓存未加载",但 LPN 0 是合法页FAT 引导扇区所在页)。 resume/重新初始化后 s_cached_lpn 被复位为 0导致首次 f_mount 读 LBA0 时误判缓存命中、返回 memset 的全 0 缓存, 引导扇区签名变成 0000FatFs 报 FR_NO_FILESYSTEM。正常启动因 f_mkfs 兜底分支掩盖了此问题(第二次挂载才真正读盘)。 修复:将"缓存空"哨兵改为非法值 (dhara_sector_t)-10xFFFFFFFF远超实际容量涉及 disk_initialize / nand_ftl_deinit / nand_ftl_format

TC-STO-01: FTL 掉电恢复journal 持久化)

字段
ID TC-STO-01
优先级 P1
类型 集成/可靠性测试
标题 写入文件并同步后,可经 dhara_map_resume 恢复映射,文件不丢
前置条件 gd5f2gq5ue_init() + nand_ftl_init() 已成功FatFS 可挂载
测试步骤 1. f_mount → 写已知内容文件 pl.dat4KB 位置相关模式)→ f_sync/f_close 落盘
2. 模拟掉电:f_mount("",0) 卸载 → nand_ftl_deinit() 复位 FTL → nand_ftl_init() 重新走 dhara_map_resume
3. f_mount("",1) 重新挂载 → 打开 pl.dat 读回比对
通过标准 掉电模拟前后文件内容逐字节一致resume 后映射有效(无异常)
覆盖原则 disk_initialize / dhara_map_resume / FatFS 掉电安全
依赖 nand_ftl_deinit()(清 s_initialized/s_cached_lpn,使下次 init 真正重新 resume
实测 PASSSTORAGE 套件resume 后 pl.dat 内容逐字节一致;修复 s_cached_lpn 哨兵 bug 后通过)

TC-STO-02: 大文件 / 多扇区 / 随机 seek

字段
ID TC-STO-02
优先级 P1
类型 功能/压力测试
标题 256KB 文件顺序写读 + 随机偏移 seek 读一致性
前置条件 FTL 已初始化、FatFS 已挂载
测试步骤 1. 写 256KB 文件 big.dat,每字节按位置相关模式填充(便于任意偏移校验)
2. 顺序读回全量比对
3. f_lseek 到若干随机偏移(如 0/33KB/128KB/200KB/末段)读小块比对
通过标准 顺序与全部随机偏移读回内容均一致(验证 FTL 大范围映射 + GC + FatFS 随机访问)
覆盖原则 FTL 大范围 LBA 映射 / 垃圾回收 / FatFs f_lseek + f_read
实测 PASSSTORAGE 套件256KB 顺序 + 随机 seek 读回一致)

TC-STO-03: 坏块注入下存储写入

字段
ID TC-STO-03
优先级 P1
类型 负向/健壮性测试
标题 运行时注入坏块后FatFS 仍可正常写读且坏块未被占用
前置条件 gd5f2gq5ue_init() 成功FTL 已复位
测试步骤 1. nand_ftl_format() 清空旧 map → 选若干出厂好块 gd5f2gq5ue_mark_block_bad() 注入(更新并持久化 BBT
2. nand_ftl_deinit() + nand_ftl_init() 使 dhara 经 is_block_bad 看到新坏块
3. f_mkfs 重建文件系统 → 正常文件写读 bbt.dat 并校验
4. 校验注入坏块仍 gd5f2gq5ue_is_block_bad()==1
通过标准 文件内容完整;注入坏块未被 dhara 分配使用(仍报告坏),存储可用
注意事项 本例会永久将若干好块标记为坏并持久化(测试设备专用);如需恢复,运行 TC-STO-04启用 ENABLE_STORAGE_RECOVERY_TESTS 编译 STORAGE 套件一次)即可重建 BBT + 重新格式化
实测 PASSSTORAGE 套件:注入 3 坏块后文件完整且坏块仍报告坏)

TC-STO-04: 重建 BBT + 重新格式化(恢复)

字段
ID TC-STO-04
优先级 P1
类型 恢复/清理测试
标题 重建 BBT重新扫描出厂坏块并持久化并清空 dhara map恢复设备干净态
前置条件 gd5f2gq5ue_init() 成功;需启用 ENABLE_STORAGE_RECOVERY_TESTS 编译
测试步骤 1. gd5f2gq5ue_bbt_rebuild()(关 ECC → 重新扫描出厂坏块 → 开 ECC → gd5f_bbt_save 持久化,覆盖注入坏块)
2. nand_ftl_format() 清空 dhara map
3. gd5f_bbt_dump_flash 校验持久化 BBT 版本 ≥1
通过标准 重建返回 OK 且持久化 BBT 版本 ≥1设备坏块回到出厂集合注入坏块被清除
注意事项 运行一次即恢复;恢复后建议断电重启让 init 重新加载干净 BBT。本 TC 默认关闭,避免常规测试每次重置设备
依赖 gd5f2gq5ue_bbt_rebuild(详见 §4.8 持久化设计)

附录 B通过/失败汇总

TC-ID 标题 优先级 实测
TC-GD5F-101 init 全流程 P0 PASS
TC-GD5F-102 read_id 正确 ID P0 PASS
TC-GD5F-103 reset 成功 P1 PASS
TC-GD5F-201 出厂坏块扫描 P0 PASS
TC-GD5F-202 is_block_bad 查询 P0 PASS
TC-GD5F-203 mark/clear 一致性 P1 PASS
TC-GD5F-204 init BBT 稳定(无需 rescan P2 PASS
TC-GD5F-205 可用块数 < 总块数(保留池生效) P1 PASS
TC-GD5F-206 RAM 标记→闪存持久化bit+version P1 PASS
TC-GD5F-207 清 RAM→reload 恢复坏块 P1 PASS
TC-GD5F-301 整页写读 P0 PASS
TC-GD5F-302 跨页写读 P0 PASS
TC-GD5F-303 非对齐 offset P1 PASS
TC-GD5F-304 多页顺序写读 P1 PASS
TC-GD5F-305 随机单字节访问 P2 PASS
TC-GD5F-401 单块擦除读 0xFF P0 PASS
TC-GD5F-402 多块擦除 P1 PASS
TC-GD5F-403 非块对齐返回错误 P0 PASS
TC-GD5F-404 擦-写-读 闭环 P0 PASS
TC-GD5F-501 ECC 开启写读 P0 PASS
TC-GD5F-502 check_ecc 干净读 P1 PASS
TC-GD5F-503 ECC 纠错(可选) P3 未实现(可选)
TC-GD5F-601 page_read+cache 组合 P1 PASS
TC-GD5F-602 program_load+exec 组合 P1 PASS
TC-GD5F-603 block_erase 原语 P1 PASS
TC-GD5F-604 write_enable WEL 位 P2 PASS
TC-GD5F-605 wait_busy 正常返回 P2 PASS
TC-GD5F-701 DMA 阈值下界(32) P1 PASS
TC-GD5F-702 DMA 阈值上界(33) P1 PASS
TC-GD5F-703 大块 DMA 一致性 P1 PASS
TC-GD5F-801 nand_ftl_init P0 PASS
TC-GD5F-802 nand_ftl_format P1 PASS
TC-GD5F-901 FatFS 挂载写读 P2 PASS
TC-GD5F-1001 offset 越界 P1 PASS
TC-GD5F-1002 size=0 P2 PASS
TC-GD5F-1003 未擦除写入 P0 PASS
TC-GD5F-1004 写保护解除 P1 PASS
TC-STO-01 FTL 掉电恢复journal P1 PASS
TC-STO-02 大文件/随机 seek P1 PASS
TC-STO-03 坏块注入下存储写入 P1 PASS
TC-STO-04 BBT 重建 + 重新格式化(恢复) P1 ENABLE_STORAGE_RECOVERY_TESTS 控制(默认关)

当前实测:TEST_SUITE_GD5F 构建一次运行全部阶段,结尾输出 === GD5F2GQ5UE Tests: 65/65 PASSED (failed=0) ===65 为各 TC 内部断言总数,含 TC-GD5F-205~207 BBT 持久化用例TC 覆盖见上表)。TEST_SUITE_STORAGE 套件结尾输出 === Storage Tests: 11/11 PASSED (failed=0) ===TC-STO-01/02/03 各含若干内部断言,且 TC-STO-01 依赖的 s_cached_lpn 哨兵 bug 已修复)。两套件均 0 错误 0 警告通过 MDK 编译。


附录 C驱动函数覆盖

函数 覆盖 TC
gd5f2gq5ue_init TC-GD5F-101
gd5f2gq5ue_read_id TC-GD5F-102
gd5f2gq5ue_reset TC-GD5F-103
gd5f2gq5ue_read TC-GD5F-301/302/303/304/305
gd5f2gq5ue_write TC-GD5F-301/302/303/304/305
gd5f2gq5ue_erase TC-GD5F-401/402/403/404
gd5f2gq5ue_is_block_bad TC-GD5F-202
gd5f2gq5ue_mark_block_bad TC-GD5F-203
gd5f2gq5ue_bbt_clear TC-GD5F-203
gd5f2gq5ue_is_block_bad / 初始化 BBT TC-GD5F-204
gd5f2gq5ue_print_bbt TC-GD5F-201
gd5f_wait_busy TC-GD5F-605
gd5f_write_enable TC-GD5F-604
gd5f_read_status TC-GD5F-103/604
gd5f_page_read TC-GD5F-601
gd5f_read_from_cache TC-GD5F-601
gd5f_program_load TC-GD5F-602
gd5f_program_exec TC-GD5F-602
gd5f_block_erase TC-GD5F-603
gd5f_check_ecc TC-GD5F-501/502
nand_ftl_init TC-GD5F-801
nand_ftl_format TC-GD5F-802
nand_ftl_deinit TC-STO-01 / TC-STO-03
gd5f2gq5ue_bbt_rebuild TC-STO-04
storage_test_run(存储套件) TC-STO-01/02/03/04

附录 D参数速查

页数据/Spare/总长 2048 / 64 / 2112 B
每块页数 / 块大小 64 / 128 KB
总块数 / 容量 2048 / 256 MB
ID MID=0xC8, DID=0x52
擦除最小单位 1 块128 KB须对齐
DMA 阈值 32 B>32 走 DMA
状态寄存器 0xC0OIP=0, WEL=1, E_FAIL=2, P_FAIL=3, ECCS=4/5
Feature 寄存器 0xB0ECC_EN=4, QE=0
Protect 寄存器 0xA0init 后写 0x00 解除保护
SPI 引脚 CS=PE0, SCK=PB3, MISO=PB4, MOSI=PB5, WP=PB8, HOLD=PE1