cancel
Showing results for 
Search instead for 
Did you mean: 

Jump from my own bootloader into my application NUCLEO-F429ZI

AFara.2
Associate II

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

7 REPLIES 7
TDK
Guru

> __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.

If you feel a post has answered your question, please click "Accept as Solution".
AFara.2
Associate II

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.

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.
If you feel a post has answered your question, please click "Accept as Solution".
AFara.2
Associate II

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?

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

TDK
Guru

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.

If you feel a post has answered your question, please click "Accept as Solution".
MM..1
Chief II
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 ...