STM32 series of MCUs from ST Microelectronics are almost always armed with an USB peripheral. The USB port can be used as a USB device or host and is often used for DFU, serial output as a virtual COM port or as an HID device. Either way, “STM32 USB Device Not Recognized” or “failed to read device descriptors” are one of those common errors that you have to usually face as a USB product developer.
Here are some solutions to this common STM32 USB problem that we often encounter when developing firmware for our clients.
STM32 "USB Device Not Recognized" Error
This error shows up when you plug in your STM32 USB device (could be a custom PCB or an STM32 Discovery board).
A brief error description like “The USB device you connected malfunctioned” is not really helpful towards troubleshooting at all!
You might also get an error that says that “Windows failed to read USB device descriptors“.
After developing hundreds of applications and running into this error numerous types, I have listed every solution that I have used before in this article.
Solution 1: Check the STM32 PCB Design
PCB design can very rarely cause issues with a USB Full Speed device. The clock rate is simply not fast enough to matter unless you have made some crazy routing error like running the USB traces under a switching inductor.
Some things you should check on the PCB is:
- The length of the USB D+ and D- traces is short – less than 2 inches.
If the trace is longer, it needs to have the right differential impedance and width.
- Make sure the D+ and D- traces of the connector are connected to the D+ and D- pins of the STM32 respectively. Do not reverse them!
- Do not use an external pull up on the USB data line.
The STM32 handles that. Adding an external pullup can cause early detection by host before the STM32 can boot and handle the USB peripheral.
- Check the crystal value. It should be 8 MHz, 12 MHz, or anything that can produce 48 MHz USB clock accurately.
The USB schematics for STM32 are pretty straightforward. There are two 22 ohm series termination resistors that need to be placed close to the STM32 USB pins.
Everything else is optional. You can skip the USB OTG power switch in USB device designs. However, make sure VBUS is connected is VBUS detection is turned on!
If it was a hardware issue, you might have caught up with it by now.
Solution 2: Check the STM32 Clock Configuration
The clock source is very important with USB communication. The USB host will reject any USB device that has an erratic clock running its USB peripheral. We have seen this happen a lot with cheap chinese USB-UART bridge ICs with terrible resonators!
- Ensure that the STM32 is using the HSE crystal as the primary clock source.
- Double check to ensure that the crystal is actually active. You can prove the OSC_OUT pin to ensure this if you suspect a bad crystal.
- Make sure your program has the correct crystal oscillator frequency set! If you copied an STM32 USB example off the internet, this might be the problem.
Here is a reference from STM32CubeMX clock configuration utility for you to refer to. We know that this configuration works with a 8 MHz crystal!
In the RCC block configuration, make sure that the HSE source is properly selected.
Solution 3: Ensure that MX_USB_DEVICE_Init() is Called
Inside the file usb_device.c, you will find a function called MX_USB_DEVICE_Init() if you generated your code using the STM32CubeMX utility.
Make sure that this function is called and the function calls within it are completely successfully.
You can check this using the SWD interface of custom hardware or STM32 Discovery board.
Solution 4: Are USB Interrupts Enabled?
If USB interrupts are disabled, the STM32Cube USB device driver will not be able to respond to requests from the USB host.
While STM32CubeMX forces you to keep updates enabled for the USB block when you use that tool to generate startup code, you can still disable global interrupts in your code.
If your application disables interrupts, make sure you either leave the USB interrupts on or re-enable them as soon as possible!
Please fill in the Quick Contact form in the sidebar if you did something else that fixed the problem!
- Initial Release: 19 June 2021