Agent skill

flash-firmware-dfu

Flash INAV firmware to flight controllers using DFU (Device Firmware Update)

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/flash-firmware-dfu

SKILL.md

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:

bash
# 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):

bash
# 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):

bash
# 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:

  1. Send ####\r\n to enter CLI mode
  2. Read from serial and wait for "CLI" string in response (timeout: 2 seconds)
  3. Only after receiving CLI prompt: send dfu\r\n
  4. Disconnect

Why simple echo + sleep doesn't work:

bash
# 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 dfu command 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):

python
# 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 reboot
  • b'\x01' = reboot to DFU mode

Step 2: Verify DFU Mode

Check that the device is in DFU mode:

bash
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:

bash
cd inav/build
objcopy -I ihex inav_x.y.z_TARGETNAME.hex -O binary inav_x.y.z_TARGETNAME.bin

Example:

bash
objcopy -I ihex inav_8.0.0_MATEKF405.hex -O binary inav_8.0.0_MATEKF405.bin

Step 4: Flash the Firmware

bash
dfu-util -d 0483:df11 --alt 0 -s 0x08000000:force:leave -D inav_x.y.z_TARGETNAME.bin

Example:

bash
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

bash
# 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:

bash
#!/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:

bash
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:

bash
sudo udevadm control --reload-rules
sudo udevadm trigger

Add your user to the plugdev group:

bash
sudo usermod -a -G plugdev $USER

Log out and back in for group changes to take effect.

Alternative Methods

INAV Configurator (GUI)

  1. Open INAV Configurator
  2. Click "Firmware Flasher"
  3. Select "Load Firmware [Local]"
  4. Browse to your .hex file
  5. Click "Flash Firmware"

msp-tool (Command Line)

bash
# 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

See mwptools documentation

Safety Notes

  • ALWAYS verify you're flashing the correct target for your hardware
  • Backup your settings using CLI dump command 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:

bash
# 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 mode
  • tasks - Show task execution times
  • status - Show flight controller status
  • version - Show firmware version
  • Any other CLI command - just pass it as an argument

How it works:

  1. Opens serial connection to flight controller
  2. Enters CLI mode by sending ####\r\n
  3. Waits for "CLI" prompt (with timeout)
  4. Sends your command
  5. Reads and displays the response (except for dfu which disconnects)

Adding new commands: Edit fc-cli.py and add to the COMMANDS dictionary:

python
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):

bash
.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:

bash
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

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results