Skip to main content
Visitor II
October 15, 2021
Question

Jump from my own bootloader into my application NUCLEO-F429ZI

  • October 15, 2021
  • 5 replies
  • 1966 views

Hi,

I'm trying to write my own bootloader. It's located in 0x8000000 address of internal flash. I simply want to jump into 0x8080000 internal flash address when I press the external pushbutton connected to the EXTI. The code located into 0x8080000 just toggles a user led. I wrote my own bootloader code:

Bootloader

#define APPLICATION_BASE_ADDR                          0x8080000

typedef void (*pFunction)(void); /* Function pointer definition */

/* ------------------------- Functions -------------------------------------- */

void Bootloader_JumpToApplication(void){

   

  uint32_t JumpAddress = *(__IO uint32_t*)(APPLICATION_BASE_ADDR+4);

  pFunction Jump = (pFunction)JumpAddress;    

   

  HAL_UART_DeInit(&huart3);

  HAL_GPIO_DeInit(USER_Btn_GPIO_Port, USER_Btn_Pin);

  HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin|RMII_RXD0_Pin|RMII_RXD1_Pin);

  HAL_GPIO_DeInit(GPIOA, RMII_REF_CLK_Pin|RMII_MDIO_Pin|RMII_CRS_DV_Pin);

  HAL_GPIO_DeInit(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin);

  HAL_GPIO_DeInit(RMII_TXD1_GPIO_Port, RMII_TXD1_Pin);

  HAL_GPIO_DeInit(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin);

  HAL_GPIO_DeInit(USB_OverCurrent_GPIO_Port, USB_OverCurrent_Pin);   

  HAL_GPIO_DeInit(GPIOA, USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin); 

  HAL_GPIO_DeInit(USB_VBUS_GPIO_Port, USB_VBUS_Pin);

  HAL_GPIO_DeInit(GPIOG, RMII_TX_EN_Pin|RMII_TXD0_Pin);  

  __HAL_RCC_GPIOC_CLK_DISABLE();

  __HAL_RCC_GPIOH_CLK_DISABLE();

  __HAL_RCC_GPIOA_CLK_DISABLE();

  __HAL_RCC_GPIOB_CLK_DISABLE();

  __HAL_RCC_GPIOD_CLK_DISABLE();

  __HAL_RCC_GPIOG_CLK_DISABLE();

  

  SysTick->CTRL = 0;

  SysTick->LOAD = 0;

  SysTick->VAL = 0; 

   

  HAL_RCC_DeInit();  

  HAL_DeInit();

   

  __disable_irq();

   

  SCB->VTOR = APPLICATION_BASE_ADDR;  

   

  /* let's do The Jump! */  

  __set_MSP(*(__IO uint32_t*)APPLICATION_BASE_ADDR); 

  Jump(); 

}

Both of codes are generated with STM32CubeMX. Both main.c code are:

Bootloader

int main(void){

 HAL_Init();

 SystemClock_Config();

 MX_GPIO_Init();

 MX_USART3_UART_Init();

 while (1) { }

}

Application

int main(void){

 HAL_Init();

 SystemClock_Config();

 MX_GPIO_Init();

 MX_USART3_UART_Init();

 while (1){

  HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);

   HAL_Delay(500);

  }

}

I also modified linker files as shown:

Bootloader

/*-Memory Regions-*/

define symbol __ICFEDIT_region_ROM_start__  = 0x08000000;

define symbol __ICFEDIT_region_ROM_end__   = 0x0807FFFF;

define symbol __ICFEDIT_region_RAM_start__  = 0x20000000;

define symbol __ICFEDIT_region_RAM_end__   = 0x2002FFFF;

define symbol __ICFEDIT_region_CCMRAM_start__ = 0x10000000;

define symbol __ICFEDIT_region_CCMRAM_end__  = 0x1000FFFF;

Application

/*-Memory Regions-*/

define symbol __ICFEDIT_region_ROM_start__  = 0x08080000;

define symbol __ICFEDIT_region_ROM_end__   = 0x081FFFFF;

define symbol __ICFEDIT_region_RAM_start__  = 0x20000000;

define symbol __ICFEDIT_region_RAM_end__   = 0x2002FFFF;

define symbol __ICFEDIT_region_CCMRAM_start__ = 0x10000000;

define symbol __ICFEDIT_region_CCMRAM_end__  = 0x1000FFFF;

When I try to debug bootloader code, so I push the button, the led should toggle in my application only lights up. If I try to stop debug, it seems the jump is correctly done. So where is the problem? Could you help me please? Thank you.

Best regards,

Antonio

    This topic has been closed for replies.

    5 replies

    Super User
    October 15, 2021

    > __disable_irq();

    There's no need to globally disable interrupts before you jump. They should all be disabled individually since, if they're not, they're going to jump to incorrect code in the new application.

    So either remove that line, or enable interrupt again in your main program.

    AFara.2Author
    Visitor II
    October 16, 2021

    Unfortunately I tried both to remove "__disable_irq()" line and to individually disable bootloader IRQs but nothing changes. Do you have any other suggestions? Thank you.

    Super User
    October 16, 2021
    Your bootloader code doesn’t include a call to Bootloader_JumpToApplication anywhere in the main loop. Are you performing the jump from within an interrupt? That won’t work out well.
    AFara.2Author
    Visitor II
    October 16, 2021

    You're right, I should not jump inside an interrupt service routine. In general, despite being inside an interrupt, it works only if I disable the same interrupt I also use in my application. Is it correct? Should I not use the same interrupts both in the bootloader and in the application? Maybe the problems are:

    1) the jump is into an interrupt service routine

    2) I use the same interrupt in my application for another scope

    Could it be possible?

    AFara.2Author
    Visitor II
    October 16, 2021

    Ok the only problem is the first. I can't jump into an interrupt service routine. I verified that and It's working fine now! I jump from bootloader to application and back again to the bootloader. Thank you @TDK​ for the support.

    Best regards,

    Antonio

    Super User
    October 16, 2021

    If you jump from within an ISR, your are now running your main loop from that ISR. The jump to bootloader code functions similarly to a "goto" statement. Thus, the same ISR can never fire (since you're already in it) and only interrupts with a higher preemption than it will fire.

    Graduate II
    October 17, 2021
    int main(void){
     HAL_Init();
     SystemClock_Config();
     MX_GPIO_Init();
     MX_USART3_UART_Init();
     while (1) { }
    }

    In EXTI or other ISR you need only set semaphore, and in main while if and jump to ...