cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with custom bootloader on STM32F4

Roberto Fortunato
Associate II
Posted on June 01, 2017 at 17:34

Hello,

I have some problems to implement a bootloader in a STM32F4. I searched on internet and I found coherent informations and examples, but I 'm not able to make simple test work.

Here my simple code:

bootloader (writed on 0x08000000 address):

&sharpdefine APPLICATION_ADDRESS        0x08008000

typedef void (*pFunction)(void);

pFunction appEntry;

uint32_t appStack, test, i;

int main(void){

    /* Get the application stack pointer (First entry in the application vector table) */

    appStack = (uint32_t) *((__IO uint32_t*)APPLICATION_ADDRESS);

    /* Get the application entry point (Second entry in the application vector table) */

    appEntry = (pFunction) *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);

    /* Reconfigure vector table offset register to match the application location */

    SCB->VTOR = APPLICATION_ADDRESS;

    /* Set the application stack pointer */

    __set_MSP(appStack);

    /* Start the application */

    appEntry();

    while(1);

    return 0;

}

program (writed on 0x08008000 address):

int main(void){

    register uint32_t tl;

    GPIO_InitTypeDef GPIO_InitStructure;

    ErrorStatus HSEStartUpStatus;

    RCC_DeInit();

    // Enable HSE

    RCC_HSEConfig(RCC_HSE_ON);

    // Wait till HSE is ready

    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if(HSEStartUpStatus == SUCCESS){

        // HCLK = SYSCLK impostato a 168 tick

        RCC_HCLKConfig(RCC_SYSCLK_Div1);

        // PCLK2 = HCLK/2 perch� massimo � 84Mhz

        RCC_PCLK2Config(RCC_HCLK_Div2);

        // PCLK1 = HCLK/4 perch� massimo � 42Mhz

        RCC_PCLK1Config(RCC_HCLK_Div4);

        // PLLCLK = 168 MHz

        RCC_PLLConfig(RCC_PLLSource_HSE, 12, 336, 2, 7);

        // PLLCLK = 144 MHz

        //RCC_PLLConfig(RCC_PLLSource_HSE, 12, 288, 2, 6);

        // Enable PLL

        RCC_PLLCmd(ENABLE);

        // Wait till PLL is ready

        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

        {

        }

        // Select PLL as system clock source

        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        // Wait till PLL is used as system clock source

        while(RCC_GetSYSCLKSource() != 0x08){}

        SystemCoreClockUpdate();

    }

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    GPIO_Init(GPIOG, &GPIO_InitStructure);

    GPIO_SetBits(GPIOG, GPIO_Pin_4);

    while(1){

        

        for(tl=0; tl < 0xFFFFFF; tl++);        // about 0.6 seconds    

        

        GPIO_ToggleBits(GPIOG, GPIO_Pin_4);

    }

    

    return 0;

}

I write program to 0x08000000 address for test and it works, so I'm sure there is no bugs.

When I use bootloader system doesn't work. I try to understand with debugger and I see that instruction appEntry(); has no effect and next command is while(1);

Can anyone tell me where it is wrong?

Thanks

Roberto

#bootloader #stm-32f407
14 REPLIES 14
Posted on January 15, 2018 at 18:25

If use debugger try to see if the interrupts are enabled. If you have right VTOR value the interrupt might be disabled. I understand that program does not crash i.e. does not go to the Hard_Fault handler...

Posted on January 16, 2018 at 09:47

SOLVED!

I found that what kept my code from working was that I was trying to launch the application from an ISR. To solve the issue I simply returned from the ISR and launched the application from the main code

Posted on January 16, 2018 at 10:53

Great! I just implemented my bootloader and was interesting what kind of new issues we can have - different than I came across

May be you have solved the problem, but...

The question is ( I think): when the application starts at APPLICATION_ADDRESS+4,calls the Reset_Handler that activate the function SystemInit () . This function (as you can read) do

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; (to set vector table address)

but in the application project you have

#define VECT_TAB_OFFSET 0x00 (in system_stm32f4xx.c) and

#define FLASH_BASE           0x08000000U (in my case in stm32f429xx.h).

So now the vector table is at 0x8000000 (this is booloader! not application....)

The boootloader with

 SCB->VTOR =APP_ADDRESS;

do a useless thing.

The solution I find? may be inserting in the application code NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000);

or

 SCB->VTOR =APP_ADDRESS;

or (I do that) modifyng the file system_stm32f4xx.c

//#define VECT_TAB_OFFSET 0x00

#define VECT_TAB_OFFSET  0x8008000 (or other application APP_ADDRESS).

I hope that a new option in cubeMX (may be there is), ask me the starting address of the application and modify the .ld file and the system_stm32f4xx.c (or the Reset_Handler code).

Ciao!

You know you can just use the symbol table entry for the vector table that the linker sets to the base of the image as it fixes it for a specific address. No smoke and mirrors, it knows exactly where the image is built to function.

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