1
\$\begingroup\$

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();
}
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.