深入解析NAND Flash:从存储原理到驱动开发实战

📅 2026/7/31 8:10:54
深入解析NAND Flash:从存储原理到驱动开发实战
1. 从“黑盒子”到“透明世界”为什么我们需要理解NAND基础在嵌入式开发、存储系统设计甚至日常的数码产品维修中我们常常听到“NAND Flash”这个词。它就像一个无处不在的“黑盒子”我们知道它能存数据知道它比硬盘快也知道它怕突然断电。但当我们真正需要动手——比如为一块新的主控芯片移植驱动、优化存储系统的寿命、或者仅仅是修复一个因坏块而“变砖”的设备时对这个“黑盒子”内部运作机制的一知半解就会立刻让我们寸步难行。我遇到过太多这样的场景工程师对着Datasheet里“Page”、“Block”、“ECC”这些术语发愣调试SPI NAND驱动时读写时序总是对不上移植U-Boot到i.MX6ULL的NAND启动时烧录成功却无法引导。这些问题归根结底都是因为我们对NAND Flash的基础概念和物理特性缺乏系统性的理解。它不是一个简单的、按地址线性访问的存储器而是一个具有复杂内部结构、特定操作约束和固有缺陷的“有机体”。因此这篇内容的目的就是亲手拆开这个“黑盒子”。我们不满足于知道“NAND是什么”而是要彻底搞懂“NAND为什么这样工作”。从最基础的存储单元Cell原理到影响你每次读写操作的组织架构Page, Block再到关乎数据生死存亡的可靠性机制ECC, 坏块管理。这些知识是你后续进行驱动开发如SPI NAND裸机驱动、系统移植如T113、i.MX6ULL适配NAND Flash、硬件设计如STM32H743核心板上的NAND电路乃至产品选型SLC/MLC/TLC/QLC的基石。理解了这些你再看热词里的“FG和CT NAND Flash”、“NAND接口”、“NAND Flash Controller”就不会再是一头雾水而是能清晰地看到它们在整个技术图谱中的位置和作用。2. 存储单元的微观世界电荷陷阱与阈值电压要理解NAND Flash必须从它的基本存储单元Memory Cell说起。你可以把它想象成一个微型的“水桶”但这个桶里装的不是水而是电子。这个“水桶”本身是一个MOSFET金属-氧化物半导体场效应晶体管但它在栅极Gate和沟道Channel之间增加了一个特殊的“浮栅”Floating Gate或“电荷陷阱层”Charge Trap Layer。这就是热词中“FG和CT NAND Flash”所指的两种核心技术路径。2.1 浮栅FG技术经典的电子仓库浮栅技术是更传统、更主流的设计。这个浮栅被一层高质量的超薄二氧化硅SiO₂绝缘层完全包裹与上下层绝缘处于“悬浮”状态。一旦电子被注入进去在理想情况下没有直接路径可以逃逸电荷可以保存数年甚至十年以上。编程写1变0 需要向存储单元写入数据通常将“1”状态变为“0”状态时会在控制栅Control Gate施加一个较高的正电压如15V-20V同时在漏极Drain施加一个中等电压。这会产生一个强大的垂直电场使得沟道中的电子获得足够高的能量以“福勒-诺德海姆隧穿”Fowler-Nordheim Tunneling的方式穿透绝缘层被“注射”到浮栅中。浮栅捕获了这些额外电子。擦除写0变1 需要擦除数据将“0”状态恢复为“1”状态时过程相反。在衬底Substrate施加一个高正电压而控制栅接地或施加负压。这样产生的电场方向相反将浮栅中的电子“吸”出来排空浮栅。关键点在于阈值电压Vth的偏移。浮栅中有无电子会改变这个MOSFET的开启电压阈值电压。我们通过测量阈值电压来判断单元的状态浮栅无电子擦除态 阈值电压较低如Vth 2V。施加一个中等的读取电压如3V时晶体管导通我们将其定义为逻辑“1”。浮栅有电子编程态 阈值电压被拉高如Vth 4V。同样的读取电压下晶体管无法导通我们将其定义为逻辑“0”。2.2 电荷陷阱CT技术更精细的电子“牢笼”随着制程工艺不断缩小到20nm以下浮栅技术遇到了瓶颈。浮栅是一个导体相邻单元之间的浮栅可能通过绝缘层发生电容耦合导致干扰这就是“单元间干扰”。此外超薄绝缘层下的浮栅如果有一个缺陷点可能导致整个浮栅的电荷泄漏。电荷陷阱技术应运而生。它用一层非导体的氮化硅Si₃N₄层取代了导体浮栅。这层氮化硅中有大量可以捕获电子的“陷阱”。编程和擦除的原理与浮栅类似也是通过FN隧穿注入和移除电子。CT技术的核心优势抗干扰性更强 电荷被局域化地捕获在氮化硅层的陷阱中而非一个连续的导体中大大降低了单元间的电容耦合干扰。可靠性更高 即使绝缘层有局部缺陷也只会影响附近少数陷阱的电荷不会导致整个存储单元的电荷全部漏光提升了数据保持能力。更适合3D NAND 在3D堆叠结构中CT技术更容易在垂直方向上进行工艺集成因此成为了3D NAND如三星的V-NAND英特尔的3D XPoint底层原理之一的主流选择。给你的选型启示 当你看到芯片规格书或方案介绍时如果它强调高密度、先进工艺尤其是3D结构那么它很可能采用了CT技术。这对于追求高容量和可靠性的消费级SSD和eMMC/UFS存储至关重要。而许多传统的、工艺较老的SLC或MLC NAND可能仍在使用FG技术。3. NAND的宏观组织架构Page, Block与Plane理解了单个细胞如何工作我们再来看看它们是如何被组织起来构成一个我们能以“地址”来访问的存储阵列的。这是驱动开发者和系统工程师最需要关心的部分直接关系到你如何编写读写函数、如何进行坏块管理和磨损均衡。NAND Flash的访问不是字节或字随机的而是遵循严格的层级结构Cell - Page - Block - Plane - Die - Target。3.1 页Page读写的最小单元这是NAND Flash读取和编程写入操作的最小单位。当你调用一个写NAND的函数时你至少需要写入一个完整页的数据。一个页的典型大小在过去是2KB、4KB现在随着工艺进步主数据区大小常见为8KB、16KB甚至更大。但一个页不仅仅包含用户数据区Main Area。它后面还紧跟着一个备用区Spare Area或称为OOB区。OOB区的大小与页大小相关例如一个4KB的页可能配有128B或256B的OOB。这个区域是绝对不能被用户数据覆盖的它是为NAND控制器服务的“元数据区”主要存放ECC校验码 用于纠正该页数据中可能出现的位错误。坏块标记 工厂或系统在识别到坏块时会在该块第一页或第二页的OOB特定位置写入标记。逻辑到物理地址映射信息 在FTL闪存转换层中可能会用到。操作约束页编程只能将位从“1”变成“0”在SLC中。这意味着如果你想修改一个页中某个字节的数据你不能直接覆盖它。你必须先将整个页的数据读出来在内存中修改然后擦除该页所在的整个块最后再将修改后的整个页数据写回去。这引出了下一个更重要的概念。3.2 块Block擦除的最小单元块是NAND Flash擦除操作的最小单位。一个块由固定数量的页组成例如64个页、128个页或256个页。因此一个块的大小 页大小 × 每块页数。例如4KB页 × 128页/块 512KB/块。这是NAND Flash所有特性中最为关键的一个也是所有软件算法设计的核心出发点。因为擦除耗时极长 一次块擦除操作可能需要几毫秒而一次页编程仅需几百微秒一次页读取仅需几十微秒。擦除比读写慢一个数量级。擦除次数有限 每个块的擦除次数P/E Cycle是有限的这就是闪存的“寿命”。SLC可达10万次MLC约1-3万次TLC约1-3千次QLC可能只有几百次。频繁擦写同一个块会使其提前报废。必须先擦后写 由于页编程只能写“0”如果一个页里已经有数据部分位是0你想写入新数据必须保证新数据中为“1”的位对应旧数据中也是“1”。这通常无法保证所以最安全、最通用的做法就是要改写一个页必须先擦除其所在的整个块。这个“擦除粒度远大于写入粒度”的特性直接催生了FTLFlash Translation Layer和垃圾回收Garbage Collection等复杂机制。在无FTL的裸机驱动中比如你写SPI NAND Flash的裸机驱动你必须自己在脑海里或通过简单算法管理这个“先擦后写”的过程。3.3 平面Plane与Die并行化的艺术为了提升性能现代NAND Flash在内部引入了并行性。平面 一个Die晶片内部可以划分成2个或4个平面。这些平面可以独立执行读、编程命令但擦除操作通常需要跨平面同步进行Multi-Plane Erase。这允许你在一个平面上读取数据的同时向另一个平面编程数据提升了吞吐量。Die 一个物理的NAND Flash芯片可能包含1个或多个Die。多个Die可以真正并行操作通过不同的片选CE#信号这是实现高性能SSD多通道架构的基础。给你的驱动开发启示 当你阅读SPI NAND Flash的Datasheet时一定要找到“Memory Organization”这一章。它会明确告诉你页大小Page Size、块大小Block Size、每块的页数Pages per Block、以及是否有多个平面。这些参数是你设计读写缓冲区、坏块表结构和擦写算法的直接依据。例如你的驱动代码里write_page()函数内部必须确保目标块处于已擦除状态否则操作会失败。4. 与NAND共舞可靠性机制与接口演进了解了NAND的物理特性和组织方式我们就能明白为什么需要那么多额外的机制来保证它能可靠工作以及它的接口是如何演进来适应不同需求的。4.1 可靠性三支柱ECC、坏块管理与磨损均衡1. ECC纠错码NAND Flash的存储单元非常微小电荷量少容易受到干扰读干扰、编程干扰、保持期电荷泄漏导致位翻转Bit Flip即原本是0的位变成了1或反之。随着MLC/TLC/QLC在每个单元存储更多比特电压状态间隔更小位错误率急剧上升。作用 ECC通过在写入时计算校验码存入OOB区读取时重新计算并比对来检测和纠正错误位。强度 早期使用汉明码Hamming Code只能纠正1位错误。现在普遍采用BCH码或更强大的LDPC码能纠正几十甚至上百个随机错误。驱动开发中你必须根据芯片要求实现或集成相应的ECC算法。很多MCU的NAND控制器或外部SPI NAND芯片会内置ECC引擎。2. 坏块管理NAND Flash出厂时就可能存在坏块并且在生命周期中也会不断产生新的坏块。坏块是指无法可靠保证数据完整性的块。工厂坏块 出厂时会在坏块第一页或第二页的OOB特定位置如第0列标记为非0xFF值例如0x00。后天坏块 在使用过程中如果擦除或编程失败系统软件或FTL需要将其标记为坏块标记在OOB中并从可用地址池中移除。管理策略 在简单系统中可以维护一个坏块表BBT跳过这些块。在复杂的FTL中坏块管理是地址映射和垃圾回收的一部分。对于线刷如cm201-2 nand线刷这类操作刷机工具必须能识别并跳过坏块否则会导致刷机失败或系统不稳定。3. 磨损均衡由于每个块的擦除次数有限如果系统总是频繁擦写某几个块比如存放文件系统FAT表的块这些块会很快耗尽寿命而其他块却闲置着。磨损均衡算法就是为了将写操作均匀地分布到所有块上延长整体寿命。动态磨损均衡 在写入新数据时优先选择擦除次数少的块。静态磨损均衡 还会将冷数据不常修改的数据从磨损程度低的块迁移到磨损程度高的块以平衡所有块的磨损。实现层面 这是FTL的核心功能之一。在无操作系统的裸机环境下实现完善的磨损均衡非常复杂通常需要借助成熟的文件系统如LittleFS、SPIFFS或中间件。4.2 接口演进从并行到串行从裸片到集成并行接口Async / ONFI / Toggle 这是经典NAND接口拥有独立的I/O数据线8位或16位、控制线CE#, CLE, ALE, WE#, RE#, R/B#等。优点是带宽高缺点是引脚多、布线复杂、需要控制器处理繁琐的时序。在核心板设计如STM32H743核心板上的NAND布线和早期嵌入式系统中常见。串行接口SPI NAND 将并行接口通过一个内置的控制器封装起来对外只暴露标准的SPI总线CLK, CS#, MOSI, MISO和少数几个控制引脚。优点是引脚数极少可低至8个布线简单可以直接与任何有SPI接口的MCU连接大大降低了使用门槛。热词中的“SPI NAND flash裸机驱动”就是指为这类芯片编写驱动。你需要通过SPI命令去访问内部的状态寄存器、发送读/写/擦除命令和地址。虽然峰值速度可能不如高端并行接口但对于许多成本敏感、空间受限的应用如IoT设备是绝佳选择。集成控制器eMMC / UFS 这不是单纯的NAND接口演进而是将NAND Flash晶片、一个强大的Flash控制器集成ECC、坏块管理、磨损均衡、FTL封装成一个标准化的“黑盒子”设备。eMMC采用并行接口UFS采用串行高速接口。对于主控SoC如T113、i.MX6ULL来说它不再直接面对脆弱的原始NAND而是通过一个简单的、类似操作SD卡或硬盘的标准化命令集来访问存储。“移植”工作从复杂的NAND驱动开发变成了配置好SoC端的eMMC/UFS主机控制器驱动难度大大降低。这也是移动设备和消费电子产品的绝对主流。5. 实战透视从芯片选型到驱动调试掌握了理论我们最后把它投射到几个具体的实战场景中看看这些基础概念是如何起作用的。5.1 场景一为STM32H743设计NAND硬件电路假设你正在设计一块STM32H743的核心板需要支持NAND Flash启动或扩展存储。你拿到一个NAND芯片的Datasheet需要设计原理图和PCB。接口类型判断 首先看是并行还是SPI NAND。并行NAND引脚众多数据线D0-D7 地址锁存ALE命令锁存CLE写使能WE#读使能RE#就绪忙R/B#片选CE#等你需要确认STM32H743的FMC灵活存储器控制器是否支持NAND模式并将这些信号线正确连接到FMC对应的引脚。PCB布线时数据线和控制线需要等长处理以保证时序这就是“nand mos电路图”和硬件设计时要考虑的。原理图连接数据线 连接至FMC的数据端口。CLE/ALE 连接至FMC的地址线如A16, A17用于在复用总线上区分命令和地址周期。CE# 连接至FMC的片选信号NE。WE#/RE# 连接至FMC的写使能和读使能。R/B# 这是一个重要的状态信号需要连接到一个GPIO或具有中断功能的引脚上用于在编程或擦除时等待操作完成查询或中断方式。上拉电阻 通常R/B#信号需要外部上拉。软件配置关键 在CubeMX或代码中配置FMC时你需要根据Datasheet精确设置FMC_NAND_PCC_Timing和FMC_NAND_AttributeSpace_Timing。这些时序参数建立时间、保持时间、高电平时间等直接来源于芯片的AC特性表设置错误会导致读写不稳定。5.2 场景二为i.MX6ULL移植NAND启动驱动i.MX6ULL支持从多种设备启动NAND是常见选择。这里的“移植”主要涉及U-Boot和内核。U-Boot阶段确定芯片型号 在U-Boot的板级配置文件中如include/configs/mx6ull_xxx.h或arch/arm/dts/xxx.dtsi你需要正确定义NAND Flash的几何参数页大小、OOB大小、每块页数、总块数。这些参数必须与你的硬件完全一致。驱动适配 i.MX6ULL的NAND控制器驱动通常已经存在drivers/mtd/nand/raw/nand_mxc.c。你需要确保DTS中的nand-controller节点和nand子节点配置正确包括时序参数、ECC模式BCH位数等。坏块处理 U-Boot在烧录镜像如u-boot.imx,zImage,dtb,rootfs时必须跳过坏块。常见的做法是使用nand write命令它会自动处理。但如果你是自己写的烧录工具就必须在代码里实现坏块扫描和跳过逻辑。内核阶段MTD子系统 内核通过MTDMemory Technology Device子系统来统一管理NAND、NOR等存储。你需要确保DTS配置能正确引导内核识别NAND并创建对应的MTD设备如/dev/mtd0。分区表 在DTS中定义好NAND的分区例如partition0 { label bootloader; ... };。这决定了U-Boot、内核、文件系统在NAND上的物理布局。文件系统 对于NAND通常会选用支持坏块管理和磨损均衡的专用文件系统如UBIFS无排序块映像文件系统它比传统的JFFS2更先进尤其适用于大容量NAND。5.3 场景三编写SPI NAND Flash裸机驱动这是最“原始”但也最能锻炼对NAND理解的操作。假设你用的是一颗Winbond的SPI NAND芯片。初始化与识别通过SPI发送Read ID (9Fh)命令读取制造商ID和设备ID确认芯片型号。根据型号在代码中定义好PAGE_SIZEPAGES_PER_BLOCKBLOCK_SIZETOTAL_BLOCKS等宏。状态轮询在发送Page Program (02h-10h)或Block Erase (D8h)命令后必须不断发送Read Status Register (05h)命令检查状态寄存器的BUSY位直到操作完成。这是驱动稳定性的关键绝对不能省略。地址计算与发送SPI NAND的地址通常需要分多次发送。例如对于一个2048字节的页需要3个字节的地址A19-A0。你需要根据芯片手册正确拆分行地址Row Address包含块内页号和列地址Column Address页内偏移通常从0开始。ECC处理许多SPI NAND芯片内部集成了ECC引擎。你需要通过命令如Read ECC Status来获取ECC状态判断读取的数据是否可靠或者在写入时使能内部ECC。如果芯片没有内部ECC或者你需要更强的纠错能力就必须在MCU端用软件实现BCH等算法并将校验码写入OOB区。坏块检查在擦除或编程前应读取目标块第一页OOB区的特定字节通常是第0列检查是否为非0xFF。如果是则标记为坏块跳过该块操作下一个块。写操作流程核心// 伪代码流程强调“先擦后写” int spi_nand_write(uint32_t page_addr, uint8_t *data, uint8_t *oob) { // 1. 计算该页属于哪个块 uint32_t block_num page_addr / PAGES_PER_BLOCK; // 2. 检查该块是否为坏块读取块内第一页的OOB标记 if (is_bad_block(block_num)) { return ERROR_BAD_BLOCK; } // 3. 擦除整个块这是最耗时的操作 spi_nand_block_erase(block_num); // 4. 等待擦除完成轮询状态寄存器 while (spi_nand_is_busy()); // 5. 对页进行编程 spi_nand_page_program(page_addr, data, oob); // 6. 等待编程完成 while (spi_nand_is_busy()); // 7. 可选验证写入的数据 return SUCCESS; }注意 在实际的FTL或文件系统中步骤3和5不会这么简单。为了优化性能和寿命通常会采用“写时复制”和“垃圾回收”策略不会每次写都擦除而是写入到一个新的、已擦除的页并更新逻辑映射表。上述流程是最基础的、保证功能正确的裸机操作流程。通过以上从微观到宏观从理论到实战的梳理希望你对NAND Flash不再感到陌生和畏惧。它确实复杂但所有的复杂性都源于其物理特性和为了克服这些特性而衍生的工程智慧。下次当你再面对“NAND Flash Controller”的配置、调试“SPI NAND驱动”、或是为“T113适配NAND Flash”时脑海中能清晰地浮现出电荷在浮栅中进出的画面、数据以页为单位流动的路径、以及擦除操作在块级别进行的约束那么很多问题都将迎刃而解。理解基础是解决一切高级问题的前提。