ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SD NAND 深度解析:嵌入式存储选型、SPI/SDIO 驱动与 ECC 机制

SD NAND 深度解析:嵌入式存储选型、SPI/SDIO 驱动与 ECC 机制 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 NANDSPI NANDeMMCSD 卡容量范围128MB-8GB128MB-4GB4GB-256GB8GB-1TB接口SPI/SDIOSPISDIO/并行SDIO/SPI封装LGA/BGASOP/BGABGA卡座坏块管理内置主控负责内置内置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 作为片选初始电平拉高第四使能 DMASPI 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如果要 24MHzCLKDIV 设为 0如果要 12MHzCLKDIV 设为 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 的块大小是 4KBFatFS 的 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 后再发 CMD0CMD8 返回错误电压范围不匹配检查 VCC 电压确认 SD NAND 支持 2.7-3.6VACMD41 一直忙初始化超时降低 SPI 时钟用 400KHz 以下时钟初始化读写数据错误时序问题降低时钟测试调整 SPI 极性相位或加匹配电阻ECC 报错位翻转超限检查坏块和电源擦除后重写必要时更换文件系统挂载失败分区表损坏读原始扇区重新格式化或恢复备份掉电数据丢失写入未完成检查电源电容加 f_sync 和掉电保护电路高温下读写不稳定温度超规格高低温测试换工业级 SD NAND6. 几个我踩过的坑和实操心得第一个坑是 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 里做缓存积累到一定大小再一次性写入减少擦写次数。另外日志文件用追加模式不要频繁创建删除文件这样也能延长寿命。
返回列表