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
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on June 26, 2017 at 18:05

I've presented multiple examples over the years here. Perhaps the better course is to provide the two sides of the transaction you are doing, and it might be more apparent. Ideally as a complete project.

If you disable IRQ's before the jump, you have to reenable them.

If you jump from interrupt context this will also block interrupts, at this preemption level and above, moving forward.

Make sure SystemInit() isn't changing SCB->VTOR to some other address.

Use breakpoints and a debugger, better understand the state you've left the system in.

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

View solution in original post

14 REPLIES 14
Posted on June 01, 2017 at 18:34

>>

Can anyone tell me where it is wrong?

Not from information presented. Use the debugger in disassembly mode and look at where the transfer goes. Confirm the addresses match those described by the .MAP for the application.

Make sure NO interrupts are firing, ie SysTick, etc

Print out the appStack and appEntry values.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Roberto Fortunato
Associate II
Posted on June 05, 2017 at 12:19

SOLVED!

Thanks for your help. the problem was mapping program memory. I changed stm32f4xx_flash.ld file (program) from

MEMORY

{

...

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

...

}

to

MEMORY

{

...

  FLASH (rx) : ORIGIN = 0x8008000, LENGTH = 992K

...

}

checked .MAP file and tested. All works. If it may be usefull for anyother...

Thanks Roberto

Roberto Fortunato
Associate II
Posted on June 26, 2017 at 17:45

I have another problem: I'm unable to run interrupt in the program.

I try a simple test with SysTick_Handler but after bootloader no interrupts work.

Any suggestions?

Any simple examples?

I try to disable all thinks in bootloader before jump to program, but it may not be sufficient

thank in advance

Roberto

Posted on June 26, 2017 at 18:05

I've presented multiple examples over the years here. Perhaps the better course is to provide the two sides of the transaction you are doing, and it might be more apparent. Ideally as a complete project.

If you disable IRQ's before the jump, you have to reenable them.

If you jump from interrupt context this will also block interrupts, at this preemption level and above, moving forward.

Make sure SystemInit() isn't changing SCB->VTOR to some other address.

Use breakpoints and a debugger, better understand the state you've left the system in.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Roberto Fortunato
Associate II
Posted on June 28, 2017 at 10:21

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6pS&d=%2Fa%2F0X0000000bwM%2FV2KtP3u_TxkIe.CbnaMCj7m5OX13P1UxV96eqkORBYc&asPdf=false
Roberto Fortunato
Associate II
Posted on July 05, 2017 at 08:41

help from anyone?

Roberto Fortunato
Associate II
Posted on July 05, 2017 at 17:25

Today I add this line at start of application main function:

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000);

and the SysTick interrupt works. I hope this is the solution.

If it may be usefull for anyother...

Roberto

Roberto Fortunato
Associate II
Posted on July 06, 2017 at 08:29

Ok, I 've understood. For a mistake I don't correctly set the VECT_TAB_OFFSET macro.

thanks Clive for your suggestions.

Roberto

Posted on January 15, 2018 at 17:16

Hi Roberto, I have the same problem as you when trying to jump to the application from a custom bootloader.

I followed your code and I'm stuck at the same point as you,

If I launch the bootloader and then try to switch to the main application the interrupts stop working the SysTick Handler  doesn't work too.

You said in your solution that you failed to set correctly the VECT_TAB_OFFSET, but to me I think that I'm setting it correctly:

BOOTLOADER_START: 0x8000000

APPLICATION_START:  0x8004000

SCB->VTOR in the boot loader start code is 0x8000000

SCB->VTOR in the application start code is 0x8004000

moreover if I halt the code with the debugger in the application, the SCB->VTOR variable is correctly set to  0x8004000

Do you have any hints for me?