Skip to content

Instantly share code, notes, and snippets.

@deadprogram
Last active March 27, 2026 10:53
Show Gist options
  • Select an option

  • Save deadprogram/d779c6f4c5e1007dc6f4f6d23c506a3f to your computer and use it in GitHub Desktop.

Select an option

Save deadprogram/d779c6f4c5e1007dc6f4f6d23c506a3f to your computer and use it in GitHub Desktop.
Flashing Arduino UNO Q from your local computer via ADB or SSH

Flashing the Arduino UNO Q - Bare Metal

Here are some helpful scripts to flash bare-metal .HEX files from your computer to an Arduino UNO Q board that is connected either via Android Debug Bridge (adb) or via SSH.

adb

adb is useful for when you want to connect the Arduino UNO Q directly to your computer without a monitor or keyboard.

You can install the adb command line tool for your platform here: https://developer.android.com/tools/releases/platform-tools

macOS/Linux

./flash_arduino_unoq_adb.sh build/firmware.hex

Windows

.\flash_arduino_unoq_adb.ps1 -LocalHexFile "build\firmware.hex"

ssh

ssh is useful for when you want to connect to an Arduino UNO Q that is already on a network.

Make sure to edit TARGET_HOST="192.168.1.100" to match your device's IP.

If you haven't set up SSH keys, this script will prompt you for the arduino user's password multiple times (once for every ssh and scp command). To avoid this, set up SSH keys by running ssh-copy-id arduino@<target_ip> on your local machine first.

macOS/Linux

./flash_arduino_unoq_ssh.sh build/firmware.hex

Windows

./flash_arduino_unoq_ssh.sh build/firmware.hex
<#
.SYNOPSIS
Flashes firmware to the target via adb and openocd.
.DESCRIPTION
This script stops the arduino-router service, ensures the SWD configuration
file is present on the target, uploads the specified .hex firmware file,
and then invokes OpenOCD to flash the firmware.
.PARAMETER LocalHexFile
The local path to the firmware .hex file to be uploaded and flashed.
#>
param (
[Parameter(Mandatory=$true, HelpMessage="Path to the firmware .hex file")]
[string]$LocalHexFile
)
# Configuration Variables
$HexFilename = Split-Path -Leaf $LocalHexFile
$TargetHexPath = "/home/arduino/$HexFilename"
$LocalCfgFile = "QRB2210_swd.cfg"
$TargetCfgPath = "/home/arduino/$LocalCfgFile"
# 1. Stop the arduino-router service
Write-Host "Stopping arduino-router..." -ForegroundColor Cyan
adb shell "sudo systemctl stop arduino-router"
# 2 & 3. Check if QRB2210_swd.cfg exists, and upload if it doesn't
Write-Host "Checking for $TargetCfgPath on target..." -ForegroundColor Cyan
# Run 'test -f' on the target. If it exits with 0, the file exists.
adb shell "test -f $TargetCfgPath"
if ($LASTEXITCODE -ne 0) {
Write-Host "Configuration file not found on target. Uploading..." -ForegroundColor Yellow
if (-not (Test-Path $LocalCfgFile)) {
Write-Error "Error: Local file '$LocalCfgFile' not found. Please place it in the current directory."
exit 1
}
adb push $LocalCfgFile $TargetCfgPath
} else {
Write-Host "Configuration file already exists on target." -ForegroundColor Green
}
# 4. Upload the .hex file
Write-Host "Uploading firmware '$HexFilename'..." -ForegroundColor Cyan
adb push $LocalHexFile $TargetHexPath
if ($LASTEXITCODE -ne 0) {
Write-Error "Error: Failed to upload $LocalHexFile"
exit 1
}
# 5. Run the OpenOCD command on the target to program the firmware
Write-Host "Flashing firmware..." -ForegroundColor Cyan
# Use single quotes for the inner command argument to prevent PowerShell from confusing adb's string parsing
$OpenOcdCmd = "/opt/openocd/bin/openocd -s /opt/openocd/share/openocd/scripts -s /opt/openocd -f $TargetCfgPath -f /opt/openocd/stm32u5x.cfg -c 'program $TargetHexPath verify reset exit'"
adb shell $OpenOcdCmd
Write-Host "Done!" -ForegroundColor Green
#!/bin/bash
# Ensure a hex file argument was provided
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <path_to_firmware.hex>"
exit 1
fi
LOCAL_HEX_FILE="$1"
HEX_FILENAME=$(basename "$LOCAL_HEX_FILE")
TARGET_HEX_PATH="/home/arduino/$HEX_FILENAME"
LOCAL_CFG_FILE="QRB2210_swd.cfg"
TARGET_CFG_PATH="/home/arduino/$LOCAL_CFG_FILE"
# 1. Stop the arduino-router service
echo "Stopping arduino-router..."
adb shell "sudo systemctl stop arduino-router"
# 2 & 3. Check if QRB2210_swd.cfg exists, and upload if it doesn't
echo "Checking for $TARGET_CFG_PATH on target..."
if adb shell "[ ! -f $TARGET_CFG_PATH ]"; then
echo "Configuration file not found on target. Uploading..."
if [ ! -f "$LOCAL_CFG_FILE" ]; then
echo "Error: Local file '$LOCAL_CFG_FILE' not found. Please place it in the current directory."
exit 1
fi
adb push "$LOCAL_CFG_FILE" "$TARGET_CFG_PATH"
else
echo "Configuration file already exists on target."
fi
# 4. Upload the .hex file
echo "Uploading firmware '$HEX_FILENAME'..."
if ! adb push "$LOCAL_HEX_FILE" "$TARGET_HEX_PATH"; then
echo "Error: Failed to upload $LOCAL_HEX_FILE"
exit 1
fi
# 5. Run the OpenOCD command on the target to program the firmware
echo "Flashing firmware..."
adb shell "/opt/openocd/bin/openocd -s /opt/openocd/share/openocd/scripts -s /opt/openocd -f $TARGET_CFG_PATH -f /opt/openocd/stm32u5x.cfg -c \"program $TARGET_HEX_PATH verify reset exit\""
echo "Done!"
<#
.SYNOPSIS
Flashes firmware to the target via ssh and scp.
.DESCRIPTION
This script safely copies a .hex file, checks for the necessary openocd config,
stops the router, and flashes the target via openocd.
.PARAMETER LocalHexFile
The local path to the firmware .hex file to be uploaded and flashed.
#>
param (
[Parameter(Mandatory=$true, HelpMessage="Path to the firmware .hex file")]
[string]$LocalHexFile
)
# --- Configure your target device here ---
$TargetUser = "arduino"
$TargetHost = "192.168.1.159" # Change this to your target's actual IP or hostname
# -----------------------------------------
$Target = "$TargetUser@$TargetHost"
# File path configurations
$HexFilename = Split-Path -Leaf $LocalHexFile
$TargetHexPath = "/home/arduino/$HexFilename"
$LocalCfgFile = "QRB2210_swd.cfg"
$TargetCfgPath = "/home/arduino/$LocalCfgFile"
# 1. Stop the arduino-router service
Write-Host "Stopping arduino-router on $TargetHost..." -ForegroundColor Cyan
ssh -o PreferredAuthentications=password -o PasswordAuthentication=yes $Target "sudo systemctl stop arduino-router"
# 2 & 3. Check if QRB2210_swd.cfg exists, and upload if it doesn't
Write-Host "Checking for $TargetCfgPath on target..." -ForegroundColor Cyan
# Check using 'test -f'
ssh -o PreferredAuthentications=password -o PasswordAuthentication=yes $Target "test -f $TargetCfgPath"
if ($LASTEXITCODE -ne 0) {
Write-Host "Configuration file not found on target. Uploading..." -ForegroundColor Yellow
if (-not (Test-Path $LocalCfgFile)) {
Write-Error "Error: Local file '$LocalCfgFile' not found. Please place it in the current directory."
exit 1
}
# Using ${Target}:${TargetCfgPath} prevents PowerShell from misinterpreting the colon
scp -o PreferredAuthentications=password -o PasswordAuthentication=yes $LocalCfgFile "${Target}:${TargetCfgPath}"
} else {
Write-Host "Configuration file already exists on target." -ForegroundColor Green
}
# 4. Upload the .hex file
Write-Host "Uploading firmware '$HexFilename'..." -ForegroundColor Cyan
scp -o PreferredAuthentications=password -o PasswordAuthentication=yes $LocalHexFile "${Target}:${TargetHexPath}"
if ($LASTEXITCODE -ne 0) {
Write-Error "Error: Failed to upload $LocalHexFile"
exit 1
}
# 5. Run the OpenOCD command on the target to program the firmware
Write-Host "Flashing firmware..." -ForegroundColor Cyan
# Build the command using single quotes for the inner OpenOCD argument
$OpenOcdCmd = "/opt/openocd/bin/openocd -s /opt/openocd/share/openocd/scripts -s /opt/openocd -f $TargetCfgPath -f /opt/openocd/stm32u5x.cfg -c 'program $TargetHexPath verify reset exit'"
ssh -o PreferredAuthentications=password -o PasswordAuthentication=yes $Target $OpenOcdCmd
Write-Host "Done!" -ForegroundColor Green
#!/bin/bash
# --- Configure your target device here ---
TARGET_USER="arduino"
TARGET_HOST="192.168.1.159" # Change this to your target's actual IP or hostname
# -----------------------------------------
TARGET="$TARGET_USER@$TARGET_HOST"
ALLOW_SSH_AUTH_WITH_PASSWORD="-o PreferredAuthentications=password -o PasswordAuthentication=yes"
# Ensure a hex file argument was provided
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <path_to_firmware.hex>"
exit 1
fi
LOCAL_HEX_FILE="$1"
HEX_FILENAME=$(basename "$LOCAL_HEX_FILE")
TARGET_HEX_PATH="/home/arduino/$HEX_FILENAME"
LOCAL_CFG_FILE="QRB2210_swd.cfg"
TARGET_CFG_PATH="/home/arduino/$LOCAL_CFG_FILE"
# 1. Stop the arduino-router service
echo "Stopping arduino-router on $TARGET_HOST..."
ssh "$TARGET" $ALLOW_SSH_AUTH_WITH_PASSWORD "sudo systemctl stop arduino-router"
# 2 & 3. Check if QRB2210_swd.cfg exists, and upload if it doesn't
echo "Checking for $TARGET_CFG_PATH on target..."
if ssh "$TARGET" $ALLOW_SSH_AUTH_WITH_PASSWORD "[ ! -f $TARGET_CFG_PATH ]"; then
echo "Configuration file not found on target. Uploading..."
if [ ! -f "$LOCAL_CFG_FILE" ]; then
echo "Error: Local file '$LOCAL_CFG_FILE' not found. Please place it in the current directory."
exit 1
fi
scp $ALLOW_SSH_AUTH_WITH_PASSWORD "$LOCAL_CFG_FILE" "$TARGET:$TARGET_CFG_PATH"
else
echo "Configuration file already exists on target."
fi
# 4. Upload the .hex file
echo "Uploading firmware '$HEX_FILENAME'..."
if ! scp $ALLOW_SSH_AUTH_WITH_PASSWORD "$LOCAL_HEX_FILE" "$TARGET:$TARGET_HEX_PATH"; then
echo "Error: Failed to upload $LOCAL_HEX_FILE"
exit 1
fi
# 5. Run the OpenOCD command on the target to program the firmware
echo "Flashing firmware..."
ssh "$TARGET" $ALLOW_SSH_AUTH_WITH_PASSWORD "/opt/openocd/bin/openocd -s /opt/openocd/share/openocd/scripts -s /opt/openocd -f $TARGET_CFG_PATH -f /opt/openocd/stm32u5x.cfg -c \"program $TARGET_HEX_PATH verify reset exit\""
echo "Done!"
adapter driver linuxgpiod
adapter gpio swclk -chip 1 26
adapter gpio swdio -chip 1 25
adapter gpio srst -chip 1 38
transport select swd
adapter speed 1000
reset_config srst_only srst_push_pull
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment