Skip to main content

STM32 USB Implementation

STM32 provides four kinds of USB peripherals as shown below. You can refer to the CDC code generated by the code generator to understand how USB endpoints are configured.

NameRoleBidirectional EndpointsDouble BufferingDMA Support
USB_DEVICE_FSDeviceHW double buffer not bidirectionalSoftware/HardwareNot supported
USB_DRV_FSHost/DeviceHW double buffer not bidirectionalSoftware/HardwareNot supported
USB_OTG_FSHost/DeviceBidirectionalSupportedNot supported
USB_OTG_HSHost/DeviceBidirectionalSupportedSupported

USB_DEVICE_FS/USB_DRV_FS

Two endpoint declaration styles are supported; endpoint numbers for the buffers auto-increment:

  1. {usb_fs_ep0_in_buf, usb_fs_ep0_out_buf, 8, 8}: declares a bidirectional endpoint; hardware double buffering is not available
    • usb_fs_ep0_in_buf: EP0 IN software buffer array
    • usb_fs_ep0_out_buf: EP0 OUT software buffer array
    • 8: EP0 IN hardware RAM size
    • 8: EP0 OUT hardware RAM size
  2. {usb_fs_ep2_in_buf, 16, true}: declares a unidirectional endpoint using hardware double buffering
    • usb_fs_ep2_in_buf: EP2 IN software buffer array
    • 16: EP2 IN hardware RAM size

To ensure throughput, for Bulk endpoints the hardware RAM size should be no less than 64. The software buffer can be much larger than 64, and its size is proportional to transfer speed.

STM32USBDeviceDevFs usb_fs(
/* USB Handler */
&hpcd_USB_FS,
/* Endpoints */
{
{usb_fs_ep0_in_buf, usb_fs_ep0_out_buf, 8, 8},
{usb_fs_ep1_in_buf, usb_fs_ep1_out_buf, 128, 128},
{usb_fs_ep2_in_buf, 16, true}
},
USB::DeviceDescriptor::PacketSize0::SIZE_8,
0x483, 0x5740, 0xF407,
{&USB_FS_LANG_PACK},
{{&usb_fs_cdc}}
);

USB_OTG_FS/USB_OTG_HS

STM32USBDeviceOtgHS and STM32USBDeviceOtgFS also support two endpoint declaration styles. IN and OUT endpoint numbers each auto-increment independently:

  1. {{usb_otg_fs_ep0_in_buf, 8},...}: IN endpoints must declare both a buffer and a FIFO size
  2. {usb_otg_fs_ep0_out_buf, ...}: OUT endpoints only need to declare a buffer

All OUT endpoints share a single RX FIFO, which should be given a relatively large size. For performance, the IN endpoint FIFO size should not be smaller than the packet size, and the software buffer size is proportional to transfer speed.

// STM32USBDeviceOtgHS usb_hs(
STM32USBDeviceOtgFS usb_fs(
/* USB Handler */
&hpcd_USB_OTG_FS,
/* RX Fifo Size */
256,
/* Out Endpoints */
{usb_otg_fs_ep0_out_buf, usb_otg_fs_ep1_out_buf},
/* In Endpoints */
{{usb_otg_fs_ep0_in_buf, 8}, {usb_otg_fs_ep1_in_buf, 128}, {usb_otg_fs_ep2_in_buf, 16}},
USB::DeviceDescriptor::PacketSize0::SIZE_8,
0x483, 0x5740, 0xF407,
{&USB_OTG_FS_LANG_PACK},
{{&usb_otg_fs_cdc}}
);
usb_fs.Init();
usb_fs.Start();

Running

Just add the following statements:

usb_fs.Init();
usb_fs.Start();