I have an STM32F072 and am using the built-in bootloader (see AN3156) to flash it via DFU over USB. Flashing works fine, but often it fails to leave the bootloader afterwards.
I am using dfu-util
to flash (tried version 0.10 or latest from git):
dfu-util -a0 -D myfile.bin -s 0x08000000:leave
And when it fails to exit, I run this multiple times:
dfu-util -a0 -s 0x08000000:leave
I've went manually through the protocol steps for leaving DFU, and found it is always stuck in dfuMANIFEST
(manifestation stage). However, if I issue a bunch of DFU_GETSTATUS commands afterwards, it leaves DFU 100% of the time. This should not be neccessary. It looks like just generating some USB traffic causes it to complete. This makes me think that maybe the interrupt setup is not right.
I also tried pydfu.py
, which has the same problem. Example output of dfu-util
:
# /opt/whizcart/easytest/dfu-util -s 0x08000000:leave -a0
dfu-util 0.10-dev
[...]
Opening DFU capable USB device...
Device ID 0483:df11
Device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Interface #0 ...
Determining device status...
DFU state(10) = dfuERROR, status(10) = Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations
Clearing status
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash "
DfuSe command mode
Submitting leave request...
Transitioning to dfuMANIFEST state
I think the "device's firmware is corrupt" is a red herring, I've confirmed that it is OK. This is just the response dfu-util gives on any error. I sometimes also get:
[...]
DFU state(7) = dfuMANIFEST, status(0) = No error condition is present
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash "
DfuSe command mode
dfu-util: Failed to enter idle state on abort
The code I use to enter the bootloader is:
void reboot_to_bootloader(){
void (*jump_to_bootloader)(void);
volatile uint32_t addr = 0x1FFFC800;
//disable RCC, set to default
HAL_RCC_DeInit();
//disable systick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
//reset USB;
USB->BCDR=0;
//disable irqs
NVIC->ICER[0]=0xFFFFFFFF;
//map system flash to 0x00000000
SYSCFG->CFGR1 = 0x01;
jump_to_bootloader = (void (*)(void)) (*((uint32_t *)(addr + 4 )));
//set stack pointer
__set_MSP(*(uint32_t *)addr);
jump_to_bootloader();
}