Skip to main content
Schmid.M.
Associate III
October 30, 2020
Solved

application jump to system memory bootloader

  • October 30, 2020
  • 5 replies
  • 3951 views

Hi,

I have an stm32l43 connected as a USB device. Using the BOOT0 pin, I can start the built-in Bootloader and use DFU. Now I wish to jump to the BL without this Pin by a software jump.

But with this jump, I only seem to reset the device (my code starts again like after a reset). It seems to me that the Bootloader starts, checks for valid code in flash and then streight jumps back there (as my firmware of course is valid code).

How can I get the Bootloader staying active without using a boot pin or an option bit?

here is my jump function for reference:

void jump2STinternalBootloader(void){
	void (*SysMemBootJump)(void);
 
	/**
	 * Set system memory address.
	 * check AN2606 document for descriptions of memory addresses
	 */
	volatile uint32_t addr = 0x1FFF0000;
 
	/**
	 * Disable RCC, set it to default (after reset) settings
	 * Internal clock, no PLL, etc.
	 */
	HAL_RCC_DeInit();
 
	/**
	 * Disable systick timer and reset it to default values
	 */
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;
 
	/**
	 * Disable all interrupts
	 */
	__disable_irq();
 
	/**
	 * Remap system memory to address 0x0000 0000 in address space
	 */
	__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
 
	/**
	 * Set jump memory location for system memory
	 * Use address with 4 bytes offset which specifies jump location where program starts
	 */
	SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
 
	/**
	 * Set main stack pointer.
	 * This step must be done last otherwise local variables in this function
	 * don't have proper value since stack pointer is located on different position
	 *
	 * Set direct address location which specifies stack pointer in SRAM location
	 */
	__set_MSP(*(uint32_t *)addr);
 
	/**
	 * Actually call our function to jump to set location
	 * This will start system memory execution
	 */
	SysMemBootJump();
	while(1);
}

This topic has been closed for replies.
Best answer by Schmid.M.
I have a solution now: it seems like there was still a problem in my jump function. I added stopping of FreeRTOS, stopping and de-init of USB and also a HAL_DeInit() and now it stays in Bootloader as it should. Probably there were some registers which needed to be completely de-initialized before jumping.
Thanks for your help and best regards,
Michael
void jump2STinternalBootloader(void){
void (*SysMemBootJump)(void);
volatile uint32_t addr = 0x1FFF0000;
// suspend kernel
osKernelLock();
//stop and deinit USB
USBD_Stop(&hUsbDeviceFS);
USBD_DeInit(&hUsbDeviceFS);
/**
* Disable RCC, set it to default (after reset) settings
* Internal clock, no PLL, etc.
*/
HAL_RCC_DeInit();
/**
* Disable systick timer and reset it to default values
*/
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
//reset all periphals
HAL_DeInit();
__disable_irq();
/**
* Remap system memory to address 0x0000 0000 in address space
*/
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
/**
* Set jump memory location for system memory
* Use address with 4 bytes offset which specifies jump location where program starts
*/
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
/**
* Set main stack pointer.
* This step must be done last otherwise local variables in this function
* don't have proper value since stack pointer is located on different position
*
* Set direct address location which specifies stack pointer in SRAM location
*/
__set_MSP(*(uint32_t *)addr);
/**
* Actually call our function to jump to set location
* This will start system memory execution
*/
SysMemBootJump();
while(1);
}

5 replies

Uwe Bonnes
Chief
October 30, 2020

As often explained here, best way is a switch at the start of bootup, loking for some magic in some unerase RAM. To enter bootloader, set the magic and do a hard reset. Look at older threads about that in this forum.

Schmid.M.
Schmid.M.Author
Associate III
October 30, 2020

sure, when writing my own bootloader, I used to do it this way. But i don't have influence on what the built-in Bootloader in System memory does. If there is valid code, it jumps there, no matter what magic I have done before.

TDK
Super User
October 30, 2020

> It seems to me that the Bootloader starts, checks for valid code in flash and then streight jumps back there (as my firmware of course is valid code).

That's not what the bootloader does. Why do you think it's aborting its mission?

"If you feel a post has answered your question, please click ""Accept as Solution""."
Schmid.M.
Schmid.M.Author
Associate III
October 30, 2020

I just watched it directly restarting after my jump-command. If there are no errors in my jump function(see above), this was the only explanation I had. If it jumps to Bootloader and then normal code execution restarts, the bootloader must have jumped back to flash (or there was a reset for some reason).

TDK
Super User
October 30, 2020
Look at RCC->CSR to find the reason for the reset.
"If you feel a post has answered your question, please click ""Accept as Solution""."
Tesla DeLorean
Guru
October 30, 2020

Yes, it does this. ST has an extremely short-sighted approach, making it difficult to adapt.

You'd need to do some technical analysis, and find secondary access points, or use other methods to change the behaviour.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Schmid.M.
Schmid.M.AuthorAnswer
Associate III
November 2, 2020
I have a solution now: it seems like there was still a problem in my jump function. I added stopping of FreeRTOS, stopping and de-init of USB and also a HAL_DeInit() and now it stays in Bootloader as it should. Probably there were some registers which needed to be completely de-initialized before jumping.
Thanks for your help and best regards,
Michael
void jump2STinternalBootloader(void){
void (*SysMemBootJump)(void);
volatile uint32_t addr = 0x1FFF0000;
// suspend kernel
osKernelLock();
//stop and deinit USB
USBD_Stop(&hUsbDeviceFS);
USBD_DeInit(&hUsbDeviceFS);
/**
* Disable RCC, set it to default (after reset) settings
* Internal clock, no PLL, etc.
*/
HAL_RCC_DeInit();
/**
* Disable systick timer and reset it to default values
*/
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
//reset all periphals
HAL_DeInit();
__disable_irq();
/**
* Remap system memory to address 0x0000 0000 in address space
*/
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
/**
* Set jump memory location for system memory
* Use address with 4 bytes offset which specifies jump location where program starts
*/
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
/**
* Set main stack pointer.
* This step must be done last otherwise local variables in this function
* don't have proper value since stack pointer is located on different position
*
* Set direct address location which specifies stack pointer in SRAM location
*/
__set_MSP(*(uint32_t *)addr);
/**
* Actually call our function to jump to set location
* This will start system memory execution
*/
SysMemBootJump();
while(1);
}
Schmid.M.
Schmid.M.Author
Associate III
November 2, 2020

*edit: found solution, see above.

Amel NASRI
Technical Moderator
November 3, 2020

Thanks for update. Don't hesitate to select your post as Best Answer in order to close this thread (I did it for you this time ;) ).

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.