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 | 串口 | 极低 | 极慢 | 调试、应急恢复 |
3.2 各介质的启动细节与避坑
3.2.1 NOR Flash:最直接的启动方式
NOR Flash支持XIP(Execute In Place),意思是CPU可以直接从Flash里取指令执行,不需要先拷贝到RAM。启动速度最快,延迟最低。
但有个坑:NOR Flash的写入速度很慢,而且容量做不大。我记得有一次做工业控制器,选了8MB的NOR Flash,结果固件版本迭代到第3版就塞不下了。后来不得不改成SPI Flash + 搬运方案。
3.2.2 NAND Flash:容量大但麻烦多
NAND Flash的密度高、价格低,但天生带坏块。出厂时就有坏块,使用过程中还会产生新坏块。BootROM如果要从NAND启动,必须内置ECC校验和坏块跳过逻辑。
我曾经在一个项目里踩过这个坑:芯片的BootROM只支持NAND的1-bit ECC,但我们用的NAND颗粒是4-bit ECC的。结果启动时经常校验失败,折腾了两天才发现是ECC强度不匹配。嗯,选型时一定要确认BootROM支持的ECC算法。
NAND启动的典型流程:
- BootROM初始化NAND控制器
- 读取NAND的0号块(通常存放启动头)
- 校验ECC,如果坏块则跳过找下一个可用块
- 将启动代码搬运到SRAM或DDR中
- 跳转到RAM执行
3.2.3 eMMC:现代嵌入式的主流选择
eMMC内部集成了NAND Flash和控制器,坏块管理、ECC、磨损均衡都由芯片内部搞定。对BootROM来说,eMMC就是一个标准的块设备,读写接口简单。
我个人习惯在eMMC上划分多个分区:Boot1、Boot2、RPMB、User Data。BootROM通常只认Boot1分区,如果Boot1坏了,可以回退到Boot2。这个冗余设计在量产中非常实用。
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寄存器值不符合芯片的预期。
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 启动介质选择决策树
说了这么多,到底怎么选?我画了一张决策图,你可以对照自己的项目需求来走一遍。
3.4 BootROM的启动顺序策略
大多数芯片的BootROM不会只支持一种介质,而是按照固定的优先级顺序去轮询。比如:
- 先检查eMMC Boot1分区
- 如果失败,检查eMMC Boot2分区
- 再失败,检查SPI Flash
- 然后检查SD卡
- 最后检查USB或UART
这个顺序通常由芯片的fuse位或外部引脚电平决定。我习惯在硬件设计时留一组GPIO做启动模式选择,这样量产时不用改代码,直接拨码开关就能切换启动源。
3.5 我的选型建议
最后,给几个实际项目的选型参考:
- IoT传感器节点:SPI Flash(512KB ~ 2MB),成本低,功耗低,启动时间可以接受
- 工业PLC:NOR Flash(8MB ~ 32MB),需要XIP保证实时性
- 智能家居网关:eMMC(4GB ~ 16GB),需要存储Linux内核和文件系统
- 开发板:SD卡 + SPI Flash,SD卡方便调试,SPI Flash存最终固件
- 量产烧录:USB,速度快,支持批量烧录