case 08 · Personal · 2025
STM32 USB
A USB device implementation on the STM32F446RE — descriptor table, endpoint configuration, and enumeration over the on-chip OTG_FS peripheral.
↗ github.com/Prateek2174/usbWhat's in it
A usb.c / usb.h pair that brings the OTG_FS peripheral up
as a USB device — clock setup, endpoint allocation, and the descriptor responses
that let a host enumerate the board. main.c ties it together.
What was interesting
USB enumeration is one of those rituals where the host walks the device through a fixed sequence and any mistake — wrong descriptor length, late ack on EP0, a single byte off in the configuration descriptor — looks identical from the host side: "device descriptor request failed." The fun is in narrowing that down without a USB analyzer; mostly you stare at the OTG_FS interrupt status register and a log line per packet.
Notes
- OTG_FS clocked off the PLL with a 48 MHz target for USB.
- Control endpoint (EP0) handles standard requests directly.
- Designed as a starting point — easy to layer a class driver (HID, CDC) on top.
void usb_core_init(void){
USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_GINT; //Unmask core interrupts
USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; //Enable Rx FIFO non-empty
//Enable and choose at what FIFO level of Tx the interrupt fires
USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_PTXFEM;
USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_PTXFELVL;
//2. Program the following fields in the OTG_GUSBCFG register
USB_OTG_FS->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP; //Enable HNP capability
USB_OTG_FS->GUSBCFG |= USB_OTG_GUSBCFG_SRPCAP; //Enable SRP capability
//Set OTG_FS/OTG_HS timeout calibration field
USB_OTG_FS->GUSBCFG &= ~USB_OTG_GUSBCFG_TOCAL; //*****change this field if using external PHY
//Set USB turn around time field
USB_OTG_FS->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
USB_OTG_FS->GUSBCFG |= (0x6 << USB_OTG_GUSBCFG_TRDT_Pos);
//3. The software must unmask the following bits in the OTG_GINTMSK register
USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OTGINT;
USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_MMISM;
}
- MCU
- STM32F446RE
- Peripheral
- USB OTG_FS
- Speed
- Full-Speed (12 Mb/s)
- Build
- STM32CubeIDE
What's next
- CDC virtual COM port — implement the USB Communications Device Class on top of the existing device stack so the board appears as a serial port to the host; useful for debug output without a separate UART adapter
- DFU mode — add a Device Firmware Upgrade interface so firmware can be flashed over USB rather than a debug probe
- USB mass storage — expose an SD card or internal flash as a USB drive; requires a bulk-only transport layer on top of the endpoint logic
- USB HID — implement a HID descriptor to enumerate as a keyboard or gamepad; low endpoint count and straightforward report format make it a good next class to tackle