Skip to main content
Lee3
Associate III
August 28, 2019
Question

STM32F4 USB DFU bootloader not working reliably

I have a self powered STM32F446 with 24 MHz oscillator, not crystal. When trying to activate the bootloader mode, I get variable results. Sometimes it shows up properly, sometimes it shows up but in a corrupted type of state, and sometimes it doesn't come up at all. The corrupted states seems to get most of the usb descriptors correctly, but the string descriptors don't come up as well.

I use USB in the main application mode of my program as well, and that works without issue.

A previous design with the F446 that was usb powered, 24 MHz crystal had no issues. Some of the pinout has changed between designs. Any ideas where I should be looking? Improper clock detection? Other bootloader mode activated, but still somewhat communicating over USB?

Example top of descriptor, corrupted,

Device Descriptor:
 bLength 18
 bDescriptorType 1
 bcdUSB 1.00
 bDeviceClass 0 (Defined at Interface level)
 bDeviceSubClass 0 
 bDeviceProtocol 0 
 bMaxPacketSize0 64
 idVendor 0x0483 STMicroelectronics
 idProduct 0xdf11 STM Device in DFU Mode
 bcdDevice 22.00
 iManufacturer 1 (error)
 iProduct 2 (error)
 iSerial 3 Љ
 bNumConfigurations 1
 Configuration Descriptor:
 bLength 9

This topic has been closed for replies.

6 replies

Tesla DeLorean
Guru
August 28, 2019

AN2606 would indicate the pins which the ROM is looking for activity on.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Lee3
Lee3Author
Associate III
August 28, 2019

Then my question there is if it possible that it could potentially partially communicate over usb if it entered a different mode. If so then I'd look more into the pin states and forcing them low, etc.

Lee3
Lee3Author
Associate III
August 29, 2019

I can connect the debugger when the bootloader is running and see that in fact it's detecting the oscillator as 23 MHz when usb doesn't work. It addition the bootloader does not set HSEBYP. So is it just that the bootloader is not compatible with oscillators, only crystals?

Lee3
Lee3Author
Associate III
August 30, 2019

So it seems that the issue is just poor HSI accuracy such that autodetect doesn't work. My measured HSI is 16.4 MHz. This is described here: https://community.st.com/s/article/FAQ-DFU-mode-with-system-bootloader-is-not-working-while-USB-does

My workaround is to trim hsi. This won't help for a brand new board, but it does for reboot to bootloader from application code. Here is some code:

// Find the best value of hsi_trim
uint8_t calibrate_hsi(uint8_t hse_freq) {
 // hsi frequency is supposed to be 16 MHz
 // Switch to hsi for sysclk, connect hse_rtc to tim11 for counting
 RCC->APB2ENR |= RCC_APB2ENR_TIM11EN;
 RCC->CFGR &= ~(RCC_CFGR_SW | RCC_CFGR_PPRE2); // HSI at 16MHz for sysclk, APB2 at 16MHz for TIM11
 RCC->CFGR |= (uint32_t) hse_freq << RCC_CFGR_RTCPRE_Pos; // HSE_RTC at 1 MHz
 
 TIM11->OR = 2;
 TIM11->CR1 |= TIM_CR1_CEN;
 TIM11->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_IC1PSC; // input capture IC1, max prescaler, 8
 TIM11->CCER |= TIM_CCER_CC1E; // enable input capture
 
 int16_t min_error = INT16_MAX;
 uint8_t min_hsi_trim = 0x10;
 for (uint32_t i=0; i<=0x1F; i++) {
 uint32_t hsi_trim = i << RCC_CR_HSITRIM_Pos;
 RCC->CR &= ~RCC_CR_HSITRIM;
 RCC->CR |= hsi_trim;
 
 uint16_t start_count = TIM11->CCR1;
 uint16_t tmp[10];
 for (int j=0; j<10; j++) {
 while(!(TIM11->SR & TIM_SR_CC1IF)); // wait for capture
 tmp[j] = TIM11->CCR1;
 } 
 // The ideal total count is 10*8*16
 uint16_t total_count = TIM11->CCR1 - start_count;
 int16_t error = 10*8*16 - (int16_t) total_count;
 if (abs(error) < abs(min_error)) {
 min_hsi_trim = i;
 min_error = error;
 }
 }
 return min_hsi_trim;
}
 
// Call bootloader, trigger is go_to_bootloader==1 on reboot + software reset
uint8_t go_to_bootloader = false;
uint32_t hsi_trim = 0x10l << RCC_CR_HSITRIM_Pos;
void reboot_to_bootloader() {
 __disable_irq();
 go_to_bootloader = true;
 hsi_trim = (uint32_t) calibrate_hsi(get_pin_config()->crystal_frequency_MHz) << RCC_CR_HSITRIM_Pos;
 NVIC_SystemReset();
}
.section .text
Reboot_Loader:
 ldr r0, =0x40023844 /* RCC_APB2ENR */
 ldr r1, =0x00004000 /* ENABLE SYSCFG CLOCK */
 str R1, [R0, #0]
 ldr r0, =0x40023800 /* RCC_CR */
 ldr r1, =hsi_trim
 ldr r1, [r1]
 str r1, [r0]
 ldr R0, =0x40013800 /* SYSCFG_MEMRMP */
 ldr R1, =0x00000001 /* MAP ROM AT ZERO */
 str R1, [R0, #0]
 ldr R0, =0x1FFF0000 /* ROM BASE */
 ldr SP,[R0, #0] /* SP @ +0 */
 ldr R0,[R0, #4] /* PC @ +4 */
 bx R0

Tesla DeLorean
Guru
August 30, 2019

Thanks for details

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..