Improved Maple bootloader for STM32

Improved Maple bootloader for STM32

posted in: Arduino, STM32 | 5

The LeafLabs Maple bootloader has a number of shortcommings which I have addressed by making a new version which dovetails with new features in Arduino STM32

The Maple bootloader was originally written by LeafLabs for their Maple and Maple products.

It allows uploads via USB using the DFU protocol. (DFU meaning Device Firmware Upgrade)

The existing bootloader had a number of issues, but the main reason update and improve the existing bootloader was that it requires the Arduino sketch to allocate 3k of RAM to the bootloader, even though the bootloader doesn’t run after the sketch has started to be run.

The reason that the sketch could not use any RAM below the first 3K, is because the bootloader has an option to upload a sketch into RAM and run from RAM. This feature was able to survive a soft reset, because regardless of whether the bootloader had just uploaded to Flash, or to RAM, the code always checked for a magic number in the upload to RAM start address.

However the magic number wasn’t that magical, and was just a check of the first 4 bytes, of the sketch, which are the STM32 Stack Pointer vector, which the STM32 loads into the SP after it boots.

And this number could be a variety of addresses, hence the code was only able to test 13 of the 32 bits of the first 4 bytes, hence the chances of the memory containing a seemly valid magic number where high enough for the bootloader to frequently think that variables we the magic number

The other other improvement that can now be made to the bootloader is reduction of size from 20k to under 8k. This has been achieved by using a bug fixed version of the bootloader, as a starting point, which could be compiled using the optimise for size compiler setting “-Os”

So with the compiler now less than 8K, the start location for the sketch upload could be lowered by 8k, hence giving the sketch 8k more room.

 

Initially, I just changed the Flash start settings in the bootloader, and made changes to the Arduino STM32, code and linker settings to compile for this new start address, (0x8002000 instead of 0x8005000). However after a discussion with @VictorPV on the Arduino forum, we realised that a better solution was to add another upload mode to the bootloader, and to retain the existing upload to 0x800500 rather than to replace it with the new address

We realised that the bootloader published 2 possible upload types using the AltID numbers 0 and 1, where Alt ID 0 = upload to RAM and Ald ID 1 means upload to Flash (at 0x8005000), and that the Alt ID is specified in the boards.txt and is passed via plaform.txt and finally to dfu-util

So if I added another DFU profile (Alt ID 2), it would be possible to make a bootloader that was backwards compatible with the existing bootloader for flash uploads

The only difference in functionality to an existing function was to the RAM upload.

For upload to RAM, it was only possible to run a sketch in RAM immediately after an upload. Because after a soft reset, it was not practical for the bootloader to determine by looking in the RAM, whether the last upload was to RAM or to Flash (as described above)

After a soft boot, (reset button being pressed or the sketch resetting the microprocessor), the code won’t run code in RAM because a variable records whether there has been a DFU upload.

The code then first check if there is a valid magic number in 0x8002000 and runs the code if present. If no code is found in that address it checks 0x8005000 and runs the code if found at 0x8005000

To prevent the code at 0x8002000 being run, which is left over from a 0x8002000 upload followed by a subseequent upload to 0x8005000, before code is uploaded to 0x800500, the code at 0x8002000 is cleared.

Note. The flash page size on the STM32F103 series is 2k, hence not just the first 4 bytes of 0x8002000 are cleared, a 2k section is cleared and reading the flash memory reveals that its filled with 0xFF, by nature of the way the Flash memory work.

 

The other improvement that has been made is the build process for different targets.

In the original Leaflabs maple-bootloader repo on GitHub, there were separate branches for each target board. This has resulted in code fragmentation, where bug fixes have been applied to one branch and not others.

To resolve this problem, I took code from the “mini-boot” branch of https://github.com/jonatanolofsson/maple-bootloader and created a new repo.

The mini-boot branch is for the Maple mini board, and seemed to have the most up to date and bug fixed code. Jonatan Olofsson had mostly merged the fixes from one target into another, but when I diff’ed the various branches it soon became clear that the code was actually quite divergent, but that the mini-boot branch seemed to be the cleanest.

I checked an unchanged version of the mini-boot branch into my repo, so that its technically possible to diff my changes and re-apply to the mini-boot branch if anyone wants to do this at a later date. However I suspect that will never happen.

I did also try to contact @jonatanolosffon via github but so far he has not responded to an issue I posted.  (unfortunatly he has not allowed issues on his fork of maple-bootloader, so I can’t send him an issue directly.)

Getting back to build targets… I have modified the Makefile to add targets for Maple mini “maple-mini” and also “maple-rev3” which are controlled using a #define in the makefile via a define in the  compiler flags (CFLAGS).

Then in config.h there are blocks of config using #ifdef to specify the things that are different between the boards like the GPIO pin for the USB disconnection hardware (aka DISC) and the LED and the Maple “button” (which is used to enter the perpetual bootloader mode).

At the time of writing, this config system does need to be improved, and config settings need to be added or Maple rev3, however it does work for maple-mini and will be easily updatable for the other target

 

Hence

make maple-mini   builds for the Maple mini board

make maple-rev3 is defined as a build target, but lacks a config block at the moment

I will add maple-ret6 and other boards at a later date, as required

 

 

All the code and sources have been pushed to GitHub , https://github.com/rogerclarkmelbourne/Arduino_STM32/tree/master/usb_bootloader/STM32F1

including a binary for the Maple mini

5 Responses

  1. Antonio
    |

    Hi Roger, I’m trying to work with the Maple mini but I am not able to connect to the Arduino board to go via mini USB, the Arduino ide does not detect the port, you can you lend a hand?

    best regards

  2. Roger Clark
    |

    I am not able to provide individual support via my blog, as there would not be enough hours in a day to answer each question individually.

    So I setup a forum http://www.stm32duino.com where people can help each other resolve this sort of problem.

    Please register on the forum and post your question to the forum if you can not find the answer in the thousands of existing posts.

    Thanks

    Roger

  3. Hossein
    |

    Hi Roger, I used your new bootloader on my maple mini and it was great. I appreciate of what you’ve done. Thank you

  4. Treblig
    |

    typo: http://www.stm32duion.com ==> http://www.stm32duino.com

  5. Roger Clark
    |

    OK

    Found and fixed in my comment

Leave a Reply