cancel
Showing results for 
Search instead for 
Did you mean: 

Jump to USB DFU Bootloader in startup code on STM32F042

ethanzonca
Associate
Posted on February 21, 2015 at 18:11

I'm running a STM32F04 and want to jump to the USB DFU bootloader from user code. As recommended in other posts, I set a magic bit in SRAM, issue a soft reset, check for the magic value and branch to the bootloader if the magic value exists in the startup code.

My problem is that I branch to the bootloader but the F042 doesn't show up as a USB DFU device, it just seems to hang. I'm confident I have the correct memory addresses and I can't find any issues with my approach. Any ideas? Thanks.

Reset_Handler:
/* Bootloader jumping */
ldr r0, =0x200017F0 
/* address of magic token */
ldr r1, =0xDEADBEEF 
/* magic token */
ldr r2, [r0, #0] 
/* load data from magic address */
str r0, [r0, #0] 
/* zero data at magic address so we don't get stuck here */
cmp r2, r1 
/* compare data at magic address to magic token */
beq Reboot_Loader 
/* jump to bootloader if token match */
/* End bootloader jumping */
ldr r0, =_estack
mov sp, r0 
/* set stack pointer */
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit

// On reset, SP=value at address 0x0
ldr r0, =0x00000000
ldr r0, [r0, #0]
mov sp, r0
ldr r0, =0x1FFFC800 
/* Address of bootloader on f042 from CD00167594 pg 15 table 3 */
// Branch to bootloader
ldr r0, [r0, #4]
bx r0

#bootloader #dfu #stm32f0 #stm32f042-bootloader-dfu
27 REPLIES 27
vector950
Associate II
Posted on May 21, 2015 at 08:11

I have used the same code from you link and as I have mentioned above MCU in reset loop... And strange this MCU has VTOR register, why use SYSCFG_CFGR1 to remap?

Reboot_Loader

  LDR     R0, =0x40021034 ; RCC_APB2ENR (+0x34)

  LDR     R1, =0x00000001 ; ENABLE SYSCFG CLOCK

  STR     R1, [R0, #0]

  LDR     R0, =0x40010000 ; SYSCFG_CFGR1 (+0x00)

  LDR     R1, =0x00000001 ; MAP ROM AT ZERO

 

  STR     R1, [R0, #0]

  LDR     R0, =0x1FF00000 ; ROM BASE (STM32L051)

  LDR     R1, [R0, #0]    ; SP @ +0

  MOV     SP, R1

  LDR     R0, [R0, #4]    ; PC @ +4

  BX      R0

  END

Posted on May 21, 2015 at 11:20

And strange this MCU has VTOR register, why use SYSCFG_CFGR1 to remap?

That would make yours a very unique Cortex-M0 part.

May be you need to start over here, and more clearly explain what you're doing, how you're doing it, and your debugging process/observations.

For the ROM to work you're trying to hand control to it in as near to normal reset conditions as possible. If the system doesn't behave in the same manner as strapping BOOT0 High and resetting you're going to need to describe and identify what's actually happening.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Denis Krasutski
Associate III
Posted on May 26, 2015 at 00:06

>-My project don't use Watchdog.

>>The System Loader however typically does.

I am sure, my project don't launch watchdog and also don't update watchdog during run.

fenugrec
Associate II
Posted on May 26, 2015 at 16:35

Hi,

>>> My project don't use Watchdog.

>>The System Loader however typically does.

> I am sure, my project don't launch watchdog and also don't update watchdog during run.

You misunderstand. Regardless of what *your* code does, the System Loader (not programmed by you; built-in to the MCU) could possibly use the watchdog.

Denis Krasutski
Associate III
Posted on May 27, 2015 at 05:37

I know, but Clive1 make suggested that system bootloader not started because happened reset of watchdog,

Posted on May 27, 2015 at 05:41

The more specific point is that once the System Loader resets via a watchdog it won't reenter as it normally would have, because the BOOTx pins don't reflect the ROM execution state.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ethanzonca
Associate
Posted on May 30, 2015 at 06:38

Denis, how are you erasing your flash memory from user code? I gave up on jumping to the bootloader so I want to try your approach of erasing memory to blank the device and get into the bootloader that way.

I attempted a mass erase of the entire flash, but it appears to have bricked my processor... I'm guessing I overwrote the option bytes or did something else incorrectly. Thanks!

Denis Krasutski
Associate III
Posted on May 31, 2015 at 13:03

>

Denis

, howare you erasing your flash memory from user code? I prepared code witch execute from SRAM, but this mechanismnot stable, sometimes MCU requiredhardware restart for detecting in Dfu. I found solution with using ''Option Bytes'', 100% work solution!

void

GoToBootloader()
{
FLASH_OBProgramInitTypeDef OBParam;
HAL_FLASHEx_OBGetConfig(&OBParam);
OBParam.OptionType = OPTIONBYTE_USER;
/*Reset NBOOT0 and BOOT_SEL, see: RM 2.5 Boot configuration*/
OBParam.USERConfig = 0x77;

//Sorry for magic number :)

HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
HAL_FLASHEx_OBErase();
HAL_FLASHEx_OBProgram(&OBParam);
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
HAL_FLASH_OB_Launch();
}

Now CPU alway detected in Dfu after reboot, for switch CPU to normal mode you should restore ''Option bytes'' after flashing new firmware. 1. Use DfuSe 0690X00000605HVQAY.png 2. or use code(for case when you can jump to firmware after flashing)

void

CheckOB()
{
FLASH_OBProgramInitTypeDef OBParam;
HAL_FLASHEx_OBGetConfig(&OBParam);
if

(OBParam.USERConfig != 0xFF)
{
OBParam.OptionType = OPTIONBYTE_USER;
OBParam.USERConfig = 0xFF;
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
HAL_FLASHEx_OBErase();
HAL_FLASHEx_OBProgram(&OBParam);
HAL_FLASH_OB_Lock();
HAL_FLASH_OB_Launch();
}
}

Best Regards, Denis Krasutski
tarkles9
Associate
Posted on June 17, 2015 at 01:03

I stepped through the DFU firmware instruction by instruction, and discovered that it was checking the BOOT0 pin before allowing programming to continue. That's likely why you were experiencing the restarts (it was causing mine at least). Glad you guys worked out a better solution.

atx
Associate II
Posted on November 30, 2015 at 21:28

Are there any updates on this? Maybe an official code example or something. AN2606 claims that ''In addition to patterns described above, user can execute bootloader by performing a jumpto system memory from user code.'' but I cannot figure out how to actually make this work. I use following to jump to the bootloader right after .data and .bss get relocated in my Reset_Handler:

void enter_bootloader()
{
RCC->APB2ENR = RCC_APB2ENR_SYSCFGCOMPEN;
SYSCFG->CFGR1 |= SYSCFG_CFGR1_MEM_MODE_0;
__set_MSP(*bootloader_msp);
(*bootloader)();
/* Should never happen */
while (1) {}
}

The MCU seems to spend some time in the bootloader but then just ends up back in my Reset_Handler without doing anything.