Jump to bootloader STM32F103

Post here first, or if you can't find a relevant section!
terancer
Posts: 5
Joined: Sun Jan 17, 2021 6:46 am

Jump to bootloader STM32F103

Post by terancer »

Hi All,

I am building a prototype controller board using the STM32F103C8 (Bluepill based board)with remote download & control capability (via serial modem). As an enhancement, I am trying to call the bootloader from the program so that I can set the controller in bootloader mode. That way I dont have to open the enclosure and change the BOOT 0 pin state.

During start-up, with in the first 5 or 10 seconds, if a sequence of character(s) is received at the serial port the "JumpToBootLoader" function will be called.

After looking around on internet, I found a tutorial at this link
https://stm32f4-discovery.net/2017/04/t ... are-stm32/

The function is defined as below

void JumpToBootloader(void) {

void (*SysMemBootJump)(void);
volatile uint32_t addr = 0x1FFFF000;

/**
* Step: Disable RCC, set it to default (after reset) settings
* Internal clock, no PLL, etc.
*/
#if defined(USE_HAL_DRIVER)
HAL_RCC_DeInit();
#endif /* defined(USE_HAL_DRIVER) */
#if defined(USE_STDPERIPH_DRIVER)
RCC_DeInit();
#endif /* defined(USE_STDPERIPH_DRIVER) */

/**
* Step: Disable systick timer and reset it to default values
*/
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;

/**
* Step: Disable all interrupts
*/
__disable_irq();

* Step: Set jump memory location for system memory
* Use address with 4 bytes offset which specifies jump location where program starts
*/
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));

/**
* Step: Set main stack pointer.
* This step must be done last otherwise local variables in this function
* don't have proper value since stack pointer is located on different position
*
* Set direct address location which specifies stack pointer in SRAM location
*/
__set_MSP(*(uint32_t *)addr);

SysMemBootJump();
}

The function compiles without any error on Arduino STM32 Core 1.9.0 version. But when i run the code on the controller and the above function is called, the controller sends a garbage character to serial port and seems to go into an indeterminate state. Same Code runs normally if the JumpToBoootloader function is not called.

I have tried this routine on STM32Cube IDE and it works perfectly. The MCU goes into download state and I am able to program the MCU.

My knowledge about core HAL libraries and debugging STM32 on Arduino is very minimal. I would like to develop the code on Arduino due to vast collection of libraries and simplicity.

Is there a trick to getting this function to work in Arduino could anybody point me in the right direction.

Any help would be much appreciated.

Thanks in advance
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Jump to bootloader STM32F103

Post by ag123 »

> custom (maple) dfu bootloader
take a look inside the codes for usb-serial. the trigger is actually by matching particular strings received on usb-serial
and usb control toggles (e.g. dtr in usb-cdc (acm)).
normally if you use roger's (libmaple) dfu bootloader,
https://github.com/rogerclarkmelbourne/ ... bootloader
the 1st 6 seconds is when a new sketch/firmware bin file can be loaded after pressing reset.
so in normal circumstances you may be able to goto the bootloader by doing a reset (in libmaple - something lie nvic_sys_reset())

there is also a USB HID based bootloader implementation but i'm not sure if it uses the same protocol
https://github.com/Serasidis/STM32_HID_Bootloader

i think some ehnancements has been made so that by saving a value in a (rtc) backup register - that survives across resets.
the bootloader can read that same register to see if it should simply stay in bootloader mode.
either way review the codes in usb-serial to see how that is done.

note that the above is for *customised* boot loader that has been invented since the 'libmaple' days
http://docs.leaflabs.com/static.leaflab ... oader-mode

what you are doing is to activate the on chip stm32 native bootloader.
that is different and on stm32f103 only the uart serial boot loader is available on uart1 (pa9 rx, pa10 tx)

for an external device interfacing the uart1 (pa9 rx, pa10 tx) pins.
one way to get into on chip boot loader mode is to set the boot0 pin and triggering reset externally from the pins
that'd make it fall into the boot loader mode
i think stm32loader uses such a method by (ab)using the dtr/rts signals/pins for that purpose
https://github.com/jsnyder/stm32loader
https://github.com/jsnyder/stm32loader/ ... er.py#L100
https://github.com/jsnyder/stm32loader/ ... der.py#L95

in the libmaple (roger's) core
i made a little example sketch of turning a stm32f103 pill board into a usb-uart dongle (with the dtr/rts signal handling)
https://github.com/rogerclarkmelbourne/ ... -w-signals
this is 'non standard' and on the official stm core if you want to handle those signals, u'd need to review the codes to see how to do that
in libmaple core, i found a place to patch a callback / hook for usb setup commands.
i intercepted commands from the host that does USB_CDCACM_SET_LINE_CODING read the dtr/rts settings and used it to toggle 2 user defined pins for that purpose.
i think ordinary usb-uart dongles e.g. FT232 type dongles could already have that with with those supported pins labelled
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Jump to bootloader STM32F103

Post by stevestrong »

Have a look into the libmaple solution: https://github.com/rogerclarkmelbourne/ ... #L285-L319.
This uses a magic character sequence transmitted over USB serial to reset and stay and in bootloader mode, but of course you can define your own trigger condition.
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Jump to bootloader STM32F103

Post by ag123 »

i think we'd need to await someone familiar with HAL to comment. what i've mentioned prior are 'custom' approaches
which are used in the past since maple (libmaple) et.al.
the codes given by op seem rather complete so it is hard to tell what else could be wrong.

in the example, there is this curious code, which doesn't have an example for stm32f1
https://stm32f4-discovery.net/2017/04/t ... are-stm32/

Code: Select all

    /**
     * Step: Remap system memory to address 0x0000 0000 in address space
     *       For each family registers may be different. 
     *       Check reference manual for each family.
     *
     *       For STM32F4xx, MEMRMP register in SYSCFG is used (bits[1:0])
     *       For STM32F0xx, CFGR1 register in SYSCFG is used (bits[1:0])
     *       For others, check family reference manual
     */
    //Remap by hand... {
#if defined(STM32F4)
    SYSCFG->MEMRMP = 0x01;
#endif
#if defined(STM32F0)
    SYSCFG->CFGR1 = 0x01;
#endif
    //} ...or if you use HAL drivers
    //__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();    //Call HAL macro to do this for you
i'm not too sure if that matters

maybe you may want to try adding that

Code: Select all

__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); 
call before

Code: Select all

SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
if that works this is an undocumented hardware feature being used. STM32F103 don't have the SYSCFG register
at least it isn't found in rm0008

a related thread found from a google search
https://stackoverflow.com/questions/609 ... r-from-app
which has additional suggestions

Code: Select all

__HAL_RCC_SYSCFG_CLK_ENABLE();           //make sure syscfg clocked
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); //remap system memory to address 0x000000
SCB->VTOR = 0; //set vector table offset to 0
User avatar
fpiSTM
Posts: 1745
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Jump to bootloader STM32F103

Post by fpiSTM »

I've started since a while a POC on this. But do not have time to finish.
https://github.com/stm32duino/Arduino_C ... 2/pull/710

I guess the main issue is how the MCU is reset. That's why I decided to simply call system reset and then check in a flash stored variable if a jump is requested.
terancer
Posts: 5
Joined: Sun Jan 17, 2021 6:46 am

Re: Jump to bootloader STM32F103

Post by terancer »

Thank you for your suggestions, I am very appreciative of your time.

ag123: Yes you are correct, I understand from the datasheet that the remapMemory function is not applicable to F103 as it doesnt have that specified register and I do agree that an Expert on the HAL can definetly resolve the issue. Current design doesnt make use of DTR signal on the board. I will consider that for the next design.

stevestrong: The current prototype board doesnt have USB implemented so I will have to use UART1 for download but i will definetly consider for the next version. will continue to read through the USB interface although i will not be able to implement USB based bootloader for this prototype.

fpiSTM : Suggestion seems to be practical. I have to write a function to process a special character sequence on UART1 during 5 to 6 seconds of power up. if the MCU receives the special sequence of characters then call the function to write set flag in flash location and reset. But I still dont know any other method of calling the system Bootloader(UART1)

I will keep you all updated on any developments
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Jump to bootloader STM32F103

Post by stevestrong »

To upload over UART is only possible if you enter the ROM bootloader, which is accessible by pulling BOOT0 pin low during reset.
So you basically have to use external circuitry to achieve this.
Or you use (write yourself) a serial bootloader, or search the net for such a solution.
We had someone who implemented a bootloader which loaded the program from SD card.
Last edited by stevestrong on Tue Feb 09, 2021 2:15 pm, edited 1 time in total.
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Jump to bootloader STM32F103

Post by ag123 »

if you are willing to go the distance you may want to write your own boot loader, the boot loader for instance can live in 'high' flash memory.
i.e. you need an entry point in your sketch/app to jump to the 'high memory' boot loader. once there, it listens to serial input take that
and write to location 0x8000000 (note u'd need to use the flash programming means / api) until it is done. then reset and the new app runs.
a trouble is stm32f103c8 has only 64k flash, so flash is tight as well. that could be alleviated with one with more flash e.g. stm32f103cb 128k
many similar examples on github
https://github.com/search?q=stm32+boot+loader
stm32duino(s) is a good native environment to write one as serial uart is supported natively. one can look up rm0008 on flash programming as well as review the current codes/apis if those already exists

the slightly tricky thing is the ld script to set the start location of your boot loader say if you place it at 56k (0x8000000 + 0xe000)
and the (nvic) vector tab address that needs to reference the correct tables. some of those examples can be found reviewing the existing platform.txt boards.txt and variant sources.
darkspr1te
Posts: 26
Joined: Tue Jan 07, 2020 4:22 pm

Re: Jump to bootloader STM32F103

Post by darkspr1te »

Implementing a serial bootloader and bootloader check ,
the best way to do this is have them as two parts, bootloader/program and maintain as such.
In the bootloader you need to decide on your check, You can look for a single magic value in the memory , bear in mind you could possibly end in boot loader if that magic value appears there by pure chance. Suggest multiple memory magics and then a timeout to continue if no serial activity provides the magic matching your second magic value. (magic is just a check of a value to see if you should goto booloader or carry onto application code, they can be a special value in memory , pin(s) held high/low, file exists, serial data and more.
in my case i did not use serial to act as firmware portal I used SD-Card as shown here and used the fact the file exist as second magic check.
https://github.com/darkspr1te/stm32f107 ... Src/main.c
before writing this I bootloader i had same issue, i needed custom based on situation.
onto serial part,
i think this is the code you're looking for,
https://github.com/w4ssimh/BootloaderSTM32-custom-
there are difference between the two hardware's but the datasheet and the maple bootloader write to flash in the same way for the 103,so you could add the serial code from that to the maple bootloader and use it's memory write functions, but the basic is
unlock flash,
erase from 0x7000(0x8000 7000+2 execute address for new firmware) to end of flash flash or what ever size you choose after the bootloader code has finished ,in my case my bootloader finished at 0x6B00 so i chose 0x7000 which gave me space to grow a little. Then write new data from your start of app address.
Most of my code in the stm32cube which cant be used in arduino IDE directly , you are limited to patching some arduino files and they get kegged every upgrade sadly.
I think there's a way of including you own files instead of arduino(arduino ide) inbuilt ones but I always failed at getting it to work so cant help there. a work around is maintain your own git repo of the branch you use and keep patching it every time they do commits.
see this commit on adding your own board with custom booting options(entry point , clock speeds etc) these are the area you will have to mod in order to have the ability to write both custom bootloader and app to go with and have it as a option on your IDE.
https://github.com/darkspr1te/Arduino_C ... a63b51910e
if you use platformio and arduino you can use the platformio.ini to ignore the core files and you can the copy the one from the repo to your project folder and instruct it to use that instead with the <-location/filename/> parameters (see platformio examples and my stm repo's for examples)

I highly recommend you attempt the bootloader part, the learning is worth it, My repo has many examples including using spi etc for the option.
the various methods for booting into a memory location , setting up the stack etc, looking for magics in memory (like forcing boot to factory serial bootloader, stm32f107 but it's similar) , be forwarned that when you goto serial (rom mask) bootloader then comms is right away , i'am not sure of actual timeout though but see
https://www.st.com/resource/en/applicat ... ronics.pdf
for further info on that.
and just remember that when reading/writing flash it's 0x0--0xffffff etc and when executing it's 0x8000000 -- 0x800fffff(EDIT* not strictly true, there are reasons for addressing both ways) ,
also most official 103c8 board have more flash than officially listed and you can use it with modded tools or in you own bootloader(see blackmagic probe debug tool wiki for how too do this with unmodded tools ) , now all of this is looking at a deployed device but for development I do recommend a blackmagic probe for debug, not having direct access to the ram for debug without adding tons of debug code can get boring real quick :-)

darkspr1te
terancer
Posts: 5
Joined: Sun Jan 17, 2021 6:46 am

Re: Jump to bootloader STM32F103

Post by terancer »

darkspr1te

Thank you!

I had a quick look through the links, it looks promising. I will try and implement it.
Post Reply

Return to “General discussion”