树莓派3启动流程全解析:从OTP配置到USB启动实战
1. 树莓派启动流程深度解析:从硬件上电到系统加载
对于任何一个玩树莓派的开发者或爱好者来说,理解它的启动流程(Boot Sequence)是深入掌控这块板子的第一步。这不仅仅是知道它从哪里加载系统,更是理解其硬件初始化、固件加载和系统引导的完整链条。今天,我们就以树莓派3(基于BCM2837/BCM2837B0)为例,彻底拆解这个看似简单、实则精密的启动过程。如果你曾困惑于为什么SD卡启动需要等几秒,或者想实现无SD卡的USB启动,那么这篇文章将为你提供清晰的答案和实操依据。
启动流程决定了树莓派上电后如何找到并执行第一行代码。与传统的x86 PC通过BIOS/UEFI引导不同,树莓派采用了一种更“嵌入式”的方式,其引导ROM(Boot ROM)固化了最基础的初始化代码,负责探测各种可能的启动介质。这个过程充满了时序、超时和优先级逻辑,任何一个环节的配置或硬件状态都会影响最终的启动结果。掌握它,你就能在系统无法启动时快速定位问题,也能实现更灵活、更符合项目需求的定制化启动方案。
2. 启动流程全景与核心硬件依赖
2.1 启动流程的版本差异与适用范围
首先必须明确,树莓派的启动流程并非一成不变,它随着核心SoC(系统级芯片)的迭代而演进。本文聚焦的流程仅适用于基于BCM2837和BCM2837B0芯片的树莓派型号,这主要就是树莓派3系列(包括3B, 3B+, 3A+)以及同期的计算模块(如CM3)。对于更早的型号(如树莓派1和2),其流程更为简单:先尝试从SD卡启动,如果失败,则尝试USB设备模式启动(即被PC识别为USB大容量存储设备进行编程)。
而从树莓派4和树莓派5开始,启动机制发生了革命性的变化,引入了EEPROM引导流程。这些新款树莓派的引导加载程序(bootloader)存储在一块可独立更新的SPI Flash EEPROM中,不再依赖SD卡上的bootcode.bin。这意味着它们可以实现网络启动、USB启动等高级功能而无需任何SD卡,并且启动顺序和超时等行为可以通过更新EEPROM中的引导加载程序来灵活配置。因此,千万不要将本文的流程套用到树莓派4/5上,否则会南辕北辙。
2.2 硬件基石:OTP与GPIO引导模式
BCM2837上电后,其内置的Boot ROM代码会首先查询两块至关重要的硬件信息源,以决定启用哪些启动路径。
第一块是一次性可编程存储器(OTP)。你可以把它想象成芯片出厂时被“烧录”好的永久性配置位。这些OTP位定义了芯片支持哪些基础的启动方式,例如SD卡启动、USB主机启动、NAND启动、SPI启动等是否在硬件层面被“允许”。OTP在芯片生产时被设置,对于普通用户而言是只读的,但树莓派基金会通过特定的软件命令(如program_usb_boot_mode)可以“熔断”其中某些位,来永久性地启用一些高级启动模式(如USB主机启动)。
第二块是GPIO引导模式。这是一个非常灵活的硬件级选择机制。即使OTP允许了多种启动方式(比如同时允许SD卡和USB启动),树莓派在启动瞬间还可以通过检测特定GPIO引脚的电平状态,来进一步筛选或排序这些OTP已启用的模式。例如,你可以通过将某个GPIO接地,告诉树莓派:“跳过SD卡,直接尝试USB启动”。
重要提示:GPIO引导模式只能用于选择那些已经在OTP中被启用的启动模式。它本身无法“无中生有”地开启一个OTP未允许的模式。并且,该功能默认是禁用的,需要额外配置才能使用。
3. 启动流程的逐帧拆解
理解了硬件基础后,我们来看BCM2837上电后的具体执行步骤,这是一个严格的顺序决策过程。
3.1 第一阶段:初始化与模式决策
- SoC上电复位:BCM2837芯片通电,内部Boot ROM代码开始运行。
- 读取OTP配置:Boot ROM读取OTP存储器,获得一份“允许启动模式清单”。这份清单是后续所有操作的基础。
- GPIO模式筛选(如果启用):如果OTP中启用了GPIO引导模式功能,Boot ROM会立即检测预设的GPIO引脚组(具体引脚定义需查阅
Arm Peripherals datasheet第102页的默认上拉/下拉配置)。Boot ROM会比较这些引脚在启动瞬间的实际电平与它们的默认状态。如果电平状态与默认状态不同,则根据预先定义好的映射关系,对“允许启动模式清单”进行动态调整,可能禁用某些模式或改变尝试顺序。
3.2 第二阶段:按序尝试启动介质
Boot ROM接下来会按照一个固定的优先级顺序,遍历经过上一步筛选后的启动模式清单,寻找一个名为bootcode.bin的文件。这个文件是树莓派启动链中的第二阶段引导加载程序。一旦在任何介质上找到它,Boot ROM会将其加载到芯片内部的128KB二级缓存(L2 Cache)中并跳转执行,启动流程即告成功,控制权交给bootcode.bin。
尝试顺序如下:
主SD卡接口(GPIO 48-53):
- 条件:该模式在OTP中默认启用。
- 动作:Boot ROM通过SD卡控制器,在连接到GPIO 48-53(即树莓派板载SD卡槽)的SD卡上寻找
bootcode.bin。 - 超时:如果SD卡槽中没有插入卡,或者卡中没有有效分区/FAT文件系统,这个过程会持续5秒钟然后宣告失败。这是树莓派3开机时可能出现的“黑屏5秒”的主要原因之一。
- 结果:成功则启动,失败则超时后进入下一项。
从SD卡接口:
- 条件:需要OTP启用,且通过GPIO引导模式等机制配置。
- 动作:在另一组GPIO引脚(非板载卡槽)上连接的SD卡中寻找
bootcode.bin。这是一个较少使用的特性,通常用于特殊硬件设计。 - 结果:成功则启动,失败则超时。
NAND Flash启动:
- 条件:需要OTP启用。
- 说明:此模式可用,但GPU支持尚不完整,主要用于工业或定制化模块。
SPI Flash启动:
- 条件:需要OTP启用。
- 说明:与NAND类似,可用但GPU支持不完整。
USB主机模式启动:
- 条件:需要OTP中
USB host boot位被启用(默认关闭,需用program_usb_boot_mode=1命令开启)。 - 决策点 - OTGID引脚:Boot ROM会检查SoC上的OTGID引脚电平。
- 如果OTGID == 0:进入USB主机模式。树莓派将作为主机去枚举连接的USB设备。
- 如果OTGID == 1:进入USB设备模式(见下一阶段)。
USB主机模式启动的详细子流程:
- 启用USB控制器:初始化USB主机控制器。
- 等待设备连接(2秒):给连接的USB设备(如U盘、硬盘、USB网卡)上电,并等待它们完成USB枚举。枚举是USB设备向主机报告自身身份(是集线器、U盘还是网卡)的过程。对于机械硬盘,自旋启动可能需要时间,因此这里设置了2秒的初始等待时间。
- 设备发现与分类:
- 如果发现的是USB集线器,则递归检查其下的每个端口。
- 如果发现的是大容量存储设备(MSD,如U盘/硬盘)或LAN951x系列USB转以太网芯片,则将其加入待检查设备列表。
- 递归搜索
bootcode.bin:- 遍历列表中的每一个大容量存储设备(MSD),在其FAT分区中寻找
bootcode.bin。找到则启动。 - 遍历列表中的每一个LAN951x设备,尝试进行DHCP获取IP,然后通过TFTP协议从网络服务器下载
bootcode.bin。找到则启动。
- 遍历列表中的每一个大容量存储设备(MSD),在其FAT分区中寻找
- 超时调整:如果2秒不够(例如某些慢速硬盘),可以在SD卡
config.txt文件中添加program_usb_boot_timeout=1,将超时延长至5秒。
- 条件:需要OTP中
USB设备模式启动:
- 条件:OTP中
USB device boot位默认已启用。且OTGID引脚电平为1(或悬空)。 - 场景:主要适用于树莓派Zero、计算模块(CM)或某些特定布线的主板。在此模式下,树莓派将自己模拟成一个USB设备(通常是USB大容量存储设备)。
- 动作:树莓派等待连接它的主机(通常是一台PC)来枚举它。当PC识别到该设备后,可以通过特定的工具(如Raspberry Pi官方提供的
usbboot工具)向这个“虚拟的USB磁盘”写入bootcode.bin等引导文件,从而实现对树莓派系统的直接烧录或修复,无需SD卡读卡器。 - VID/PID:在设备模式下,树莓派会向PC报告特定的供应商ID(VID)和产品ID(PID),以便PC端工具识别。树莓派1/2报告
VID: 0a5c, PID: 0x2763;树莓派3报告VID: 0a5c, PID: 0x2764。
- 条件:OTP中
4. 关键细节与实操要点
4.1 关于SD卡启动超时的优化
如前所述,空SD卡槽会导致5秒的探测超时。如果你主要使用USB启动,希望加快启动速度,有两个方法:
- 插入一张空白SD卡:即使卡里没有系统,Boot ROM检测到有卡存在,也会更快地判断启动失败,从而更快地跳转到USB启动流程。
- 使用GPIO引导模式:通过配置OTP和GPIO,直接禁用SD卡启动模式,这样Boot ROM根本不会去尝试SD卡,实现“秒切”到USB启动。
4.2 USB主机启动的优先级与分区支持
- MSD优先于网络:在USB主机模式下,Boot ROM会先搜索所有USB存储设备,只有在所有存储设备上都找不到
bootcode.bin后,才会尝试通过USB网卡进行网络(TFTP)启动。这个顺序是固定的。 - 灵活的FAT分区查找:早期的Boot ROM要求FAT分区必须是存储设备的第一个分区。现在这个限制已经解除。Boot ROM会遍历存储设备上的所有分区,直到找到一个包含
bootcode.bin的FAT分区为止。 - 支持GUID分区表(GPT):Boot ROM现在也支持GPT分区格式。这意味着你可以在同一块硬盘上同时安装macOS、Windows、Linux和树莓派系统,并使用GPT来管理它们,树莓派依然能正确找到自己的引导分区。
4.3 网络启动与硬件识别
- LAN951x的识别:Boot ROM通过特定的VID(
0x0424)和PID(0xec00)来识别内置的LAN951x系列USB以太网芯片(树莓派3B等型号板载的正是此芯片)。如果你想使用独立的LAN9500USB网卡来实现网络启动,会发现其PID(0x9500或0x9e00)不匹配,因此无法被Boot ROM直接识别用于网络引导。 - 解决方案:需要为独立的LAN9500网卡添加一个I2C EEPROM,并在其中编程,将其VID/PID伪装成LAN951x(
0x0424:0xec00)。这是一个比较硬核的硬件修改,通常只用于特定的工业或定制场景。
4.4 不同树莓派型号的USB启动差异
- 树莓派3 Model B/B+:其OTGID引脚在板级设计上被硬拉低(驱动为0)。因此,一旦通过
program_usb_boot_mode命令启用了USB主机启动,它只能以USB主机模式启动,无法进入USB设备模式(因为LAN951x芯片物理上占用了USB OTG端口)。 - 树莓派Zero/计算模块:它们的OTGID引脚通常被设计为可悬空。当通过Micro USB口连接到PC时,引脚悬空,电平被识别为高,从而进入USB设备模式。这正是实现“无需读卡器,直接用USB线刷系统”功能的硬件基础。官方提供的
usbboot工具就是利用了这一特性。
5. 常见问题与故障排查实录
在实际操作中,尤其是尝试配置USB启动或网络启动时,经常会遇到各种问题。下面是我根据多年经验总结的常见问题与排查思路。
5.1 USB主机启动失败
现象:已按照教程在OTP中启用USB启动,插入包含bootcode.bin的U盘,但树莓派仍然从SD卡启动或无法启动。
排查步骤:
- 确认OTP已生效:在已启用USB启动的树莓派上,通过终端命令
vcgencmd otp_dump | grep 17:查看输出。如果17:行的值为3020000a,则说明USB主机启动位(bit 3)已成功熔断启用。 - 检查启动介质:确保U盘或硬盘的第一个分区是FAT32格式,并且根目录下包含正确的
bootcode.bin文件(可从官方Raspberry Pi OS镜像中获取)。虽然Boot ROM支持非第一分区,但从第一分区开始是最稳妥的。 - 移除SD卡:确保SD卡槽中没有插入任何SD卡,或者插入的SD卡是完全空白的(无分区表)。否则Boot ROM会优先尝试SD卡并等待超时。
- 电源问题:USB启动,尤其是连接机械硬盘时,对电源要求更高。使用质量不合格的电源或Micro USB线可能导致硬盘无法正常启动或枚举。务必使用官方推荐或质量可靠的5V/2.5A以上电源。
- 延长超时时间:对于启动缓慢的硬盘,在SD卡的
config.txt中(如果还能从SD卡启动)添加一行program_usb_boot_timeout=1,将USB枚举超时从2秒增加到5秒。 - 硬件兼容性:并非所有USB集线器、U盘或硬盘盒都100%兼容。尝试更换一个已知兼容的设备(例如SanDisk Cruzer Fit U盘或某些品牌的2.5英寸硬盘盒)。
5.2 网络启动(TFTP)失败
现象:树莓派通过USB以太网卡连接,但无法从TFTP服务器获取文件。
排查步骤:
- 确认网卡被识别:首先确保你使用的是板载的LAN951x芯片或已修改EEPROM的LAN9500网卡。其他型号的USB网卡基本不被Boot ROM支持。
- 检查网络连接:确保树莓派、TFTP服务器、DHCP服务器在同一局域网段。用网线直连时,可能需要交叉线或支持自动翻转的网口。
- 分析DHCP过程:在DHCP服务器上查看日志,确认树莓派是否成功获取了IP地址。Boot ROM发出的DHCP请求中,会包含一个特殊的选项66(TFTP服务器名)和选项67(启动文件名)。你需要确保DHCP服务器能正确回应这些选项,指向你的TFTP服务器和
bootcode.bin文件。 - TFTP服务器配置:TFTP服务器通常需要设置为允许匿名访问,并且根目录权限正确。确保
bootcode.bin文件直接位于TFTP根目录下,或者与DHCP返回的路径一致。TFTP协议是明文传输,防火墙需要放行UDP 69端口。 - 使用串口调试:最有效的调试方法是连接树莓派的UART串口(GPIO14/15),在启动时查看Boot ROM输出的详细调试信息。它会显示是否识别了网卡、DHCP请求是否发出、是否收到了回应、TFTP连接是否建立等关键信息。没有串口输出,网络启动的调试将非常困难。
5.3 GPIO引导模式配置疑难
现象:按照文档设置了GPIO,但未能改变启动顺序。
排查要点:
- 确认OTP已启用GPIO模式:GPIO引导模式本身需要在OTP中启用一个总开关。默认是关闭的。你需要先确认或启用它。
- 理解“非默认电平”:Boot ROM检测的是GPIO在上电瞬间的电平,并与该GPIO的默认上拉/下拉状态进行比较。例如,某个GPIO默认内部是弱上拉到高电平。如果你想让这个GPIO选择某个模式,你需要在外部电路上,在通电前就将该引脚拉低到地,造成“非默认”的低电平状态。
- 硬件稳定性:确保上拉/下拉电阻焊接可靠,连接稳定。接触不良或信号毛刺都可能导致检测失败。最好在电源和GPIO之间使用一个阻值合适的电阻(如10kΩ),而不是直接连接到VCC或GND,以避免过流。
- 查阅正确的引脚映射表:不同树莓派型号、不同启动模式(SD卡、USB等)所对应的GPIO引脚组是不同的。必须查阅对应SoC(BCM2837)的官方文档或
Arm Peripherals datasheet来确认,不能想当然。
5.4 USB设备模式(USB Boot)无法使用
现象:树莓派Zero连接电脑后,电脑没有识别出新的USB设备。
排查步骤:
- 确认型号支持:只有树莓派Zero、Zero W、Zero 2 W和计算模块原生支持此模式。树莓派3B/B+不支持。
- 使用正确的USB口:在树莓派Zero上,必须使用靠近HDMI口的那个Micro USB口(标记为“USB”),而不是标记为“PWR IN”的电源口。“USB”口是OTG端口,而“PWR IN”口仅用于供电。
- 检查连接和数据线:使用一条质量好的、支持数据传输的Micro USB线连接电脑。很多廉价的充电线只有电源线,没有数据线。同时,电脑的USB口最好直接连接在主板后置接口上,避免使用前端面板或经过不稳定的集线器。
- 安装驱动(Windows):首次连接时,Windows可能需要安装驱动程序才能正确识别树莓派为“BCM2708 Boot”设备。
usbboot工具包中通常包含所需的驱动(win32目录下的dwin开头的文件)。 - Linux/Mac权限:在Linux或macOS上使用
usbboot工具时,需要以root权限运行,或者配置合适的udev规则,否则无法访问USB设备。
6. 高级技巧与配置实例
6.1 永久启用USB主机启动(熔断OTP)
对于树莓派3,USB主机启动默认是关闭的。启用它是一个不可逆的“熔断”OTP位的过程。操作前请三思,但操作本身很简单。
- 准备一张可启动的SD卡,安装最新的Raspberry Pi OS(原Raspbian)。
- 启动树莓派,打开终端。
- 确保系统是最新的:
sudo apt update && sudo apt full-upgrade -y - 执行OTP编程命令:
echo program_usb_boot_mode=1 | sudo tee -a /boot/config.txt - 重启树莓派:
sudo reboot - 重启后,OTP位即被熔断。此后,即使你擦除SD卡或重装系统,这个设置依然有效,因为它是硬件级的改变。
- 验证是否成功:
如果输出结果中vcgencmd otp_dump | grep 17:17:的值包含3020000a(注意看bit 3),则表示成功。
警告:此操作一旦完成无法撤销。并且,根据树莓派官方文档,在某些非常早期的树莓派3B版本上,启用此功能可能存在极低概率的风险。建议在操作前备份重要数据,并确认你的树莓派已更新到最新的固件。
6.2 配置GPIO引导模式实现自动切换
假设你有一个项目,需要树莓派在“正常模式”和“恢复模式”之间切换。正常模式从SD卡启动,恢复模式从USB启动以进行系统维护。你可以通过一个拨动开关和GPIO引导模式来实现。
- 选择GPIO引脚:例如,我们选择GPIO22。根据数据手册,GPIO22默认内部是弱下拉(输入低电平)。
- 硬件连接:将GPIO22通过一个10kΩ电阻连接到3.3V。在电阻和GPIO22之间,连接一个拨动开关到地(GND)。开关断开时,GPIO22被上拉到3.3V(高电平,非默认状态)。开关闭合时,GPIO22被拉低到地(低电平,默认状态)。
- 配置OTP启用GPIO模式并映射:这通常需要通过更底层的配置或编译特定固件来实现,超出了本文基础范围。你需要参考
bootcode.bin源码或高级配置文档,将“GPIO22高电平”映射到“禁用SD卡启动,启用USB启动”这一行为。 - 使用:开关断开(GPIO22高电平)时,树莓派上电后检测到非默认状态,根据映射,跳过SD卡,直接从USB设备启动进入恢复模式。开关闭合(GPIO22低电平)时,为默认状态,GPIO引导模式不生效,树莓派按正常顺序(先SD卡后USB)启动。
这个方案提供了硬件级别的启动选择,非常可靠,适用于工业或嵌入式场景。
6.3 利用USB设备模式进行无卡系统部署
对于树莓派Zero或计算模块,USB设备模式是极佳的批量刷机或系统修复工具。
- 在PC上准备:从GitHub获取
usbboot工具集(git clone https://github.com/raspberrypi/usbboot),并按照说明编译(需要libusb开发库)。 - 准备镜像文件:下载官方的Raspberry Pi OS镜像文件(
.img格式)。 - 连接树莓派:用数据线将树莓派Zero的USB口连接到PC。给树莓派通电。
- 运行刷机命令(Linux示例):
此时,cd usbboot sudo ./rpibootrpiboot工具会将一个最小的引导程序推送到树莓派,树莓派随后会将自己模拟成一个USB大容量存储设备(通常是一个约64MB的虚拟磁盘)。 - 在PC上识别设备:几秒后,你的PC应该会识别到一个新的可移动磁盘。
- 写入系统镜像:你可以使用
dd命令(Linux/macOS)或Win32DiskImager(Windows)将完整的.img文件写入这个虚拟磁盘。写入完成后,树莓派即拥有了一个可启动的系统,无需使用SD卡读卡器。
这个过程本质上是在通过USB线直接“烧录”树莓派的存储设备(通常是SD卡或eMMC),效率极高,特别适合为计算模块批量安装系统。
