cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F303RE Nucleo custom bootloader jumping to application not working

Steve Neves
Associate II
Posted on May 31, 2018 at 17:53

I've been going through numerous old posts that ask similar questions however I'm seeing something slightly different then everyone else.

I've written bootloaders before for Kinetis MCU's which I had hoped to essentially tweak and bring forward.  The only real difference I've noticed is the flash location is set to 0x08000000.  Very small wrinkle but easy enough to deal with.

I have two separate linker files (I'm using Atollic 9.0's GCC compiler for what it's worth) with the bootloader starting at:

MEMORY

{

RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 64K

CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 16K

FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 32K

}

and the Application's:

MEMORY

{

RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 64K

CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 16K

FLASH (rx)      : ORIGIN = 0x8008000, LENGTH = 480K /* Offset 32K for bootloader */

}

I've decided to keep the vector table in flash so there are two instances of it in flash (from system_stm32fxx.c):

#ifdef UPGRADE_IMAGE

#define VECT_TAB_OFFSET  0x8000 /*!< Vector Table base offset field.

                                  This value must be a multiple of 0x200. */

#else

#define VECT_TAB_OFFSET  0x0 /*!< Vector Table base offset field.

                                  This value must be a multiple of 0x200. */

I'm sharing files so the application will obviously grab the correct define.  However do not pay much attention to this as the application for some reason never gets here.

I looked at my flash image dump and verified that at 0x08000000 (0x00000000 relative to the binary) we have 0x20010000 and at 0x08000004 we have 0x08000F29.  I looked into the memory map for this bootloader portion and verified that is where the reset handler lives:

 .text.Reset_Handler

                0x08000f28       0x50 bin/startup_stm32f303xe.o

                0x08000f28                Reset_Handler

This stage works fine.  The bootloader launches.

The jump logic is pretty cookie cutter compared to what I've seen on this forum and the IAP example:

/* Private variables ---------------------------------------------------------*/

//typedef  void (*pFunction)(void);

//pFunction JumpToApplication;

//uint32_t JumpAddress;

#define APPLICATION_ADDRESS           ((uint32_t)0x08008000)

//uint32_t AppAddress = APPLICATION_ADDRESS;

void FirmwareUpgrade_JumpToApp(void)

{

    SysTick->CTRL = 0;

    SCB->VTOR = APPLICATION_ADDRESS;

    __disable_irq();

////    Set SP and PC

    __asm(

            'ldr r0, =0x8008000\n\t'

            'ldr sp, [r0]\n\t'

            'ldr r0, =0x8008004\n\t'

            'ldr pc, [r0]\n\t'

        );

//    /* Jump to user application */

//    JumpAddress = *(__IO uint32_t*) (AppAddress + 4);

//    JumpToApplication = (pFunction) JumpAddress;

//    __disable_irq();

//    /* Reconfigure vector table offset */

//    SCB->VTOR = AppAddress;

//    /* Initialize user application's Stack Pointer */

//    __set_MSP(*(__IO uint32_t*) AppAddress);

//    JumpToApplication();

}

Don't mind the mess, it's essentially two ways of performing the same task.  Neither seems to do the trick and both send me to the same location which is where I'd assume I want to go which is 0x0800C379.  The same bin dump as mentioned above shows at offset 0x8000 we have the same 0x20010000 for the top of the stack and 0x0800C379.  Confirming with the map file for the upgrade image we see:

 .text.Reset_Handler

                0x0800c378       0x50 bin/startup_stm32f303xe.o

                0x0800c378                Reset_Handler

At this point I'm pretty confused.   Previously in my Kinetis days I accomplished all this virtually in an identical fashion expect rather than offset the second vector table for the upgrade image, I just threw it in RAM.  That process doesn't seem to be as straight forward and RAM is more of premium in this particular project. 

Just to clarify, I do not hard fault.  The application is just out there in the weeds even though the PC register and SP register are exactly what I want them to be.

Thanks in advance for any help you guys may give me.

4 REPLIES 4
Steve Neves
Associate II
Posted on May 31, 2018 at 18:02

Just want to note that I am using FreeRTOS.  I compiled it as well as the BSP into two static libraries and link it in to the main application.

Steve Neves
Associate II
Posted on May 31, 2018 at 20:44

Bah I fixed it myself.  Here was my fix, it lives in the jump code, essentially had to DeInit the two peripherals I was using rather than blindly disable all interrupts:

void FirmwareUpgrade_JumpToApp(void)

{

    UART_DeInit();

    Timer_DeInit();

    SysTick->CTRL &= 0xFFFFFFFE;

    NVIC->ISER[0] = 0;

    SCB->VTOR = APPLICATION_ADDRESS;

//    __disable_irq();

////    Set SP and PC

    __asm(

            'ldr r0, =0x8008000\n\t'

            'ldr sp, [r0]\n\t'

            'ldr r0, =0x8008004\n\t'

            'ldr pc, [r0]\n\t'

        );

}

Posted on June 01, 2018 at 08:05

If you use __disable_irq() on one side of the transaction then you'll need an __enable_irq() on the other side. The processor doesn't do any of that in the Reset_Handler, and interrupts at the CPU level are not disabled at start up.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
varani luciano
Associate III

I use an F429. Problem solved (I do not know why) ,rewriting

SCB->VTOR = APPLICATION_ADDRESS;

in the application , after SystemClock_Config();