1. SD NAND 到底是什么,为什么突然被频繁提起
第一次听到“SD NAND”这个词,很多人会下意识把它和 SD 卡、eMMC、SPI Flash 混在一起。我刚开始接触的时候也一样,觉得不就是个存储芯片换个封装吗?但真正在项目里用起来才发现,这东西解决的是一个非常具体的痛点:小容量、低成本、高可靠、贴片式存储之间的平衡问题。
SD NAND,本质上是一种把 NAND Flash 晶圆和控制器封装在 LGA 或 BGA 封装里的存储器件。它的接口兼容 SD 协议,支持 SPI 和 SDIO 两种通信模式,容量通常在 128MB 到 8GB 之间。你可以把它理解成“焊在板子上的 SD 卡”,但比 SD 卡更可靠,因为它没有卡座、没有弹片接触、不怕震动脱落。
它解决的核心问题是什么?传统 SPI NOR Flash 容量小、擦写寿命有限、写入速度慢;eMMC 容量大但价格高、封装大、对小项目来说浪费;SD 卡便宜但接触不可靠、不适合工业场景。SD NAND 刚好卡在中间:容量够用、价格适中、贴片焊接、内置 ECC 和坏块管理,主控端只需要一个 SPI 或 SDIO 接口就能驱动。
适合谁看?如果你在做 STM32、RK3588S、嵌入式 Linux 主板、数据采集终端、工业 HMI、车载记录设备,或者你正在纠结“用 SPI Flash 还是 eMMC 还是 SD 卡”,那这篇内容应该能帮你省下不少选型和调试时间。下面我会从市场格局、技术原理、接口协议、ECC 机制、实操踩坑几个维度,把 SD NAND 这件事讲透。
2. 市场格局与选型逻辑拆解
2.1 为什么小容量存储市场突然有了 SD NAND 的位置
过去十年,存储市场基本是两极分化:一边是 SPI NOR Flash,容量 1MB 到 128MB,价格低、接口简单、可靠性高,但写入速度慢、擦写次数有限;另一边是 eMMC 和 SSD,容量 8GB 起步,速度快、管理完善,但价格和封装尺寸对小项目不友好。
中间这段 128MB 到 8GB 的需求一直存在,只是以前大家用 SD 卡或者 raw NAND 来填。SD 卡的问题是接触可靠性差,工业现场震动、氧化、灰尘都会导致接触不良;raw NAND 的问题是主控端必须自己做坏块管理、ECC 校验、磨损均衡,软件开发成本高,而且不同厂家的 NAND 晶圆特性还不一样,换料就要重新调。
SD NAND 的出现,本质上是把 SD 卡的控制器的功能集成到了芯片内部,同时把接口做成贴片封装。主控端看到的就是一个标准 SD 设备,不需要关心底层 NAND 的坏块、ECC、磨损均衡。对嵌入式工程师来说,这相当于把存储的复杂度从主控端转移到了存储芯片内部,开发周期缩短,硬件设计简化。
从市场趋势看,几个因素在推动 SD NAND 的需求:第一,工业设备和车载设备对小容量可靠存储的需求在增长;第二,国产 NAND 晶圆和控制器方案成熟,成本下降;第三,嵌入式主控芯片如 STM32、RK 系列对 SDIO 和 SPI 的支持非常完善,驱动生态好;第四,很多项目不需要大容量,8GB 已经绰绰有余,eMMC 的性能过剩。
2.2 SD NAND、SPI NAND、eMMC、SD 卡到底怎么选
选型这件事,我一般会从五个维度来打分:容量需求、接口资源、可靠性要求、开发成本、单板成本。下面这张表是我在实际项目中总结的对比,你可以直接拿去用。
| 维度 | SD NAND | SPI NAND | eMMC | SD 卡 |
|---|---|---|---|---|
| 容量范围 | 128MB-8GB | 128MB-4GB | 4GB-256GB | 8GB-1TB |
| 接口 | SPI/SDIO | SPI | SDIO/并行 | SDIO/SPI |
| 封装 | LGA/BGA | SOP/BGA | BGA | 卡座 |
| 坏块管理 | 内置 | 主控负责 | 内置 | 内置 |
| ECC | 内置 | 主控负责 | 内置 | 内置 |
| 可靠性 | 高 | 中 | 高 | 低 |
| 开发难度 | 低 | 中 | 中 | 低 |
| 单板成本 | 中 | 低 | 高 | 低 |
| 适用场景 | 工业、车载、嵌入式 | 小容量固件存储 | 大容量系统盘 | 消费类临时存储 |
从这张表可以看出来,SD NAND 的核心优势是“内置管理 + 贴片封装 + 中等容量”。如果你需要 1GB 左右的可靠存储,又不想在主控端写复杂的 NAND 管理代码,SD NAND 是最省事的选择。SPI NAND 虽然更便宜,但主控端要做 ECC 和坏块管理,软件工作量不小,而且不同厂家的 NAND 指令集有差异,换料风险高。eMMC 适合需要 8GB 以上、对速度有要求的场景,但成本和封装尺寸上去了。SD 卡只适合对可靠性要求不高的消费类产品。
2.3 选型时容易被忽略的三个隐藏成本
第一个隐藏成本是主控端的软件适配。SD NAND 虽然内置了控制器,但主控端的 SDIO 或 SPI 驱动还是要调通。特别是 SPI 模式下,很多主控的 SPI 控制器有硬件片选和软件片选的区别,时序参数也要根据 SD NAND 的规格书来配。如果驱动没调好,会出现初始化失败、读写超时、数据校验错误等问题。
第二个隐藏成本是电源设计。NAND Flash 在擦写时电流会有波动,如果电源纹波太大,会导致写入失败或者数据损坏。SD NAND 的规格书一般会给出工作电流和峰值电流,LDO 的选型和去耦电容的布局要特别注意。我见过一个项目因为 LDO 响应速度不够,批量生产时出现偶发性写入错误,最后换了 LDO 才解决。
第三个隐藏成本是温度范围。消费级 SD NAND 通常是 0 到 70 度,工业级是 -40 到 85 度。如果你的产品要过工业温度测试,选型时一定要确认芯片的温度等级,不要只看价格。有些厂家标的是工业级,但实际测试下来高温下读写稳定性会下降,这个要提前做高低温老化测试。
3. 核心技术点深度解析
3.1 NAND Flash 的物理特性与 SD NAND 的内部架构
要理解 SD NAND,先要理解 NAND Flash 的物理特性。NAND Flash 的存储单元是浮栅晶体管,通过控制浮栅中的电荷量来表示数据。写入时通过隧穿效应注入电荷,擦除时把电荷拉出来。这个过程会对氧化层造成磨损,所以 NAND Flash 有擦写寿命限制,SLC 通常在 10 万次左右,MLC 在 3000 到 1 万次,TLC 在 1000 到 3000 次。
NAND Flash 的读取和写入单位不一样。读取是按页读,一页通常是 2KB 或 4KB;写入也是按页写,但写入之前必须先擦除,擦除是按块擦,一块通常包含 64 页或 128 页。这就意味着你不能直接覆盖写一个页,必须先擦除整个块,再写入。这个特性叫“先擦后写”,是 NAND Flash 管理复杂度的根源。
SD NAND 的内部架构,简单来说就是 NAND 晶圆 + 控制器 + 接口逻辑。控制器负责几件事:第一,把主控发来的 SD 协议命令翻译成 NAND 的读写擦命令;第二,做 ECC 校验和纠错;第三,做坏块管理和磨损均衡;第四,维护逻辑地址到物理地址的映射表。主控端看到的是一个线性的逻辑块设备,不需要关心底层 NAND 的物理特性。
这个架构的好处是主控端软件简单,坏处是控制器的能力决定了 SD NAND 的实际性能和可靠性。不同厂家的控制器算法不一样,有的侧重顺序读写速度,有的侧重随机读写,有的侧重掉电保护。选型时不能只看容量和价格,还要看控制器的规格。
3.2 SPI 与 SDIO 两种接口模式的取舍
SD NAND 支持 SPI 和 SDIO 两种接口模式,这是它灵活的地方,也是选型时容易纠结的地方。SPI 模式的好处是引脚少,只需要 CS、CLK、MOSI、MISO 四根线,几乎所有单片机都支持;坏处是速度慢,SPI 时钟通常最高到 50MHz,实际读写速度在几 MB/s 到十几 MB/s 之间。SDIO 模式的好处是速度快,4 位数据线并行传输,时钟可以到 50MHz 甚至更高,读写速度能到几十 MB/s;坏处是引脚多,需要 CLK、CMD、DAT0-DAT3 六根线,而且主控要支持 SDIO 控制器。
我一般这样选:如果主控是 STM32F103 这种资源有限的单片机,SPI 模式就够了,因为 F103 的 SDIO 控制器有 bug,用起来反而麻烦;如果主控是 STM32F4、F7、H7 或者 RK 系列,SDIO 模式更合适,速度快而且驱动成熟。如果项目对读写速度要求不高,比如只是存日志、配置参数、小文件,SPI 模式完全够用,而且硬件设计简单,布线容易。
SPI 模式下还有一个细节要注意:硬件片选和软件片选的区别。硬件片选是 SPI 控制器自动控制 CS 引脚,软件片选是 GPIO 手动拉低拉高。硬件片选速度快,但有些主控的硬件片选时序和 SD NAND 的规格书不匹配,会导致初始化失败。软件片选灵活,可以在命令之间插入延时,但会增加 CPU 开销。我一般建议先用软件片选调通,再切硬件片选优化速度。
3.3 ECC 校验原理与 SD NAND 的内置纠错机制
ECC 是 NAND Flash 可靠性的核心。NAND Flash 在读写过程中会出现位翻转,原因是氧化层老化、读干扰、编程干扰、电荷泄漏等。位翻转率通常在 10^-6 到 10^-12 之间,看起来很低,但 NAND 的页大小是 KB 级别,一页里出现几个位翻转是正常的。如果没有 ECC,这些位翻转会导致数据错误。
ECC 的原理是在写入数据时计算校验码,一起写入 NAND;读取时重新计算校验码,和存储的校验码对比,如果发现错误就纠正。常见的 ECC 算法有汉明码、BCH 码、LDPC 码。汉明码只能纠 1 位错,BCH 码可以纠多位错,LDPC 码纠错能力更强但计算复杂度高。SD NAND 内置的控制器通常用 BCH 或 LDPC,纠错能力在 40bit/1KB 到 120bit/1KB 之间。
这里要区分两个概念:SD NAND 内置 ECC 和主控端 ECC。SD NAND 内置 ECC 意味着主控端不需要做 ECC 计算,读写数据是透明的。SPI NAND 通常需要主控端做 ECC,因为 SPI NAND 的控制器比较简单,只负责基本的读写擦,ECC 要主控的 NAND 控制器或者软件来做。这就是为什么 SD NAND 开发比 SPI NAND 简单的原因之一。
但内置 ECC 不代表可以完全不管。如果 NAND 的位翻转率超过了 ECC 的纠错能力,数据就会出错。所以 SD NAND 的规格书会给出 ECC 纠错能力和数据保持时间。工业级 SD NAND 通常要求数据保持 10 年以上,消费级可能只有 1 到 5 年。如果你的产品需要长期保存数据,选型时要特别关注这个参数。
3.4 坏块管理与磨损均衡的底层逻辑
NAND Flash 出厂时就有坏块,使用过程中也会产生新的坏块。坏块管理就是标记坏块、跳过坏块、用备用块替换坏块。SD NAND 的控制器内置坏块管理,主控端看到的是连续的逻辑地址,坏块对主控透明。
磨损均衡是让每个块的擦写次数尽量均匀,避免某些块被频繁擦写而提前失效。磨损均衡算法有动态和静态两种。动态磨损均衡只对经常写入的块做均衡,静态磨损均衡会对所有块做均衡,包括那些长期不写入的块。静态磨损均衡效果更好,但需要更多的映射表空间和计算资源。
SD NAND 的控制器通常用静态磨损均衡,因为容量小,映射表可以放在 SRAM 里。但磨损均衡的效果和控制器算法有关,不同厂家的实现差异很大。我见过一些低端 SD NAND,在频繁写入小文件的场景下,寿命明显低于规格书标称值。所以如果你的应用是频繁写入日志或者数据库,选型时要问厂家要磨损均衡的实测数据。
4. 实操过程与核心环节实现
4.1 硬件设计要点与电源布局
SD NAND 的硬件设计看起来简单,就是几根线连到主控,但有几个细节容易踩坑。第一,电源去耦。SD NAND 的 VCC 引脚旁边要放 0.1uF 和 1uF 的电容,越近越好。如果板子上有多个 SD NAND 或者 NAND 和 DDR 共用电源,要在电源入口加磁珠或者电感隔离。第二,CLK 信号线要尽量短,避免过孔和分支,如果走线长要考虑串联匹配电阻。第三,DAT 和 CMD 线要加 pull-up 电阻,通常 10K 到 50K,具体看规格书。
电源设计还有一个容易忽略的点:上电时序。有些 SD NAND 要求 VCC 先上电,VCCQ 后上电,或者反过来。如果时序不对,芯片可能无法初始化。规格书里一般会给出上电时序图,硬件设计时要确保电源芯片的使能顺序符合要求。如果做不到,可以在软件里加延时,等电源稳定后再初始化 SD NAND。
4.2 STM32 SPI 模式驱动移植与 CubeMX 配置
以 STM32F103 为例,用 SPI 模式驱动 SD NAND 是最常见的方案。CubeMX 配置步骤如下:第一,使能 SPI1,模式选 Full-Duplex Master,硬件片选选 Disable,因为我们要用软件片选;第二,SPI 时钟分频先设大一点,比如 256 分频,初始化成功后再提高速度;第三,使能一个 GPIO 作为片选,初始电平拉高;第四,使能 DMA,SPI RX 和 TX 都配 DMA 通道,这样读写大数据时 CPU 占用低。
初始化流程是这样的:拉低片选,发送 CMD0 让 SD NAND 进入 SPI 模式,然后发送 CMD8 检查电压范围,发送 CMD58 读取 OCR 寄存器,发送 CMD55 + ACMD41 初始化,最后发送 CMD58 确认卡类型。每一步都要等待响应,如果超时就重试。初始化成功后,把 SPI 时钟提高到 18MHz 或者 36MHz,具体看 SD NAND 支持的最高 SPI 时钟。
这里有一个坑:STM32F103 的 SPI 在高速下容易出现数据错误,特别是用 DMA 的时候。我一般会在 SPI 的 SCK 和 MOSI 上串联 22 欧姆电阻,减少反射。另外,DMA 传输完成后要检查 SPI 的 BSY 标志,确保数据完全移出后再拉高片选。如果拉高片选太早,最后一个字节可能没发完,导致命令错误。
4.3 SDIO 模式下的 4 位并行读写实现
如果主控支持 SDIO,比如 STM32F407 或者 RK3588S,用 SDIO 模式能获得更高的读写速度。SDIO 初始化流程和 SPI 类似,但命令格式不一样。SDIO 模式下,CMD 线用于发送命令和接收响应,DAT0-DAT3 用于数据传输。初始化时先用 1 位模式,初始化成功后切换到 4 位模式。
SDIO 的时钟配置要注意:初始化阶段时钟不能超过 400KHz,初始化成功后可以提高到 25MHz 或者 50MHz。STM32 的 SDIO 控制器有一个 SDIO_CK 引脚,时钟分频要按公式算:SDIO_CK = SDIOCLK / (2 + CLKDIV)。SDIOCLK 通常是 48MHz,如果要 24MHz,CLKDIV 设为 0;如果要 12MHz,CLKDIV 设为 2。
4 位模式下的读写要用 DMA,因为数据量大,CPU 轮询效率太低。STM32 的 SDIO 有内置 DMA,配置好之后读写速度能到 10MB/s 以上。但要注意 DMA 的传输完成中断和 SDIO 的中断优先级,如果优先级设低了,可能会出现数据溢出或者超时。我一般把 SDIO 中断设为最高优先级,DMA 中断次之。
4.4 文件系统挂载与读写性能实测
SD NAND 初始化成功后,下一步是挂载文件系统。嵌入式常用的文件系统有 FatFS、LittleFS、SPIFFS。FatFS 兼容性好,支持 SD 卡和 SD NAND,适合需要和 PC 交换数据的场景;LittleFS 和 SPIFFS 适合 SPI NOR Flash,对 SD NAND 的支持不如 FatFS 成熟。我一般用 FatFS,因为 SD NAND 的块设备接口和 SD 卡一样,FatFS 的 diskio 层改一下就能用。
性能实测方面,我用 STM32F407 + SDIO 4 位模式 + FatFS 测过:顺序写入速度约 8MB/s,顺序读取约 12MB/s,随机写入 4KB 小文件约 200 次/秒。用 STM32F103 + SPI 模式测过:顺序写入约 1.5MB/s,顺序读取约 3MB/s。这个数据供你参考,实际性能取决于 SD NAND 的控制器和主控的接口速度。
文件系统挂载时要注意:FatFS 的 sector size 要和 SD NAND 的块大小匹配,通常是 512 字节。如果 SD NAND 的块大小是 4KB,FatFS 的 sector size 要设为 4096,否则读写会出错。另外,FatFS 的簇大小也要根据容量来选,小容量用小簇,大容量用大簇,避免浪费空间。
5. 常见问题与排查技巧实录
5.1 初始化失败与命令超时的排查思路
初始化失败是最常见的问题,表现是 CMD0 无响应、CMD8 返回错误、ACMD41 一直忙。排查思路如下:第一,检查硬件连接,CS、CLK、MOSI、MISO 是否接对,有没有虚焊;第二,用示波器看 CLK 和 MOSI 波形,确认 SPI 时钟频率和极性相位是否正确;第三,检查片选时序,CS 拉低到第一个 CLK 之间要有足够延时,通常 1us 以上;第四,检查电源电压,SD NAND 的 VCC 要在规格范围内,纹波不能太大。
如果硬件没问题,那就是软件时序问题。SPI 模式下的 SD NAND 初始化有一个特殊要求:CMD0 之前要发送至少 74 个 CLK,让 SD NAND 完成内部上电复位。很多驱动代码忘了这一步,导致 CMD0 无响应。另外,CMD0 的 CS 要在发送命令期间保持低电平,发送完 8 个字节后再拉高,中间不能有中断。
5.2 读写数据错误与 ECC 报错的定位方法
读写数据错误的表现是 FatFS 返回 FR_INT_ERR 或者 FR_DISK_ERR,或者读出的数据和写入的不一致。定位方法:第一,用单块读写测试,不经过文件系统,直接读写扇区,确认底层驱动没问题;第二,降低 SPI 或 SDIO 时钟,看错误是否消失,如果消失就是时序问题;第三,检查 DMA 配置,特别是 DMA 的传输长度和内存地址对齐;第四,用逻辑分析仪抓 SPI 或 SDIO 波形,看数据线上是否有毛刺或者时序违规。
ECC 报错通常意味着 NAND 的位翻转超过了纠错能力,或者数据保持时间到了。如果 ECC 报错集中在某些块,可能是坏块;如果分散在所有块,可能是电源问题或者温度问题。处理方法是先备份数据,然后做全盘擦除,重新写入。如果擦除后还是报错,说明 NAND 已经老化,需要更换。
5.3 文件系统挂载失败与掉电数据丢失的应对
文件系统挂载失败的原因很多:分区表损坏、引导扇区损坏、FAT 表损坏、根目录损坏。排查时先用磁盘工具读一下 SD NAND 的原始数据,看分区表和引导扇区是否正常。如果损坏,可以用 FatFS 的 f_mkfs 重新格式化。但格式化会丢失数据,所以生产环境要有掉电保护机制。
掉电数据丢失是嵌入式存储的老大难问题。NAND Flash 在写入过程中掉电,会导致页数据不完整,甚至影响整个块。SD NAND 的控制器通常有掉电保护,但保护能力有限。我的经验是:第一,关键数据写入后要调用 f_sync 强制刷盘;第二,用双备份或者日志文件系统,避免单点损坏;第三,电源设计要加足够大的电容,保证掉电后能完成当前写入操作。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| CMD0 无响应 | 上电复位未完成 | 示波器看 CLK 和 CS | 发送 74 个 CLK 后再发 CMD0 |
| CMD8 返回错误 | 电压范围不匹配 | 检查 VCC 电压 | 确认 SD NAND 支持 2.7-3.6V |
| ACMD41 一直忙 | 初始化超时 | 降低 SPI 时钟 | 用 400KHz 以下时钟初始化 |
| 读写数据错误 | 时序问题 | 降低时钟测试 | 调整 SPI 极性相位或加匹配电阻 |
| ECC 报错 | 位翻转超限 | 检查坏块和电源 | 擦除后重写,必要时更换 |
| 文件系统挂载失败 | 分区表损坏 | 读原始扇区 | 重新格式化或恢复备份 |
| 掉电数据丢失 | 写入未完成 | 检查电源电容 | 加 f_sync 和掉电保护电路 |
| 高温下读写不稳定 | 温度超规格 | 高低温测试 | 换工业级 SD NAND |
6. 几个我踩过的坑和实操心得
第一个坑是 SPI 模式下的片选时序。我一开始用硬件片选,STM32 的 SPI 控制器在发送完最后一个字节后会自动拉高 CS,但 SD NAND 要求 CS 在命令响应完成后才能拉高。结果就是命令响应还没读完,CS 就拉高了,导致响应丢失。后来改成软件片选,在发送命令和读取响应之间保持 CS 低电平,问题解决。这个坑花了我两天时间,最后用逻辑分析仪抓波形才找到原因。
第二个坑是 DMA 传输的内存对齐。STM32 的 SDIO DMA 要求内存地址 4 字节对齐,如果 FatFS 的缓冲区没有对齐,DMA 传输会出错。我一开始没注意,读写小文件时偶尔出错,大文件反而正常。后来在 diskio 层加了attribute((aligned(4))) 强制对齐,问题消失。这个坑比较隐蔽,因为错误是偶发的,不容易复现。
第三个坑是电源纹波导致的写入错误。有一个项目用 LDO 给 SD NAND 供电,LDO 的响应速度不够,NAND 擦写时电流突变导致电压跌落,写入数据出错。后来在 LDO 输出端加了 100uF 的钽电容,问题解决。这个坑的教训是:NAND 的电源设计不能只看平均电流,要看峰值电流和瞬态响应。
第四个坑是文件系统的簇大小。FatFS 默认的簇大小是 512 字节,对于 8GB 的 SD NAND 来说太小了,导致 FAT 表巨大,读写效率低。后来把簇大小改成 32KB,读写速度明显提升。这个参数在 f_mkfs 的时候可以指定,格式化时要注意。
最后分享一个小技巧:SD NAND 的寿命和写入放大有关。如果你频繁写入小文件,写入放大会很严重,寿命会缩短。我的做法是在 RAM 里做缓存,积累到一定大小再一次性写入,减少擦写次数。另外,日志文件用追加模式,不要频繁创建删除文件,这样也能延长寿命。