衡山派Luban-Lite SPI NAND驱动配置与移植实战指南:从Baremetal到RT-Thread文件系统

📅 发布时间:2026/7/5 15:17:22 👁️ 浏览次数:
衡山派Luban-Lite SPI NAND驱动配置与移植实战指南:从Baremetal到RT-Thread文件系统
衡山派Luban-Lite SPI NAND驱动配置与移植实战指南从Baremetal到RT-Thread文件系统最近在衡山派开发板上做项目需要用到SPI NAND Flash来存储数据和文件系统。很多刚开始接触这块板子的朋友问我怎么把SPI NAND用起来从底层驱动配置到上层文件系统挂载整个流程该怎么走。今天我就结合官方文档和实际调试经验手把手带大家走一遍这个流程咱们以Foresee的F35SQA001G芯片为例从最基础的menuconfig配置开始一直讲到文件系统镜像的制作。这篇文章适合正在或打算在衡山派平台上使用SPI NAND Flash的嵌入式开发者特别是那些需要在RT-Thread系统下挂载FatFS或UFFS文件系统的朋友。我会尽量把每一步都讲清楚包括我踩过的一些坑。1. SPI NAND驱动的基础配置要让SPI NAND工作首先得在Luban-Lite的配置系统里把它“打开”。配置分两种情况裸机Baremetal环境和RTOS这里特指RT-Thread环境。两者的配置大部分相同但RTOS下多了一些文件系统相关的选项。1.1 裸机Baremetal环境配置咱们先看看在不用操作系统的情况下怎么配。这个配置主要是让板子的硬件能识别和访问SPI NAND芯片。首先进入你的Luban-Lite工程根目录打开终端输入配置命令scons --menuconfig这个命令会启动一个图形化的配置界面用键盘方向键和回车键操作就行。进入界面后按照下面的路径一步步选择Board options这是板级配置的入口。找到[*] Using Qspi0这一项按空格键选中它前面会出现*号。这表示我们要使用QSPI0这个硬件接口来连接SPI NAND。衡山派开发板可能有多个QSPI接口具体用哪个要看你的硬件连接这里以QSPI0为例。选中后下面会出现Qspi0 Parameter ---的子菜单按回车进入。(1) Max frequency(Hz)这里设置QSPI控制器的最大工作频率。根据你的SPI NAND芯片手册来填比如100000000就是100MHz。注意这个频率不能超过芯片支持的最高频率。Set SPI0 bus width (Quad) ---这个很重要是设置数据线的宽度。SPI NAND通常支持Quad四线模式来提升速度所以这里选择Quad。退回到Board options主菜单找到[*] QSPI0 Devices: SPINAND ---并选中然后按回车进入其子菜单。(100000000) SPINAND bus frequency(Hz)这里设置SPI NAND芯片本身的通信频率。通常和上面控制器的频率设成一样就行比如100000000。[*] Continuous Read Mode Enable连续读模式使能。部分SPI NAND芯片支持这个模式开启后能提升连续读取数据的性能。如果你的芯片支持建议勾选。Drivers options这里是驱动库的配置。进入Peripheral ---子菜单。确保-*- SPINAND Driver library被选中前面是*号表示核心驱动必须选。找到[*] Support Winbond SPI NAND。注意这里虽然写的是Winbond华邦但只是一个示例。我们用的是Foresee的芯片所以先不要勾选这个。后面在移植章节我们会把它换成Foresee的支持。进入AIC Bare Driver ---子菜单。选中[*] Enable AIC MTD Bare Driver。MTDMemory Technology Device是内存技术设备的抽象层勾选它才能以“块设备”的形式访问SPI NAND。提示为了方便当你选中AIC_QSPI0_DEVICE_SPINAND即QSPI0设备为SPI NAND后系统会自动帮你选上AIC_SPINAND_DRVSPI NAND驱动、LPKG_USING_SPINAND使用SPI NAND包和AIC_MTD_BARE_DRVMTD裸驱动这几个依赖项不用自己一个个去找。1.2 RTOSRT-Thread环境配置在RT-Thread系统下的配置前面关于硬件接口QSPI0和基础驱动的部分和裸机配置完全一样。你需要重复上面1.1节中Board options和Drivers options - Peripheral里的所有步骤。区别在于RT-Thread下多了文件系统相关的配置选项。所以在完成上述相同配置后还需要进行以下操作在menuconfig主界面找到Rt-Thread options并进入。进入RT-Thread Components ---。进入Device Drivers ---。选中-*- Using MTD Nand Flash device drivers。这个选项非常重要它告诉RT-Thread我们要使用MTD框架来管理NAND Flash包括SPI NAND这样上层文件系统才能识别这个存储设备。提示同样地选中AIC_QSPI0_DEVICE_SPINAND后系统会自动选上AIC_SPINAND_DRV、LPKG_USING_SPINAND以及这里需要的RT_USING_MTD_NAND。配置完成后按S键保存再按Q键退出menuconfig界面。2. SPI NAND芯片移植实战以Foresee F35SQA001G为例配置好系统支持后接下来就要告诉系统“我用的具体是哪个型号的SPI NAND芯片”。这个过程就是移植。我们以Foresee F35SQA001G这个型号为例。2.1 准备工作添加厂商驱动文件Luban-Lite的驱动通常按芯片厂商来组织。如果某个厂商的驱动文件已经存在我们只需要在里面添加新型号如果不存在就需要新建。检查厂商文件首先去bsp/peripheral/spinand/目录下看看有没有类似foresee.c这样的文件。如果没有就需要创建一个。创建/修改源文件在bsp/peripheral/spinand/目录下创建或打开foresee.c文件。这个文件将包含Foresee公司所有SPI NAND芯片的驱动信息。声明厂商结构体在bsp/peripheral/spinand/inc/spinand.h头文件中添加一行声明extern const struct spinand_manufacturer foresee_spinand_manufacturer;这行代码告诉编译器存在一个叫foresee_spinand_manufacturer的结构体里面定义了Foresee芯片的操作方法。2.2 关键一步将芯片加入驱动列表驱动系统通过两级列表来查找和匹配芯片。我们必须确保我们的芯片在这两个列表里。第一级厂商列表打开bsp/peripheral/spinand/spinand.c文件找到spinand_manufacturers这个数组。我们需要把Foresee的厂商结构体加进去。static const struct spinand_manufacturer *spinand_manufacturers[] { winbond_spinand_manufacturer, xtx_spinand_manufacturer, gigadevice_spinand_manufacturer, // 添加下面这一行 foresee_spinand_manufacturer, };这样系统就知道有Foresee这家厂商了。第二级芯片型号列表接下来在刚才的foresee.c文件中我们需要定义一个数组列出Foresee公司支持的所有SPI NAND型号。这里就是添加我们具体芯片的地方。const struct aic_spinand_info foresee_spinand_table[] { /* 参数顺序设备ID, 页大小, OOB大小, 每LUN块数, 每块页数, 平面数, Die选择, 描述字符串, 命令配置表 */ /* F35SQA512M */ { DEVID(0x70), PAGESIZE(2048), OOBSIZE(64), BPL(512), PPB(64), PLANENUM(1), DIE(0), foresee 64MB: 20486464512, cmd_cfg_table }, /* F35SQA001G - 这就是我们要用的芯片 */ { DEVID(0x71), PAGESIZE(2048), OOBSIZE(64), BPL(1024), PPB(64), PLANENUM(1), DIE(0), foresee 128MB: 204864641024, cmd_cfg_table }, /* F35SQA002G */ { DEVID(0x72), PAGESIZE(2048), OOBSIZE(64), BPL(2048), PPB(64), PLANENUM(1), DIE(0), foresee 256MB: 204864642048, cmd_cfg_table }, /* FS35ND04G */ { DEVID(0xEC), PAGESIZE(2048), OOBSIZE(64), BPL(4096), PPB(64), PLANENUM(1), DIE(0), foresee 512MB: 204864644096, cmd_cfg_table }, };这个aic_spinand_info结构体是驱动的核心它描述了芯片的所有关键参数。系统上电时会读取芯片的设备ID比如F35SQA001G是0x71然后在这个表里查找匹配项。2.3 理解芯片参数表咱们详细看看上面结构体里的每个参数是干嘛用的这样以后换其他芯片你也知道怎么改。参数名宏定义说明示例值 (F35SQA001G)设备IDDEVID(x)芯片的唯一标识符通过读ID命令获得。必须和芯片手册一致。0x71页大小PAGESIZE(x)芯片进行读写操作的最小单位单位是字节。2048(2KB)OOB大小OOBSIZE(x)每页附带的“备用区”大小用于存放ECC校验码、坏块标记等元数据。64字节每LUN块数BPL(x)每个逻辑单元LUN包含的擦除块数量。对于小容量单Die芯片可以简单理解为总块数。1024每块页数PPB(x)每个擦除块包含的页数。64平面数PLANENUM(x)芯片内部的平面Plane数量用于并行操作提升速度。单平面芯片填1。1Die选择DIE(x)是否需要选择Die晶片。单Die芯片填0即可。0描述信息字符串一段描述芯片容量和规格的字符串方便调试时识别。foresee 128MB: ...命令表cmd_cfg_table指向该芯片特定操作命令表的指针一般用通用的即可。cmd_cfg_table注意对于RT-Thread文件系统来说128MB的容量通常已经足够。大部分SPI NAND都是单Die设计所以is_die_select对应DIE宏设为0就行。2.4 使能Foresee厂商支持芯片信息加好了最后一步是回到menuconfig把对Foresee厂商的支持打开。再次运行scons --menuconfig进入Drivers options --- Peripheral --- -*- SPINAND Driver library [ ] Support Winbond SPI NAND // 把这个取消 [*] Support Foresee SPI NAND // 把这个勾选上把之前可能勾选的Support Winbond SPI NAND取消然后勾选我们刚添加的Support Foresee SPI NAND。重要这个配置在Bootloader和RTOS中都需要进行确保两个阶段都能正确识别芯片。3. 处理ECC状态寄存器高级话题大部分SPI NAND芯片的ECC状态寄存器是标准的驱动里有一个通用的spinand_check_ecc_status函数来处理。但有些芯片比较特殊需要我们自己写处理函数。怎么判断是否需要自定义函数在系统运行时如果SPI NAND驱动打印出类似ECC status error[0x30].这样的错误信息就说明通用的ECC状态解析失败了需要为这个芯片单独适配。如何自定义以ETRON EM73C044VCF芯片为例虽然我们用的是Foresee但方法通用需要在对应的厂商文件如etron.c里添加一个函数static int em73c044vcf_ecc_get_status(struct aic_spinand *flash, u8 status) { // STATUS_ECC_MASK 是一个掩码用于从状态字节中提取ECC相关的位 switch (status STATUS_ECC_MASK) { case STATUS_ECC_NO_BITFLIPS: return 0; // 状态0没有检测到位翻转完美 case STATUS_ECC_HAS_1_4_BITFLIPS: return 4; // 状态1检测到1-4个位翻转但已被ECC纠正数据是好的 case STATUS_ECC_UNCOR_ERROR: return -SPINAND_ERR_ECC; // 状态2无法纠正的错误位翻转太多这个块应该标记为坏块 case STATUS_ECC_MASK: return 4; // 状态3在某些芯片定义里也可能表示1-4个位翻转 default: break; } return -SPINAND_ERR; // 其他未知状态返回通用错误 }然后在芯片信息表里把这个函数的地址赋给对应的芯片条目{ DEVID(0x25), PAGESIZE(2048), OOBSIZE(64), BPL(1024), PPB(64), PLANENUM(1), DIE(0), etron 128MB: 204864641024, cmd_cfg_table, em73c044vcf_ecc_get_status}, // 注意最后多了这个函数指针对于Foresee F35SQA001G如果它的ECC状态是标准的就不需要这一步使用驱动默认函数即可。具体需要查芯片手册确认。4. 在RT-Thread中挂载文件系统驱动移植好了芯片能读写了接下来就是让RT-Thread的文件系统能用到这个SPI NAND。这里介绍两种常用的文件系统FatFS和UFFS。4.1 配置FatFSFatFS是一个通用的FAT文件系统兼容性好适合在电脑上直接读写镜像文件。在menuconfig中配置Rt-Thread options --- RT-Thread Components --- [*] DFS: device virtual file system --- [*] Using posix-like functions, open/read/write/close [*] Using working directory (4) The maximal number of mounted file system (4) The maximal number of file system type (16) The maximal number of opened files [*] Using mount table for file system // 关键启用自动挂载表 [*] Enable elm-chan fatfs elm-chans FatFs, Generic FAT Filesystem Module --- (512) Maximum sector size to be handled. // 扇区大小通常512 [ ] Using devfs for device objects [*] Enable ReadOnly file system on flash // 如果文件系统只读可以勾选 [ ] Enable RAM file system关键点挂载表勾选Using mount table for file system后系统启动时会自动按照一个预定义的表格来挂载文件系统。这个表格通常在board.c文件中定义#ifdef RT_USING_DFS_MNTTABLE #include dfs_fs.h const struct dfs_mount_tbl mount_table[] { // 参数设备名, 挂载点, 文件系统类型, 读写标志, 私有数据, 自动格式化标志 {blk_rodata, /rodata, elm, 0, 0, 0}, // 例如将块设备blk_rodata以elm(FatFS)类型挂载到/rodata目录 {0} // 结束标记 }; #endif你需要根据实际情况修改设备名blk_rodata和挂载点/rodata。设备名是MTD框架为你的SPI NAND创建的块设备名称。4.2 配置UFFSUFFS是专为NAND Flash设计的文件系统能更好地处理NAND的特性如坏块管理、ECC但镜像文件在电脑上直接读写不太方便。在menuconfig中配置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.) ---UFFS的ECC模式选择很重要如果SPI NAND控制器硬件能计算ECC并自动写入OOB区就选模式3性能最好。同样UFFS也需要使用挂载表。在board.c的mount_table中添加UFFS的条目#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}, // 类型改为uffs最后一个参数1表示如果挂载失败则尝试格式化 #endif {0} }; #endif5. 制作与烧录文件系统镜像以FatFS为例很多时候我们希望把一些初始数据比如网页资源、配置文件提前放到文件系统里和固件一起烧录。这就需要制作一个文件系统镜像。在menuconfig中配置镜像生成Application options --- [*] Using File System Image 0 --- Select File System Type (FATFS) --- // 选择文件系统类型如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 // FATFS的簇大小扇区数通常为1操作步骤在Data Directory里填入你电脑上一个文件夹的绝对路径或相对于工程根目录的路径。这个文件夹里的所有文件和子目录都会被打包进镜像。编译工程时构建系统会自动读取这个目录生成一个名为rodata.fatfs或其他你指定的名字的镜像文件。这个镜像文件通常会和其他固件部分如bootloader、应用程序一起通过烧录工具写入到SPI NAND Flash的指定地址。系统启动后MTD驱动会识别SPI NANDRT-Thread的DFS会根据挂载表尝试将对应的块设备分区以FatFS格式挂载到指定目录。如果挂载成功你就能通过/rodata目录访问到之前打包进去的所有文件了。好了关于衡山派Luban-Lite上SPI NAND驱动配置、移植和文件系统挂载的完整流程就讲到这里。实际操作中最需要仔细核对的就是芯片参数表和menuconfig里的选项。如果遇到问题先检查芯片ID是否正确识别再检查参数是否与手册一致最后一步步调试文件系统的挂载过程。