Edit online

SPI NAND 配置

5 Dec 2024
Read time: 7 minute(s)

SPI NAND 驱动配置

  • Baremetal 配置

    Luban-Lite 根目录下执行 scons --menuconfig,进入 menuconfig 的功能配置界面,按如下选择。

    Board options  --->
        [*] Using Qspi0
        [ ] Using Qspi1
        [ ] Using Qspi2
        [ ] Using Qspi3
            Qspi0 Parameter  --->
                 (1) Max frequency(Hz)
                Set SPI0 bus width (Quad)  ---> //配置 QSPI data width
        [*] QSPI0 Devices: SPINAND  --->
             --- QSPI0 Devices: SPINAND
            (100000000) SPINAND bus frequency(Hz)
            [*]   Continuous Read Mode Enable //部分 SPI NAND 支持该模式
    
    Drivers options  --->
        Peripheral  --->
             -*- SPINAND Driver library
             [*]   Support Winbond SPI NAND  //使能对应 spinand 芯片厂家配置
        AIC Bare Driver  --->
            [*] Enable AIC MTD Bare Driver
    
    注:

    为了方便配置, 使能 AIC_QSPI0_DEVICE_SPINAND 后, 会自动选上 AIC_SPINAND_DRV, LPKG_USING_SPINAND, AIC_MTD_BARE_DRV

  • RTOS 配置

    Luban-Lite 根目录下执行 scons --menuconfig,进入 menuconfig 的功能配置界面,按如下选择:

    Board options  --->
        [*] Using Qspi0
        [ ] Using Qspi1
        [ ] Using Qspi2
        [ ] Using Qspi3
            Qspi0 Parameter  --->
                 (100000000) Max frequency(Hz)
                 Set SPI0 bus width (Quad)  ---> //配置 QSPI data width
        [*] QSPI0 Devices: SPINAND  --->
             --- QSPI0 Devices: SPINAND
            (100000000) SPINAND bus frequency(Hz)
            [*]   Continuous Read Mode Enable //部分 SPI NAND 支持该模式
    
    Drivers options  --->
        Peripheral  --->
             -*- SPINAND Driver library
             [*]   Support Winbond SPI NAND //使能对应 spinand 芯片厂家配置
    
    Rt-Thread options  --->
        RT-Thread Components  --->
            Device Drivers  --->
                -*- Using MTD Nand Flash device drivers
    
    注:

    为了方便配置,使能 AIC_QSPI0_DEVICE_SPINAND 后, 会自动选上 AIC_SPINAND_DRV, LPKG_USING_SPINAND, RT_USING_MTD_NAND

SPI NAND 移植指南

SPI NAND 移植工作需要 SoC 端 SPI 模块的驱动能力以及对 SPI NAND 模块的正确配置。本节以 ForeseeF35SQA001G 为例,详细说明 SPI NAND 器件的移植流程。

注:

SPI NAND 在 Boot 和 RTOS 中的实现一致。

  1. 准备文件
    1. bsp/peripheral/spinand/ 目录下创建带相应公司标识的文件,如 foresee.c。如果该公司的文件已经存在,则略过此步,直接添加新器件支持即可。

      一般情况下,同一个公司的 SPI NAND 的操作接口类似,创建一个文件可方便管理公司的接口配置。

    2. bsp/peripheral/spinand/inc/spinand.h 中声明如下:
      extern const struct spinand_manufacturer foresee_spinand_manufacturer;
      
  2. 添加驱动索引

    通过两级列表,设置 RTOS 支持的 SPI NAND 设备和驱动的关联。

    1. 检查 bsp/peripheral/spinand/spinand.c 中的 spinand_manufacturers 信息,查看新设备的厂商是否在列表之中:
      static const struct spinand_manufacturer *spinand_manufacturers[] = {
          &winbond_spinand_manufacturer,
          &xtx_spinand_manufacturer,
          &gigadevice_spinand_manufacturer,
          &foresee_spinand_manufacturer,
      };

      spinand_manufacturer 数据结构为第一级索引,用来描述厂商的系列器件信息,是 SPI NAND 驱动的核心。

    2. 检查具体的设备厂商文件,确认具体的型号是否在列表之中。
      const struct aic_spinand_info foresee_spinand_table[] = {
          /*devid page_size oob_size block_per_lun pages_per_eraseblock is_die_select*/
          /*F35SQA512M*/
          { DEVID(0x70), PAGESIZE(2048), OOBSIZE(64), BPL(512), PPB(64), PLANENUM(1),
          DIE(0), "foresee 64MB: 2048+64@64@512", cmd_cfg_table },
          /*F35SQA001G*/
          { DEVID(0x71), PAGESIZE(2048), OOBSIZE(64), BPL(1024), PPB(64), PLANENUM(1),
          DIE(0), "foresee 128MB: 2048+64@64@1024", cmd_cfg_table },
          /*F35SQA002G*/
          { DEVID(0x72), PAGESIZE(2048), OOBSIZE(64), BPL(2048), PPB(64), PLANENUM(1),
          DIE(0), "foresee 256MB: 2048+64@64@2048", cmd_cfg_table },
          /*FS35ND04G*/
          { DEVID(0xEC), PAGESIZE(2048), OOBSIZE(64), BPL(4096), PPB(64), PLANENUM(1),
          DIE(0), "foresee 512MB: 2048+64@64@4096", cmd_cfg_table },
      };

      一般 SPI NAND 都采用标准操作接口,接口比较固定但参数可能会有差别,而参数主要由 SPINAND_INFO 描述。

  3. 配置 xxx_cmd_cfg_table

    SPI NAND 的接口和操作命令基本统一,一般无需特殊处理。驱动上为了更好的兼容性,预留了部分接口方便配置使用。如无需自定义配置,可略过此步。

  4. 配置 F35SQA001G 相关参数
    #define SPINAND_MFR_FORESEE 0xCD
    
    /*F35SQA001G*/
    { DEVID(0x71), PAGESIZE(2048), OOBSIZE(64), BPL(1024), PPB(64), PLANENUM(1),
      DIE(0), "foresee 128MB: 2048+64@64@1024", cmd_cfg_table },

    以下是对相关参数的说明:

    1. F35SQA001G 参数描述
    参数 ID 参数名字 说明
    1 devid 设备 id
    2 page_size page 大小
    3 oob_size oob 大小
    4 block_per_lun 一个目标节点内包含 block 个数
    5 pages_per_eraseblock 一个 block 里包含 page 个数
    6 is_die_select 是否需要选择目标节点,一般单 die,设置为 0 即可

    rtt spinand 不需要太大容量,128MB 即可满足要求。因此一般只有一个目标节点,is_die_select 设置为 0。

    7 sz_description spinand 芯片描述信息
    8 cmd 特定芯片操作命令组合
  5. 使能 Foresee 厂家的配置
    Drivers options  --->
        Peripheral  --->
             -*- SPINAND Driver library
              [*]   Support Foresee SPI NAND
     
    注:

    Boot 和 RTOS 需要同时配置

  6. 配置 状态寄存器 ECC Status,处理函数替换
    • 寄存器 ECC Status Bit 返回状态值一般为通用值,使用默认 spinand_check_ecc_status 处理函数。如果 ECC Status 打印错误信息:
      • 返回如下信息,表示发现了新的坏块:
        ECC status error[0x20].
      • 返回如下信息,表示需要单独适配 ECC Status Bit 返回值:
        ECC status error[0x30].
      • 对于 0x30 Bit 返回值,厂家一般不会使用,因此也不会打印该值。如果厂家使用,则表示检测了 1 ~ 4 位 ecc 位校验纠正情况,具体需以用户手册为准。

    • 正常情况下,ECC Status Bit 有 2 位。对于 ECC Status Bit 有 3 位或者 4 位的芯片,需要单独适配该寄存器:
      1. 以 ETRON EM73C044VCF 为例,在对应 SPINAND 厂家文件 bsp/peripheral/spinand/etron.c 里面,添加 ECC Status 处理函数:
        static int em73c044vcf_ecc_get_status(struct aic_spinand *flash, u8 status)
        {
            switch (status & STATUS_ECC_MASK) {
                case STATUS_ECC_NO_BITFLIPS:
                    return 0;                   //没有检测到 ecc 位校验纠正情况
                case STATUS_ECC_HAS_1_4_BITFLIPS:
                    return 4;                   //检测了 1 ~ 4 位 ecc 位校验纠正情况
                case STATUS_ECC_UNCOR_ERROR:
                    return -SPINAND_ERR_ECC;    //ecc 位校验纠正失败,错误 bit 超过 4 位,需要标记坏块
                case STATUS_ECC_MASK:
                    return 4;                   //检测了 1 ~ 4 位 ecc 位校验纠正情况
                default:
                    break;
            }
        
            return -SPINAND_ERR;
        }
      2. 将功能函数地址添加到对应 SPINAND 配置上,以替换 ECC Status 通用处理函数。
        { DEVID(0x25), PAGESIZE(2048), OOBSIZE(64), BPL(1024), PPB(64), PLANENUM(1),
          DIE(0), "etron 128MB: 2048+64@64@1024", cmd_cfg_table,
          em73c044vcf_ecc_get_status},

文件系统配置

  • RT-Thread FatFS 配置
    Using mount table for filesystem 选项打开时,系统启动后会根据一个 Table 配置来自动挂载文件系统。该 Table 定义在 board.c 中:
    Local packages options  --->
        Third-party packages options  --->
            [*] UFFS: Ultra-low-cost Flash File System.  --->
                UFFS ECC mode (3: Hardware calculate the ECC and automatically write to spare.)  --->
  • RT-Thread UFFS 配置
    Using mount table for filesystem 选项打开时,系统启动后会根据一个 Table 配置来自动挂载文件系统。该 Table 定义在 board.c 中:
    #ifdef RT_USING_DFS_MNTTABLE
    #include <dfs_fs.h>
    
    const struct dfs_mount_tbl mount_table[] = {
    #ifdef LPKG_USING_DFS_UFFS
        {"data", "/data", "uffs", 0, 0, 1},
    #endif
        {0}
    };
    #endif

文件系统镜像制作和烧录

FatFS 镜像
Application options  --->
     [*] Using File System Image 0  --->
        Select File System Type (FATFS)  --->
        (application/os/helloworld/lvgl/base_demo/lvgl_src/) Data Directory
        (rodata.fatfs) Image Name
         [*]   auto calcuate image size
    (1) size of cluster in fatfs image