Bootloader EEPROM & USB Power Limits by Board
Before wiring anything, you must understand the hard limits of your specific board variant. The Raspberry Pi 5 handles USB and PCIe boot natively with higher current limits, while the Pi 4 requires strict EEPROM configuration and is notorious for tripping its 1.2A total USB current limit during SSD spin-up.
| Board Variant | Default BOOT_ORDER | USB Boot Target Order | Max USB Current (Total) | USB Boot Timeout |
|---|---|---|---|---|
| Raspberry Pi 4 Model B | 0x1 (SD only) | 0xf41 (USB, SD, Restart) | 1.2A (across all 4 ports) | 2000ms (default) |
| Raspberry Pi 5 (4GB/8GB) | 0xf41 (SD, USB, Restart) | 0xf416 (SD, USB, PCIe, Restart) | 1.6A (with 5A PD supply) | 2000ms (default) |
| Compute Module 4 (CM4) | 0xf1 (eMMC/SD) | 0xf41 (USB, SD, Restart) | 1.2A (depends on carrier board) | 2000ms (default) |
| Raspberry Pi 400 | 0xf41 (USB, SD, Restart) | 0xf41 (Already optimized) | 1.2A | 2000ms (default) |
Hardware Parts List & SSD Power Monitor Pinout
To debug power-related boot failures, we need to measure the actual current draw of the USB SSD. We will wire a Texas Instruments INA219 I2C power monitor inline with a USB breakout, or simply monitor the Pi's 3.3V/5V rail drop if using a powered hub. For this build, we are monitoring the Pi's 5V rail to detect brownouts caused by the USB controller.
Target Board: Raspberry Pi 5 (8GB) running Raspberry Pi OS (Bookworm 64-bit).
SSD: Sabrent Rocket Nano 512GB USB 3.2.
Monitor: Adafruit INA219 Breakout Board (Product ID: 904).
INA219 to Raspberry Pi 5 GPIO Pin Mapping
| INA219 Pin | Pi 5 GPIO / Function | Physical Pin # | Wire Color (Standard) |
|---|---|---|---|
| VCC | 3.3V Power | Pin 1 | Red |
| GND | Ground | Pin 6 | Black |
| SDA | GPIO 2 (I2C1 SDA) | Pin 3 | Blue |
| SCL | GPIO 3 (I2C1 SCL) | Pin 5 | Yellow |
Flashing the USB Drive & EEPROM Configuration
Follow these exact steps to configure the Pi 5 bootloader and flash the OS. Do not skip the EEPROM verification step.
- Flash the OS: Use Raspberry Pi Imager to write Raspberry Pi OS (64-bit) to your USB SSD. In the OS Customization settings, enable SSH and set your hostname.
- Check Current EEPROM: Boot the Pi temporarily from an SD card (or via network boot) and open the terminal. Run:
sudo rpi-eeprom-update
Ensure you are on the latest stable release (e.g., 2024+ for Pi 5). - Edit Boot Order: Run
sudo -E rpi-eeprom-config --edit. This opens the configuration innano. - Set USB/PCIe Priority: Change or add the
BOOT_ORDERline to:
BOOT_ORDER=0xf416
(This tells the ROM to try SD, then USB mass storage, then PCIe/NVMe, then restart). - Increase USB Timeout (Optional but recommended): If using a slow-spinning mechanical USB drive or a hub, add:
USB_MSD_PWR_OFF_TIME=1000
USB_MSD_STARTUP_DELAY=1000 - Save and Reboot: Press
Ctrl+O,Enter,Ctrl+X. Remove the SD card and reboot. The Pi will now boot from the USB SSD.
Debugging: Exact Error Strings & Ranked Causes
When a raspberry pi boot usb setup fails, the bootloader outputs specific error strings to the UART serial console (or the connected HDMI display if BOOT_UART=1 is set). Here is how to read them.
- Power Supply Wattage: Are you using the official 27W USB-C PD supply for the Pi 5? A standard 15W phone charger will cause immediate USB brownouts.
- USB Cable Integrity: Many cheap NVMe enclosures ship with charge-only or USB 2.0 data cables. Swap to a certified 10Gbps USB-C to USB-C cable.
- EEPROM BOOT_ORDER: Run
vcgencmd bootloader_configfrom an SD boot and verifyBOOT_ORDERincludes the4(USB) nibble.
Error 1: "USB boot: timeout" or "FSBL error: USB boot timeout"
What it means: The bootloader enumerated the USB bus but could not find a valid FAT32 boot partition within the 2000ms window.
Ranked Causes:
- Missing EFI Partition: The SSD was formatted as exFAT or NTFS instead of the required FAT32 for the boot partition. (Fix: Re-image with Pi Imager).
- Hub Initialization Delay: The SSD is behind a USB hub that takes >2 seconds to initialize. (Fix: Add
USB_MSD_STARTUP_DELAY=2000to EEPROM config). - UAS (USB Attached SCSI) Incompatibility: The SSD enclosure's JMicron or ASMedia controller crashes during UAS handoff. (Fix: Add
usb-storage.quirks=XXXX:XXXX:utocmdline.txtto disable UAS).
Error 2: "Failed to parse device tree"
What it means: The bootloader found the drive and loaded start5.elf, but the kernel panicked while reading the .dtb file.
Ranked Causes:
- Corrupt Filesystem: Sudden power loss corrupted the FAT32 boot partition. (Fix: Run
fsck.faton a PC or re-flash). - Mismatched Firmware: You moved the SSD from a Pi 4 to a Pi 5 without updating the
start.elfandfixup.datbinaries. (Fix: Runsudo rpi-updateor re-image).
Python Boot Monitor Script (Raspberry Pi 5 Target)
To prove your USB SSD isn't causing brownouts, use this Python script. It reads the INA219 sensor via I2C to log the 5V rail current draw during heavy I/O operations. This code targets the Raspberry Pi 5 (8GB) and uses the raw smbus2 library to avoid dependency bloat.
#!/usr/bin/env python3
"""
INA219 USB Power Monitor for Raspberry Pi 5 USB Boot Debugging.
Reads Bus Voltage and Shunt Current to detect SSD brownouts.
Target: Raspberry Pi 5 (8GB) / Raspberry Pi OS Bookworm 64-bit
Requires: sudo apt install python3-smbus2 i2c-tools
"""
import smbus2
import time
import sys
# --- PIN & ADDRESS DEFINITIONS ---
# I2C Bus 1 (Physical Pins 3/SDA and 5/SCL on Pi 5)
I2C_BUS = 1
# INA219 Default I2C Address (A0 and A1 jumpers grounded)
INA219_ADDR = 0x40
# INA219 Registers
REG_BUS_VOLTAGE = 0x02 # Bus Voltage Register
REG_CURRENT = 0x04 # Current Register
# Conversion Constants (Based on default INA219 calibration)
# Bus Voltage: 1 LSB = 4mV, shifted right by 3 bits
BUS_VOLTAGE_LSB = 0.004
# Current: 1 LSB = 1mA (default calibration for 0.1 ohm shunt)
CURRENT_LSB = 0.001
def read_word(bus, addr, reg):
"""Reads a 16-bit unsigned integer from the specified I2C register."""
try:
result = bus.read_word_data(addr, reg)
# INA219 returns big-endian, smbus2 read_word_data expects little-endian
# Swap bytes manually for correct reading
return ((result & 0xFF) << 8) | ((result >> 8) & 0xFF)
except OSError as e:
print(f"[ERROR] I2C Communication Failed: {e}")
sys.exit(1)
def get_bus_voltage(bus):
"""Calculates the bus voltage in Volts."""
raw = read_word(bus, INA219_ADDR, REG_BUS_VOLTAGE)
# Shift right by 3 bits to drop the CNVR and OVF flags
raw = raw >> 3
return raw * BUS_VOLTAGE_LSB
def get_current_amps(bus):
"""Calculates the current draw in Amps."""
raw = read_word(bus, INA219_ADDR, REG_CURRENT)
# Handle signed 16-bit integer for negative current (regeneration)
if raw > 32767:
raw -= 65536
return raw * CURRENT_LSB
def main():
print("Starting INA219 Power Monitor for USB Boot Debugging...")
print("Monitoring 5V Rail / USB SSD Draw. Press Ctrl+C to stop.\n")
try:
bus = smbus2.SMBus(I2C_BUS)
except FileNotFoundError:
print("[FATAL] I2C bus not found. Did you enable I2C in raspi-config?")
sys.exit(1)
except PermissionError:
print("[FATAL] Permission denied. Run with sudo or add user to i2c group.")
sys.exit(1)
try:
while True:
voltage = get_bus_voltage(bus)
current = get_current_amps(bus)
power = voltage * current
# Flag potential brownout condition (Pi 5 requires >4.8V under load)
status = "[OK]" if voltage >= 4.85 else "[WARNING: BROWNOUT RISK]"
print(f"V: {voltage:5.2f}V | I: {current:5.3f}A | P: {power:5.2f}W | {status}")
# Poll at 10Hz to catch SSD spin-up transients
time.sleep(0.1)
except KeyboardInterrupt:
print("\nMonitor stopped by user.")
finally:
bus.close()
if __name__ == "__main__":
main()
Run this script during a reboot sequence (sudo python3 ina219_monitor.py via SSH right before issuing sudo reboot, or log to a file). If you see the voltage dip below 4.85V exactly when the bootloader attempts to mount the USB drive, your power supply or cable is insufficient.
Extending and Simplifying the Build
How to Simplify
If you do not need hardware-level power debugging and just want a reliable USB boot drive, drop the INA219 circuit entirely. Instead, rely on the Pi's built-in software throttling and voltage monitoring. You can check for historical undervoltage events in the OS by running:
vcgencmd get_throttled
If the output is anything other than 0x0, your USB SSD is pulling too much peak current, and you should switch to a powered USB 3.0 hub rather than adding I2C sensors.
How to Extend
For remote embedded deployments where physical access is impossible, extend this build by adding a hardware watchdog. The Raspberry Pi 5 includes an internal hardware watchdog. Enable it by adding dtparam=watchdog=on to your /boot/firmware/config.txt. Combine this with a systemd service that pings the watchdog only when your critical application is running. If the USB SSD hangs and the OS locks up, the hardware watchdog will force a clean reboot, bypassing the need for a physical power cycle.
For deeper hardware integration, refer to the official Raspberry Pi USB boot documentation and the Texas Instruments INA219 Datasheet for advanced calibration register tuning.






