有天午休,同事捏着一颗黑色LGA-8封装的小芯片凑过来问:“BOM表里写着SD NAND,里面装的既然是Flash,为什么偏偏是NAND,不是NOR?我以前学的都是NOR随机读快、字节寻址简单,NAND又要管坏块、又要做ECC,怎么到了这个芯片上反而全用NAND了?” 这个问题问得很有水平。它没法用一句“因为NAND容量大”草草糊弄过去。SD NAND这套方案,链路上是“SD控制器 + 存储介质”的组合:控制器负责把主机的SD协议翻译成对存储晶圆的读写请求,存储介质则决定了这套翻译层的复杂程度。如果介质换成NOR,SD协议社区沉淀多年的“管理NAND的经验”几乎全废;而介质用NAND,SD协议几乎不用改就能跑得顺顺当当。这篇文章就围绕这个核心把原理拆开,讲讲两者的工艺差异、协议匹配度、成本账和应用分工。刚入行的朋友花十分钟看完,再有人问起这件事,就能不慌不忙地把逻辑讲明白。
1. 先认清两兄弟:NAND和NOR的组织方式完全不同
1.1 存储单元的“接线方式”决定了命运
NAND和NOR在电路底层都算浮栅晶体管家族,但阵列结构完全不一样。NOR里每个存储单元的源极、漏极、字线、位线基本都是各自引出的,像一个真正的“仓库格子”:任何一格,只要给出对应的行地址和列地址,就能单独把里面存的数读出来。这种近似SRAM/ROM的寻址模型,让NOR天生支持随机字节读取,控制逻辑非常简单,MCU甚至可以把NOR直接映射到地址空间里,当成一颗慢速内存来取指令。
代价是,每个单元都要预留独立的接触孔和连接线,单元面积被接线大量占用。工艺微缩到一定程度后,连线占的面积比重越来越大,密度很难继续往上走。NAND则换了思路,把一串存储单元像手拉手一样串联起来,共用少数的位线接触点。读取某个页的时候,先把整页数据搬进片上缓存(page register),再通过I/O引脚按顺序搬出去。因为横向只占一个接触孔、纵向压缩到一个器件间距,阵列集成密度能比NOR高出几个量级——同样一片晶圆,NAND能产出的容量是NOR没法比的。这就像仓库改成传送带:单件取货确实不如仓格方便,但整批整批过传送带的效率完全不同。理解这个组织方式差异,是理解后面所有问题的起点。
1.2 读写粒度:页 vs 字节,这是所有答案的起点
NAND的操作粒度是页(page),常见一页4KB到16KB,一次编程必须对一个页整体写入;擦除则按块(block)进行,一个块通常包含几十页甚至上百页,整体擦除要耗时毫秒到几十毫秒。NOR的操作粒度则灵活得多:读可以按字节、按字,编程(把1写为0)也能按字节/字进行;只有擦除才需要按扇区或块来操作,常见扇区4KB到64KB。这个“粒度差”不是小差异,而是两种Flash服务不同上层应用的根本原因。
读速度的区别必须分开说。NOR的随机读延迟极低,通常在几十纳秒到微秒级别,对“随时从任意地址取代码”非常友好;NAND读一个页时,要发命令、发地址,等存储阵列把整页数据加载到缓存,这个过程通常要20~80微秒,之后的数据传输速度才由I/O时钟决定。所以只要访问方式落在“单点、随机”上,NOR完胜;一旦访问方式是“大批量、连续”,NAND就能用吞吐率找补回来。写和擦除则是另一个故事:NOR往单元里写数据用的是沟道热电子注入,需要较高的编程电压,功耗大;NAND用Fowler-Nordheim隧穿做编程和擦除,整个页可以并行编程,典型页写时间几百微秒,块擦除一两毫秒。同样是连续大批量写入,NAND比NOR快出几个数量级。
| 维度 | NAND | NOR |
|---|---|---|
| 阵列结构 | 存储单元串联,共用位线 | 单元独立引线,随机寻址 |
| 读操作粒度 | 页读取到缓存后I/O输出 | 字节/字随机读 |
| 写操作粒度 | 页编程 | 字节/字编程 |
| 擦除粒度 | 块擦除 | 扇区/块擦除 |
| 随机读首字节延迟 | 页加载20~80µs级别 | 极低,ns~µs级别 |
| 顺序读吞吐 | 高,可到几十MB/s以上 | 受限于IO时钟,中等 |
| 写/擦性能 | 页级并行,批量写入快 | 写入功耗大,批量擦写明显慢 |
| 容量密度 | 高,3D堆叠可达数百层 | 低,工艺微缩难度大 |
| 单bit成本 | 极低 | 高,容量越大越明显 |
| 是否需要FTL | 必须(坏块+ECC+磨损均衡) | 不需要也能用 |
| 典型应用 | SD/eMMC/UFS/SSD | XIP启动、代码存储、小数据 |
1.3 NAND的脏活累活提前认识一下
NAND因为密度高、串行结构,天然伴随几个“特性”:出厂就可能带坏块;读写过程中可能产生比特翻转;反复擦写会磨损块。所以NAND存储系统绕不开三件事——坏块管理(BBM)、ECC纠错、磨损均衡(wear leveling)。NOR则因为阵列结构规整、可字节随机访问,坏块少得多,ECC可以做得很轻,磨损均衡压力也小很多。
这些差异决定了上层设计的走向。把NAND比作一个“高速但有点毛躁”的仓库管理员:吞吐量大,但偶尔把货号记错、个别货架容易坏,必须有调度员跟着擦屁股。NOR则是“精准但手脚慢”的老员工:每次拿单件货又快又准,但一次只能搬一小箱,整个仓库的规模也扩展不上去。理解了这两类角色的性格,再去看SD协议为什么非要选NAND,就顺理成章了。
2. SD家族的底层基因就是NAND
2.1 SD协议从诞生起就是围绕NAND写的
SD卡在当年设计时,存储介质就定位为NAND Flash,整个命令体系和寄存器定义都建立在NAND的块页模型上。主机的读操作是CMD17/CMD18(读单块/多块),写操作是CMD24/CMD25(写单块/多块),最小访问单位是512B扇区。主机看到的512B扇区,其实已经是SD卡控制器处理过的“逻辑块”视图——底层物理NAND的页可能4KB、8KB,控制器会把若干个逻辑扇区映射到一个物理页里,再负责搬数据。
这种“逻辑块到物理页”的转换,本质上和SSD里的FTL(Flash Translation Layer)是一回事。SD卡出厂时也内置了这样一层地址映射,只是它把复杂度全部封在了卡片内部,对外只暴露统一命令。所以当你把SD NAND焊上板子时,你用的SD协议从寄存器到命令,全部是照着NAND的脾气写的。协议栈、文件系统、主机驱动,一整条生态都是为“NAND介质”服务的。
2.2 坏块、ECC、磨损均衡:这些能力被协议默认具备
NAND不像NOR那样出厂就“干干净净”,它允许存在坏块,运行中还会老化出新坏块。因此SD卡/SD NAND控制器必须内置几个关键模块:第一是坏块管理,出厂时记录工厂坏块,使用中发现的坏块被标记并替换到保留块区;第二是ECC纠错,常见BCH、RS或更高级的LDPC,保证Flash出现随机位错时依然能返回正确数据;第三是磨损均衡,把写入操作尽量均匀分摊到所有块上,避免个别块先被写穿。
主机拿到手的是什么?是一个“无论底层怎么坏、都不需要你操心”的块设备。这套能力从SD协议诞生之初就被默认了。反过来想,如果SD协议面向的是NOR,这些设计就变成了一种浪费:NOR坏块极少,ECC需求很轻,磨损均衡几乎不用做。协议没有为NOR做这么多准备,因为它压根不是为NOR设计的。这就是为什么“SD里面装NAND”不是偶然,而是基因层面的匹配。
2.3 如果介质换成NOR,SD架构会塌在哪
假设有一天真有芯片厂推出“SD NOR”——外面是SD协议的LGA封装,里面换成NOR晶圆,会怎样?第一个问题是指令语义错配:SD协议最小读写单位是512B扇区,主机和文件系统根本不会对SD设备发起“随机单字节写”,NOR最引以为傲的字节随机写在这里毫无用武之地;而协议要求的连续扇区写入、频繁擦写,又正好是NOR最不擅长的场景。第二个问题是写放大的惨剧:NOR擦除要按块,擦写慢、功耗大,一旦FATFS频繁更新文件,NOR会被拖得很痛苦。第三,SD卡协议还要求卡片提供CID/CSD寄存器、支持电压切换、流式写等机制,这些对NOR来说既不是特长也不是刚需,硬塞进去只会让系统更复杂。所以“SD NAND里装NAND”是协议栈和介质特性高度匹配的必然结果,而不是顺手选了个流行方案。
3. 为什么装在SD卡里的必须是NAND:容量、成本和性能的账
3.1 容量密度这道坎,NOR真的过不去
贴一个典型物联网项目的真实场景:BootLoader加固件可能只有1~4MB,但GUI图片资源、字库、语音素材、日志缓存、OTA升级包,动辄几十MB到几百MB。NOR的工艺决定了它在16MB以上容量就会遭遇成本良率的剪刀差。市面上常见NOR容量大多在1Mbit(128KB)到128Mbit(16MB)之间,再往上,单片NOR的价格会非常难看。NAND这边完全是另一个世界:主流SD卡从4GB起步,SD NAND作为嵌入式封装,常见容量从128MB到8GB甚至更高,单位bit成本随工艺演进不断下降。
所以容量需求一摆出来,选NAND几乎不需要犹豫。更关键的是,NAND工艺已经进入3D堆叠时代,垂直堆到几十层、上百层,容量和良率还能继续优化。NOR因为结构限制,很难做3D化,工艺微缩也遇到瓶颈。这是物理规律决定的,不是哪家厂商偏心。
3.2 写入性能的真实差距:别被“NOR读得快”带偏
NOR给人的印象常常是“快”,但这个快必须严格限定在随机读和低延迟代码执行上。一旦进入批量写场景,情况就反转了。比如往存储里写一个1MB的固件更新包:NAND按页编程,一个4KB页写几百微秒,整个过程毫秒级完成;NOR要先擦除若干扇区(一次4KB/64KB擦除可能几十毫秒甚至更久),再逐字节写入,整体可能拖到秒级。
更麻烦的是NOR按字节编程需要较高的编程电压和更大的瞬态电流,对电池类设备不友好;NAND的页级并行编程,单位bit能耗更低。所以“NOR快”在数据存储任务里其实是个以偏概全的说法。一线量产选型时,只要看到日志缓存、FATFS频繁更新、OTA升级这类需求,工程师会毫不犹豫倾向NAND。把数据写入类比成搬家:NOR是一辆随叫随到的小车,单趟灵活但运量小;NAND是整节火车皮,调度门槛高,一靠站就几十节一起装卸。只搬一个箱子,小车好;搬一整个仓库,火车无可替代。
3.3 算一笔成本与人力账
拿一个实际选型场景举例。某项目原本用16MB SPI NOR存代码和资源,单颗BOM成本在预算表里看着还行;后来资源膨胀到64MB,NOR方案要么用多颗并联,要么找特殊的大容量NOR,要么接受极高的单价。这时候接入一颗128MB甚至256MB的SD NAND,价格区间反而更友好,而且LGA-8封装只有8个引脚,PCB占用比多颗SOIC-8 NOR还小。
人力成本也是大头。SD NAND走标准SD协议,MCU的HAL库、SDIO驱动、SPI模式驱动基本现成,上层还能直接套FatFS;而裸NAND方案需要自己写NAND时序、坏块扫描、ECC算法和磨损均衡,这部分开发和维护成本非常高。把硬件成本、开发成本、维护成本放在一起算,NAND方向几乎全面胜出。
4. 那NOR什么时候登场?它没有死,只是角色不同
4.1 XIP:NOR不可替代的舞台
XIP(Execute in Place,就地执行)是NOR最不可替代的看家本领。MCU上电后,代码可以直接从NOR映射地址取指执行,BootLoader和关键启动参数必须能在不加任何RAM拷贝的情况下跑起来。NAND不具备这个能力:它的读操作需要命令、地址、等待页装载、ECC校验,执行粒度和CPU取指完全不匹配;一旦读出的页里有不可纠正的错误,程序甚至可能直接跑飞。
所以在绝大多数嵌入式板子上,你会看到一套固定组合:一颗SPI NOR保存不能出错、必须上电即执行的BootLoader和关键启动参数;一颗SD NAND或eMMC保存大容量用户数据、固件镜像、日志、资源包。它俩不是竞争关系,而是上下游配合关系。
4.2 从启动链看NOR和SD NAND为什么总是一起出现
画一条典型启动链:上电 → CPU从片内ROM读固化启动代码 → 从SPI NOR引导BootLoader → BootLoader初始化DDR和外部控制器 → 从SD NAND/eMMC加载内核或App镜像 → 运行期文件系统读写SD NAND。
每一步的存储选型都有明确理由。第一步要求绝对可靠、时序实时,NOR当仁不让;后面的镜像和文件系统要求大容量和高吞吐,NAND的优势完全释放。看懂这条启动链,初级工程师就不会再纠结“既然SD NAND这么好,为什么还要NOR”,而是能主动判断某个存储元件该放到哪一环。
4.3 工程选型决策:什么时候坚持NOR,什么时候果断上SD NAND
| 需求特征 | 推荐介质 | 主要理由 |
|---|---|---|
| 代码量小、需要上电即执行 | SPI NOR | XIP、随机读延迟低、无需驱动初始化 |
| 需要频繁字节级随机修改、保存小参数 | NOR或小容量EEPROM | 字节寻址简单,没有磨损管理负担 |
| 需要存几十MB~GB级资源/日志/固件包 | SD NAND / eMMC | 容量、吞吐、单bit成本最均衡 |
| MCU只有SDIO/SPI接口、没有NAND控制器 | SD NAND | 协议成熟,驱动现成,省去FTL |
| 容量小于16MB、追求BOM最低 | 视情况NOR更便宜 | 此时NOR单价仍可接受 |
| 频繁连续擦写、日志型负载 | SD NAND(工业级优先) | 控制器承担磨损均衡与掉电管理 |
实战里还有一个常见过渡:项目原来的代码只有几MB,跑在SPI NOR里;后来资源膨胀,代码搬到SD NAND,启动变慢,于是把最核心的启动片段留在NOR,业务代码和资源包放到SD NAND。这种“既有NOR又有NAND”的混合架构,是嵌入式系统里最典型的存储布局。
5. SD NAND内部的黑匣子到底干了什么
5.1 NAND裸颗粒在外面是“刺头”,在SD NAND里被控制器管住了
很多初级工程师觉得NAND“难用”,因为裸NAND直接暴露在MCU面前时,所有脏活都要自己扛:发命令前要检查状态寄存器、写之前要整块擦除、要维护坏块表、每次读要自己做ECC、还要处理读干扰和数据保持。真接了裸NAND,驱动代码上千行很正常,边界条件还特别多。
SD NAND的做法,就是把整套“NAND管家”固件和NAND晶圆封进同一个芯片。外面只露出8个引脚,对MCU来说它就是一颗“只要喂命令就有数据返回”的SD卡,内部固件负责消化NAND的所有脾气。这也是SD NAND在量产里特别受欢迎的原因:不需要养NAND领域的资深驱动工程师,就能稳定使用大容量Flash。
5.2 控制器里的日常:坏块标记、磨损均衡、掉电管理
SD NAND控制器内部常年跑着几件事,值得心里有数。第一是逻辑地址映射:主机写LBA 100,控制器此刻把它映射到物理页A;下次再写LBA 100,可能就映射到另一个空闲页B,旧页A等垃圾回收。换页意味着不会反复写同一个物理块,这叫动态映射+磨损均衡。第二是坏块替换:当某个物理块出现不可纠正的ECC错误或编程失败,控制器把该块标记为坏,把逻辑地址挪到保留区好块上。第三是掉电保护:突然断电可能让一个页只写了一半,控制器需要靠日志或备份区保证重启后要么返回旧数据、要么返回完整新数据,而不是半截脏数据。
这些工作,裸NOR几乎不需要做得这么重,因为NOR可以字节级改写、坏块极少。但NAND必须做。从外部用户的视角看,你的程序只需要调用f_write,复杂度全被芯片吃掉了。
5.3 给初学者的落地实操:从焊接到第一条CMD0
SD NAND的实用之处在于,它不像裸NAND需要从头写驱动。如果你用RTOS或HAL库,SDIO/SPI驱动基本可以直接套用。实际落地时注意几个点:
焊接上,LGA-8无引脚封装与普通IC无异,注意焊盘散热和清洗,别让助焊剂残留在引脚之间。硬件上,DAT线和CMD线都要接上拉电阻,CLK不需要上拉;供电要加去耦电容,电源纹波对NAND初始化成功率的影响比很多人想象的大。软件上,初始化序列按顺序来:上电后先等至少74个时钟周期,然后CMD0进IDLE、CMD8核对接口电压(参数0x000001AA)、ACMD41反复查询直到Ready、CMD2/CMD3取CID和RCA、CMD7选中卡、读CSD确认容量,之后就能用CMD17/18读、CMD24/25写。
代码层面的最小序列示意(伪代码):
// 伪代码:SD NAND初始化最小序列 sd_power_on(); // 上电,等待至少74个时钟 send_cmd(CMD0, 0x00000000); // 进入Idle send_cmd(CMD8, 0x000001AA); // 检查SD 2.0电压窗口 do { send_cmd(CMD55, 0); // ACMD41的前缀命令 send_cmd(ACMD41, 0x40000000); // HCS置位,等待初始化完成 } while (!(response & OCR_READY)); send_cmd(CMD2, 0); // 读CID send_cmd(CMD3, 0); // 获取RCA send_cmd(CMD7, rca); // 选中卡 send_cmd(CMD9, rca); // 读CSD,解析容量 // 之后即可用CMD17/CMD18、CMD24/CMD25读写数据块注意ACMD41必须先发CMD55;SPI模式下初始化流程略有差异,但总体思想一致。这些细节在现场调试时能省下不少时间,我建议第一次接触SD NAND的朋友把这套序列在逻辑分析仪上抓一遍,亲眼看看响应波形,理解会深很多。
6. 常见误区与经验速查
6.1 五个高频误区逐个拆
误区一:“NOR比NAND快。”准确说法是NOR的随机读延迟低、代码执行体验好;顺序读、大规模写、擦除性能上NAND优势明显。不同负载下结论完全不同,别拿一个“快”字一刀切。
误区二:“NOR更可靠,所以重要数据都要放NOR。”NAND在正确FTL管理下能提供很强的数据完整性,控制器有ECC和刷新机制;裸NAND的易错点反而被SD NAND的控制器吸收掉了。数据可靠性不是介质单独扛,而是“介质+控制器+应用冗余”的组合。
误区三:“SD NAND就是把SD卡去壳焊接。”封装不同、电气引脚不同,SD NAND的LGA-8与SD卡金手指完全两回事,它取消了卡座插拔链路,专为板级集成设计;但协议层面和SD卡一致,驱动可以直接复用。
误区四:“NAND写入以块为单位,所以只能整块操作。”准确说法是编程按页、擦除按块。单页内不能重复编多个不同数据,控制器会做映射,把文件系统的扇区访问转换成页操作,用户并不直接感知。
误区五:“MCU有QSPI接口就能直接驱动SD NAND。”QSPI是给SPI NOR/Flash准备的,SD NAND需要SDIO接口,或者用SPI模式(速度受限)。SPI模式虽然也能跑,但吞吐远远不如SDIO,别指望测出几十MB/s。
6.2 给初级工程师的几条工程建议
第一,先分清数据类型:掉电必须保留的启动代码放NOR,经常改写的业务数据放SD NAND。第二,别在SD NAND上做高频率的单扇区小写,即使有控制器磨损均衡,过于极端的写放大依然会缩短寿命;日志先缓存到内存、按块落盘,是应用层最常见的优化手段。第三,量产前一定做掉电老化测试,SD NAND控制器的掉电策略直接决定数据安全,这个测试环节省不得。第四,对启动时间敏感的硬实时场景,要预留SD NAND的上电初始化时间——ACMD41轮询可能比NOR的“上电即用”慢不少。第五,学会看数据手册里的TBW/寿命参数和温标等级,工业级和消费级在严苛环境下的表现有明显差距。
最后聊一点个人体会。我帮朋友做存储选型时,见过不少初级工程师把NOR和NAND当成两个相似的通用选项纠结半天。其实它们更像两种性格的工具:NOR适合做“打开即执行”的代码仓库,NAND适合做“大吞吐、多数据”的粮仓。SD NAND的出现,是为了让你在不接触裸NAND驱动的前提下,依然能获得SD生态的成熟便利。把这个思路理顺,以后再遇到“为什么这颗芯片里装的不是NOR”这类问题,你已经站在存储选型的正确起跑线上了。接下来,打开数据手册,把初始化序列亲手跑一遍,比任何结论都更管用。