Skip to main content
Visitor II
November 7, 2020
Question

Can't make software jump to Bootloader/DFU on STM32F767

  • November 7, 2020
  • 5 replies
  • 3643 views

I've read various articles/guides how to jump to bootloader form main program (without using boot0 pin and reset). All code that I've tried seems to fail...

My current approach is like this:

#define BOOTLOADER_ADDR 0x1FF00000U
 
void (*SysMemBootJump)(void);
 
void JumpToBootloader(void)
{
	vTaskSuspendAll();
	HAL_RCC_DeInit();
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;
	__disable_irq();
	SysMemBootJump = (void (*)(void)) (*((uint32_t *)(BOOTLOADER_ADDR + 4)));
	__set_MSP	(*((uint32_t*) BOOTLOADER_ADDR));
 	SysMemBootJump();
 	while(1);
}

Looks good but it doesn't work... however not completely....

When I use Boot0 pin and reset it STM32F767VIT goes to bootloader/DFU mode and DfuSe detects STM32F7 device correctly.

When runs code as above, it jumps somewhere, but DfuSe do not detect device to flash. After a while Windows reports unknown device - 43 error code (A request for the USB device descriptor failed). It seems that I'm close... but no clue how to fix it :unamused_face:

Edit:

I wonder if FreeRTOS is causing incorrect behaviour of bootloader. I've added "vTaskSuspendAll()" but this seems to be not enough.

Edit2:

To avoid FreeRTOS at this stage, I've called JumptoBootLoader() as first instruction in main() - nothing changes. Detected USB device is broken - 43 error code (A request for the USB device descriptor failed).

best regards

Mikolaj Tutak

    This topic has been closed for replies.

    5 replies

    Graduate II
    November 8, 2020
    NixzAuthor
    Visitor II
    November 8, 2020

    Yes, this is one of the best I've found. My code is strictly based on this tutorial.

    I wonder is FreeRTOS related issue? I've added vTaskSuspendAll(); in the beginning but without any change...

    Graduate II
    November 8, 2020

    you miss or remove

        //Remap by hand... {

    #if defined(STM32F4)

        SYSCFG->MEMRMP = 0x01;

    #endif

    #if defined(STM32F0)

        SYSCFG->CFGR1 = 0x01;

    #endif

        //} ...or if you use HAL drivers

        //__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();    //Call HAL macro to do this for you

    you use F7XX then i recommend use __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();    //Call HAL macro to do this for you

    NixzAuthor
    Visitor II
    November 8, 2020

    I've tried "SYSCFG->MEMRMP = 0x01;" but it seems that this is not needed on STM32F7, anyway it doesn't changed anything (windows reports USB device with error code).

    I could use "__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH()" but this is not included in my HAL firmware anywhere. If you have one for F767 please share, I will try it.

    Edit:

    The only existence of remap macro I've found is in "stm32_hal_legacy.h" header:

    #define __HAL_REMAPMEMORY_SYSTEMFLASH __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH

    But this doesn't help much...

    Graduate II
    November 8, 2020

    Hmm you have right try coment out disabling irq from your code.

    NixzAuthor
    Visitor II
    November 8, 2020

    Oh yes! It works from non FreeRTOS (before osKernelInitialize()). From FreeRTOS it is restarting. Have to add something to disable FreeRTOS.

    Current approach is (no disabling irq, no memory remap):

    #define BOOTLOADER_ADDR ((bootloader_t *)0x1FF00000UL)
     
    struct bootloader_t
    {
    	uint32_t stackptr;
    	void (*jumpptr)(void);
    } *bootloader = BOOTLOADER_ADDR;
     
    void JumpToBootloader(void)
    {
    	HAL_RCC_DeInit();
    	SysTick->CTRL = 0;
    	SysTick->LOAD = 0;
    	SysTick->VAL = 0;
    	__set_MSP(bootloader->stackptr);
    	bootloader->jumpptr();
    	while(1);
    }

    Graduate II
    November 9, 2020

    For similar purpose i use IWDG or WWDG reset and in main detect it and start before RTOS what you need.

    NixzAuthor
    Visitor II
    November 9, 2020

    You mean that you set WDG flag and make reset and during startup you check the reason of reset and enter bootloader if needed? That sounds like idea worth to try.

    Do you use IWDG/WWDG or just manually trigger it for purpose of doing something special before starting FreeRTOS scheduler? Could you share your code you are using trigger such request?

    Graduate II
    November 9, 2020

    I manualy enable it

    // WWDG configuration

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);

    WWDG_SetPrescaler(WWDG_Prescaler_8);

    WWDG_SetWindowValue(80); 

    WWDG_Enable(244);

    while(1);

    and after reboot detect

    int main(void)

    {

    if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) )

    {

    RCC_ClearFlag();

    //here do what you need

    JumpToBootloader();

    }

    Graduate II
    November 10, 2020

    After you set RDP 1 you need i mean remove power from MCU. When this dont work , i only see use own bootloader writed in FLASH.

    NixzAuthor
    Visitor II
    November 11, 2020

    Hi,

    Yes, I've removed power. It was working with software jump with protection on level 0 not level 1. Entering bootloader with Boot0 pin worked in all cases.

    Finally I've found solution - jump have to be made before all init stuff, possibly in the first line of main(). It works so good now without deinit that "Leave DFU" returns control to main so it is worth to replace endless loop with "NVIC_SystemReset();". Here is my code:

    int main(void)
    {
     /* USER CODE BEGIN 1 */
    	if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST))
    	{
    		__HAL_RCC_CLEAR_RESET_FLAGS();
    		JumpToBootloader();
    	}
     /* USER CODE END 1 */
    ....
    }

    In this case JumpToBootloader() function can be simplified:

    #define BOOTLOADER_ADDR (0x1FF00000UL)
     
    struct bootloader_t
    {
    	uint32_t stackptr;
    	void (*jumpptr)(void);
    } *bootloader = (bootloader_t *)BOOTLOADER_ADDR;
     
    void JumpToBootloader()
    {
    	__set_MSP(bootloader->stackptr);
    	bootloader->jumpptr();
    	NVIC_SystemReset();
    }

    Thank you for all the hints and ideas helped me solve this ^&*$&^#^*% bootloader thing =)

    PS: Last step will be prepare hex with option bytes to prepare one DFU file with all required parameters (firmware, protection, BOR lever etc).