13 KiB
ESPRESSObin U-Boot Boot Commands — Eye Remote
Overview
This guide covers configuring ESPRESSObin U-Boot to boot from Eye Remote mass storage (active slot) or TFTP (shadow slot). The Eye Remote Pi Zero W provides USB OTG connectivity and network access for dual-boot management.
Key network setup:
- Eye Remote IP:
10.55.0.2 - ESPRESSObin IP:
10.55.0.1 - Network:
10.55.0.0/30(routable via USB OTG ECM)
Prerequisites
-
Eye Remote Pi Zero W
- Running v2.1.0 or later
- USB OTG ECM mode enabled
- DHCP server active on
10.55.0.2
-
ESPRESSObin
- U-Boot installed in SPI NOR flash or eMMC
- Serial console access (TTL UART 115200 baud)
- USB OTG micro-AB port (supports OTG mode)
-
Connectivity
- USB OTG cable (Pi Zero ↔ ESPRESSObin USB OTG port)
- Serial console cable (UART3, pins TXD/RXD/GND)
- Optional: Ethernet for TFTP boot (fallback)
-
Host Files
- Kernel:
Image(Linux ARM64 binary) - DTB:
armada-3720-espressobin.dtb(device tree) - Present on Eye Remote mass storage or TFTP server
- Kernel:
Power Ordering — Two Approaches
Option A: Independent Power (Recommended)
Safest method — power devices independently:
-
Connect USB OTG cable (Pi Zero ↔ ESPRESSObin OTG port)
- Pi Zero: micro-AB port
- ESPRESSObin: OTG micro-B port
- Cable acts as data link only
-
Power Pi Zero separately (5V via micro-USB)
- Pi Zero boots → enables USB host (via g_ether overlay)
- Exports mass storage LUN
-
Power ESPRESSObin independently (external 5V)
- Detects USB device (mass storage LUN) after U-Boot starts
- No risk of back-power or brown-out
Option B: Retry Loop in U-Boot
For scenarios where ESPRESSObin must power from USB OTG:
# In U-Boot console (press Enter during boot)
setenv bootcmd 'usb start; if usb storage; then fatload usb 0 ${kernel_addr_r} Image && fatload usb 0 ${fdt_addr_r} armada-3720-espressobin.dtb && booti ${kernel_addr_r} - ${fdt_addr_r}; fi; false'
saveenv
reset
U-Boot will:
- Power on via USB OTG
- Wait ~2s for Pi Zero to stabilize
- Attempt
usb start→usb storage - If USB device appears → load kernel/DTB → boot
- If timeout → retry or fall back to TFTP
Mass Storage Boot (Active Slot)
Quick Check: USB Enumeration
Enter U-Boot console and verify USB device is detected:
ESPRESSObin=> usb start
Starting USB Controller
USB XHCI 1.00
ESPRESSObin=> usb storage
Device 0: Vendor: QEMU Rev: 2.5+ Type: Removable Hard Disk
Capacity: 1024 MB = 1 GB (2097152 x 512)
ESPRESSObin=> usb tree
USB device tree:
1 XHCI 1.00
| 1 Hub: QEMU QEMU USB Storage Controller (product id 0x0070)
| | 1 Mass Storage: QEMU USB Storage (000010000000000000000000)
Boot Command: Active Slot
Set boot command to load kernel and DTB from mass storage:
ESPRESSObin=> setenv bootcmd 'usb start; usb storage; fatload usb 0 ${kernel_addr_r} Image; fatload usb 0 ${fdt_addr_r} armada-3720-espressobin.dtb; booti ${kernel_addr_r} - ${fdt_addr_r}'
ESPRESSObin=> setenv bootargs 'root=/dev/mmcblk0p2 rw rootwait console=ttyMV0,115200'
ESPRESSObin=> saveenv
Saving Environment to SPI Flash... OK
Explanation:
usb start— Initialize USB controllerusb storage— Detect USB storage devicefatload usb 0 ${kernel_addr_r} Image— Load kernel from USB LUN 0fatload usb 0 ${fdt_addr_r} armada-3720-espressobin.dtb— Load DTBbooti ${kernel_addr_r} - ${fdt_addr_r}— Boot with kernel atkernel_addr_r, no ramdisk, DTB atfdt_addr_rsaveenv— Persist to SPI NOR flash
Verify Boot Environment
List current environment variables:
ESPRESSObin=> printenv bootcmd
bootcmd=usb start; usb storage; fatload usb 0 ${kernel_addr_r} Image; fatload usb 0 ${fdt_addr_r} armada-3720-espressobin.dtb; booti ${kernel_addr_r} - ${fdt_addr_r}
ESPRESSObin=> printenv kernel_addr_r
kernel_addr_r=0x2000000
ESPRESSObin=> printenv fdt_addr_r
fdt_addr_r=0x1f00000
ESPRESSObin=> printenv bootargs
bootargs=root=/dev/mmcblk0p2 rw rootwait console=ttyMV0,115200
TFTP Boot (Shadow Slot)
Prerequisite: TFTP Server
Set up TFTP on Eye Remote or a separate machine:
# Eye Remote (10.55.0.2) or host on 10.55.0.0/30 network
mkdir -p /srv/tftp
cp Image /srv/tftp/
cp armada-3720-espressobin.dtb /srv/tftp/
# Start dnsmasq or in.tftpd listening on 10.55.0.2:69
systemctl restart dnsmasq
# or
systemctl restart tftpd-hpa
Boot Command: Shadow Slot
Configure TFTP boot for failover scenarios:
ESPRESSObin=> setenv serverip 10.55.0.2
ESPRESSObin=> setenv bootcmd 'usb start; if usb storage; then fatload usb 0 ${kernel_addr_r} Image && fatload usb 0 ${fdt_addr_r} armada-3720-espressobin.dtb && booti ${kernel_addr_r} - ${fdt_addr_r}; else tftp ${kernel_addr_r} Image && tftp ${fdt_addr_r} armada-3720-espressobin.dtb && booti ${kernel_addr_r} - ${fdt_addr_r}; fi'
ESPRESSObin=> saveenv
Logic:
- Try USB mass storage boot (active slot)
- If USB fails or times out → TFTP boot (shadow slot)
- Either way, boot the kernel + DTB combination
Direct TFTP Boot (No Fallback)
For testing the TFTP shadow channel in isolation:
ESPRESSObin=> setenv serverip 10.55.0.2
ESPRESSObin=> tftp ${kernel_addr_r} Image
Using usb_ether device
TFTP from server 10.55.0.2; our IP address is 10.55.0.1
Filename 'Image'.
Load address: 0x2000000
Loading: #################################################################
1234 Bytes/s
done
Bytes transferred = 16384000 (fa80000 in hex)
ESPRESSObin=> tftp ${fdt_addr_r} armada-3720-espressobin.dtb
Using usb_ether device
TFTP from server 10.55.0.2; our IP address is 10.55.0.1
Filename 'armada-3720-espressobin.dtb'.
Load address: 0x1f00000
Loading: #
done
Bytes transferred = 32768 (8000 in hex)
ESPRESSObin=> booti ${kernel_addr_r} - ${fdt_addr_r}
Workflow: Test Then Promote
Phase 1: Upload to TFTP (Shadow)
- Build new kernel and DTB on development machine
- Copy to TFTP server at
/srv/tftp/scp Image root@10.55.0.2:/srv/tftp/ scp armada-3720-espressobin.dtb root@10.55.0.2:/srv/tftp/
Phase 2: Test via TFTP (Shadow Boot)
- Interrupt U-Boot at prompt
- Clear USB first (in case old device present):
ESPRESSObin=> usb reset - Boot via TFTP:
ESPRESSObin=> setenv serverip 10.55.0.2 ESPRESSObin=> tftp ${kernel_addr_r} Image ESPRESSObin=> tftp ${fdt_addr_r} armada-3720-espressobin.dtb ESPRESSObin=> booti ${kernel_addr_r} - ${fdt_addr_r}
Phase 3: Verify Boot Success
Once kernel boots, verify via SSH:
ssh root@10.55.0.1
# Verify kernel version, modules, etc.
uname -a
Phase 4: Promote to Active Slot (USB Mass Storage)
Once TFTP boot is verified:
-
Copy files to Eye Remote mass storage
scp Image root@10.55.0.2:/mnt/usb/boot/ scp armada-3720-espressobin.dtb root@10.55.0.2:/mnt/usb/boot/ -
Update U-Boot bootcmd to use USB:
ESPRESSObin=> setenv bootcmd 'usb start; usb storage; fatload usb 0 ${kernel_addr_r} Image; fatload usb 0 ${fdt_addr_r} armada-3720-espressobin.dtb; booti ${kernel_addr_r} - ${fdt_addr_r}' ESPRESSObin=> saveenv -
Reset and verify USB boot:
ESPRESSObin=> reset
Troubleshooting
Issue: "No USB storage device(s) found"
Cause: Pi Zero not detected or not in host mode.
Diagnosis:
ESPRESSObin=> usb start
Starting USB Controller
USB XHCI 1.00
ESPRESSObin=> usb tree
USB device tree:
1 XHCI 1.00
1 Hub: QEMU QEMU USB Storage Controller (product id 0x0070)
(nothing under hub — no device)
Solutions:
-
Check Pi Zero power: Verify 5V applied to Pi Zero micro-USB port
# On Pi Zero: vcgencmd get_throttled # Should be 0x0 (no throttle) -
Check USB cable: Swap cable, verify all connections
# On Pi Zero: lsusb # Should show usb_ethernet module loaded lsmod | grep g_ether -
Restart U-Boot retry loop: Reset both devices
ESPRESSObin=> reset -
Check Eye Remote ECM driver: On Pi Zero, verify interface is up
ip link show usb0 # Should be "UP"
Issue: "Unable to read file Image"
Cause: File not found on mass storage, or incorrect filename.
Diagnosis:
ESPRESSObin=> usb storage
ESPRESSObin=> fatls usb 0
(no files listed, or different names)
Solutions:
-
Verify file exists on Eye Remote:
ls -lh /mnt/usb/boot/Image -
Check FAT filesystem:
mount | grep usb0 fsck.vfat -v /dev/sda1 -
Verify filename case: U-Boot FAT driver is case-sensitive
ESPRESSObin=> fatls usb 0 # Should show "Image" (capital I) -
Recreate boot partition if corrupted:
mkfs.vfat -F 32 /dev/sda1 mkdir -p /mnt/usb/boot mount /dev/sda1 /mnt/usb/boot cp Image armada-3720-espressobin.dtb /mnt/usb/boot/ umount /mnt/usb/boot
Issue: TFTP Timeout
Cause: Network unreachable, TFTP server down, or firewall blocking.
Diagnosis:
ESPRESSObin=> setenv serverip 10.55.0.2
ESPRESSObin=> tftp ${kernel_addr_r} Image
Using usb_ether device
TFTP from server 10.55.0.2; our IP address is 10.55.0.1
Filename 'Image'.
Load address: 0x2000000
Waiting for ethernet device... timeout!
Solutions:
-
Verify network connectivity:
# On Pi Zero or test host ping 10.55.0.1 # Should succeed -
Check TFTP server is running:
systemctl status dnsmasq # or tftpd-hpa netstat -uln | grep :69 # TFTP port -
Verify firewall allows TFTP:
ufw allow 69/udp # or nftables nft add rule inet filter input udp dport 69 accept -
Test TFTP connectivity manually:
# On test host on 10.55.0.0/30 network echo "test" > /srv/tftp/test.txt tftp 10.55.0.2 > get test.txt -
Set TFTP timeout in U-Boot:
ESPRESSObin=> setenv netretry 5 ESPRESSObin=> saveenv
Issue: Kernel Loads but Won't Boot
Symptoms: Files load successfully, but kernel crashes or hangs.
Diagnosis:
ESPRESSObin=> booti ${kernel_addr_r} - ${fdt_addr_r}
## Flattened Device Tree blob at 1f00000
## Kernel loaded from 0x02000000
## Loading Device Tree to 27f00000, end 27f08000 ... OK
## Booting using the fdt blob at 0x27f00000
(hangs here)
Solutions:
-
Verify DTB matches kernel version:
file armada-3720-espressobin.dtb # Should show "Device Tree Blob" -
Check kernel bootargs:
ESPRESSObin=> printenv bootargs # Verify root= device exists -
Enable serial console on kernel side:
ESPRESSObin=> setenv bootargs 'root=/dev/mmcblk0p2 rw rootwait console=ttyMV0,115200 earlyprintk' ESPRESSObin=> saveenv -
Rebuild kernel with proper config:
# Ensure CONFIG_SERIAL_MVEBU_UART=y in kernel .config make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ mvebu_v7_defconfig
Environment Variable Reference
| Variable | Default | Purpose |
|---|---|---|
bootcmd |
varies | Command executed at boot |
bootargs |
varies | Kernel boot arguments (root, console, etc.) |
kernel_addr_r |
0x2000000 | DRAM address for kernel load |
fdt_addr_r |
0x1f00000 | DRAM address for DTB load |
ramdisk_addr_r |
varies | DRAM address for ramdisk (if used) |
serverip |
10.55.0.2 | TFTP server IP |
ipaddr |
10.55.0.1 | ESPRESSObin IP (USB OTG) |
netmask |
255.255.255.252 | Network mask for USB OTG link |
netretry |
1 | TFTP retry count |
To view all:
ESPRESSObin=> printenv
To save any change:
ESPRESSObin=> saveenv
See Also
docs/eye-remote/usb-otg-ecm-mode.md— USB OTG ECM setup on Pi Zerodocs/eye-remote/mass-storage-lun.md— Exposing mass storage LUNdocs/eye-remote/network-setup.md— 10.55.0.0/30 network config- U-Boot Armada 3720 documentation: https://u-boot.readthedocs.io/
- ESPRESSObin Quick Start: https://espressobin.docs.globalscale.com/
Examples
Full Bootcmd with Fallback
Active slot (USB) with fallback to shadow slot (TFTP):
setenv bootcmd 'usb start; if usb storage; then echo "Booting from USB..."; fatload usb 0 ${kernel_addr_r} Image && fatload usb 0 ${fdt_addr_r} armada-3720-espressobin.dtb && booti ${kernel_addr_r} - ${fdt_addr_r}; else echo "USB boot failed, trying TFTP..."; tftp ${kernel_addr_r} Image && tftp ${fdt_addr_r} armada-3720-espressobin.dtb && booti ${kernel_addr_r} - ${fdt_addr_r}; fi'
setenv bootargs 'root=/dev/mmcblk0p2 rw rootwait console=ttyMV0,115200'
saveenv
reset
Development Iteration (TFTP Only)
For rapid kernel development, stay on TFTP:
setenv bootcmd 'usb reset; setenv serverip 10.55.0.2; tftp ${kernel_addr_r} Image && tftp ${fdt_addr_r} armada-3720-espressobin.dtb && booti ${kernel_addr_r} - ${fdt_addr_r}'
setenv bootargs 'root=/dev/mmcblk0p2 rw rootwait console=ttyMV0,115200 earlyprintk'
saveenv
reset
Author: CyberMind — Gérald Kerma License: Proprietary / ANSSI CSPN candidate Last Updated: 2024