Linux 5.10 SPI-NAND 驱动移植实战:以 FM25S01A 为例,3步完成新Flash适配

发布时间:2026/7/9 22:31:14
Linux 5.10 SPI-NAND 驱动移植实战:以 FM25S01A 为例,3步完成新Flash适配 Linux 5.10 SPI-NAND 驱动移植实战FM25S01A 适配全流程解析1. 理解 SPI-NAND 驱动框架在 Linux 内核中SPI-NAND 驱动架构采用分层设计主要包含以下几个关键组件SPI 控制器驱动负责底层 SPI 总线通信SPI MEM 核心层提供 SPI 存储设备的通用接口SPI-NAND 核心实现 NAND 闪存的基础操作厂商专用驱动处理特定芯片的兼容性和特性对于 FM25S01A 这类 SPI-NAND 芯片内核已经提供了良好的框架支持。我们需要重点关注的是如何将新器件信息正确集成到这个框架中。2. 提取芯片关键参数在开始编码前必须从规格书中准确提取以下三个核心参数2.1 制造商 ID (MID) 和设备 ID (DID)在 FM25S01A 的规格书中查找 Manufacture ID 和 Device ID 部分通常可以找到类似这样的信息#define SPINAND_MFR_FMSH 0xA1 #define FM25S01A_DEVICE_ID 0xE42.2 存储组织结构 (NAND_MEMORG)FM25S01A 的存储结构参数通常包括NAND_MEMORG( 1, /* bits_per_cell (SLC1) */ 2048, /* pagesize (bytes) */ 64, /* oobsize (bytes) */ 64, /* pages_per_eraseblock */ 1024, /* eraseblocks_per_lun */ 20, /* max_bad_eraseblocks_per_lun */ 1, /* planes_per_lun */ 1, /* luns_per_target */ 1 /* ntargets */ )这些参数需要根据规格书中的芯片容量和区块布局精确计算得出。2.3 ECC 需求 (NAND_ECCREQ)ECC 配置通常可以在规格书的 Error Correction 部分找到NAND_ECCREQ(1, 512) /* 1-bit ECC per 512 bytes */3. 创建厂商驱动文件在drivers/mtd/nand/spi/目录下创建fmsh.c文件内容框架如下#include linux/mtd/spinand.h #define SPINAND_MFR_FMSH 0xA1 static const struct nand_io_cmd fm25s01a_cmds { /* 定义读写擦除等操作命令 */ .read_cache ..., .write_cache ..., .erase ..., }; static const struct spinand_info fmsh_spinand_table[] { SPINAND_INFO(FM25S01A, SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(1, 512), SPINAND_INFO_OP_VARIANTS(read_cache_variants, write_cache_variants, update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(fm25s01_ooblayout, fm25s01_ecc_get_status)), }; static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops { /* 可选的厂商特定操作 */ }; const struct spinand_manufacturer fmsh_spinand_manufacturer { .id SPINAND_MFR_FMSH, .name FudanMicro, .chips fmsh_spinand_table, .nchips ARRAY_SIZE(fmsh_spinand_table), .ops fmsh_spinand_manuf_ops, };4. 集成驱动到内核构建系统4.1 修改 Makefile在drivers/mtd/nand/spi/Makefile中添加obj-$(CONFIG_MTD_SPI_NAND) fmsh.o4.2 更新厂商列表在drivers/mtd/nand/spi/core.c中将fmsh_spinand_manufacturer添加到厂商列表static const struct spinand_manufacturer *spinand_manufacturers[] { gigadevice_spinand_manufacturer, macronix_spinand_manufacturer, micron_spinand_manufacturer, paragon_spinand_manufacturer, toshiba_spinand_manufacturer, winbond_spinand_manufacturer, fmsh_spinand_manufacturer, /* 新增 */ };5. 设备树配置在目标板的设备树文件中添加 SPI-NAND 节点spi0 { status okay; flash0 { compatible spi-nand; reg 0; spi-max-frequency 100000000; spi-tx-bus-width 4; spi-rx-bus-width 4; partitions { compatible fixed-partitions; #address-cells 1; #size-cells 1; partition0 { label bootloader; reg 0x0000000 0x0100000; read-only; }; partition100000 { label kernel; reg 0x0100000 0x0500000; }; partition600000 { label rootfs; reg 0x0600000 0x0a00000; }; }; }; };6. 内核配置与编译确保内核配置中包含以下选项CONFIG_MTD_SPI_NANDy CONFIG_MTD_NAND_COREy CONFIG_MTD_NAND_ECC_SW_HAMMINGy然后执行内核编译和安装流程make menuconfig # 检查并保存配置 make -j$(nproc) make modules_install make install7. 验证驱动加载系统启动后可以通过以下命令验证驱动是否成功加载dmesg | grep -i nand # 查看内核日志 cat /proc/mtd # 查看MTD分区信息 mtdinfo /dev/mtd0 # 查看具体MTD设备信息如果一切正常应该能看到类似以下输出mtd0 Name: bootloader Type: nand Eraseblock size: 131072 bytes, 128.0 KiB Amount of eraseblocks: 8 (1048576 bytes, 1.0 MiB) Minimum input/output unit size: 2048 bytes Sub-page size: 2048 bytes OOB size: 64 bytes Character device major/minor: 90:0 Bad blocks are allowed: true Device is writable: false8. 常见问题排查8.1 驱动未加载检查点确认内核配置正确检查设备树配置是否与硬件匹配查看dmesg输出是否有相关错误8.2 读写性能不佳优化建议调整 SPI 时钟频率确保使用 Quad SPI 模式如果芯片支持检查 DMA 配置8.3 ECC 错误处理方法验证 ECC 配置是否正确检查硬件连接是否稳定考虑使用更强大的 ECC 算法如 BCH9. 高级调试技巧9.1 MTD 调试接口内核提供了多个调试接口用于分析 MTD 设备# 查看MTD设备详细信息 cat /sys/class/mtd/mtd0/device/* # 手动标记坏块 echo 0x100000 /sys/class/mtd/mtd0/badblock9.2 性能分析工具使用mtd_speedtest测试实际读写性能mtd_speedtest /dev/mtd09.3 内核调试选项在调试时可以启用以下内核配置CONFIG_MTD_DEBUGy CONFIG_MTD_DEBUG_VERBOSE310. 生产环境优化建议对于量产设备建议考虑以下优化措施坏块管理实现自动坏块检测和替换策略磨损均衡对于频繁写入的区域考虑实现磨损均衡算法数据完整性增加 CRC 或更强大的 ECC 保护关键数据电源管理正确处理突然断电情况避免数据损坏通过以上步骤开发者可以成功将 FM25S01A SPI-NAND 闪存芯片适配到 Linux 5.10 内核中。整个过程虽然涉及多个技术环节但遵循内核的标准框架和规范可以大大降低开发难度。