Skip to main content
Visitor II
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
    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

    Graduate II
    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.

    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.

    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?

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

    Super User
    October 30, 2020
    Look at RCC->CSR to find the reason for the reset.
    Graduate II
    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.

    Answer
    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);
    }
    November 2, 2020

    *edit: found solution, see above.

    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 ;) ).