AnsweredAssumed Answered

STM32 does not reset after DFU by USB

Question asked by chabin.laurent on Nov 17, 2017
Latest reply on Nov 17, 2017 by chabin.laurent

I have already read several posts about the subject. including "DFU: LEAVE does not jump to application".
and "Reset after firmware upgrade"

 

Context : 

STM32F072RB

using either DfuSeCommand.exe or DfuSeDemo

Using the DFU USB bootloader in system memory, started by sw from the main app.

Using DFU files

My API does not manipulate in any special way the vectors tables. Everything is standard from an auto generated  STM32CubeMX project.

My program is only in flash at 0x8000000

 

My need is basic and already discussed in other threads, yet I do not understand why this is so complex to solve that problem. Isn't there a little exec that does that in command line ? Or the problem is in my code ?

 

DfuSeCommand does work and upgrades using a DFU file, but does not make anything to leave the DFU mode.

 

My final need I want to modify DFuSeCommand so that it resets the chip.

 

However there is a sign that it is not that simple to do.

 

Using DfuSeDemo, after a DFU, clicking on "Leave DFU" displays "Successfully left DFU Mode!" but just makes the USB device disappear (nothing seen by USBLyzer (usb snifer)) as if the CPU had been reset or stalled, but not properly reset.  

 

As far as I understand, notes 1 and 2 of AN3156 do not apply to me

Note 2 says : "this procedure is not needed after exiting system memory boot mode". Am I right if I say that "Leave DFU" makes the CPU exiting system memory boot mode ? If yes, note 2 does not apply to me.

Note 1 says "The Jump to application works only if the user application sets the vector table correctly to
point to the application address" I don't understand that in my context. How could I set the vector table since we are running the system memory bootloader ? And in any case, 

 

Notes 2 says : "reset the core".  how do i reset the core ? I would be very surprise if it was by a NVIC_SystemReset();  since I would have to manage to avoid an infinite reset loop.

 

Then, what is wrong ? 

 

For the community, my useful code for starting DFU by SW

It works, but I need to cycle the power. That's my problem.

 

(Arm Keil)

 

/*
See CD00167594 p20
In addition to patterns described above, user can execute bootloader by performing a jump
to system memory from user code. Before jumping to Bootloader user must:
• Disable all peripheral clocks
• Disable used PLL
• Disable interrupts
• Clear pending interrupts
F0 : Memory Location 0x1FFFF6A6
bootloader firmware 12kb from 0x1FFFC800
USB DFU : PID = 0x448, BLID = 0xA1
*/

 

Since my  __initialize_hardware_early() is called just after power on reset, or a NVIC_SystemReset(),  I can assume that this is the case, right ? And by the way, the USB DFU works. It is the return from it that is a problem.

 

 

startup.s extract

 

; Reset handler routine
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT __initialize_hardware_early
LDR R0, =__initialize_hardware_early
BLX R0
LDR R0, =__main
BX R0
ENDP

 

 

code.c


#define SYSMEM_RESET_VECTOR 0x1fffC804
#define RESET_TO_BOOTLOADER_MAGIC_CODE 0xDEADBEEF
#define BOOTLOADER_STACK_POINTER 0x20002250

// do not initialize these ones
volatile uint32_t dfu_reset_to_bootloader_magic __attribute__( ( section( "NoInit"),zero_init) ) ;
void __initialize_hardware_early(void)
{
   if (dfu_reset_to_bootloader_magic == RESET_TO_BOOTLOADER_MAGIC_CODE)

   {
    void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *) SYSMEM_RESET_VECTOR));
   dfu_reset_to_bootloader_magic = 0;
    __set_MSP(BOOTLOADER_STACK_POINTER);
    bootloader();
    while (42); // NVIC_SystemReset(); instead seems to change things a little if a flash upgrade is indeed done. But that's quite random. How come the bootloader returns, shouldn't it reset when you leave ?
   }

   else

   {
     SystemInit();
   }
}

void startDFUMain(void)
{
  dfu_reset_to_bootloader_magic = RESET_TO_BOOTLOADER_MAGIC_CODE;
  NVIC_SystemReset();
}

Outcomes