Skip to content

Using the UF2 Bootloader

The UF2 Bootloader is a firmware format developed by Microsoft for PXT (now Microsoft MakeCode). It enables programming microcontrollers over MSC (Mass Storage Class) by exposing the device as a removable flash drive.

Key features

  • Simple to use: presents the microcontroller as a USB flash drive
  • Drag-and-drop firmware flashing
  • No special drivers or software required

Use cases

  1. Firmware updates: simplify the end-user upgrade process and lower the barrier to update firmware
  2. File updates: move files into flash storage

Montic product support

W02W04
ChipExpressif ESP32-C6WCH CH32V208
Status❌ Not Support✔ Support
Project❌ Not SupportArcaneNibble/wch-uf2

Build and use UF2

The examples below use Montic W04 to show how to work with the UF2 Bootloader: compiling the bootloader and updating application firmware.

Montic W04 uses the single-core CH32V208 microcontroller. WCH does not provide an official UF2 Bootloader, but the community project ArcaneNibble implements one for CH32V003 and CH32V2xx families, which we can reuse.

wch-uf2 source code

Prerequisites

Prepare the following before building and flashing the wch-uf2 bootloader.

  1. Download and install the toolchain The project uses WCH’s xw RISC-V ISA extension, so you need the official WCH RISC-V toolchain.

    1. If you installed WCH’s MounRiver Studio, it already includes the arm-none-eabi-gcc toolchain at C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12.
    2. You can also download the official WCH RISC-V GCC Embedded toolchain directly: MounRiver_Studio_Community_Win_V180.zip. We recommend using the repackaged mirror from ch32-riscv-ug. Extract it to a convenient path, for example C:\\riscv-none-elf-gcc-12-win-1.92.
    3. Install Make for Windows from the GNU Make downloads. The default path is C:\\Program Files (x86)\\GnuWin32.
    4. (Optional) Install Git to clone the wch-uf2 repository.
    5. Install Python 3 to convert .hex files to .uf2.

    For more details on the WCH toolchain, see the Montic W04 wiki.

  2. Download the wch-uf2 source code

    1. Download the ZIP archive from ArcaneNibble/wch-uf2 and extract it to a working directory.
    2. We recommend cloning the code with Git. In CMD.exe or PowerShell.exe, go to your target directory and run:
    Terminal window
    # change directory where you want to save the wch-uf2 code
    cd /path/to/save/wch-uf2-code/
    # clone wch-uf2 code
    git clone https://github.com/ArcaneNibble/wch-uf2.git
    # open the wch-uf2 directory
    cd wch-uf2

Build the UF2 Bootloader

Set the correct working path (PATH) in CMD.exe or PowerShell.exe:

Terminal window
# add make.exe to PATH
set PATH=%PATH%;"C:\\Program Files (x86)\\GnuWin32\\bin"

Go to the wch-uf2 directory:

Terminal window
# go to the wch-uf2 root directory
cd wch-uf2

Update the Makefile tool paths:

Makefile
.PHONY: all clean
RV_ARCH = rv32imacxw
# modify CC and OBJDUMP execute path with MounRiver IDE toolchain
CC = riscv-none-elf-gcc
OBJDUMP = riscv-none-elf-objdump
CC = "C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12\\bin\\riscv-none-elf-gcc.exe"
OBJDUMP = "C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12\\bin\\riscv-none-elf-objdump.exe"
CFLAGS = -Wall -ggdb3 -Os -march=$(RV_ARCH) -ffunction-sections -fdata-sections -ffreestanding
LDFLAGS = -Wall -ggdb3 -march=$(RV_ARCH) -Wl,--gc-sections --specs=nosys.specs
# more code ...

Build the bootloader with Make:

Terminal window
# run make command
make -f Makefile
# expected output
# "C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12\\bin\\riscv-none-elf-gcc.exe" -Wall -ggdb3 -Os -march=rv32imacxw -ffunction-sections -fdata-sections -ffreestanding -c -o startup.o startup.S
# "C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12\\bin\\riscv-none-elf-gcc.exe" -Wall -ggdb3 -Os -march=rv32imacxw -ffunction-sections -fdata-sections -ffreestanding -c -o bootloader.o bootloader.c
# "C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12\\bin\\riscv-none-elf-gcc.exe" -Xlinker -Map=bootloader.map -Wl,--script=linker.lds -nostartfiles -o bootloader.elf startup.o bootloader.o
# "C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12\\bin\\riscv-none-elf-objdump.exe" -xdsS bootloader.elf >bootloader.dump

The build produces bootloader.elf, which you need to convert to .hex.

Terminal window
# convert elf to hex
"C:\\MounRiver\\MounRiver_Studio\\toolchain\\RISC-V Embedded GCC12\\bin\\riscv-none-elf-objcopy.exe" -O ihex "bootloader.elf" "bootloader.hex"

Flash the UF2 Bootloader

You can flash the bootloader with the WCH-Link debugger or the built-in USB ISP, similar to the Montic W04 getting-started guide. See step 4 (Flashing) of the Blink demo in the W04 guide for details: link.

Update application firmware

After installing the UF2 Bootloader, you can update application firmware through it. Follow the steps from the W04 getting-started guide and reuse the Blink demo .hex output.

Convert WS2812_LED.hex to .uf2 to place it at the correct flash address. Use uf2conv.py (download from here).

Terminal window
# convert hex to uf2
/path/to/uf2conv.py -c -f 0x699b62ec -b 0x08001000 -o WS2812_LED.uf2 WS2812_LED.hex

Finally, connect the Montic W04 to your PC with USB-C. A new USB flash drive will appear; drag WS2812_LED.uf2 onto it to update the firmware.

UF2 limitations

UF2 is convenient for development and testing but has some constraints:

  • Compatibility: requires USB support, and not all microcontrollers support MSC mode
  • Performance: write speed is limited by the USB MSC protocol
  • Features: does not support complex boot configurations