cancel
Showing results for 
Search instead for 
Did you mean: 

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

Nixz
Associate III

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

15 REPLIES 15

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

}

Nixz
Associate III

Thank you, finally I'm almost there. My code goes like this:

#define BOOTLOADER_ADDR (0x1FF00000UL)
struct bootloader_t
{
	uint32_t stackptr;
	void (*jumpptr)(void);
} *bootloader = (bootloader_t *)BOOTLOADER_ADDR;
 
void JumpToBootloader()
{
	HAL_RCC_DeInit();
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;
	__set_MSP(bootloader->stackptr);
	bootloader->jumpptr();
	while(1);
}
void KickWWDG()
{
	SET_BIT(RCC->APB1ENR, RCC_APB1ENR_WWDGEN);
	WRITE_REG(WWDG->CFR, WWDG_CFR_WDGTB_0|WWDG_CFR_WDGTB_1|80);
	WRITE_REG(WWDG->CR, WWDG_CR_WDGA|120);
	while (1);
}

Now it works until I will change "read protection" from 0 to 1 in option bytes. When protection is set to Level 1 it enter continuous boot loop: first welcome displays banner on UART, debug info, jumps to Boot loader and display some garbage on UART (expected) and then instantly reboots.

It reboots same way when triggered with WWDG as well called directly from main().

Interesting is that with BOOT0 pin Bootloader is working as before (with or without protection). The only difference is that DfuSe can't read from protected flash ;)

----------------------------------------------
Starting ReClock MCU v3.x platform
Powered by STM32F67VIT@216.0MHz
FreeRTOS V10.2.0, CMSIS V2.1
Free heap: 28.6kB
Newlib 2.5.0
----------------------------------------------
Warning: Starting after PIN reset
JumpToBootloader()
MSP: 0x20003420
PROC: 0x1FF00211
<?▒▒<?▒<▒▒<8▒<▒▒<▒▒<▒<▒<▒▒<▒▒<▒▒<▒▒<8▒▒▒<x▒<▒▒<▒▒<▒▒▒<▒<▒▒<▒▒<▒▒<8▒<8▒<p<8▒<▒<▒▒<▒▒<8▒<?▒<▒<▒▒<p<▒▒<?▒▒▒▒▒▒▒▒▒▒<▒<▒<▒▒<<▒▒<▒<p<x▒<▒<▒▒<▒▒<x▒<▒<▒▒<▒▒<▒<▒▒<▒▒<▒▒<?▒▒▒▒▒▒▒<▒▒▒<▒<▒<▒▒<▒<▒▒<▒<▒▒▒<8▒<▒▒<▒▒<▒<▒<<▒▒▒<▒▒<▒<▒<▒▒<▒▒<▒<▒▒▒▒▒<▒▒▒<▒

How you change this RDP ? With STLink utility?

Nixz
Associate III

Exactly.

First I was testing with removed protection (level 0), and it was working just fine (direct call from main or by WWDG or Boot0 pin).

Then I've changed protection to level 1 (wit ST-Link Utility) and with protected chip I can enter bootloader only only with Boot0 pin.

When using software way (WWDG or direct) bootloader loads, send some garbage on UART3 (this is expected) and the it restarts... I would say that it stays in boot loader about 100ms...

MM..1
Chief II

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.

Nixz
Associate III

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