Electronics Design AU
STM32Firmware

How Do You Use the STM32 DFU Bootloader to Flash Firmware?

Last updated 26 June 2026 · 9 min read

Direct Answer

The STM32 DFU (Device Firmware Upgrade) bootloader is a firmware-update mode built into the factory-programmed ROM of most STM32 microcontrollers. Enter it by pulling BOOT0 high before reset, or by jumping to the system memory address in software. Once active, the device presents as a standard USB DFU class interface; flash new firmware using dfu-util on Linux or macOS, or STM32CubeProgrammer on any operating system. After flashing, pull BOOT0 low and reset to run the new firmware.

Detailed Explanation

The STM32 family includes a factory-programmed ROM bootloader embedded in protected system memory — a region separate from user flash that cannot be erased or overwritten. On USB-capable devices, this bootloader implements the USB DFU (Device Firmware Upgrade) class, allowing you to flash firmware over USB from a host computer without any debug probe or custom hardware. Which boot interfaces are available — USB DFU, UART, SPI, I2C — varies by STM32 family; see Which STM32 Family Should You Use? for a comparison of boot interface support across the major series.

This is the mechanism that makes STM32 Nucleo and Discovery boards accept firmware from STM32CubeProgrammer out of the box, and that enables field programming of products without JTAG/SWD header access.

What Is USB DFU?

USB DFU is a standard USB class (class code 0xFE, subclass 0x01), defined by the USB Implementers Forum in the DFU 1.1 specification. It defines a host–device protocol for transferring firmware blocks, verifying them, and triggering execution. The STM32 ROM bootloader implements this protocol, which is why generic tools like dfu-util work across all supported STM32 devices — they speak the same standardised protocol regardless of the specific microcontroller.

How to Enter DFU Mode

Method 1 — BOOT0 pin (hardware)

The simplest and most reliable method. Most STM32 families (F1, F2, F4, F7, L4, H7) use two boot pins to decide the boot source on power-on reset:

BOOT0BOOT1Boot source
0 (GND)×User flash (normal operation)
1 (VCC)0System memory (ROM bootloader)
1 (VCC)1Embedded SRAM (rarely used)

To enter the ROM bootloader: pull BOOT0 to VCC (3.3 V) and assert reset. Release reset while keeping BOOT0 high. The MCU executes the ROM bootloader, which detects the USB connection and presents a DFU device to the host. After flashing, pull BOOT0 back to GND and reset again — the MCU boots into user flash and runs your new firmware.

Boards sold for prototyping (Nucleo, Discovery, Blue Pill clones) typically have a BOOT0 button or jumper for exactly this purpose.

Method 2 — Software jump from user code

When hardware access to BOOT0 is unavailable — common in products where the pin is not exposed — you can trigger the ROM bootloader from running firmware:

void jump_to_bootloader(void) {
    /* Disable SysTick to prevent interrupts during the jump */
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL  = 0;

    /* Disable all NVIC interrupts and clear pending flags */
    for (int i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }

    /* Set the vector table offset back to 0 (system memory base) */
    SCB->VTOR = 0;

    /* On STM32F4: system memory is at 0x1FFF0000             */
    /* Check ST AN2606 for the address of your specific device */
    uint32_t bootloader_addr = 0x1FFF0000;

    /* Load the bootloader's initial stack pointer, then jump  */
    __set_MSP(*(uint32_t *)bootloader_addr);
    ((void (*)(void))(*(uint32_t *)(bootloader_addr + 4)))();
}

The critical requirements are:

  1. Disable all interrupts — any peripheral ISR that fires after the jump will vector through a table that no longer exists in user flash, causing a hard fault.
  2. Deinit the USB peripheral — if your application has USB running, the host sees the device disconnect and reconnect. If the D+ pull-up is not properly released before the jump, USB enumeration after the jump may fail.
  3. Clear the SysTick — HAL_Delay and other HAL timing functions use SysTick; leaving it running at an arbitrary reload value causes timing errors in the bootloader.
  4. System memory address is device-specific — 0x1FFF0000 is correct for STM32F4xx. ST AN2606 lists the correct address for every device family.

Flashing Firmware

With dfu-util (Linux and macOS)

dfu-util is an open-source DFU host implementation. Most Linux distributions include it in their package repositories. First verify the DFU device is enumerated, then flash the firmware:

dfu-util -l
dfu-util -a 0 -s 0x08000000:leave -D firmware.bin

-a 0 selects alternate setting 0 (internal flash). -s 0x08000000:leave sets the start address to the beginning of user flash and instructs the bootloader to execute the new firmware immediately after the transfer. -D firmware.bin is the raw binary (not ELF/HEX — dfu-util requires a flat binary).

With STM32CubeProgrammer (Windows, Linux, macOS)

STM32CubeProgrammer is ST's official programming tool. On Windows, it installs its own DFU drivers automatically, bypassing the Zadig/WinUSB requirement. Connect the device in DFU mode, select USB in the connection type dropdown, click Connect, then browse to your firmware file and click Download.

STM32CubeProgrammer accepts .elf, .hex, and .bin files directly — useful when you want to avoid converting build outputs.

Windows driver requirement for dfu-util

Windows does not ship with a DFU driver. Before dfu-util can communicate with the device, install a compatible driver using Zadig: select the STM32 BOOTLOADER device and install WinUSB or libusb-win32. This step is not needed if you're using STM32CubeProgrammer.

USB Clock Requirements

The STM32 USB peripheral requires a stable 48 MHz clock. On most F4 devices this comes from the PLL fed by HSE (the external crystal). If your board does not have an HSE crystal, some STM32 families (STM32F3, G0, G4, L4+) include an internal HSI48 oscillator that the USB subsystem can use directly. F4 devices without an HSE crystal cannot run USB — including the ROM bootloader's USB DFU mode — because HSI alone cannot be guaranteed accurate enough for the ±500 ppm USB clock requirement.

This is why the STM32 clock tree matters beyond just your application clock speed: if the clock source for USB isn't stable and accurate, DFU mode will fail to enumerate even when BOOT0 and the wiring are correct.

Design Considerations

  • Always tie BOOT0 to GND through a pull-down (typically 10 kΩ) on production hardware — a floating BOOT0 pin will enter the bootloader unpredictably due to capacitive coupling or board noise.
  • Expose a BOOT0 entry mechanism on prototype boards — even if the production design has no BOOT0 access, adding a solder bridge or test point on the first prototype saves hours of debugging when you need to recover a bricked device before your custom bootloader trigger is working.
  • HSE crystal is required for USB DFU on STM32F4 — if your board omits the crystal to save cost, USB DFU in the ROM bootloader will not enumerate. Consider whether UART-based firmware loading (which uses HSI) is a sufficient alternative.
  • Software jump DFU requires a complete peripheral teardown — USB, SysTick, all NVIC interrupts, and the clock tree must be in their reset state before jumping to system memory. Missing any one of these is the primary cause of "USB not detected after software jump" failures.
  • For field-updatable commercial products, consider whether the ROM DFU bootloader meets your security requirements (no authentication, no image signing) or whether a custom bootloader with verified image loading is warranted — see what is a bootloader for the trade-offs.

Common Mistakes

"No DFU device found" / device not appearing in device manager

Most likely cause: the USB cable is a charge-only cable with no data lines. Try a different cable confirmed to work with data. If the cable is correct, verify BOOT0 is actually high at the moment of reset — measure with a multimeter. If using the software jump method, check that the USB peripheral was deinitialized and the D+ pull-up released before jumping.

USB device not detected after software jump

This is the most common failure mode for products that implement a software DFU trigger. The root cause is almost always an incomplete peripheral teardown before the jump. The stm32-usb-not-detected-after-bootloader-jump forum thread covers the exact sequence and the diagnostic steps in detail.

DFU flashes successfully but MCU won't boot into new firmware

Check that BOOT0 is back to GND (or tied through a pull-down) before the post-flash reset. If it remains high, the MCU re-enters the bootloader instead of running user flash. Also verify the firmware binary was flashed to 0x08000000 — if your linker script places the vector table at a different offset (e.g. 0x08008000 for a secondary-stage bootloader), specify the correct address in the dfu-util -s argument.

Unexpected resets during development that appear BOOT0-related

A floating BOOT0 pin can behave as logic high due to noise or capacitive coupling. Always tie BOOT0 to GND through a 10 kΩ pull-down resistor when DFU mode is not actively needed — this is standard practice on production hardware. If you need hardware-triggered DFU, add a button between BOOT0 and VCC that overrides the pull-down. The STM32 reset troubleshooting page covers other reset sources that can look like boot-pin issues.

Which STM32 Families Support USB DFU

The ROM bootloader supports USB DFU on all STM32 lines that have a full-speed USB peripheral. This includes F0 (USB-capable variants), F1 (medium- and high-density, connectivity line), F2, F3, F4, F7, H7, L0 (USB variants), L4, G4, and others. The protocol table in ST AN2606 is the authoritative reference — it documents which bootloader interfaces (USB DFU, UART, SPI, I2C, CAN) are available for each specific part number.

If your device lacks a USB peripheral or the ROM bootloader does not include DFU, the UART bootloader protocol (also documented in AN2606) is the standard alternative: it uses USART1 on most devices and is supported by STM32CubeProgrammer.

If you need a fully custom update protocol — over UART, BLE, Wi-Fi, or a proprietary interface — the embedded bootloader fundamentals page covers how to design and place a secondary bootloader alongside a custom application.

If you are building a product that requires a robust, field-updatable DFU flow — including secure boot, image verification, and rollback — Zeus Design's firmware development service covers STM32 OTA and DFU integration as part of a complete embedded software engagement.

Frequently Asked Questions

What is the difference between the STM32 ROM bootloader and a custom bootloader?
The ROM bootloader is factory-programmed into STM32's protected system memory and cannot be erased or modified. It supports predefined interfaces (USB DFU, UART, SPI, I2C depending on the STM32 family) and is immediately available on any new device — no developer toolchain required for basic field updates. A custom bootloader is application code written by the developer and placed in user flash, usually at 0x08000000, which then relocates the application vector table to an offset (e.g. 0x08008000). Custom bootloaders give full control over the update protocol, encryption, authentication, and interface choice, but require careful memory map planning and must handle the vector table relocation themselves. The `what-is-a-bootloader-embedded-systems` article covers the general architecture of both approaches.
Does USB DFU mode work on all STM32 microcontrollers?
No. USB DFU mode in the ROM bootloader requires the STM32 to have a USB peripheral. Families without USB hardware (some STM32F0 variants, STM32G0 basic lines) cannot use USB DFU; they use the UART bootloader protocol instead. Within USB-capable families, some low-density parts omit USB from the ROM bootloader's interface selection — check the device-specific bootloader protocol table in AN2606 for your exact part number. STM32 devices with USB FS peripherals — including the F4, F7, H7, L4, and G4 mainstream lines — all support USB DFU in the ROM bootloader.

References

Related Questions

Related Forum Discussions