A high-performance DFU (Device Firmware Update) implementation for flashing STM32 devices in DFU mode. Built in Rust with C++ interoperability, rs_dfu is specifically designed for flashing EdgeTX radios and supports both traditional raw binaries and modern UF2 firmware files.
- Multiple Firmware Formats:
- Raw binary files
- UF2 (USB Flashing Format) firmware files
- EdgeTX Radio Support: Optimized for EdgeTX radio hardware, including new platforms with external FLASH
- Dual Interface:
- Command-line tool (
rdfu) for direct device flashing - C++ library for embedding in custom applications
- Command-line tool (
- Cross-Platform: Support for Windows, macOS, and Linux
| Platform | Architecture | CLI Tool | Library |
|---|---|---|---|
| Windows | x86_64 | ✅ | ✅ |
| Windows | ARM64 | ✅ | ✅ |
| macOS | x86_64 (Intel) | ✅ | ✅ |
| macOS | ARM64 (Apple Silicon) | ✅ | ✅ |
| Linux | x86_64 | ✅ | ✅ |
| Linux | ARM64 | ✅ | ✅ |
Download the latest release for your platform from the releases page:
- Command-line tool:
rdfu-{os-arch} - C++ library:
rs_dfu-{target-triple}.tar.gzcontaining static library and header
Please note:
On macOS, you will probably need to "unflag" the binary before use:
xattr -c rdfu-macos-arm64git clone https://github.com/EdgeTX/rs-dfu.git
cd rs-dfu
cargo build --all --releaseList all DFU devices:
rdfu listWrite firmware to device (auto-detects UF2 vs raw binary):
rdfu write firmware.uf2
rdfu write firmware.binRead firmware from device:
rdfu read firmware.binFilter devices by vendor/product ID:
# List only STM32 DFU devices
rdfu list --vendor 0483 --product df11
# Write to specific device
rdfu write --vendor 0483 --product df11 firmware.binWrite raw binary to custom address:
rdfu write --start-address 0x08000000 firmware.binRead raw binary from custom address with custom length:
rdfu read --start-address 0x08001000 --length 51640 firmware.binReboot EdgeTX radio into DFU bootloader:
# Reboot with tag address
rdfu reboot 0x08000000
# Reboot specific device
rdfu reboot --vendor 0483 --product df11 0x08000000Inspect UF2 file contents:
rdfu uf2 firmware.uf2Extract the library archive and use CMake's find_package:
# Extract rs_dfu-{target}.tar.gz to your project
find_package(rs_dfu REQUIRED)
target_link_libraries(your_app rs_dfu::rs_dfu)#include "rs_dfu.h"
#include <stdio.h>
using ::rust::Vec;
void print_devices(const Vec<DfuDevice> &devices)
{
for (const auto &device : devices) {
auto dev_info = device.device_info();
printf("%04x:%04x: %s (0x%08x)\n",
dev_info.vendor_id,
dev_info.product_id,
dev_info.product_string.c_str(),
device.default_start_address());
}
}
int main() {
try {
// Find DFU devices
auto device_filter = DfuDeviceFilter::empty_filter();
auto devices = device_filter->find_devices();
if (devices.empty()) {
printf("No DFU devices found\n");
return 1;
}
print_devices(devices);
} catch (const std::exception& e) {
printf("Error: %s\n", e.what());
return 1;
}
return 0;
}For a complete example including UF2 handling, error management, and progress
reporting, see examples/cpp/main.cpp.
The project uses cxx for C++ interoperability:
# Build Rust library
cargo build --all --release
# Generate distribution package
./package.shThis creates a distribution archive containing:
- Static and dynamic libraries
- C++ header files
- CMake configuration files
cargo testOn Windows, if your DFU device is not listed or cannot be connected, it is most certainly because DFU devices on Windows always need a driver.
You can either:
On macOS, you might experience the annoying user confirmation dialog when connecting a device the first, or maybe even every time. This behaviour can be configured in System Settings (see here).
This project is licensed under the MIT License - see the LICENSE file for details.
- Built for the EdgeTX community
- Inspired by the DFU specification and existing DFU tools
- Uses the USB DFU protocol as defined by the USB Implementers Forum
For issues, questions, or contributions:
- Open an issue on GitHub
- Check the EdgeTX community forums for radio-specific questions