//! # USB On-The-Go (USB OTG) //! //! ## Overview //! The USB OTG Full-speed (FS) peripheral allows communication //! with USB devices using either blocking (usb-device) or asynchronous //! (embassy-usb) APIs. //! //! It can operate as either a USB Host or Device, and supports full-speed (FS) //! and low-speed (LS) data rates of the USB 2.0 specification. //! //! The blocking driver uses the `esp_synopsys_usb_otg` crate, which provides //! the `USB bus` implementation and `USB peripheral traits`. //! //! The asynchronous driver uses the `embassy_usb_synopsys_otg` crate, which //! provides the `USB bus` and `USB device` implementations. //! //! The module also relies on other peripheral modules, such as `GPIO`, //! `system`, and `clock control`, to configure and enable the `USB` peripheral. //! //! ## Configuration //! To use the USB OTG Full-speed peripheral driver, you need to initialize the //! peripheral and configure its settings. The [`Usb`] struct represents the USB //! peripheral and requires the GPIO pins that implement [`UsbDp`], and //! [`UsbDm`], which define the specific types used for USB pin selection. //! //! The returned `Usb` instance can be used with the `usb-device` crate, or it //! can be further configured with [`asynch::Driver`] to be used with the //! `embassy-usb` crate. //! //! ## Examples //! Visit the [USB Serial] example for an example of using the USB OTG //! peripheral. //! //! [USB Serial]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/usb_serial.rs //! //! ## Implementation State //! - Low-speed (LS) is not supported. pub use esp_synopsys_usb_otg::UsbBus; use esp_synopsys_usb_otg::UsbPeripheral; use crate::{ gpio::InputSignal, peripheral::{Peripheral, PeripheralRef}, peripherals, system::{Peripheral as PeripheralEnable, PeripheralClockControl}, }; #[doc(hidden)] /// Trait representing the USB D+ (data plus) pin. pub trait UsbDp: crate::private::Sealed {} #[doc(hidden)] /// Trait representing the USB D- (data minus) pin. pub trait UsbDm: crate::private::Sealed {} /// USB peripheral. pub struct Usb<'d> { _usb0: PeripheralRef<'d, peripherals::USB0>, } impl<'d> Usb<'d> { /// Creates a new `Usb` instance. pub fn new
( usb0: impl Peripheral
+ 'd, _usb_dp: impl Peripheral
+ 'd, _usb_dm: impl Peripheral
+ 'd,
) -> Self
where
P: UsbDp + Send + Sync,
M: UsbDm + Send + Sync,
{
PeripheralClockControl::reset(PeripheralEnable::Usb);
PeripheralClockControl::enable(PeripheralEnable::Usb);
Self {
_usb0: usb0.into_ref(),
}
}
fn _enable() {
unsafe {
let usb_wrap = &*peripherals::USB_WRAP::PTR;
usb_wrap.otg_conf().modify(|_, w| {
w.usb_pad_enable().set_bit();
w.phy_sel().clear_bit();
w.clk_en().set_bit();
w.ahb_clk_force_on().set_bit();
w.phy_clk_force_on().set_bit()
});
#[cfg(esp32s3)]
{
let rtc = &*peripherals::LPWR::PTR;
rtc.usb_conf()
.modify(|_, w| w.sw_hw_usb_phy_sel().set_bit().sw_usb_phy_sel().set_bit());
}
use crate::gpio::Level;
InputSignal::USB_OTG_IDDIG.connect_to(Level::High); // connected connector is mini-B side
InputSignal::USB_SRP_BVALID.connect_to(Level::High); // HIGH to force USB device mode
InputSignal::USB_OTG_VBUSVALID.connect_to(Level::High); // receiving a valid Vbus from device
InputSignal::USB_OTG_AVALID.connect_to(Level::Low);
}
}
fn _disable() {
// TODO
}
}
unsafe impl<'d> Sync for Usb<'d> {}
unsafe impl<'d> UsbPeripheral for Usb<'d> {
const REGISTERS: *const () = peripherals::USB0::ptr() as *const ();
const HIGH_SPEED: bool = false;
const FIFO_DEPTH_WORDS: usize = 256;
const ENDPOINT_COUNT: usize = 5;
fn enable() {
Self::_enable();
}
fn ahb_frequency_hz(&self) -> u32 {
// unused
80_000_000
}
}
/// Async functionality
pub mod asynch {
use embassy_usb_driver::{
EndpointAddress,
EndpointAllocError,
EndpointType,
Event,
Unsupported,
};
pub use embassy_usb_synopsys_otg::Config;
use embassy_usb_synopsys_otg::{
on_interrupt,
otg_v1::Otg,
Bus as OtgBus,
ControlPipe,
Driver as OtgDriver,
Endpoint,
In,
OtgInstance,
Out,
PhyType,
State,
};
use procmacros::handler;
use super::*;
use crate::Cpu;
// From ESP32-S3 TRM:
// Six additional endpoints (endpoint numbers 1 to 6), configurable as IN or OUT
const MAX_EP_COUNT: usize = 7;
static STATE: State