3、启动介质选择:eMMC、NAND Flash、NOR Flash、SPI Flash、SD卡、USB、UART等启动模式

芯片上电后,第一件事就是找启动代码。但代码放在哪?这取决于你的硬件设计。我见过不少新手工程师,一上来就纠结「到底该用哪种Flash」,其实这个问题没有标准答案——不同的启动介质,对应的是不同的应用场景和成本考量。

说白了,BootROM的任务就是按照芯片厂商预设的启动顺序,挨个去检查这些介质上有没有合法的启动头。谁先响应,谁就是启动源。

核心原则:启动介质的选择 = 性能需求 + 成本预算 + 量产便利性。没有最好的介质,只有最合适的方案。

3.1 主流启动介质一览

先给个全景图。我把常见的启动介质按接口类型和典型应用场景整理了一下,方便你快速建立认知。

介质类型 接口协议 典型容量 启动速度 常见场景
NOR Flash Parallel / SPI 1MB ~ 128MB 快(XIP) 小容量固件、BIOS、早期Bootloader
NAND Flash Parallel / SPI 128MB ~ 8GB 中(需搬运) 嵌入式Linux、大容量存储
eMMC MMC / SDIO 4GB ~ 256GB 快(DMA) 手机、平板、高端嵌入式
SPI Flash SPI / QSPI 512KB ~ 64MB 中(XIP受限) IoT设备、MCU固件
SD卡 SD / SDIO 1GB ~ 128GB 慢(需初始化) 开发板、单板计算机
USB USB 2.0/3.0 取决于U盘 慢(需枚举) 量产烧录、调试
UART 串口 极低 极慢 调试、应急恢复
我的经验:量产项目里,我90%的情况都用eMMC或SPI Flash。NOR Flash虽然支持XIP(片上执行),但容量上去后价格太贵。NAND Flash有坏块问题,BootROM里必须做坏块管理,否则启动到一半就挂了。

3.2 各介质的启动细节与避坑

3.2.1 NOR Flash:最直接的启动方式

NOR Flash支持XIP(Execute In Place),意思是CPU可以直接从Flash里取指令执行,不需要先拷贝到RAM。启动速度最快,延迟最低。

但有个坑:NOR Flash的写入速度很慢,而且容量做不大。我记得有一次做工业控制器,选了8MB的NOR Flash,结果固件版本迭代到第3版就塞不下了。后来不得不改成SPI Flash + 搬运方案。

注意:如果使用NOR Flash启动,BootROM通常直接跳转到Flash的基地址+偏移处执行。此时要确保Flash的时序配置正确,否则CPU取到的全是0xFF,直接跑飞。

3.2.2 NAND Flash:容量大但麻烦多

NAND Flash的密度高、价格低,但天生带坏块。出厂时就有坏块,使用过程中还会产生新坏块。BootROM如果要从NAND启动,必须内置ECC校验和坏块跳过逻辑。

我曾经在一个项目里踩过这个坑:芯片的BootROM只支持NAND的1-bit ECC,但我们用的NAND颗粒是4-bit ECC的。结果启动时经常校验失败,折腾了两天才发现是ECC强度不匹配。嗯,选型时一定要确认BootROM支持的ECC算法。

NAND启动的典型流程:

  1. BootROM初始化NAND控制器
  2. 读取NAND的0号块(通常存放启动头)
  3. 校验ECC,如果坏块则跳过找下一个可用块
  4. 将启动代码搬运到SRAM或DDR中
  5. 跳转到RAM执行

3.2.3 eMMC:现代嵌入式的主流选择

eMMC内部集成了NAND Flash和控制器,坏块管理、ECC、磨损均衡都由芯片内部搞定。对BootROM来说,eMMC就是一个标准的块设备,读写接口简单。

我个人习惯在eMMC上划分多个分区:Boot1、Boot2、RPMB、User Data。BootROM通常只认Boot1分区,如果Boot1坏了,可以回退到Boot2。这个冗余设计在量产中非常实用。

关键点:eMMC启动时,BootROM需要发送CMD0(复位)、CMD1(获取OCR)、CMD2(获取CID)、CMD3(设置RCA)等一系列命令。如果eMMC的初始化时序不对,芯片会一直卡在等待响应状态。

3.2.4 SPI Flash:小成本大用途

SPI Flash是MCU和低端SoC的标配。接口简单,引脚少,成本低。但SPI Flash通常不支持XIP(除非是QSPI且芯片支持内存映射模式)。

BootROM的做法是:先通过SPI接口把Flash前几KB的内容读到芯片内部的SRAM里,然后执行。这部分代码通常是二级Bootloader,再由它去加载完整的固件。

你想想看,如果SPI Flash的时钟频率太低,启动时间就会很长。我建议至少用50MHz以上的QSPI Flash,配合DMA传输,能把启动时间压缩到几百毫秒以内。

3.2.5 SD卡:开发板的宠儿

SD卡启动在开发板上很常见,比如树莓派、各种ARM开发板。BootROM会按照SD协议初始化卡,读取MBR或GPT分区表,找到启动分区,然后加载bootloader。

但SD卡有个问题:不同品牌的卡,初始化时间差异很大。有些卡需要几百毫秒才能准备好,而BootROM通常有超时限制。我曾经遇到过某品牌的SD卡在A芯片上能启动,在B芯片上就超时失败。最后发现是卡返回的OCR寄存器值不符合芯片的预期。

避坑指南:量产项目尽量不要用SD卡做启动介质。SD卡是消费级产品,可靠性不如eMMC。如果非要用,建议选工业级SD卡,并在BootROM里增加重试机制。

3.2.6 USB和UART:调试与烧录专用

USB和UART启动通常不是产品最终形态,而是用于工厂烧录或现场升级。BootROM会检测USB设备枚举或UART数据流,一旦收到合法的启动镜像,就把它下载到RAM中执行。

UART启动速度极慢,一般只有115200bps或921600bps。烧录一个1MB的固件要等好几分钟。所以我只在芯片变砖、没有其他启动手段时才用UART。

USB启动就快多了。USB 2.0 High Speed能达到480Mbps,烧录效率很高。但USB需要芯片内部有USB控制器,且BootROM要支持USB HID或MSC协议。我记得有一次调试USB启动,发现芯片枚举成功后,主机发送的OUT包芯片收不到,最后定位是USB D+上拉电阻没焊——硬件工程师忘了放。

3.3 启动介质选择决策树

说了这么多,到底怎么选?我画了一张决策图,你可以对照自己的项目需求来走一遍。

启动介质选择决策树 启动介质选择决策树 启动介质选型 容量 < 128MB 容量 ≥ 128MB 需要XIP? 不需要XIP NOR Flash SPI Flash 需要内置控制器? 开发调试用 SD卡 / USB eMMC NAND Flash 决策说明: 1. 容量小于128MB且需要XIP → NOR Flash(成本高但启动快) 2. 容量小于128MB且不需要XIP → SPI Flash(性价比高) 3. 容量大于128MB且需要内置控制器 → eMMC(稳定可靠) 4. 容量大于128MB且不需要控制器 → NAND Flash(成本低但需坏块管理) 5. 开发调试或应急恢复 → SD卡 / USB / UART 注:实际项目中,BootROM通常支持多种介质,按优先级轮询。

3.4 BootROM的启动顺序策略

大多数芯片的BootROM不会只支持一种介质,而是按照固定的优先级顺序去轮询。比如:

  1. 先检查eMMC Boot1分区
  2. 如果失败,检查eMMC Boot2分区
  3. 再失败,检查SPI Flash
  4. 然后检查SD卡
  5. 最后检查USB或UART

这个顺序通常由芯片的fuse位或外部引脚电平决定。我习惯在硬件设计时留一组GPIO做启动模式选择,这样量产时不用改代码,直接拨码开关就能切换启动源。

重要提醒:BootROM的启动顺序是写死的,但你可以通过烧写fuse来改变默认顺序。不过fuse是一次性编程的,烧错了芯片就废了。所以量产前一定要反复确认启动顺序配置。

3.5 我的选型建议

最后,给几个实际项目的选型参考:

  • IoT传感器节点:SPI Flash(512KB ~ 2MB),成本低,功耗低,启动时间可以接受
  • 工业PLC:NOR Flash(8MB ~ 32MB),需要XIP保证实时性
  • 智能家居网关:eMMC(4GB ~ 16GB),需要存储Linux内核和文件系统
  • 开发板:SD卡 + SPI Flash,SD卡方便调试,SPI Flash存最终固件
  • 量产烧录:USB,速度快,支持批量烧录