cancel
Showing results for 
Search instead for 
Did you mean: 

Jump to internal bootloader

trevor23
Associate III
Posted on May 07, 2010 at 19:20

Jump to internal bootloader

#bootloader-gpio
27 REPLIES 27
Posted on May 17, 2011 at 13:50

Yes, just set up the MSP and PC.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
damh
Associate II
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.

trevor23
Associate III
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

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 Venmo
Up vote any posts that you find helpful, it shows what's working..
trevor23
Associate III
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.

 
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 Venmo
Up vote any posts that you find helpful, it shows what's working..
trevor23
Associate III
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?

Posted on May 17, 2011 at 13:50

LDR        R13,[R0, #0]

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
trevor23
Associate III
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