NOR_FLASH_TESTING_QUICK_START

0 阅读8分钟

/**

  • NOR FLASH 驱动快速测试指南
  • 本指南帮助你快速验证 NOR Flash 驱动是否工作正常
  • 预计花时间:30-60 分钟 */

========================================================================================

快速测试攻略:5 个步骤验证 NOR Flash

========================================================================================

步骤 1️⃣:编译测试套件

# 进入代码目录
cd d:\code\fbb_ws63-master

# 编译整个项目(包括 NOR Flash 驱动)
python src/build.py -b WS63_board -m release

# 或者如果使用 CMake (可选)
cd build
cmake ..
make

编译过程中检查:

  • SFC 驱动是否编译成功
  • littlefs 驱动是否编译成功
  • 日志管理器是否编译成功
  • 没有链接错误

步骤 2️⃣:物理硬件检查

在烧录到板子之前,先检查硬件连接:

使用万用表检查

测试项目                     标准值          你的测试结果
────────────────────────────────────────────────────────
Flash 电源 (VCC)            3.3V ± 0.2V    ┌─────────┐
                                             │         │
                                             └─────────┘

地 (GND)                    0V              ┌─────────┐
                                             │  OK/NOK │
                                             └─────────┘

Flash 芯片型号             (查看标签)       ┌─────────┐
                          如 GD25Q32       │         │
                                             └─────────┘

使用示波器检查 SPI 信号

信号        频率范围        波形        连接检查
────────────────────────────────────────────────────────
CLK         33-150 MHz      ▃▂▃▂▃▂    [ ] 有信号
MOSI        跟随 CLK        ▄▅▄▅▄▅    [ ] 有信号  
MISO        跟随 CLK        ▄▅▄▅▄▅    [ ] 有信号
CS          低电平选中      ╔║╚║╔║    [ ] 有脉冲

✅ 如果所有信号都正常,proceed to step 3


步骤 3️⃣:烧录到板子

# 使用 HiSparkStudio 或命令行工具
# 以 HiSparkStudio 为例:

1. 打开 HiSparkStudio
2. 连接开发板(USB 或 JTAG)
3. 选择项目文件夹
4. 配置编译选项
5. 点击 "Build and Flash"

# 也可以用命令行
python tools/hiflash.py --board WS63_board --image build/ws63_App.bin

烧录进度:

  • 0% ─────────────────────────── 100%

步骤 4️⃣:运行测试套件

方法 A:通过串口运行(推荐)

# 1. 打开串口终端工具(如 SecureCRT, Tera Term, PuTTY)
# 2. 连接到开发板的串口
# 3. 波特率:115200
# 4. 数据位:8,停止位:1,校验:None

# 在开发板上运行命令
>> nor_flash_driver_test_suite

# 如果没有这个命令,可能需要在代码中做以下调整

方法 B:在代码中集成测试

如果不能直接执行,修改 main.c:

#include "nor_flash_driver_test_suite.h"

int main(void) {
    // app_init();
    
    // 调用测试(可选)
    int test_result = test_sfc_device();
    
    if (test_result == 0) {
        printf("✅ All tests PASSED!\n");
    } else {
        printf("❌ Some tests FAILED!\n");
    }
    
    // 继续正常应用程序流程
    // app_run();
    
    return 0;
}

步骤 5️⃣:检查测试结果

5.1 预期输出示例

════════════════════════════════════════
NOR Flash Driver Test Suite
════════════════════════════════════════
Configuration Summary:
  NOR Flash Start: 0x00200000
  Max Mapping Size: 4096 KB (4.00 MB)
  Read Interface: QUAD_READ (150MHz)
  Write Interface: QUAD_PROGRAM

════════════════════════════════════════
Level 1: Hardware Detection
════════════════════════════════════════

[TEST] SFC Driver Initialization
  - Mapping address: 0x00200000
  - Mapping size: 0x00400000
 PASSED: SFC initialization

[TEST] Flash ID Detection
  - Detected Flash ID: 0x1640C8
  - Chip Name: GigaDevice GD25Q32
 PASSED: Flash ID detection

[TEST] Flash Configuration Verification
  - Flash chip detection: OK
  - Command set loaded: OK
  - Protection bits: Verified
 PASSED: Flash config verification

════════════════════════════════════════
Level 2: Basic Read/Write/Erase
════════════════════════════════════════

[TEST] Basic Write Test
  - Writing 36 bytes at 0x00200000
  - Erase 4K block: OK
  - Data written: OK
 PASSED: Basic write

[TEST] Basic Read Test
  - Reading 36 bytes from 0x00200000
  - Read data: OK
  - Data verify: OK
  - Content: Hello NOR Flash! This is a test.
 PASSED: Basic read

[TEST] Basic Erase Test
  - Writing pattern 0xAA to 4K block
  - Erasing 4K block...
  - Verifying erased data (should be 0xFF)...
  - Erase verification: OK
 PASSED: Basic erase

════════════════════════════════════════
Test Summary
════════════════════════════════════════
Total Tests: 12
Passed: 12 (100.0%)
Failed: 0
Skipped: 0
Total Bytes Tested: 5.34 MB
Total Time: 245.63 ms
════════════════════════════════════════

5.2 结果分析

结果含义下一步
✅ 100% PASSED完美!开始集成日志系统
⚠️ 80-99% PASSED大部分功能正常调查失败的测试项
❌ < 80% PASSED有严重问题返回步骤 2,检查硬件

5.3 如果测试失败

失败 1:SFC 初始化失败
❌ FAILED: SFC initialization
ERROR: SFC init failed with code 0x xxxxx

✅ 解决方案:

  1. 检查 CONFIG_HAS_SFC=y
  2. 检查 SPI 引脚是否正确映射
  3. 检查 Flash 芯片电源
失败 2:Flash ID 检测失败
 FAILED: Flash ID detection
ERROR: Failed to read Flash ID
Detected Flash ID: 0x00000000  0xFFFFFFFF

✅ 解决方案:

  1. 检查 SPI 接线(特别是 MISO 线)
  2. 使用示波器观察 SPI 信号
  3. 检查 Flash 芯片是否损坏
失败 3:Basic Write/Read 失败
❌ FAILED: Basic write
ERROR: Erase failed with code 0x xxxxx

✅ 解决方案:

  1. 检查分区地址是否正确
  2. 检查 Flash 是否是写保护状态
  3. 尝试其他读写地址
失败 4:littlefs 挂载失败
❌ FAILED: littlefs mount
ERROR: mount failed with errno xxxxx

✅ 解决方案:

  1. 确保分区与 SFC 映射地址一致
  2. 清空 Flash:fs_adapt_format()
  3. 重新初始化文件系统

========================================================================================

高级测试:逐项验证

========================================================================================

测试 A:单独测试 SFC 驱动

如果完整测试失败,逐项测试以定位问题:

/* 最小化测试代码 */

#include "sfc.h"

int main(void) {
    // 1. 测试初始化
    printf("1. Testing SFC initialization...\n");
    sfc_flash_config_t cfg = {
        .mapping_addr = 0x200000,
        .mapping_size = 0x400000,
        .read_type = STANDARD_READ,     // 先用标准模式
        .write_type = PAGE_PROGRAM,
    };
    
    if (uapi_sfc_init(&cfg) != ERRCODE_SUCC) {
        printf("ERROR: SFC init failed!\n");
        return -1;
    }
    printf("✅ SFC initialized\n");
    
    // 2. 测试 ID 读取
    printf("\n2. Testing Flash ID detection...\n");
    uint32_t flash_id;
    if (hal_sfc_get_flash_id(&flash_id) != ERRCODE_SUCC) {
        printf("ERROR: Cannot read Flash ID!\n");
        return -1;
    }
    printf("✅ Flash ID: 0x%08X\n", flash_id);
    
    // 3. 测试简单擦除
    printf("\n3. Testing erase...\n");
    if (uapi_sfc_reg_erase(0x200000, 4096) != ERRCODE_SUCC) {
        printf("ERROR: Erase failed!\n");
        return -1;
    }
    printf("✅ Erase successful\n");
    
    // 4. 测试简单写入
    printf("\n4. Testing write...\n");
    uint8_t test_data[] = "TEST";
    if (uapi_sfc_reg_write(0x200000, test_data, 4) != ERRCODE_SUCC) {
        printf("ERROR: Write failed!\n");
        return -1;
    }
    printf("✅ Write successful\n");
    
    // 5. 测试简单读取
    printf("\n5. Testing read...\n");
    uint8_t read_buf[10] = {0};
    if (uapi_sfc_reg_read(0x200000, read_buf, 4) != ERRCODE_SUCC) {
        printf("ERROR: Read failed!\n");
        return -1;
    }
    printf("✅ Read successful: %s\n", (char *)read_buf);
    
    printf("\n✅ All basic tests passed!\n");
    return 0;
}

编译并运行:

gcc -o test_sfc test_sfc.c -lsfc
./test_sfc

# 预期输出:
# ✅ SFC initialized
# ✅ Flash ID: 0x1640C8
# ✅ Erase successful
# ✅ Write successful  
# ✅ Read successful: TEST
# ✅ All basic tests passed!

测试 B:单独测试 littlefs

#include "littlefs_adapt.h"

int main(void) {
    printf("Testing littlefs...\n");
    
    // 1. 挂载文件系统
    printf("1. Mounting...\n");
    int ret = fs_adapt_mount();
    if (ret != LFS_ERR_OK) {
        printf("ERROR: mount failed %d\n", ret);
        printf("   Trying format...\n");
        fs_adapt_format();
        ret = fs_adapt_mount();
        if (ret != LFS_ERR_OK) {
            printf("ERROR: still failed!\n");
            return -1;
        }
    }
    printf("✅ Mounted\n");
    
    // 2. 创建目录
    printf("2. Creating directory...\n");
    fs_adapt_mkdir("/logs");
    printf("✅ Directory created\n");
    
    // 3. 创建文件
    printf("3. Creating file...\n");
    int fd = fs_adapt_open("/logs/test.txt", O_RDWR | O_CREAT);
    if (fd < 0) {
        printf("ERROR: open failed\n");
        return -1;
    }
    printf("✅ File created (fd=%d)\n", fd);
    
    // 4. 写入数据
    printf("4. Writing data...\n");
    const char *data = "Hello littlefs!";
    int written = fs_adapt_write(fd, data, strlen(data));
    printf("✅ Written %d bytes\n", written);
    
    // 5. 同步
    printf("5. Syncing...\n");
    fs_adapt_sync(fd);
    printf("✅ Synced\n");
    
    // 6. 重新定位
    printf("6. Seeking to start...\n");
    fs_adapt_lseek(fd, 0, SEEK_SET);
    printf("✅ Seeked\n");
    
    // 7. 读取数据
    printf("7. Reading data...\n");
    char buffer[32] = {0};
    int read = fs_adapt_read(fd, buffer, sizeof(buffer));
    printf("✅ Read %d bytes: %s\n", read, buffer);
    
    fs_adapt_close(fd);
    fs_adapt_unmount();
    
    printf("\n✅ All littlefs tests passed!\n");
    return 0;
}

测试 C:性能基准

#include <time.h>

void benchmark_read(void) {
    uint8_t buf[4096];
    uint32_t start_addr = 0x200000;
    
    clock_t start = clock();
    for (int i = 0; i < 100; i++) {
        uapi_sfc_reg_read(start_addr, buf, 4096);
    }
    clock_t end = clock();
    
    double ms = (double)(end - start) / CLOCKS_PER_SEC * 1000;
    double throughput = 100.0 * 4096 / 1024 / 1024 / (ms / 1000);
    
    printf("Read Performance:\n");
    printf("  100 x 4KB reads in %.2f ms\n", ms);
    printf("  Throughput: %.2f MB/s\n", throughput);
    printf("  ✅ Expected: 50-150 MB/s depending on SPI mode\n");
}

void benchmark_write(void) {
    uint8_t buf[256];
    uint32_t start_addr = 0x200000;
    
    clock_t start = clock();
    for (int i = 0; i < 100; i++) {
        uapi_sfc_reg_erase(start_addr + i * 4096, 4096);
        uapi_sfc_reg_write(start_addr + i * 4096, buf, 256);
    }
    clock_t end = clock();
    
    double ms = (double)(end - start) / CLOCKS_PER_SEC * 1000;
    double throughput = 100.0 * 256 / 1024 / 1024 / (ms / 1000);
    
    printf("\nWrite Performance:\n");
    printf("  100 x (erase 4KB + write 256B) in %.2f ms\n", ms);
    printf("  Throughput: %.2f MB/s\n", throughput);
    printf("  ✅ Expected: 1-10 MB/s depending on erase time\n");
}

========================================================================================

常见问题快速表

========================================================================================

症状可能原因快速解决
SFC 初始化 failSFC 未启用检查 CONFIG_HAS_SFC=y
Flash ID = 0xFFFFFFFFMISO 线未连接检查 SPI 接线
Flash ID = 0x000000SPI 时钟未启用检查时钟门控寄存器
写入成功但读不出未调用 sync添加 fs_adapt_sync(fd)
littlefs mount fail分区地址错检查 CONFIG_LFS_START_ADDR
读写速度慢用的 STANDARD_READ切换到 QUAD_READ
文件损坏Flash 寿命已尽更换 Flash 芯片

========================================================================================

验证检查表(打印并填写)

========================================================================================

测试项                              状态         备注
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
编译成功                           [ ] ✅ ❌
烧录成功                           [ ] ✅ ❌
SFC 初始化测试                     [ ] ✅ ❌
Flash ID 检测                      [ ] ✅ ❌   ID: _____
基础写入测试                       [ ] ✅ ❌
基础读取测试                       [ ] ✅ ❌
基础擦除测试                       [ ] ✅ ❌
littlefs 挂载                      [ ] ✅ ❌
文件创建测试                       [ ] ✅ ❌
文件写入测试                       [ ] ✅ ❌
文件读取测试                       [ ] ✅ ❌
性能基准测试                       [ ] ✅ ❌   速度: __MB/s
整体测试通过率                                  ___%

批准人: ________________            日期: ____________

========================================================================================

后续步骤

========================================================================================

✅ 如果所有测试通过,恭喜!你可以:

  1. 集成日志管理系统

    使用 log_manager.c/h 实现 20+ 文件日志
    
  2. 开始应用开发

    // 现在可以安心使用文件系统
    int fd = fs_adapt_open("/logs/app.log", O_APPEND | O_CREAT);
    fs_adapt_write(fd, log_data, size);
    
  3. 性能优化

    - 换用 QUAD_READ 获得 150MB/s 性能
    - 优化缓冲区大小
    - 批量操作减少上下文切换
    

❌ 如果测试失败,按以下顺序排查:

  1. 物理硬件连接(看硬件)
  2. 驱动配置参数(看软件配置)
  3. 固件烧录(重新烧录)
  4. 芯片损坏(更换芯片)

祝你测试顺利!🎉