Raw NAND 驱动库学习


author: xiexun

tags: Raw NAND, ONFI, SEMC, BootROM, OOB, ECC


Raw NAND 驱动库学习

代码学习:NXP i.MX RT BootROM 风格的并行 NAND 驱动库ONFD(GitHub - JayHeng/RT-RNAND: An ONFI-compliant Raw NAND flash universal driver | 一款基于ONFI标准的并行NAND Flash通用驱动,适配多款MCU硬件接口,目前主要适配i.MXRT的SEMC接口 · GitHub)


核心概念

Raw NAND :主机直接面对 Page/Block 命令接口;ECC、坏块、地址映射由主机侧完成。

Managed NAND(eMMC/UFS 等):主机多使用 LBA;ECC/坏块/磨损由片内 FTL 完成,OOB 对主机不可见。

ONFI(Open NAND Flash Interface):并行 Raw NAND 规范集合,覆盖命令集、时序、Parameter Page、存储组织等,不仅是软件协议名。

text 复制代码
Device → Plane/LUN → Block → Page → Main + Spare(OOB)
单位 含义
Page Read / Program 粒度
Block Erase 粒度
Plane/LUN 并行/多逻辑单元组织

Main / Spare(OOB):同一 Page 内主数据区与冗余区。Spare 存放:

内容 作用
ECC 校验/纠正 Main(或 ECC chunk)bit 错误
坏块标记 标识 Block 是否禁用(位置以 datasheet 为准,常见在特定 Page 的 Spare)
元数据 逻辑页号、有效标志等管理信息(是否使用取决于软件)

寻址:

视图 含义
线性字节地址 mem_read/write(addr) 的入参;软件抽象
pageIndex + column Flash 层单位;addr/pageSize、addr%pageSize
Column (CA) / Row (RA) 器件周期;由 SA = pageIndex × pageSize 按 COL 位宽拆分

操作约束:

  1. 擦后为 0xFF;Program 将目标 bit 置 0,不可按 RAM 原地改写

  2. 阵列操作后必须等 Ready(R/B# 或 Status 0x70)

  3. 必须处理 ECC 与坏块

    薄地址抽象对比FTL: memory 层做线性换算、页缓存、DBBT 整块跳过;无磨损均衡/GC/精细 LPN 映射。

上层:RT BootROM、Flashloader下载工具;并非通用文件系统块层。

【控制器 IP 行为】

SEMC(fsl_semc)职责:把软件意图变成命令/地址/数据周期,硬件自动翻译成 ONFI 8080 总线时序波形,并完成与 NAND 芯片的硬件交互、等待响应、数据收发闭环。

  1. 命令编码 :get_nand_code 打包 NAND 命令字节与地址/命令模式(CMD+ADDR、HOLD、READ/WRITE),硬件行为输出时序:CLE 拉高、ALE 拉低、WE# 脉冲,将命令字节锁存进 NAND
  2. 地址拆分 :软件提供字节地址 SA;IP 按 columnAddressWidth 生成 CA/RA(x8/x16 规则不同)。Spare 访问时 COL 可能多扩 1 bit(convert_nand_address) ,硬件行为输出时序:ALE 拉高、CLE 拉低、WE# 连续脉冲,逐周期发送地址。
  3. 数据通路:命令完成后经 IP Bus 或 AXI 搬 Main;Ready 走 R/B# 或 Status。

【软件驱动逻辑】

text 复制代码
BootROM / Flashloader
  → semc_nand_memory    # 线性地址、页缓存、DBBT、FCB/DBBT
    → semc_nand_flash   # ONFI 页/块、Parameter、ECC
      → fsl_semc        # IP 事务
        → NAND
层 对外接口 职责
fsl_semc IP 命令事务 地址转换、发令、搬数
semc_nand_flash pageIndex / blockIndex 命令序列、ECC
semc_nand_memory 字节 address 换算、缓存、跳坏块、Boot 控制块

Boot 相关数据 :FCB(含 nandConfig、固件副本表、DBBT 搜索区);DBBT(坏块列表)。mem_init:默认配置拉起 → 搜 FCB → 按 FCB 重 init → 搜 DBBT。

生命周期:片内 BootROM 极简路径加载下一级后交权;完整驱动在 Flashloader/应用侧接力,一般不同时占用同一套 SEMC+NAND 软件栈。本 archive 即 Boot/下载链路风格实现。


关键代码片段

配置字段(semc_nand_flash.h):

c 复制代码
uint32_t bytesInPageDataArea;   /* Main */
uint32_t bytesInPageSpareArea;  /* Spare/OOB */
uint32_t pagesInBlock;
uint32_t blocksInPlane;
uint32_t planesInDevice;

页读:页号 → SA → SEMC → issue (semc_nand_flash_read_page):

c 复制代码
ipgCmdAddr = pageIndex * config->bytesInPageDataArea; /* 字节 SA */
ipgCmdAddr = semc_ipg_command_convert_nand_address(&config->memConfig, ipgCmdAddr);
status = semc_nand_issue_read_page(config, ipgCmdAddr); /* 0x00/0x30 + wait */
/* 再 IP/AXI 搬 Main,并按配置做 Device/Software ECC */

Spare 路径地址整形 (semc_ipg_command_convert_nand_address):

c 复制代码
/* 输入始终为 byte address;Main 路径通常直接使用 SA */
if (columnAddressOption == SpareAreaAccess) {
    converted = (sa >> col) << (col + 1);
    converted |= sa & ((1u << col) - 1u);
}

线性读 (semc_nand_mem_read):

c 复制代码
pageIndex = address / pageSize;
pageColumnAddress = address % pageSize;
semc_nand_skip_bad_blocks(&pageIndex); /* DBBT:逻辑连续,物理可跳块 */
/* cache miss → flash_read_page;再按 column 切片拷出 */

调用链:

text 复制代码
mem_read → pageIndex/column + skip BB → flash_read_page
        → convert_nand_address + issue_read_page + 搬数/ECC

相关推荐
apple-mapping4 小时前
网络RTK定位学习总结
学习·网络rtk
楚山之石5 小时前
【Lancet Neurology 】多发性硬化认知障碍的 SDMT 筛查、灰质萎缩标志与认知康复循证路径
图像处理·人工智能·学习·mri
海海不掉头发6 小时前
CSDN博客_时序预测9模型复现对比
人工智能·学习·软件工程
蓝祁子yoky8 小时前
Qt学习日记 Day13:网络编程(一)-TCP基础与Socket实战
网络·qt·学习
架构师伯子明9 小时前
Ros 学习十三:IK Demo
学习
小羊没烦恼!9 小时前
关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
java·服务器·网络·学习·负载均衡
幼儿园蛋小黄10 小时前
从 STM32N647 的 AI 部署入门嵌入式:一条可落地的学习路线
人工智能·stm32·学习
Y.99911 小时前
电脑黑屏只有鼠标能动
学习
架构师伯子明12 小时前
FFmpeg C++学习(一):编译和demo
开发语言·c++·学习
叼烟扛炮12 小时前
[LangChain] 学习笔记(02):LCEL 链式调用与动态模型配置实战
服务器·开发语言·网络·笔记·学习·langchain