Skip to main content
Roberto Fortunato
Associate II
June 1, 2017
Solved

Problems with custom bootloader on STM32F4

  • June 1, 2017
  • 14 replies
  • 3419 views
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
This topic has been closed for replies.
Best answer by Tesla DeLorean
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.

14 replies

Tesla DeLorean
Guru
June 1, 2017
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
Roberto Fortunato
Associate II
June 5, 2017
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
June 26, 2017
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

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
June 26, 2017
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
Roberto Fortunato
Associate II
June 28, 2017
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
July 5, 2017
Posted on July 05, 2017 at 08:41

help from anyone?

Roberto Fortunato
Associate II
July 5, 2017
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
July 6, 2017
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

Carmine Gianni
Visitor II
January 15, 2018
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?

varani luciano
Associate III
December 8, 2018

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!

Bogdan Golab
Lead
January 15, 2018
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...

Carmine Gianni
Visitor II
January 16, 2018
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

Bogdan Golab
Lead
January 16, 2018
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