cancel
Showing results for 
Search instead for 
Did you mean: 

Starting bootloader from software on STM32F427 to use the USB port in DFU

MarcoM
Associate II

Hello, I am trying to start the bootloader on a STM32F427 to program the MCU via USB port in DFU mode. I am not new to this topic because I wrote some programs for STM32F072 where I can successfully start the bootloader and take externally control of the MCU via serial port (there I don't need to program the boards via USB). In that products my software calls correctly the bootloader that works without any problem.

On this new design there is a bigger STM32F427; this time I need to program the MCU via the USB port and not via an UART. Here is the problem:

  • If I start the bootloader using hardware signals (BOOT0 and RESET), all works as it should do: using STM32CubeProgrammer I can take control both via an UART or via the USB port.
  • If I start the bootloader by software, STM32CubeProgrammer can take control only via the UART: the USB port doesn't start in DFU mode so the programmer doesn't find it.

After many attemps, to have a clean situation I finally put the bootloader call as the very first instruction in the main(). Despite this, I always have the same result: the bootloader starts but programmer works correctly via the UART and it doesn't see at all the USB port because it doesn't start in DFU mode.

This is the code I use to launch the bootloader (remember, after several tests now I call it as the first instruction in main() ). The code of this functions is derived from the many examples about starting bootloader, and (with the proper address) it is the same I use on smaller STM32F072.

/*

JumpToBootloader()

*/

void JumpToBootloader(void) {

void (*SysMemBootJump)(void);

/**

* Step: Set system memory address.

*

*    For STM32L051, system memory is on 0x1FF00000

*    For STM32F051, system memory is on 0x1FFFEC00

*    For STM32F070xB, system memory is on 0x1FFFC800

*    For STM32F072, system memory is on 0x1FFFC800

*    For STM32F4xx, system memory is on 0x1FFF0000

*/

volatile uint32_t addr = 0x1FFF0000;

/**

* Step: Disable RCC, set it to default (after reset) settings

*    Internal clock, no PLL, etc.

*/

HAL_RCC_DeInit();

  HAL_DeInit();

/**

* Step: Disable systick timer and reset it to default values

*/

SysTick->CTRL = 0;

SysTick->LOAD = 0;

SysTick->VAL = 0;

/**

* Step: Disable all interrupts

*/

__disable_irq();

/* ARM Cortex-M Programming Guide to Memory Barrier Instructions.*/

__DSB();

/**

* Step: Remap system memory to address 0x0000 0000 in address space

*    For each family registers may be different.

*    Check reference manual for each family.

*

*/

  __HAL_RCC_SYSCFG_CLK_ENABLE();

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

  /* Remap is bot visible at once. Execute some unrelated command! */

  __DSB();

  __ISB();

/**

* Step: 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)));

/**

* Step: 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);

/**

* Step: Actually call our function to jump to set location

*    This will start system memory execution

*/

SysMemBootJump();

}

Can anyone help me to understand why after this the USB port doesn't start in DFU mode (but the UART works)? And why the USB port starts in DFU mode if I instead launch the bootloader by hardware?

Thank you very much.

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

Try this code

int main(void) {
  volatile uint32_t * vect = 0x1FFF0000;
#if 0
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
  __DSB();
  __ISB();
#endif
  asm volatile(
    "mov sp, %[boot_sp]\n\t"
    "bx %[boot_pc]\n\t"
    :: [boot_sp]"r"(vect[0]), [boot_pc]"r"(vect[1])
  );
}

If it works (with or without the block enclosed by #if/#endif), try adding init and deinit stuff back in pairs, and see where it breaks.

I suspect that it does not like the part where you disable all irqs, rather disable them one by one. Don't disable systick like an irq!

View solution in original post

5 REPLIES 5
TDK
Guru

Are all other bootloader options (usart, spi, etc) idle when trying to connect on usb dfu? If the bootloader sees a signal on usart, it will no longer respond to the usb.

If you feel a post has answered your question, please click "Accept as Solution".
MarcoM
Associate II

Yes, they are idle. When I try to connect via USB, it is the only port connected. If I instead connect the programmer via USART it works, meaning that in that moment the MCU is scanning the various ports.

The problem is that the USB port appears inactive, so it is not listed in the PC device list, and for the same reason the programmer doesn't see it as DFU.

berendi
Principal

Try this code

int main(void) {
  volatile uint32_t * vect = 0x1FFF0000;
#if 0
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
  __DSB();
  __ISB();
#endif
  asm volatile(
    "mov sp, %[boot_sp]\n\t"
    "bx %[boot_pc]\n\t"
    :: [boot_sp]"r"(vect[0]), [boot_pc]"r"(vect[1])
  );
}

If it works (with or without the block enclosed by #if/#endif), try adding init and deinit stuff back in pairs, and see where it breaks.

I suspect that it does not like the part where you disable all irqs, rather disable them one by one. Don't disable systick like an irq!

MarcoM
Associate II

Hi Berendi,

thank you, it works!

Your code starts correctly the bootloader and the USB goes in DFU mode, so I can take control with the programmer.

It is needed to enclose the block #if/#endif, otherwise I don't get DFU mode.

In this moment I still don't know what in my original code breaks the operations. I will soon investigate to better understand what's wrong (and what to avoid). Now the priority is to show to my customer that the device can be updated from the USB port... it is very important because this is the last required feature of the device...

Thank you very much again!

Marco

NPati.1
Associate

0693W000003RmlaQAC.pngThanks Berendi the above code . It is working fine. But I am trouble while upgrade the firmware using DfuSe application. I am using STM32F072 MCU and jump to bootloader address 0x1FFFC800. I am writing logic in such way that when i pressed the key then it will jump to bootloader.

Doing following steps for firmware upgrade.

1) press the key and it call Jump_To_Bootloader() function

void Jump_To_Bootloader(void)

{

volatile uint32_t * vect = (uint32_t *)0x1FFFC800;

__HAL_RCC_SYSCFG_CLK_ENABLE();

__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();

__DSB();

__ISB();

__asm__ volatile(

"mov sp, %[boot_sp]\n\t"

"bx %[boot_pc]\n\t"

:: [boot_sp]"r"(vect[0]), [boot_pc]"r"(vect[1])

);

}

2) Opened the DfuSe Demo (v3.0.6). The device is detected successfully. 

3) Choose the dfu file and click on upgrade. The firmware upgrade successfully

4) When click to verify then it shows data is not matching. please find snippet. Due to this my device is not functioning properly.

5) When I do the Boot0 pin as high and do the firmware upgrade and do verify then the data verify successfully.

Thank you

Please suggest me.