Incorrect linking of the firmware for Blue Pill and DFU upload protocol

Hi everyone,

Where can I open issues against build script of framework-arduinoststm32-maple? It isn’t related to the framework per se, but the build script is contained inside framework folder.

I will post the issue here for now.

Here’s my platformio.ini:

platform = ststm32
board = bluepill_f103c8
board_build.core = maple
framework = arduino
upload_protocol = dfu
upload_port = anything

As you can see, I’m using Blue Pill board.

There is an inconsistency between build process and linker when I specify upload_protocol = dfu. It resides in

def get_vector_tab_addr(board, upload_protocol):
    # Some special cases
    boards_8005000 = (

    if any(b == board for b in boards_8005000):
        return "0x8005000"

    # depending on upload method
    if upload_protocol == "dfu":
        return "0x8002000"
    elif upload_protocol == "hid":
        return "0x8001000"
        # for other upload methods (including serial)
        return "0x8000000"

This snippet sets interrupt vector table address to 0x8002000 when using DFU bootloader.

def get_linker_script(board, mcu, upload_protocol):
    if upload_protocol == "dfu":
        boards_with_boot_20 = (

        if any(b in board for b in boards_with_boot_20):
            return "bootloader_20.ld"
        elif board.startswith("genericSTM32F103R"):
            return "bootloader.ld"
        elif board.startswith("genericSTM32F103V"):
            return "stm32f103veDFU.ld"
        elif board.startswith("genericSTM32F103Z"):
            return "stm32f103z_dfu.ld"
        elif board == "maple_ret6":
            return "stm32f103re-bootloader.ld"

    elif upload_protocol == "hid":
        # a rare case only one board
        if board.startswith("genericSTM32F103C"):
            return "hid_bootloader.ld"
                "%s doesn't support uploading using HID method\n" % board)
        # Any other upload protocol
        specific_scripts = (

        flash_scripts = (

        jtag_scripts = (

        if any(b in board for b in specific_scripts):
            return "%s.ld" % mcu[0:11]
        elif any(b in board for b in flash_scripts):
            return "flash.ld"
        elif any(b in board for b in jtag_scripts):
            return "jtag.ld"
        elif board == "genericSTM32F103C8":
            return "jtag_c8.ld"
        elif board == "genericSTM32F103T8":
            return "jtag_t8.ld"

    return "flash.ld"

While this one sets linker script to flash.ld which includes which sets rom origin to 0x8005000.

But I have manually flashed DFU bootloader to Blue Pill and now I want to use DFU upload protocol. As a consequence, the program does not start. If I edit manually and set rom origin to 0x8002000, the software works correctly.

1 Like

I’ve found a temporary workaround: you need to supply custom linker script. Suppose it’s placed in src folder with other source files and named flash.ld, you need to add build_flags = -Wl,-T'"$PROJECT_DIR\src\flash.ld"' to your platformio.ini build environment section. The single quotes enclosing double quotes enclosing actual path is needed to escape possible spaces in path.

More info: Allow to specify own path to linker script (ld) using "build_flags" option · Issue #233 · platformio/platformio-core · GitHub

1 Like