cancel
Showing results for 
Search instead for 
Did you mean: 

Jump from Bootloader code to application code

KHira.2
Associate II

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;
}

6 REPLIES 6
berendi
Principal

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.2
Associate II

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;
 
}

> 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?

Piranha
Chief II

> 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

Uwe Bonnes
Principal III

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.

Uwe Bonnes
Principal III