Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

batch-uf2

Watches for a UF2 bootloader drive to appear, copies a firmware file to it, waits for the device to reset and disappear, then goes back to waiting. Repeats until you cancel it.

No drag-and-drop for every device! Just run the script, plug a board in, it flashes, unplug it, plug the next one in.

Why you'd want this

Built for short production runs: batch-programming a stack of boards with the same firmware, where you want to plug, wait for the LED/prompt, unplug, and immediately plug the next one in without touching a file browser or a keyboard each time.

Also useful for:

  • Bench iteration where you rebuild and reflash the same board repeatedly during development.
  • Test-jig or panel-testing workflows where a free hand and no GUI interaction matters.

How it works

  1. Polls for a removable volume with the target label (default RPI-RP2).
  2. Confirms it's actually the expected device, not just something else that happens to share the label, by checking the underlying device's USB vendor:product ID against a known list, and that the filesystem is what's expected. If it doesn't match, the volume is ignored and the script keeps waiting.
  3. Copies the nominated file across.
  4. Waits for the device to disappear. UF2 bootloaders reset themselves once the file lands, which unmounts the drive.
  5. Repeats from step 1.

Ctrl+C exits cleanly at any point in the loop.

Workflow: run the script once, then plug boards in one after another — each is verified, flashed, and ejected automatically until you press Ctrl+C

Supported platforms

Three independent, single-file scripts, no shared library between them. Copy the one for your OS.

File Platform Status
batch-uf2 Linux ✅ Tested and working
batch-uf2-macos macOS ⚠️ Needs further testing
batch-uf2.ps1 Windows (PowerShell) ⚠️ Needs further testing

Out of the box, all three are configured for RP2040 and RP2350 (Raspberry Pi Pico / Pico 2 and boards built on those chips) in BOOTSEL mode. See Adding target devices to point it at something else.

Requirements

  • Linux: bash, findmnt, lsblk, udevadm. All standard on any systemd-based distro (Ubuntu, Mint, Debian, Fedora, etc).
  • macOS: bash and system_profiler, both ship with macOS. This variant is the least tested of the three, see Known limitations.
  • Windows: PowerShell 5.1 or later (ships with Windows 10/11), the in-box PnpDevice module.

Usage

Linux

chmod +x batch-uf2
./batch-uf2 /path/to/firmware.uf2

To make it available everywhere:

sudo cp batch-uf2 /usr/local/bin/
sudo chmod +x /usr/local/bin/batch-uf2
batch-uf2 /path/to/firmware.uf2

macOS

chmod +x batch-uf2-macos
./batch-uf2-macos /path/to/firmware.uf2

Windows

.\batch-uf2.ps1 -FirmwarePath C:\path\to\firmware.uf2

If script execution is blocked, allow it for the current session only:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

All platforms

Leave it running and connect boards one after another. Press Ctrl+C to stop.

Adding target devices

Every variant is driven by two settings near the top of the file:

  • Volume label — the name the drive mounts under. Linux/macOS: LABEL. Windows: $Label.
  • Known boot IDs — an allowlist of accepted USB vendor:product ID pairs. Linux/macOS: KNOWN_BOOT_IDS, a bash array of "vid:pid" strings (lowercase hex, no 0x). Windows: $KnownBootIds, an array of "VID_xxxx&PID_xxxx" strings.

To target a different UF2 board:

  1. Put it into its bootloader mode and note the volume name it mounts as. That's your new LABEL / $Label (or add a second label check if you need to support two different boards, the current scripts assume one label at a time).
  2. Find its USB vendor and product ID:
    • Linux: lsusb while it's connected, or udevadm info -a -p $(udevadm info -q path -n /dev/sdX) for the exact attributes the script reads.
    • macOS: system_profiler SPUSBDataType while it's connected, look for Vendor ID: and Product ID: under the device's entry.
    • Windows: Device Manager → the disk drive's Properties → Details → Hardware Ids, or Get-PnpDevice -Class DiskDrive | Select-Object InstanceId.
  3. Add the pair to KNOWN_BOOT_IDS / $KnownBootIds in the matching format for that platform.

Boards from the same vendor with a different chip (like RP2040 → RP2350) usually just need a new product ID added alongside the existing ones. A board from an entirely different vendor needs its own full vendor:product pair, since the list holds complete pairs rather than a fixed vendor ID, adding one doesn't affect matching for any other entry.

Known limitations

  • The vendor:product ID check protects against a coincidental label collision (some unrelated drive happens to be named the same thing).
  • The macOS variant parses system_profiler's text output for the USB device fields. It hasn't been verified against a real Mac. If the guardrail doesn't seem to trigger, run system_profiler SPUSBDataType | grep -B8 "<your label>" and check the field names in the script's get_usb_ids function still match.
  • The Windows variant walks up to four levels of the PnP device tree looking for the vendor:product ID. That covers the layouts this normally takes, but hasn't been verified against real hardware either. If it's not matching, check Get-PnpDevice -Class DiskDrive | Select-Object InstanceId against what Test-IsRP2Drive is walking.
  • One nominated file per run. The script doesn't inspect the connected board and pick firmware for it, thought that might be possible if you point it at a wrapper script instead of a raw .uf2.

About

A CLI tool for batch programming UF2 bootloader devices like RP2040, RP2350

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages