Search code examples
usbstm32

USB ENUMDNE interrupt not received until SDIS is set on STM32F446


I'm working on a USB device using the STM32F446ZE.

After successfuly initializing the USB FS OTG module in forced device mode and receiving a USBRST interrupt, no ENUMDNE is fired, even though the host recognizes the full speed device and starts sending setup packets on the bus (checked with a logic analyzer).

Interestingly, setting the SDIS bit later on to trigger a soft reset does cause an ENUMDNE interrupt to fire .. which seems backwards.

The hardware shouldn't be a problem since the DFU USB firmware works fine. I believe the PLLQ output is also correctly configured at 48 MHz and is selected as the source of the USB PHY clock.

From what I can understand from the (terrible) reference manual RM0390, the firmware I wrote should be enough to at least reach enumeration. I did not exactly follow the core and device initialization procedures given in sections 31.16.1 and 31.16.3, because they seem incomplete and done out of order. My code is hosted here.

Any clue as to what is missing from the initialization or might be misconfigured ?


Solution

  • Turns out I did not correctly configure the alternate functions of the DM and DP pins. My muxing function was only setting the GPIO_AFR register, and not the GPIO_MODER one.

    What lead me to this was the fact that reading the pins as GPIO inputs reflected the logic levels measured on the lines as expected. However reading from DEVLNSTS in OTG_DSTS always returned a low level. So the signal was somehow not reaching the USB module, and the only logical place where this could happen is at the alternate function multiplexer.

    Interestingly, I was still receiving the reset interrupt, because the USB module was seing an SE0 state (both DP and DM low). But the enumeration done interrupt never came because the DP high level at the end of the reset never reached the USB module.

    As for why the enumeration done interrupt came in when setting SDIS, I have yet to understand why that is exactly. My guess is the USB module internally pulls DP high and keeps DM low when soft disconnecting, which coincidentally also is the end of reset signal. Maybe.

    Anyways I only lost a hundred hours of my life on this, I'm not even slightly mad.