Skip to main content
trevor23
Associate III
May 7, 2010
Question

Jump to internal bootloader

  • May 7, 2010
  • 26 replies
  • 5124 views
Posted on May 07, 2010 at 19:20

Jump to internal bootloader

#bootloader-gpio
This topic has been closed for replies.

26 replies

damh
Associate III
May 17, 2011
Posted on May 17, 2011 at 13:50

You have to disable IRQ, reset USART1 and RCC before setting MSP/PC. If you want to have correct hard fault handling, you have to change the interrupt table address to 0x1FFFF000. WARNING: The hard fault initiates a hard reset! If you haven't changed the boot pins, the STM32 will try to start at code position. Some commands of the internal bootloader also initiate a hard reset! Be sure, that you have runnable code ;)

The internal bootloader expects some registers to be in reset state.

Tesla DeLorean
Guru
May 17, 2011
Posted on May 17, 2011 at 13:50

Yes, just set up the MSP and PC.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
May 17, 2011
Posted on May 17, 2011 at 13:50

As damh indicates, getting the processor into a suitable state from an application can be difficult. I would not do it this way.

I get into the boot loader by reseting the device, and having a code path in my assembler startup code to fork into the boot loader. This can be done very early prior to any peripherals, interrupts or vectors being set up. Instead of checking for a button, I check for a magic constant in RAM, but you could do both or either.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
trevor23
trevor23Author
Associate III
May 17, 2011
Posted on May 17, 2011 at 13:50

Thanks guys. I've tried this code below (which I've used previously in my own bootloader) and it does not get me into the ST bootloader. Any ideas?

#define RESET_VECTOR_TABLE_OFFSET           4               // 1st 32 bit location is reserved, 2nd is reset vector

#define ST_BOOTLOADER_ADDRESS               0x1FFFF000

#define APPLICATION_RESET_VECTOR_ADDRESS    (ST_BOOTLOADER_ADDRESS + RESET_VECTOR_TABLE_OFFSET)

typedef  void (*pFunction)(void);

pFunction Jump_To_Application;

u32 JumpAddress;

.

.

.

    // Need to reset USART1 and RCC before jumping to bootloader

    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE);

    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);

    RCC_DeInit();

    ctl_global_interrupts_set(0); // disable interrupts

    JumpAddress = *(vu32*)APPLICATION_RESET_VECTOR_ADDRESS;

    Jump_To_Application = (pFunction) JumpAddress;

    // Initialize user application's Stack Pointer

    __MSR_MSP(*(vu32*) ST_BOOTLOADER_ADDRESS);

    Jump_To_Application();

     // should never get here

Tesla DeLorean
Guru
May 17, 2011
Posted on May 17, 2011 at 13:50

I had it posted here

https://my.st.com/public/STe2ecommunities/mcu/Lists/ARM%20CortexM3%20STM32/STM32%20Internal%20Bootloader

The content of the main RAM (0x20000000..0x2000????) survives a reset.

This is for Keil, but the basic concept should port to IAR, Rowley, etc.

-Clive

You can call code in the Boot ROM as you can any other. If you want to run the whole thing, don't expect it to return to your application, or have the clocks/interrupt set in the way you had them.

Generally I would recommend reseting into the Boot ROM so it starts without random clocks and interrupts enabled from your application.

In application.c

                // 1FFFF000 -> 20000200 -> SP

                // 1FFFF004 -> 1FFFF021 -> PC

                printf(''Entering Boot Loader..\r\n'');

                *((unsigned long *)0x2000FFF0) = 0xDEADBEEF; // 64KB STM32F103

                NVIC_GenerateSystemReset();

In startup.s

; Reset Handler

Reset_Handler   PROC

                EXPORT  Reset_Handler             [WEAK]

                IMPORT  __main

                LDR        R0, =0x2000FFF0

                LDR        R1, =0xDEADBEEF

                LDR        R2, [R0, #0]

                STR        R0, [R0, #0] ; Invalidate

                CMP        R2, R1

                BEQ        Reboot_Loader

                LDR     R0, =__main

                BX      R0

                ENDP

Reboot_Loader    PROC

                EXPORT    Reboot_Loader

                LDR        R0, =0x1FFFF000

                LDR        SP,[R0, #0]

                LDR        R0,[R0, #4]

                BX        R0

                ENDP

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
October 4, 2017
Posted on October 04, 2017 at 18:05

https://community.st.com/0D50X00009Xkh3DSAR

 
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
trevor23
trevor23Author
Associate III
May 17, 2011
Posted on May 17, 2011 at 13:50

Hi Clive1,

A magic constant in RAM sounds good. I take it you mean normal RAM and not backup register domain?  Are you able to share the assembly code you used to set up the MSP and PC?

Thanks Trevor.

 
trevor23
trevor23Author
Associate III
May 17, 2011
Posted on May 17, 2011 at 13:50

I tried that but get same error. SP is used without error in other parts of the assembly code anyway. r0 - r7 work but all other registers cause this error -- hence the error message referring to the ''lo'' register required. I also tried to use STR instead of LDR and got the same error. Is this a thumb/thumb2 or code allignment issue? The file has this at the top

  .section .init, ''ax''

  .code 16

  .align 2

Thanks

Trevor

Tesla DeLorean
Guru
May 17, 2011
Posted on May 17, 2011 at 13:50

LDR        R13,[R0, #0]

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
trevor23
trevor23Author
Associate III
May 17, 2011
Posted on May 17, 2011 at 13:50

Great, thanks.

LDR        SP,[R0, #0]

I get this error

Error: lo register required -- `ldr sp,[r0,#0]'

I have tried using a literal address but get the same error.

I'm using Rowley (GCC). Any ideas?

brmo
Visitor II
May 17, 2011
Posted on May 17, 2011 at 13:50

If you want to jump from your application code to the internal bootloader of the STM you have to reset also the SysTick, because the bootloader needs the counter to measure the baudrate (see AN2606).

 

USART_DeInit(USART1);

 

SysTick->CTRL = 0x04;

 

SysTick->VAL = 0;

 

 

temp = *(volatile unsigned int*)0x1FFFF004;

 

Jump_To_Bootloader = (pFunction)temp;

 

__set_MSP(*(volatile unsigned int *)0x1FFFF000);

 

Jump_To_Bootloader();