description: Flash INAV firmware to flight controllers using DFU (Device Firmware Update) triggers:
- flash firmware
- flash dfu
- dfu flash
- flash flight controller
- flash hex file
- upload firmware
- dfu-util
- flash inav
Flashing INAV Firmware via DFU
IMPORTANT: Use the fc-flasher Agent
When this skill is invoked, you MUST immediately use the Task tool with subagent_type=fc-flasher.
The fc-flasher agent handles:
- Automatic settings backup and restore
- MSP reboot to DFU mode
- Hex to bin conversion
- DFU flashing
- Verification
Example:
User: "Flash inav_9.0.0_MATEKF405.hex"
Assistant: [Immediately calls Task tool with subagent_type=fc-flasher and the hex file path]
Do NOT use manual DFU steps unless the fc-flasher agent fails or you're troubleshooting.
Manual DFU Flashing (Troubleshooting Only)
The information below is for troubleshooting when the automated agent doesn't work.
Prerequisites
Install dfu-util:
# Ubuntu/Debian
sudo apt install dfu-util
# Fedora
sudo dnf install dfu-util
# Arch
sudo pacman -S dfu-util
# Or download from source
# http://sourceforge.net/p/dfu-util
You'll also need objcopy (part of binutils, usually pre-installed):
# If needed, install gcc-arm-none-eabi or binutils
sudo apt install binutils-arm-none-eabi # Ubuntu/Debian
Step 1: Put Flight Controller into DFU Mode
Choose ONE of the following methods:
Method A: Hardware Button
Press and hold the DFU/BOOT button on the board while plugging in USB.
Method B: Serial Command (Recommended: Use Helper Script)
Using the helper script (RECOMMENDED):
# Python version (requires pyserial)
.claude/skills/flash-firmware-dfu/reboot-to-dfu.py /dev/ttyACM0
# Install pyserial if needed:
pip3 install pyserial
Manual method (not recommended - race condition):
The correct sequence requires waiting for the actual CLI prompt, not just a fixed delay:
- Send
####\r\nto enter CLI mode - Read from serial and wait for "CLI" string in response (timeout: 2 seconds)
- Only after receiving CLI prompt: send
dfu\r\n - Disconnect
Why simple echo + sleep doesn't work:
# DON'T DO THIS - race condition!
echo -ne '####\r\n' > /dev/ttyACM0
sleep 0.25 # Wrong! Doesn't wait for actual CLI prompt
echo -ne 'dfu\r\n' > /dev/ttyACM0
This fails because:
- It blindly sleeps without checking if CLI is ready
- If the FC takes >250ms to respond, the
dfucommand is sent too early - The helper scripts properly wait for the "CLI" prompt before sending
dfu
Method C: CLI Command
Connect with INAV Configurator or serial terminal and type:
dfu
Method D: MSP Reboot Command (INAV 9.x+)
Using MSP to reboot to DFU (most reliable programmatic method):
# Using mspapi2
from mspapi2 import MSPSerial
serial = MSPSerial("/dev/ttyACM0", 115200)
serial.open()
# Send MSP_REBOOT (68) with DFU parameter (1)
code, payload = serial.request(68, b'\x01')
serial.close()
# Wait for reboot
import time
time.sleep(2)
This is the most reliable programmatic method because it:
- Doesn't require CLI prompt timing
- Works through the MSP protocol
- Is supported by configurator and tools
- Provides proper backwards compatibility
Parameter values:
b'\x00'or empty = normal rebootb'\x01'= reboot to DFU mode
Step 2: Verify DFU Mode
Check that the device is in DFU mode:
dfu-util -l
You should see a device with ID 0483:df11.
Step 3: Convert HEX to BIN
DFU requires binary format, so convert the .hex file:
cd inav/build
objcopy -I ihex inav_x.y.z_TARGETNAME.hex -O binary inav_x.y.z_TARGETNAME.bin
Example:
objcopy -I ihex inav_8.0.0_MATEKF405.hex -O binary inav_8.0.0_MATEKF405.bin
Step 4: Flash the Firmware
dfu-util -d 0483:df11 --alt 0 -s 0x08000000:force:leave -D inav_x.y.z_TARGETNAME.bin
Example:
dfu-util -d 0483:df11 --alt 0 -s 0x08000000:force:leave -D inav_8.0.0_MATEKF405.bin
Command Breakdown:
-d 0483:df11- Target device ID (STM32 DFU)--alt 0- Alternative setting (default flash memory)-s 0x08000000- Start address (STM32 flash base):force- Force write even if non-blank:leave- Exit DFU mode and run firmware after flashing-D <file>- Binary file to flash
Step 5: Verify
After flashing completes, the flight controller should automatically reboot and run the new firmware.
Connect with INAV Configurator to verify the version.
Complete Example Workflow
# 1. Build the firmware
cd inav/build
make MATEKF405
# 2. Put flight controller in DFU mode
# Option A: Hardware button (press BOOT button while plugging USB)
# Option B: Serial command (use helper script)
../.claude/skills/flash-firmware-dfu/reboot-to-dfu.py /dev/ttyACM0
# 3. Verify DFU mode
dfu-util -l
# 4. Convert hex to bin
objcopy -I ihex inav_8.0.0_MATEKF405.hex -O binary inav_8.0.0_MATEKF405.bin
# 5. Flash
dfu-util -d 0483:df11 --alt 0 -s 0x08000000:force:leave -D inav_8.0.0_MATEKF405.bin
Automated Script
For repeated flashing during development:
#!/bin/bash
# flash-firmware.sh
TARGET="MATEKF405"
SERIAL_PORT="/dev/ttyACM0"
HEX_FILE="inav_*.${TARGET}.hex"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Put FC into DFU mode using helper script
echo "Entering DFU mode..."
if ! $SCRIPT_DIR/.claude/skills/flash-firmware-dfu/reboot-to-dfu.py $SERIAL_PORT; then
echo "ERROR: Failed to enter DFU mode!"
exit 1
fi
# Note: Helper script already waits and verifies DFU mode
# Convert to bin
echo "Converting hex to bin..."
objcopy -I ihex $HEX_FILE -O binary ${HEX_FILE%.hex}.bin
# Flash
echo "Flashing firmware..."
dfu-util -d 0483:df11 --alt 0 -s 0x08000000:force:leave -D ${HEX_FILE%.hex}.bin
echo "Flash complete!"
Usage:
chmod +x flash-firmware.sh
./flash-firmware.sh
Troubleshooting
| Problem | Solution |
|---|---|
No DFU capable USB device found | Ensure board is in DFU mode, try different USB cable/port |
Permission denied | Add udev rules or use sudo |
Cannot open DFU device | Check that no other program is accessing the device |
| Flash succeeds but board doesn't boot | Wrong target or corrupted file - reflash |
| Hardware doesn't work after flashing (gyro not detected, etc.) | May be target configuration issue - use target-developer agent |
udev Rules (Avoid sudo)
Create /etc/udev/rules.d/45-stm32dfu.rules:
# STM32 DFU Bootloader
SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE="0664", GROUP="plugdev"
Then reload:
sudo udevadm control --reload-rules
sudo udevadm trigger
Add your user to the plugdev group:
sudo usermod -a -G plugdev $USER
Log out and back in for group changes to take effect.
Alternative Methods
INAV Configurator (GUI)
- Open INAV Configurator
- Click "Firmware Flasher"
- Select "Load Firmware [Local]"
- Browse to your
.hexfile - Click "Flash Firmware"
msp-tool (Command Line)
# Install msp-tool
go install github.com/fiam/msp-tool@latest
# Flash
msp-tool flash --port /dev/ttyACM0 inav_x.y.z_TARGETNAME.hex
flash.sh
Safety Notes
- ALWAYS verify you're flashing the correct target for your hardware
- Backup your settings using CLI
dumpcommand before flashing - Double-check file paths and target names
- Keep a known-good firmware hex file as backup
CLI Command Tools
This skill includes Python scripts for sending commands to the flight controller via CLI:
fc-cli.py - Modular CLI Command Tool
Send any CLI command to the flight controller:
# Show task execution times (useful for performance analysis)
.claude/skills/flash-firmware-dfu/fc-cli.py tasks
# Show firmware version
.claude/skills/flash-firmware-dfu/fc-cli.py version
# Show flight controller status
.claude/skills/flash-firmware-dfu/fc-cli.py status
# Reboot to DFU mode
.claude/skills/flash-firmware-dfu/fc-cli.py dfu
# Send any custom CLI command
.claude/skills/flash-firmware-dfu/fc-cli.py "get gyro_lpf1_static_hz"
# Specify custom serial port
.claude/skills/flash-firmware-dfu/fc-cli.py tasks /dev/ttyUSB0
Available built-in commands:
dfu- Reboot to DFU bootloader modetasks- Show task execution timesstatus- Show flight controller statusversion- Show firmware version- Any other CLI command - just pass it as an argument
How it works:
- Opens serial connection to flight controller
- Enters CLI mode by sending
####\r\n - Waits for "CLI" prompt (with timeout)
- Sends your command
- Reads and displays the response (except for
dfuwhich disconnects)
Adding new commands:
Edit fc-cli.py and add to the COMMANDS dictionary:
COMMANDS = {
'mycommand': {
'handler': lambda cli: cmd_generic(cli, 'mycommand'),
'description': 'Description of my command',
'read_response': True,
},
}
reboot-to-dfu.py - Simple DFU Reboot
Simple standalone script that only reboots to DFU mode (equivalent to fc-cli.py dfu):
.claude/skills/flash-firmware-dfu/reboot-to-dfu.py [port]
Use fc-cli.py for new work - it's more flexible.
USB Debugging
When USB MSC (mass storage) or CDC (serial) modes have issues, see:
claude/developer/docs/debugging/usb-msc-debugging.md
Quick commands:
lsusb -v | grep -A20 "STM"
dmesg | tail -50
cat /sys/bus/usb/devices/*/product
Related Skills and Agents
Skills:
- build-inav-target - Build firmware before flashing
- build-sitl - Test changes in SITL before flashing hardware
- msp-protocol - MSP protocol reference
Agents:
- fc-flasher - Automated flashing with settings preservation (RECOMMENDED)
- inav-builder - Build firmware for targets
- target-developer - Fix target configuration issues if hardware doesn't work after flashing
References
- Full documentation:
inav/docs/development/Building in Linux.md - USB debugging:
claude/developer/docs/debugging/usb-msc-debugging.md