# Flash Firmware Dfu

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

- Skill: `sensei-hacker/flash-firmware-dfu` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add sensei-hacker/flash-firmware-dfu`
- Raw SKILL.md: https://api.skillmd.com/api/skills/sensei-hacker/flash-firmware-dfu/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: sensei-hacker (https://skillmd.com/u/sensei-hacker)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/sensei-hacker/flash-firmware-dfu

---


# 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](https://github.com/stronnag/mwptools/blob/master/docs/MiscTools.asciidoc#flashsh)

## 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:
`inav/docs/development/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: `inav/docs/development/usb-msc-debugging.md`

