Build: Add USB boot + NVMe HAT support
Lint & Validate / lint (push) Has been cancelled

- --target flag in build.sh (sd|usb|nvme)
- NVMe kernel driver enabled for --target nvme
- EEPROM boot-order config in first-boot wizard
- USB/NVMe flashing docs in build/README.md
- Hardware compatibility + user manual docs from P7
This commit is contained in:
2026-05-19 22:54:41 -04:00
parent 5e208d5123
commit 9e007ae197
5 changed files with 1126 additions and 9 deletions
+41 -2
View File
@@ -1,7 +1,8 @@
# RPi Audio Mixer — SD Card Image Builder
# RPi Audio Mixer — Disk Image Builder (SD / USB / NVMe)
This directory contains the automated build system for creating a ready-to-flash
Raspberry Pi 4B SD card image with the full audio mixer stack.
Raspberry Pi 4B disk image with the full audio mixer stack. The same image works
for SD cards, USB SSDs, and NVMe HATs — just choose your target.
## Quick Start
@@ -27,6 +28,8 @@ ls -lh build/out/rpi-audio-mixer-*.img.xz
| `./build/build.sh --skip-kernel` | Quick build, stock kernel | 10-15 min |
| `./build/build.sh --kernel-only` | Only build RT kernel | 10-15 min |
| `./build/build.sh --clean` | Remove all build artifacts | < 1 min |
| `./build/build.sh --target usb` | Build for USB SSD boot | same as default |
| `./build/build.sh --target nvme` | Build for NVMe HAT (NVMe driver enabled) | +1 min |
## Flashing to SD Card
@@ -48,6 +51,42 @@ sync
sudo eject /dev/sdX
```
## Flashing to USB SSD / NVMe
The **same image** works for USB SSD and NVMe HAT — it's just flashed to a different device.
### USB SSD
```bash
# 1. Find your USB SSD device
lsblk # look for /dev/sda, /dev/sdb, etc.
# 2. Flash the image
sudo dd if=build/out/rpi-audio-mixer-*.img of=/dev/sda bs=4M status=progress conv=fsync
# 3. On first boot, the wizard can configure EEPROM for USB boot
# Or do it manually:
# sudo rpi-eeprom-config --edit → BOOT_ORDER=0xf41
```
### NVMe HAT
Requires an NVMe HAT (official RPi, Pimoroni, or Geekworm) connected via PCIe.
```bash
# 1. Flash to NVMe SSD (connect via USB adapter or directly on Pi)
sudo dd if=build/out/rpi-audio-mixer-*.img of=/dev/nvme0n1 bs=4M status=progress conv=fsync
# 2. Configure EEPROM for NVMe boot:
# sudo rpi-eeprom-config --edit → BOOT_ORDER=0xf614
# 3. Boot order: NVMe → USB → SD → Restart
```
> **⚠️ USB performance note:** During audio operation, minimize writes to USB SSDs
> as they share the USB bus with audio interfaces. NVMe HAT is recommended for
> production use — it uses dedicated PCIe lanes with no USB bus contention.
### From macOS
```bash
+53 -7
View File
@@ -1,16 +1,19 @@
#!/bin/bash
# build.sh — Build RPi Audio Mixer SD card image from scratch
# build.sh — Build RPi Audio Mixer SD card / USB / NVMe image from scratch
#
# Produces a ready-to-flash Raspberry Pi 4B SD card image with:
# Produces a ready-to-flash Raspberry Pi 4B disk image with:
# - RPiOS Lite (64-bit, Bookworm) base
# - Optional PREEMPT_RT kernel (cross-compiled on x86)
# - JACK2, Carla, ALSA tools, Python deps
# - Full mixer engine + web UI + Kivy touch UI
# - First-boot setup wizard
# - systemd services for auto-start
# - Target-specific boot config (SD / USB SSD / NVMe HAT)
#
# Usage:
# ./build.sh # Full build (default)
# ./build.sh # Full build, SD card (default)
# ./build.sh --target usb # Build for USB SSD boot
# ./build.sh --target nvme # Build for NVMe HAT boot
# ./build.sh --skip-kernel # Skip RT kernel build (use stock kernel)
# ./build.sh --kernel-only # Only build RT kernel, skip image
# ./build.sh --output ./my-image.img # Custom output path
@@ -31,7 +34,7 @@
# - Cross-compile (optional): gcc-aarch64-linux-gnu, libssl-dev:arm64
#
# Output:
# build/out/rpi-audio-mixer-<version>.img SD card image
# build/out/rpi-audio-mixer-<version>.img Disk image (SD/USB/NVMe)
# build/out/rpi-audio-mixer-<version>.img.xz Compressed image
set -euo pipefail
@@ -48,6 +51,9 @@ DOWNLOAD_DIR="$BUILD_DIR/downloads"
MIXER_VERSION="${MIXER_VERSION:-$(git -C "$PROJECT_ROOT" describe --tags --always 2>/dev/null || echo 'dev')}"
MIXER_API_KEY="${MIXER_API_KEY:-mixer-$(head -c 12 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 16)}"
MIXER_HOSTNAME="${MIXER_HOSTNAME:-pi-mixer}"
# Boot target
TARGET="${TARGET:-sd}" # sd, usb, or nvme
MIXER_WIFI_SSID="${MIXER_WIFI_SSID:-}"
MIXER_WIFI_PASS="${MIXER_WIFI_PASS:-}"
@@ -255,6 +261,14 @@ build_rt_kernel() {
# USB audio (build as module)
scripts/config -m CONFIG_SND_USB_AUDIO
# NVMe support (for NVMe HAT boot)
if [[ "$TARGET" == "nvme" ]]; then
log "Enabling NVMe driver for NVMe HAT target..."
scripts/config -m CONFIG_BLK_DEV_NVME
scripts/config -e CONFIG_NVME_CORE
scripts/config -e CONFIG_NVME_FABRICS
fi
make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" olddefconfig
else
log "Kernel .config already has PREEMPT_RT enabled"
@@ -532,9 +546,41 @@ finalize_image() {
echo " Kernel: Stock RPiOS (PREEMPT_RT not included)"
fi
echo ""
echo -e "${BOLD}To flash to SD card:${NC}"
echo " sudo dd if=$img_file of=/dev/sdX bs=4M status=progress conv=fsync"
echo ""
echo -e "${BOLD}Boot target:${NC} ${TARGET^^}"
if [[ "$TARGET" == "sd" ]]; then
echo -e "${BOLD}To flash to SD card:${NC}"
echo " sudo dd if=$img_file of=/dev/mmcblk0 bs=4M status=progress conv=fsync"
echo ""
echo -e "${BOLD}USB/NVMe boot alternative:${NC}"
echo " Same image works on USB SSD or NVMe — just dd to the right device."
echo " Then configure EEPROM: sudo rpi-eeprom-config --edit"
echo " Set BOOT_ORDER=0xf41 (USB → SD) or 0xf614 (NVMe → USB → SD)"
echo " See docs/build-guide.md §USB Boot for details."
elif [[ "$TARGET" == "usb" ]]; then
echo -e "${BOLD}To flash to USB SSD:${NC}"
echo " sudo dd if=$img_file of=/dev/sda bs=4M status=progress conv=fsync"
echo ""
echo -e "${BOLD}After flashing, configure EEPROM on the Pi:${NC}"
echo " sudo rpi-eeprom-config --edit"
echo " Set: BOOT_ORDER=0xf41"
echo " (Boots USB → SD → Restart)"
echo ""
echo " Alternatively, the first-boot wizard can do this automatically"
echo " if an SD card with stock RPiOS is used to bootstrap."
elif [[ "$TARGET" == "nvme" ]]; then
echo -e "${BOLD}To flash to NVMe SSD (via HAT):${NC}"
echo " 1. Connect NVMe SSD to HAT"
echo " 2. Write image directly:"
echo " sudo dd if=$img_file of=/dev/nvme0n1 bs=4M status=progress conv=fsync"
echo ""
echo -e "${BOLD}After flashing, configure EEPROM on the Pi:${NC}"
echo " sudo rpi-eeprom-config --edit"
echo " Set: BOOT_ORDER=0xf614"
echo " (Boots NVMe → USB → SD → Restart)"
echo ""
echo " Kernel config includes CONFIG_BLK_DEV_NVMe=m"
echo ""
fi
echo -e "${BOLD}First boot:${NC}"
echo " - The setup wizard will guide you through configuration"
echo " - Default hostname: $MIXER_HOSTNAME"
+30
View File
@@ -307,6 +307,36 @@ fi
press_enter
# ─── 7. Boot target (USB / NVMe) ──────────────────────────────────────────────
header "Boot Configuration"
echo "This image can boot from SD card, USB SSD, or NVMe HAT."
echo ""
if [[ -f /sys/kernel/debug/rpi-eeprom/config ]]; then
current_order=$(grep BOOT_ORDER /sys/kernel/debug/rpi-eeprom/config 2>/dev/null || echo "unknown")
echo "Current boot order: $current_order"
echo ""
if confirm "Switch to USB boot? (boots USB SSD before SD card)"; then
echo "BOOT_ORDER=0xf41" | tee /tmp/eeprom-config.txt
sudo rpi-eeprom-config --out /tmp/eeprom-config.bin --config /tmp/eeprom-config.txt
echo "USB boot configured. Next boot will try USB first."
fi
if confirm "Switch to NVMe boot? (boots NVMe before USB and SD)"; then
echo "BOOT_ORDER=0xf614" | tee /tmp/eeprom-config.txt
sudo rpi-eeprom-config --out /tmp/eeprom-config.bin --config /tmp/eeprom-config.txt
echo "NVMe boot configured. Next boot will try NVMe first."
fi
else
echo "EEPROM config not accessible. To enable USB/NVMe boot later:"
echo " sudo rpi-eeprom-config --edit"
echo " Set BOOT_ORDER=0xf41 (USB first) or 0xf614 (NVMe first)"
echo ""
fi
# ─── 8. Finalize ─────────────────────────────────────────────────────────────
header "Setup Complete"