Skip to main content
Visitor II
February 26, 2020
Question

Jump from Bootloader code to application code

  • February 26, 2020
  • 5 replies
  • 1979 views

Hi,

I want to implement a bootloader for FOTA process. My bootloader code resides in sector 0 and application code in sector 5(the firmware to be updated ). But I am not able to jump from bootloader code to application code. Any help will be highly useful.

Bootloader code - 0x08000000

Application code - 0x08020000

Thanks

Jump Function defination :
 
int JumpToApplication(void)
{
	if (((*(__IO uint32_t*)SECTOR_START_ADDRESS) & 0x2FFE0000 ) != 0x20000000)
	{
		return -1;
	}
 
	
 __disable_irq();
 
 HAL_DeInit();
 
	/* Get the main application start address */
	uint32_t jump_address = *(__IO uint32_t *)(SECTOR_START_ADDRESS + 4);
 
	SCB->VTOR = SECTOR_START_ADDRESS;
 
	/* Set the main stack pointer to to the application start address */
 __set_MSP(*(__IO uint32_t *)SECTOR_START_ADDRESS);
	HAL_UART_Transmit(&huart1, (uint8_t*)"MSP Done \r\n ", 30, 1000);
 
	// Create function pointer for the main application
	void (*pmain_app)(void) = (void (*)(void))(jump_address);
 
	// Now jump to the main application
 
	pmain_app();
 
	return 0;
}

    This topic has been closed for replies.

    5 replies

    Visitor II
    February 26, 2020

    I'm going to shoot everyone spreading this __set_MSP() and related nonsense. Where did you find this recipe for disaster?

    If you call __disable_irq() in the bootloader, make sure that it gets enabled in the application. Do you have a reason to to call __disable_irq()? When not, don't call it at all.

    Ensure that all peripherals are in a state the application expects them to be in. Are all peripherals used in the bootloader accounted for and disabled before this farce is called?

    Disable all interrupts in NVIC that were enabled in NVIC, unless you know for sure that the application expects them to be enabled. Do you have a list of them?

    After SP is modified, no C code is safe to run. Jump to the application reset vector immediately.

    volatile uint32_t *appvectors = (volatile uint32_t *)SECTOR_START_ADDRESS;
     asm volatile(
     "mov sp, %[boot_sp]\n\t"
     "bx %[boot_pc]\n\t"
     :: [boot_sp]"r"(appvectors[0]), [boot_pc]"r"(appvectors[1])
     );

     Go through the application code, ensure that it does not set SCB->VTOR back to the start of flash.

    KHira.2Author
    Visitor II
    February 26, 2020

    Hi,

    SCB->VTOR = SECTOR_START_ADDRESS;

    This is set in bootloader code only.

    For application code in linker script we are changing the FLASH_BASE_ADDRESS to sector 5 address.

    Did not get the usage of this line

     if (((*(__IO uint32_t*)SECTOR_START_ADDRESS) & 0x2FFE0000 ) != 0x20000000)

    We also disabled all the peripherals, but did not work.

    Here is my updated code.

    int JumpToApplication(void)
    {
     if (((*(__IO uint32_t*)SECTOR_START_ADDRESS) & 0x2FFE0000 ) != 0x20000000)
     { 
     HAL_UART_Transmit(&huart1, (uint8_t*)"Mapping failed\r\n ", 30, 1000);
     //return -1;
     } 
     
     HAL_DeInit();
     HAL_SPI_DeInit(&hspi2);
     HAL_UART_DeInit(&huart1);
     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
     // __disable_irq();
     uint32_t jump_address = (__IO uint32_t )(SECTOR_START_ADDRESS + 4); 
     
     SCB->VTOR = SECTOR_START_ADDRESS;
     
     // Create function pointer for the main application
     
     void (pmain_app)(void) = (void ()(void))(jump_address);
     
     // Now jump to the main application
     
     pmain_app();
     
     
     return 0;
     
    }

    Visitor II
    February 26, 2020

    > SCB->VTOR = SECTOR_START_ADDRESS;

    > This is set in bootloader code only.

    Have you looked in the SystemInit() function of the application?

    > Did not get the usage of this line

    >  if (((*(__IO uint32_t*)SECTOR_START_ADDRESS) & 0x2FFE0000 ) != 0x20000000)

    If you don't understand what it does, why do you use it?

    It is supposed to check if the application stack pointer is valid. Unfortunately, it can reject a valid address, pass invalid addresses, and I have no way of fixing it, because I know nothing about the memory map of your MCU. The author was not paying attention in the class when they learned about binary arithmetic. Changed my mind, I won't shoot him, he deserves slow and painful death. Seriously, forget this pile of waste, and start over.

    But now it doesn't matter in the updated code, because now it doesn't set the stack pointer at all. Why?

    Graduate II
    February 26, 2020

    > Where did you find this recipe for disaster?

    From where does all the non-working bloatware come? The ST's genius code monkeys - the HAL team and creators of examples!

    Toss out that crap and implement much better and simpler approach described in my comment there:

    https://community.st.com/s/question/0D50X0000AFpTmUSQV/using-nvicsystemreset-in-bootloaderapplication-jumps

    Graduate II
    February 26, 2020

    I tink the best way is a semaphore you set when you request bootloader entry and at the begin of the normal startup code you detect that semaphore and set up the bootloader and jump to it. The semaphore might e.g. be some magic you write to RAM or perhaps you reboot from the user program with the watchdog and check for reset reason == watchdog.

    Graduate II
    February 26, 2020