imxrt-usbh provides a USB host controller implementation for NXP i.MX RT
1060/1062 microcontrollers (e.g. Teensy 4.x). It implements the
cotton-usb-host HostController trait, allowing the cotton-usb-host
stack to enumerate devices, read HID reports, transfer bulk data, and manage
USB hubs — all in async Rust with no allocator.
The driver targets the EHCI-compatible USB OTG2 controller in host mode and is designed for use with RTIC v2.
Note: This crate targets the secondary USB2 port on the Teensy 4.0/4.1 (the host-capable port with a 5-pin header), not the primary USB1 OTG port used for programming.
- Primary target: Teensy 4.1 (i.MX RT 1062) — USB2 host port (secondary 5-pin header)
- Future targets:
- Teensy 4.0 (i.MX RT 1062) — USB2 host port (SMT pads on underside)
- Other i.MX RT 1060/1062 boards with USB host capability
The Teensy 4.1 USB2 host port uses a 5-pin header (directly behind the Ethernet jack). You must supply external 5V to the VBUS pin — the host port is not powered from the programming USB connector.
| Pin | Signal | Notes |
|---|---|---|
| 1 | GND | |
| 2 | D+ | |
| 3 | D- | |
| 4 | VBUS | Connect to external 5V supply |
| 5 | ID | Leave unconnected (host mode) |
Connect a USB device (keyboard, flash drive, or hub) via a USB-A breakout wired to D+, D-, GND, and VBUS.
The driver supports Low Speed (1.5 Mbps), Full Speed (12 Mbps), and
High Speed (480 Mbps) USB devices. High Speed is available by default
for directly-connected devices. To use USB hubs, enable the hub-support
feature (see Features), which forces all connections to Full
Speed.
Tested device types:
- HID keyboards (low-speed and full-speed)
- USB mass storage flash drives (full-speed)
- USB hubs with devices behind them (requires
hub-supportfeature)
Add the crate to your Cargo.toml:
[dependencies]
imxrt-usbh = "0.1"
imxrt-ral = { version = "0.6", features = ["imxrt1062"] }Note:
cotton-usb-hosttypes (UsbBus,DeviceEvent, descriptor types, etc.) are re-exported at the crate root, so you do not need to addcotton-usb-hostas a direct dependency.
use imxrt_usbh::host::{Imxrt1062HostController, UsbShared, UsbStatics};
use imxrt_usbh::usb_bus::UsbBus;
use static_cell::ConstStaticCell;
// Static resources — must live for 'static
static SHARED: UsbShared = UsbShared::new();
static STATICS: ConstStaticCell<UsbStatics> = ConstStaticCell::new(UsbStatics::new());
// In your init code (after configuring USB2 PLL and clock gates):
let statics = STATICS.take();
let usb2 = unsafe { imxrt_ral::usb::USB2::instance() };
let usbphy2 = unsafe { imxrt_ral::usbphy::USBPHY2::instance() };
let host = Imxrt1062HostController::new(usb2, usbphy2, &SHARED, statics);
unsafe { host.init() };
// Create the USB bus and handle device events
let usb_bus = UsbBus::new(host);
let mut events = usb_bus.device_events_no_hubs();
// ... poll events in an async taskThe Imxrt1062HostController::new() method takes imxrt-ral register instances
directly. Enable a chip feature on imxrt-ral (e.g. imxrt1062) to get the
correct register definitions.
Before calling init(), you must configure:
- USB2 PLL (
CCM_ANALOG_PLL_USB2) — enable and wait for lock - USB OTG2 clock gate (
CCM_CCGR6) — un-gate the clock - VBUS power GPIO (Teensy 4.1:
GPIO_EMC_40→ HIGH via load switch)
See the RTIC examples for complete initialization sequences.
The EHCI controller uses DMA to read and write UsbStatics (queue heads,
transfer descriptors, frame list, receive buffers). This memory must not be
cached, or DMA transfers will silently corrupt data.
Two options:
- Disable the D-cache entirely — simplest, no MPU configuration needed.
- Use the MPU to mark the memory region containing
UsbStaticsas non-cacheable (Device or Strongly Ordered memory type).
The driver performs no cache maintenance internally.
| Feature | Default | Description |
|---|---|---|
log |
Yes | Internal logging via the log crate (0.4) |
defmt-03 |
No | Internal logging via defmt (0.3) — mutually exclusive with log |
hub-support |
No | Enable USB hub support. Sets PFSC=1, forcing all connections to Full Speed (12 Mbps). Without this feature, devices can negotiate High Speed (480 Mbps) but hubs must not be used. |
To use defmt logging instead of log:
[dependencies]
imxrt-usbh = { path = "../imxrt-usbh", default-features = false, features = ["defmt-03"] }To enable hub support (with log logging):
[dependencies]
imxrt-usbh = { path = "../imxrt-usbh", features = ["hub-support"] }Hardware examples live in the imxrt-hal
repository, which provides the board support infrastructure (clock setup, pin
muxing, logging). All examples target the Teensy 4.1 and log over USB CDC serial.
Build from the imxrt-hal repo root:
cargo build --example rtic_usb_host_enumerate --features=board/teensy4 --target=thumbv7em-none-eabihfFlash with:
rust-objcopy -O ihex target/thumbv7em-none-eabihf/debug/examples/rtic_usb_host_enumerate fw.hex
teensy_loader_cli --mcu=TEENSY41 -w -v fw.hex| Example | Description |
|---|---|
rtic_usb_host_enumerate |
Device detection and enumeration — logs VID/PID on connect |
rtic_usb_host_hid_keyboard |
HID keyboard input — decodes keycodes, flashes LED in morse code |
rtic_usb_host_hub |
Hub enumeration — discovers devices behind a hub (requires imxrt-usbh/hub-support) |
rtic_usb_host_mass_storage |
Mass storage sector read — SCSI READ(10) over bulk transport |
For local development, the imxrt-hal workspace uses a path dependency on
this crate. Changes to imxrt-usbh are picked up automatically when building
examples.
- Hub support requires Full Speed: With the
hub-supportfeature, all connections are forced to Full Speed (12 Mbps) via thePFSCbit. High Speed hubs require EHCI split transaction scheduling, which is not yet implemented incotton-usb-host. - No isochronous transfers: Audio/video class devices are not supported.
- No USB suspend/resume: Power management is not implemented.
- Single USB port: Only USB OTG2 (the host port) is supported. USB OTG1 (the programming port) is not usable as a host with this driver.
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.