This technical deep dive demonstrates the integration of the TinyUSB open-source stack with STM32 microcontrollers as a high-performance alternative to vendor-specific middleware like STβs USB Device library or the Azure RTOS USBX/ThreadX ecosystem. The process utilizes an STM32H743-based hardware platform to implement a dual-port Communications Device Class (CDC) virtual COM port.
The workflow encompasses low-level peripheral configuration in STM32CubeIDE, including critical 48 MHz clock synchronization and interrupt management. Key implementation stages include the manual inclusion of the TinyUSB source tree, the definition of the tusb_config.h header to specify MCU architecture and FIFO parameters, and the customization of USB descriptors for vendor/product IDs and device enumeration. The final firmware architecture relies on a non-blocking background task (tud_task) and a redirected Interrupt Service Routine (ISR) to handle USB events. Functional validation is confirmed through host-side enumeration and a bidirectional echo test across multiple CDC interfaces.
Engineering Summary: TinyUSB Integration for STM32 Microcontrollers
0:00 TinyUSB Overview: TinyUSB is highlighted as a cross-platform, open-source USB host/device stack suitable for various MCUs (ST, NXP, TI) and supports multiple classes including CDC, HID, MIDI, and Audio.
0:55 Architectural Rationale: The stack serves as a lightweight alternative to the newer USBX/ThreadX requirements in the STM32 ecosystem, offering easier integration for complex classes like MIDI or multi-port CDC.
4:45 Hardware Specifications: The demonstration uses an STM32H743 with a USB-C interface. The design includes ESD protection on differential pairs and a 26 MHz external CMOS oscillator, though internal oscillators can suffice for 48 MHz USB clock generation on certain SKUs.
5:28 CubeIDE Peripheral Configuration: The USB peripheral must be set to "Device Only" (or Host/OTG) with the "USB On-The-Go Full Speed Global Interrupt" enabled. Crucially, manufacturer middleware (HAL/USBX) must remain disabled to avoid stack conflicts.
7:13 Clock Tree Requirements: The USB peripheral requires a precise 48 MHz clock. The configuration demonstrates bypassing internal drivers to use an external CMOS source via the RCC settings.
8:42 Source Code Integration: The TinyUSB source folder is manually added to the Core directory of the project. The compiler's include paths must be updated to reference this new source directory for both Debug and Release builds.
10:09 Stack Configuration (tusb_config.h): A configuration header is created to define the target MCU (CFG_TUSB_MCU_STM32H7), the operating port, and speed parameters. For this demo, a dual-port CDC class is defined, necessitating specific FIFO and endpoint buffer allocations.
15:25 USB Descriptors: Device descriptors (VID, PID, Product Name) are implemented. A specific function, board_usb_get_serial, is utilized to fetch the unique STM32 UID for device string identification.
17:28 ISR Redirection: Within stm32xx_it.c, the default HAL interrupt handler (HAL_PCD_IRQHandler) is bypassed. It is replaced by tud_int_handler(0, true) to ensure the TinyUSB stack processes all low-level bus events.
18:46 Main Loop Execution: Firmware initialization requires calling tusb_init(). The background service routine, tud_task(), must be called periodically in the main while(1) loop to handle enumeration and data processing.
20:01 Callback Mechanisms: The stack provides weakly defined callbacks (e.g., tud_mount_cb, tud_umount_cb) for application-level event handling. Class-specific functions from cdc_device.h are used for I/O operations.
21:54 Functional Validation: Successful implementation is verified via Windows Device Manager, showing two distinct COM ports. Bidirectional data integrity is confirmed using a terminal emulator (Tera Term) to execute an echo test at 115200 baud.