cmdfu is a lightweight, cross-platform command-line host application for performing firmware updates using the Microchip Device Firmware Update (MDFU) protocol. Written in C, cmdfu provides a native, dependency-free alternative to Python-based MDFU host tools, making it well suited for production environments, manufacturing, and embedded host systems.
The tool implements the MDFU host side of the protocol, enabling reliable in-field firmware updates for Microchip microcontrollers running an MDFU-compatible bootloader. It communicates with target devices over UART, SPI, or I2C (depending on build configuration) and transfers application image files.
- Native C implementation with no runtime dependencies
- Command-line interface designed for scripting and automation
- Full MDFU protocol command/response flow with error handling and retries
- Layered architecture: protocol, transport, and MAC layers are cleanly separated
- Suitable for PC hosts and embedded Linux hosts without a Python runtime
| Interface | Platform |
|---|---|
| Serial (UART) | Windows, Linux |
| SPI (Linux spidev) | Linux |
| I2C (Linux i2cdev) | Linux |
| Network (TCP socket) | Linux (for simulation/testing) |
cmdfu [-h | --help] [-v <level> | --verbose <level>] [-V | --version] [-R | --release-info] <action>
| Action | Description |
|---|---|
update |
Perform a firmware update |
client-info |
Query MDFU client information from the target device |
tools-help |
Show parameter help for all compiled-in tools |
| Option | Description |
|---|---|
-h, --help |
Show help (context-sensitive per action) and exit |
-V, --version |
Print cmdfu version number and exit |
-R, --release-info |
Print cmdfu version and MDFU protocol version and exit |
-v <level>, --verbose <level> |
Set logging verbosity: error, warning, info, debug. Default: error |
-t <tool>, --tool <tool> |
Select the communication tool |
Perform a firmware update on a connected MDFU target device.
cmdfu [--verbose <level>] update --tool <tool> --image <image> [<tool-args>...]
| Option | Description |
|---|---|
--tool <tool>, -t <tool> |
Communication tool to use (required) |
--image <file>, -i <file> |
Path to the firmware image file (required) |
Query and print MDFU client information (protocol version, buffer sizes, timeouts, inter-transaction delay).
cmdfu [--verbose <level>] client-info --tool <tool> [<tool-args>...]
Use cmdfu tools-help to list all tool-specific parameters. Common parameters per tool:
serial (Windows and Linux)
--port <port> Serial port, e.g. /dev/ttyACM0 or COM11
--baudrate <baud> Baud rate (default: 115200)
Supported baud rates: 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000.
spidev (Linux only)
--dev <device> SPI device, e.g. /dev/spidev0.0
--clk-speed <hz> Clock speed in Hz, e.g. 1000000
--mode <mode> SPI mode: 0, 1, 2, or 3
i2cdev (Linux only)
--dev <device> I2C device, e.g. /dev/i2c-0
--address <addr> I2C target address (0-127)
network (Linux only — for simulation/testing over TCP)
--host <host> Remote host (default: localhost)
--port <port> TCP port (default: 5559)
--transport <type> Transport type: serial, serial-buffered, spi, i2c
# Firmware update over serial on Linux
cmdfu update --tool serial --image update_image.img --port /dev/ttyACM0 --baudrate 115200
# Firmware update over serial on Windows
cmdfu update --tool serial --image update_image.img --port COM11 --baudrate 115200
# Query client info over I2C
cmdfu client-info --tool i2cdev --dev /dev/i2c-0 --address 55
# Firmware update over SPI
cmdfu update --tool spidev --image fw.img --dev /dev/spidev0.0 --clk-speed 1000000 --mode 0
# Enable debug logging
cmdfu -v debug update --tool serial --image fw.img --port /dev/ttyACM0Generate the build tree:
cmake -B build| Option | Default | Description |
|---|---|---|
MDFU_MAX_COMMAND_DATA_LENGTH |
1024 |
Maximum MDFU command data buffer size. Must be at least the size reported by the MDFU client. |
MDFU_MAX_RESPONSE_DATA_LENGTH |
30 |
Maximum MDFU response data buffer size. |
MDFU_LOG_TRANSPORT_FRAME |
undefined | When defined and verbosity is debug, raw transport frames are logged. Do not use with non-buffered MAC layers as logging latency may cause missed frames. |
LINUX_SUBSYSTEM_I2C |
ON |
Include the Linux I2C tool and MAC driver. |
LINUX_SUBSYSTEM_SPI |
ON |
Include the Linux SPI tool and MAC driver. |
LINUX_SUBSYSTEM_SERIAL |
ON |
Include the Linux serial tool and MAC driver. |
LINUX_SUBSYSTEM_NETWORK |
ON |
Include the Linux network tool and socket MAC driver. |
WINDOWS_SUBSYSTEM_SERIAL |
OFF |
Include the Windows serial tool (Win32 API). |
Example: configure with a custom maximum command data size:
cmake -B build -D MDFU_MAX_COMMAND_DATA_LENGTH=1024Example: configure for Windows serial only:
cmake -B build -D LINUX_SUBSYSTEM_I2C=OFF -D LINUX_SUBSYSTEM_SPI=OFF -D LINUX_SUBSYSTEM_NETWORK=OFF -D LINUX_SUBSYSTEM_SERIAL=OFF -D WINDOWS_SUBSYSTEM_SERIAL=ONBuild using CMake:
cmake --build buildOr using the native build tool directly (e.g. make):
cd build
makeBuild only the cmdfu executable (required for Windows, which does not support the test targets):
cmake --build build --target cmdfuLinux:
./build/apps/cmdfu/cmdfuWindows:
.\build\apps\cmdfu\cmdfu.exe
Install the cmdfu binary to the system path:
cd build
make installOr via CMake:
cmake --install buildCreate a binary and source package after building:
cd build
cpackBuild and package in one step:
cmake --build build --target packagePackages produced: TGZ binary, DEB (Debian), and TBZ2 source archive.
Unit tests use the Ceedling framework. Tests are supported on Linux only and are run inside a Docker container.
The CMake build tree must be configured first so that the generated header build/include/mdfu/mdfu_config.h exists, as it is referenced by the test source paths in test/project.yml.
cmake -B build
docker run --rm -v $(pwd):/home/dev/project --user $(id -u):$(id -g) throwtheswitch/madsciencelab:1.0.1b \
/bin/bash -c "cd /home/dev/project/test && rm -rf build && ceedling test:all"To run a single test:
docker run --rm -v $(pwd):/home/dev/project --user $(id -u):$(id -g) throwtheswitch/madsciencelab:1.0.1b \
/bin/bash -c "cd /home/dev/project/test && rm -rf build && ceedling test:mdfu_client_info"Note: Windows builds do not include test targets. Use
--target cmdfuwhen building on Windows.