2021-06-06 02:38 PM
Hello gents!
I'm trying to implement jump to DFU mode from the app (bootloader), without usage of BOOT0 pin. Logic should be following: if the user button is pressed during device startup (USB cable plug in) more than 3 sec, then device should go to DFU mode (or read image from SD card in future plans), otherwise - jump to user app.
It works fine if delay is below 300ms, but if I increase it above 300ms - USB device is not enumerating somehow, I don't see it in dfu-util of lsusb commands. Is there any time limits for connected USB device to enumerates?
I tried to play with DP pin pull up/down, but it did not help. Also performed peripheral deinit (not sure if it is needed as I perform system reset anyway...) - did not help too.
Jump code in boot loader is following:
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
HAL_GPIO_WritePin(USB_DP_Port, USB_DP_Pin, GPIO_PIN_RESET);
MX_SPI1_Init();
led_init();
led_setIntensity(3);
MX_USB_DEVICE_Init(); // USB init for future CDC usage
uint32_t timeoutMs = HAL_GetTick() + 3000; // button press delay. Works fine if delay is < 300 ms
if (HAL_GPIO_ReadPin(BUT_PIN_GPIO_Port, BUT_PIN_Pin) == GPIO_PIN_RESET) {
stringToLED(" -BOOT- ", 0);
while (HAL_GetTick() < timeoutMs) {
if (HAL_GPIO_ReadPin(BUT_PIN_GPIO_Port, BUT_PIN_Pin) == GPIO_PIN_SET) {
Run_App(); // jump to user app if button is released within button press delay
}
}
HAL_GPIO_WritePin(USB_DP_Port, USB_DP_Pin, GPIO_PIN_SET);
stringToLED("DFU ON", 0);
*((unsigned long *)0x2001FFF0) = RESET_TO_BOOTLOADER_MAGIC_CODE; // DFU mode flag to read in System_Init
MX_USB_DEVICE_DeInit();
NVIC_SystemReset(); // Reset to jump in System_ Init
} else {
Run_App();
}
while (1) {
}
}
void SystemInit(void)
{
if ( *((unsigned long *)0x2001FFF0) == RESET_TO_BOOTLOADER_MAGIC_CODE ) { // read DFU mode flag
*((unsigned long *)0x2001FFF0) = 0; // Reset it
__set_MSP(0x20020000); // set stack pointer to SRAM end
// 0x1fff0000 is "System Memory" start address for STM32 F4xx
SysMemBootJump = (void (*)(void)) (*((uint32_t *) 0x1fff0004)); // Point the PC to the System Memory reset vector (+4)
SysMemBootJump(); // jump to System memory code
while (1);
}
...
}
Any thoughts on it?
2021-06-06 03:27 PM
Consider delaying initialization of USB until after you enter RunApp.
Or add a 1s or so delay just before NVIC_SystemReset so the system has time to realize the USB device was disconnected and tries to reenumerate it again.
2021-06-07 12:46 AM
As you can see in code I have 3 sec delay in while loop before enter SystemReset, and DFU doesn't work with this delay. But if I reduce it to 300 ms or less, then it is initializing normally as DFU device.
Run_App is not affected here at all, it performs jump to user app if the button is not pressed at startup.
2021-06-07 05:37 AM
Your delay is before MX_USB_DEVICE_DeInit, not after.
Disconnecting a USB device and immediately connecting another device can trip up windows because it expects the original device to still be there.
2021-06-07 05:56 AM
Ok, may be reasonable, will try to rearrange or add delay after DeInit. Thanks.
2021-06-07 12:38 PM
No, delay before SysetReset did not help...
Still no DFU if delay between USB plug in and reset to DFU mode is more than 300 ms.
2021-06-08 01:18 AM
I found bootloader timing description in AN2606 but it is about minimum timing for bootloader initialization. In my case I have delay before device reset and bootloader init.
2021-06-08 09:57 AM
According to this, the device (DFU or normal firmware) must enumerate within ~ 1.5 s. after the host detects attachment on the USB port.
"the hub driver will attempt to retry enumeration up to 3 times by returning to the beginning of the “First Port Reset�? state.
A delay of 500ms occurs between each retry to allow the device to settle.
If the port reset times out on the 3rd retry, enumeration will be cancelled and an “Unknown Device�? will be reported".
So, do not let the host detect attachment until you're ready to enumerate.
-- pa