PlatformIO Community

New target to upload bootloader

I am still quite new in the IOT world and Arduino. I had to upload few bootloader for Arduino pro or Atmel 328p.

Why not having a target to make this upload using the data given in the board json ? Do I miss something.

Thanks for your input.

This is one-time operation and you can use Arduino IDE for that. If you want to have custom target for that, please check

One time per board. But ok I understand. I already read this thread and end up with this code:

import sys
Import("env")

print env.Dump()

def miss(variable):
    sys.stderr.write(
        "Error: Please specify `%s` in the board config json " % variable
    )
    exit(1)

if "BOARD" in env:
    if "bootloader.low_fuses" in env.BoardConfig():
        env.Replace(
            LOW_FUSES = env.BoardConfig().get("bootloader.low_fuses")
        )
    else:
        miss('low_fuses')
    if "bootloader.high_fuses" in env.BoardConfig():
        env.Replace(
            HIGH_FUSES = env.BoardConfig().get("bootloader.high_fuses")
        )
    else:
        miss('high_fuses')
    if "bootloader.extended_fuses" in env.BoardConfig():
        env.Replace(
            EXTENDED_FUSES = env.BoardConfig().get("bootloader.extended_fuses")
        )
    else:
        miss('extended_fuses')
    if "bootloader.unlock_bits" in env.BoardConfig():
        env.Replace(
            UNLOCK_BITS = env.BoardConfig().get("bootloader.unlock_bits")
        )
    else:
        miss('unlock_bits')
    if "bootloader.lock_bits" in env.BoardConfig():
        env.Replace(
            LOCK_BITS = env.BoardConfig().get("bootloader.lock_bits")
        )
    else:
        miss('lock_bits')
    if "bootloader.file" in env.BoardConfig():
        env.Replace(
            FILE = env.BoardConfig().get("bootloader.file")
        )
    else:
        miss('file')
    if "build.mcu" in env.BoardConfig():
        env.Replace(
            MCU = env.BoardConfig().get("build.mcu")
        )
    else:
        miss('build.mcu')
else:
    sys.stderr.write(
        "Error: Please specify in platform ini which board"
    )
    env.Exit(1)

env.Replace(
    SETFUSECMD='$UPLOADER $UPLOADERFLAGS -v -p$MCU -cstk500v1 -Ulock:w:$UNLOCK_BITS:m -Uefuse:w:$EXTENDED_FUSES:m -Uhfuse:w:$HIGH_FUSES:m -Ulfuse:w:$LOW_FUSES:m',
    UPLOADBOOTCMD='$UPLOADER $UPLOADERFLAGS -v -p$MCU -cstk500v1 -Uflash:w:$SOURCES:i -Ulock:w:$LOCK_BITS:m',
)

uploadboot = env.Alias(
    "bootloader", './$FILE',
    [
        env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port..."),
        env.VerboseAction("$SETFUSECMD", "Setting fuses"),
        env.VerboseAction("$UPLOADBOOTCMD", "Uploading bootloader $SOURCE")
    ]
)

AlwaysBuild(uploadboot)

1 Like

Does it work? :slight_smile:

If I use the right upload speed yes :slight_smile:… I mean I have success… Well when it fails, it fail on Arduino IDE. I guess I need an external clock.

I like this implementation :slight_smile: Please tune it and I’ll put to our docs.Thanks!

1 Like

Thanks a lot. I will try my best. But I cannot anymore tonight ^^ And I still don’t know how Arduino IDE decide on the speed. It is not the one defined in the board.txt

Of course board file would need to be update to integrate all this infos.

Nice solution, do you have an example of this script in action?

Update, I’ve found this thread. This explains how it works:

We have related issue for that

Done! See http://docs.platformio.org/en/latest/platforms/atmelavr.html#bootloader-programming

1 Like

Too bad that this is only supported (according to documentation) for atmelavr.

There are boards based on STSTM32 that also use bootloaders. Uploading a firmware to such boards using stlink (even if a flash offset is specified) results in ruining the bootloader. If I use an external openocd with a proper script, the the bootloader stays intact). It wold be nice to be able to upload the built firmware to ST-based board at a given offset without erasing the flash outside the flashed region.

Can you give a reproducable project and platformio.ini for that? As I read the code,

the upload.offset_address should be respected.

1 Like

Sure. Take Marlin 2.0 (branch “2.0.x”) and do the following modifications to the default platformio.ini:

 [platformio]
 ...
+default_envs = BIGTREE_SKR_PRO
 ...
 [env:BIGTREE_SKR_PRO]
 ...
+upload.offset_address=0x8000

If you choose Upload from the PlatformIO project tasks menu, it will ruin the bootloader.
The Verbose Upload target shows that the offset_address is not passed to openocd with -c program ...

Am I doing anything wrong?

Well, I was able to configure the offset, but only by directly editing the board json file. While this works ok with Marlin (that brings a bunch of boards with it), I don’t think it’s the right way to go with the standard boards supported by ststm32 platform for PlatformIO. I would expect the setting to be available in platformio.ini for any board on any platform.

upload.offset_address is the name in the Python code. Overriding it from the platformio.ini goes different. As you can see in any board documentation (the text is always the same, example)

You can override default settings per build environment using board_*** option, where *** is a JSON object path from board manifest random board. For example, board_build.mcu , board_build.f_cpu , etc.

Since you want to override the upload and not the board definitions you have to therefor add

board_upload.offset_address = 0x8000

to the platformio.ini. Running pio run -t upload -v gives me then

AVAILABLE: dfu, jlink, stlink
CURRENT: upload_protocol = stlink
openocd -d2 -s C:\Users\Maxi\.platformio\packages\tool-openocd/scripts -f interface/stlink.cfg -c "transport select hla_swd" -f target/stm32f4x.cfg -c "program {.pio\build\BIGTREE_SKR_PRO\firmware.bin} 0x8000 verify reset; shutdown;"

In which you can see that PlatformIO has respected the upload offset perfectly well with the 0x8000 constant.

1 Like