Calling stm32 internal bootloader from application

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
geoffroy
Posts: 7
Joined: Fri Oct 30, 2015 3:28 pm

Calling stm32 internal bootloader from application

Post by geoffroy »

Hi Giovanni,

We are trying to calling the STM32 SystemMemory Bootloader from our application,
but we encountered some problems.

In order to make bootloader working, it's necessary to do some stuff before : (from ST documentation)

Disable all peripheral clocks
• Disable used PLL
• Disable interrupts
• Clear pending interrupts

Here is my function which enters in bootloader mode :

Code: Select all

void enter_bootloader_mode()
{
   chSysDisable();

   //shut down any tasks here ...

   uint32_t application_address = 0x1FF01FFE; //corresponding to stm32l152RE <=== code crash here
   __set_MSP( * (__IO uint32_t*) application_address);
   bootJump = *(__IO uint32_t*) (application_address + 4);
   bootJump();
   
   while(1);
}


But, every time, debugger stop at :
__set_MSP( * (__IO uint32_t*) application_address)
and I get a : _unhandled_exception(void) { ... }
in vectors.c

apparently, reading address 0x1FF01FFE is not permitted ..
Have you any ideas about what is occurring ?

Thanks in advance for any help ..
Geoffroy
vambwodonk
Posts: 15
Joined: Tue Oct 14, 2014 5:36 am

Re: Calling stm32 internal bootloader from application

Post by vambwodonk »

Hi, Geoffroy

Maybe you need more than ChSysDisable(). You need to stop entire OS like this
http://wiki.chibios.org/dokuwiki/doku.php?id=chibios:howtos:stop_os

Tell us if you successful with this project, :D
flabbergast
Posts: 71
Joined: Sat Aug 22, 2015 1:22 pm

Re: Calling stm32 internal bootloader from application

Post by flabbergast »

The way I do it is that I patch the ResetHandler supplied with chibios, so that it reads a word at the end of the memory, and if it matches a predefined value, it jumps to the bootloader. This jump is "safe" because nothing has been initialised yet, it is just after a reset. Now when I want to jump to bootloader from the application, I just write the predefined word to the end of the memory and request reset.

To see the code, see here.
Here are the important bits: The actual patch to crt0 chibios code is here; the correct bootloader address is passed in the Makefile like this; and finally the jump in the application is implemented here.

EDIT: This approach may work without patching chibios by performing the bootloader-jump-check in the __early_init() function, which can be redefined in the board definition files. I have not tried this yet.
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Calling stm32 internal bootloader from application

Post by Giovanni »

Editing __early_init() is legit, it is like creating new board files.

Giovanni
geoffroy
Posts: 7
Joined: Fri Oct 30, 2015 3:28 pm

Re: Calling stm32 internal bootloader from application

Post by geoffroy »

@flabbergast

We tested the solution about patching chibios. It's working great ;-)

Thanks ! :D
flabbergast
Posts: 71
Joined: Sat Aug 22, 2015 1:22 pm

Re: Calling stm32 internal bootloader from application

Post by flabbergast »

Good to know! Just to give credit where it is due, my approach is based on this forum thread.

Also, I have now moved the required code to board definition files, so patching core chibios code is no longer needed: the modifications to the board files are like this to the header and this to the __early_init function; calling from the main application is still the same (but it uses now the BOOTLOADER_MAGIC define instead of the straight value) and BOOTLOADER_ADDRESS should be now passed in the Makefile in UDEFS (not UADEFS) and as a string constant (not a number constant), like this.

I'm sure the inline assembly bit can be replaced by some C magic one-liner with lots of brackets and stars, but I'm not good enough to know how ;)
trainman419
Posts: 4
Joined: Sat Jul 11, 2015 5:28 am

Re: Calling stm32 internal bootloader from application

Post by trainman419 »

I'm trying to do the same thing with ChibiOS 3.0.5 on an STM32F407, and it doesn't seem to be working. Is there something that has changed in the Reset_Handler on newer versions of ChibiOS?

I can enter the bootloader by pulling BOOT0 high, but the jump into the bootloader from __early_init() doesn't work:

Code: Select all

#define BOOTLOADER_ADDRESS 0x1FFF0000

    /* Remap the system memory onto address 0 */
    asm("LDR r0, =0x40023844;" /* RCC_APB2ENR */\
        "LDR r1, =0x00004000;" /* enable SYSCFG clock */\
        "STR r1, [r0, #0];"\
        "LDR r0, =0x40013800;" /* SYSCFG_MEMRMP */\
        "LDR r1, =0x00000001;" /* remap ROM at zero */\
        "STR r1, [r0, #0];");

    /* Jump into the bootloader
     * Page 70 of the reference manual (RM0090) describes how to set up the
     * stack pointer and jump to the bootloader
     *
     * Load the initial stack pointer value from the first location in memory
     * then Jump to the next address */
    asm("LDR r0, =%[Is];"\
        "LDR r1, [r0, #0];"\
        "MOV sp, r1;"\
        "LDR r0, [r0, #4];"\
        "BX  r0;"\
        : : [Is] "i" (BOOTLOADER_ADDRESS));


I've also added the remap of address 0 as suggested by https://my.st.com/public/STe2ecommuniti ... views=1164 , but it doesn't seem to be helping.
flabbergast
Posts: 71
Joined: Sat Aug 22, 2015 1:22 pm

Re: Calling stm32 internal bootloader from application

Post by flabbergast »

I have actually discovered that the approach I described does not quite work (on F042) because F042's bootloader *always* checks the BOOT0 pin (and the only other possibility is setting the option byte) - so the only reliable way I found to not just jump to the bootloader code but also stay there is to devise a hardware way to keep BOOT0 high during that check (e.g. a RC circuit).

I don't think the ResetHandler code has changed recently, and my understanding is that actually not much happens before the __early_init() function is called.
LHelge
Posts: 15
Joined: Sun Sep 21, 2014 10:58 pm
Been thanked: 1 time

Re: Calling stm32 internal bootloader from application

Post by LHelge »

What is the benefit of doing this in __early_init() instead of in the beginning of main() I can the that the former is called first by the bootup code but will it make any difference?`

I would rather have the bootloader check in main() for two reasons, the __early_init() will be overwritten each time I generate new board-files from the config XML. And I think it would be cleaner to keep as much application code as possible out of the board-files.
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Calling stm32 internal bootloader from application

Post by Giovanni »

Hi,

__early_init() comes before memory initialization and static constructors which can be slow, so it is the right place for clock-up and urgent initializations.

Said that, it could be moved elsewhere, it does not have to be in board files.

Giovanni
Post Reply