extmod/machine: Add USB Host support.#7
Draft
andrewleech wants to merge 13 commits intoreview/machine-usbhostfrom
Draft
extmod/machine: Add USB Host support.#7andrewleech wants to merge 13 commits intoreview/machine-usbhostfrom
andrewleech wants to merge 13 commits intoreview/machine-usbhostfrom
Conversation
Adds TinyUSB USB Host wrapper providing CDC/HID/MSC device management, transfer handling, and GC integration. The implementation includes: - mp_usbh.c: Core TinyUSB host wrapper with device enumeration, transfer management, and class-specific interfaces (CDC, HID, MSC) - mp_usbh.h: Host configuration, init sequence, and device structs - tusb_config.h: Extended configuration to support USB Host mode with fallback values when USB Device is disabled - mp_usbd.h: Updated to include tusb_config.h unconditionally for macros used across device and host implementations The mp_usbh_init_tuh() init sequence handles two edge cases: - On shared-port boards (BOARD_TUH_RHPORT == TUD_OPT_RHPORT), calls tud_deinit() first to remove the device IRQ handler before the host resets the hardware. - Pre-sets _tusb_rhport_role to TUSB_ROLE_HOST before tuh_init() to prevent an ISR race where a connected device triggers the host interrupt before the role is set, causing an infinite loop. Updates lib/tinyusb submodule to version 0.20.0 which includes USB Host driver improvements and bug fixes required for this implementation. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Implements the Python-facing machine.USBHost() class providing USB Host functionality for MicroPython. The implementation includes: - machine_usb_host.c: Complete USBHost class with device enumeration methods (cdc_devices(), hid_devices(), msc_devices()), connection management, and class-specific interfaces for CDC, HID, and MSC devices - extmod.cmake: Build system registration for machine_usb_host.c - modmachine.c: Integration of USBHost class into machine module The class provides high-level Python access to USB devices with methods for device discovery, data transfer, and device-specific operations (e.g., HID report parsing, MSC block I/O, CDC read/write). Builds on the shared/tinyusb USB Host infrastructure added in the previous commit. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds USB Host support for ESP32-S3 with TinyUSB integration. The implementation includes: - esp32_common.cmake: Build integration for USB Host, including TinyUSB host stack configuration and source files - main.c: USB Host task initialization on startup - usb.c: ESP32-specific USB Host initialization and TinyUSB integration - tinyusb_port/tusb_config.h: TinyUSB configuration for ESP32 USB stack - tinyusb_port/tusb_config_host.h: USB Host specific TinyUSB configuration including HCD, CDC, MSC, and HID class support - boards/ESP32_GENERIC_S3_USBHOST/: New board variant with USB Host enabled, configured for ESP32-S3's native USB peripheral on GPIO19/20 USB Host support requires ESP-IDF's TinyUSB component and is only available on ESP32-S3 which has native USB OTG support. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds USB Host support for STM32F4 with TinyUSB integration. The implementation includes: - Makefile: Build integration for USB Host support, including TinyUSB port files and conditional compilation - main.c: USB Host task initialization - stm32_it.c: Interrupt handling for TinyUSB stack - msc_disk.c: Updates to support TinyUSB MSC - usbd_conf.c: USB configuration support for TinyUSB - tinyusb_port/: TinyUSB port implementation for STM32 - tusb_config.h: TinyUSB configuration for STM32 USB stack - tusb_config_host.h: USB Host specific configuration - tusb_port.c: STM32-specific USB initialization and interrupt handlers - boards/NUCLEO_F429ZI/: Base board updates for TinyUSB compatibility - boards/NUCLEO_F429ZI_USBHOST/: USB Host variant using TinyUSB host stack on USB OTG FS peripheral (CN13) - boards/NUCLEO_F429ZI_TINYUSB/: TinyUSB device-only variant for testing USB Host/Device communication between two boards USB Host support uses STM32's USB OTG FS peripheral with TinyUSB's Synopsys DWC2 driver. The VBUS detection is disabled in the TinyUSB device variant to allow device operation without external VBUS supply (when connecting two self-powered boards). Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds USB Host support for RP2040/RP2350 with TinyUSB integration: - CMakeLists.txt: Build integration for USB Host including TinyUSB host stack, PIO USB support (via tinyusb_pico_pio_usb when available for dual-mode boards), --wrap=hcd_event_handler linker flag, and -Werror suppression for third-party PIO USB sources - mpconfigport.h: Feature enables for USB Host mode - mpconfigport_usbhost.h: USB Host specific port configuration with defaults for MICROPY_HW_USB_HOST and class support (CDC, MSC, HID) - tinyusb_port/tusb_config_host.h: TinyUSB USB Host configuration including FIFO sizing, class driver configuration, and #ifndef guard on BOARD_TUH_RHPORT so boards can override - boards/RPI_PICO2_USBHOST/: USB Host variant for Pico2 with RP2350 - boards/WAVESHARE_RP2350_USB_A/: New board configuration for Waveshare RP2350-USB-A which has USB-A receptacle for USB Host mode Updates lib/pico-sdk submodule to version with RP2350 USB Host support. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds USB Host support for the i.MX RT port via the shared TinyUSB host infrastructure. Three board variants provided: - MIMXRT1010_EVK_USBHOST: RT1010 with reduced TinyUSB config (max 2 devices, no hub) due to limited memory. USB host data placed in OCRAM via custom linker script since DTCM is only 32KB. - MIMXRT1060_EVK_USBHOST: RT1060 with standard host config using DTCM. - MIMXRT1170_EVK_USBHOST: RT1170 with standard host config. Includes linker-time assertion to catch USB host RAM section overflow during build on memory-constrained boards. Adds automatic UART dupterm in _boot.py when machine.USBHost is present and machine.USBDevice is not, so single-port host boards (without USB CDC REPL) have serial console access out of the box. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds simultaneous USB device (RHPORT0/USB_OTG1 for CDC REPL) and host (RHPORT1/USB_OTG2) support for MIMXRT1170-EVK. Includes tusb_config_dual.h, dual USB PHY init, unified IRQ handlers, EHCI data placement in OCRAM, and hcd_event_handler linker wrap. The MIMXRT1170_EVK_USBHOST_DUAL board config inherits from the base MIMXRT1170_EVK with USB host overrides rather than duplicating the full config. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds multi-instance tests for USB Host functionality, testing Host/Device communication between two MicroPython boards. The test suite includes: CDC (USB Serial) tests: - cdc_basic.py: Basic CDC read/write operations between host and device - cdc_custom_lib.py: CDC operations using usb.device library - cdc_irq.py: CDC interrupt-driven I/O HID (Human Interface Device) tests: - hid_keyboard.py: HID keyboard report parsing and input - hid_mouse.py: HID mouse report parsing and movement MSC (Mass Storage Class) tests: - msc_block_rw.py: Block-level read/write operations - msc_mount_write.py: Filesystem mount and file operations Device disconnect handling: - disconnect_cdc.py: CDC device disconnect/reconnect handling - disconnect_hid.py: HID device disconnect/reconnect handling - disconnect_msc.py: MSC device disconnect/reconnect handling Multi-interface enumeration: - enum_multi_interface.py: Enumeration of composite USB devices Each test includes a .py.exp file with expected output for automated verification. Tests require two boards: one as USB Host (instance 0) and one as USB Device (instance 1), connected via USB cable. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds API reference documentation for machine.USBHost class at docs/library/machine.USBHost.rst. The documentation covers: - USBHost class constructor and activation - Device enumeration methods (devices(), cdc_devices(), hid_devices(), msc_devices()) - Class-specific interfaces: - CDC: read(), write(), irq() for serial communication - HID: read_report() for input device data - MSC: block I/O and filesystem mount operations - Device lifecycle and error handling - Example usage for each device class Provides complete reference for USB Host functionality available on ESP32-S3, RP2040/RP2350, and STM32F4 ports. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Enable MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE for all MIMXRT boards, add mp_usbd_runtime.c to the build, and freeze the usb-device Python modules (CDC, HID, keyboard, mouse). Tested on MIMXRT1170-EVK with ESP32-S3 as USB host: built-in CDC enumeration, Python CDC bidirectional data transfer, HID keyboard and mouse reports all verified. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
When CFG_TUH_RPI_PIO_USB and MICROPY_HW_USB_HOST_DP_PIN are defined, configure PIO USB pin mapping via tuh_configure() before tuh_init(). Use the default pico-sdk alarm pool (alarm_pool_get_default()) instead of creating a new one. The default PIO USB alarm_pool_create(2, 1) panics because MicroPython's soft timer already claims hardware alarm 2. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Reconfigure for dual-mode USB: native USB controller in device mode (USB-C, REPL) on rhport 0, PIO USB in host mode (USB-A receptacle, GPIO12/13) on rhport 1. Set system clock to 120MHz (multiple of 12MHz required by PIO USB). RP2350 default 150MHz doesn't divide evenly. The original board config assumed native dual-controller host mode which doesn't work as the RP2350 has only one USB controller. PIO USB provides the second port via PIO state machines. Tested on Waveshare RP2350-USB-A with ESP32-S3 native USB CDC device connected to the USB-A receptacle. Host enumeration, CDC read/write all verified. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Bump micropython-lib submodule to include usb-device-cdc fix for default timeout in CDCInterface.init(). Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
machine.USBHost()which lets MicroPython act as a USB host, enumeratingand communicating with connected USB devices. Supports CDC (serial), MSC
(storage / block devices), and HID (keyboard/mouse) device classes. MSC devices
implement the block protocol so they can be mounted directly with
vfs.mount().Built on TinyUSB's host stack (submodule updated to 0.20.0 for host support) with a shared infrastructure
layer in
shared/tinyusb/mp_usbh.cthat handles enumeration, class dispatch,and GC integration. Each port provides its own TinyUSB config and init glue.
Port support:
USBHOSTvariant ofESP32_GENERIC_S3using native USB OTGNUCLEO_F429ZI_USBHOST(host mode) andNUCLEO_F429ZI_TINYUSB(device mode, for testing against a host board) using USB OTG FS with DWC2 driver
WAVESHARE_RP2350_USB_Aboard using PIO USB for host mode on theUSB-A receptacle (GPIO12/13) while native USB stays in device mode for REPL.
System clock set to 120MHz (PIO USB needs 12MHz multiple).
MIMXRT1170_EVK_USBHOST_DUALvariant running CDC device on USB_OTG1 and hoston USB_OTG2 simultaneously
Testing
Multi-instance tests in
tests/multi_usb/cover CDC read/write, CDC withusb.devicelibrary, CDC IRQ, HID keyboard/mouse reports, MSC block I/O,MSC filesystem mount, device disconnect handling, and composite device enumeration.
These require two physical boards connected via USB cable, one running as host and
the other as device.
Tested with ESP32-S3 <-> NUCLEO-F429ZI in both host/device configurations,
MIMXRT1170-EVK in dual-port mode (CDC REPL on USB_OTG1, host on USB_OTG2),
MIMXRT1170-EVK in single-port host mode (UART REPL via dupterm, host on
USB_OTG1) with ESP32-S3 CDC device enumeration and bidirectional data transfer,
and Waveshare RP2350-USB-A with PIO USB host enumerating ESP32-S3 CDC device
(read/write verified).
Not yet tested:
for host mode so there's no CDC REPL. Builds compile but no hardware validation.
The RT1170 single-port variant has been tested using UART REPL via dupterm.
Trade-offs and Alternatives
TinyUSB host mode requires a fair chunk of RAM for transfer buffers and
descriptor caches, particularly on memory-constrained chips like RT1010 where
EHCI data has to go in OCRAM instead of DTCM. Dual-mode configs (RT1170
dual-port, RP2350 PIO USB) need a linker wrap for
hcd_event_handlerto routeevents to the correct stack when both device and host are active. PIO USB on
RP2350 also requires 120MHz clock (vs default 150MHz) since PIO USB needs a
12MHz multiple.
USB Host is opt-in per board variant so there's no size or RAM impact on
existing builds.
Generative AI
I used generative AI tools when creating this PR, but a human has checked the code and is responsible for the description above.