pub use esp_synopsys_usb_otg::UsbBus;
use esp_synopsys_usb_otg::UsbPeripheral;
use crate::{
gpio::InputSignal,
peripherals,
system::{GenericPeripheralGuard, Peripheral as PeripheralEnable},
};
#[doc(hidden)]
pub trait UsbDp: crate::private::Sealed {}
#[doc(hidden)]
pub trait UsbDm: crate::private::Sealed {}
for_each_analog_function! {
(USB_DM, $gpio:ident) => {
impl UsbDm for crate::peripherals::$gpio<'_> {}
};
(USB_DP, $gpio:ident) => {
impl UsbDp for crate::peripherals::$gpio<'_> {}
};
}
pub struct Usb<'d> {
_usb0: peripherals::USB0<'d>,
_guard: GenericPeripheralGuard<{ PeripheralEnable::Usb as u8 }>,
}
impl<'d> Usb<'d> {
pub fn new(
usb0: peripherals::USB0<'d>,
_usb_dp: impl UsbDp + 'd,
_usb_dm: impl UsbDm + 'd,
) -> Self {
let guard = GenericPeripheralGuard::new();
Self {
_usb0: usb0,
_guard: guard,
}
}
fn _enable() {
peripherals::USB_WRAP::regs().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)]
peripherals::LPWR::regs().usb_conf().modify(|_, w| {
w.sw_hw_usb_phy_sel().set_bit();
w.sw_usb_phy_sel().set_bit()
});
use crate::gpio::Level;
InputSignal::USB_OTG_IDDIG.connect_to(&Level::High); InputSignal::USB_SRP_BVALID.connect_to(&Level::High); InputSignal::USB_OTG_VBUSVALID.connect_to(&Level::High); InputSignal::USB_OTG_AVALID.connect_to(&Level::Low);
}
fn _disable() {
}
}
unsafe impl Sync for Usb<'_> {}
unsafe impl UsbPeripheral for Usb<'_> {
const REGISTERS: *const () = peripherals::USB0::PTR.cast();
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 {
80_000_000
}
}
pub mod asynch {
use embassy_usb_driver::{
EndpointAddress,
EndpointAllocError,
EndpointType,
Event,
Unsupported,
};
pub use embassy_usb_synopsys_otg::Config;
use embassy_usb_synopsys_otg::{
Bus as OtgBus,
ControlPipe,
Driver as OtgDriver,
Endpoint,
In,
OtgInstance,
Out,
PhyType,
State,
on_interrupt,
otg_v1::Otg,
};
use procmacros::handler;
use super::*;
use crate::system::Cpu;
const MAX_EP_COUNT: usize = 7;
static STATE: State<MAX_EP_COUNT> = State::new();
pub struct Driver<'d> {
inner: OtgDriver<'d, MAX_EP_COUNT>,
_usb: Usb<'d>,
}
impl<'d> Driver<'d> {
const REGISTERS: Otg = unsafe { Otg::from_ptr(Usb::REGISTERS.cast_mut()) };
pub fn new(peri: Usb<'d>, ep_out_buffer: &'d mut [u8], config: Config) -> Self {
const RX_FIFO_EXTRA_SIZE_WORDS: u16 = 30;
let instance = OtgInstance {
regs: Self::REGISTERS,
state: &STATE,
fifo_depth_words: Usb::FIFO_DEPTH_WORDS as u16,
extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS,
endpoint_count: Usb::ENDPOINT_COUNT,
phy_type: PhyType::InternalFullSpeed,
calculate_trdt_fn: |_| 5,
};
Self {
inner: OtgDriver::new(ep_out_buffer, instance, config),
_usb: peri,
}
}
}
impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> {
type EndpointOut = Endpoint<'d, Out>;
type EndpointIn = Endpoint<'d, In>;
type ControlPipe = ControlPipe<'d>;
type Bus = Bus<'d>;
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, EndpointAllocError> {
self.inner
.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, EndpointAllocError> {
self.inner
.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
let (bus, cp) = self.inner.start(control_max_packet_size);
let mut bus = Bus {
inner: bus,
_usb: self._usb,
};
bus.init();
(bus, cp)
}
}
pub struct Bus<'d> {
inner: OtgBus<'d, MAX_EP_COUNT>,
_usb: Usb<'d>,
}
impl Bus<'_> {
fn init(&mut self) {
Usb::_enable();
let r = Driver::REGISTERS;
while !r.grstctl().read().ahbidl() {}
r.gusbcfg().modify(|w| {
w.set_fdmod(true);
w.set_srpcap(false);
});
while !r.grstctl().read().ahbidl() {}
r.grstctl().modify(|w| w.set_csrst(true));
while r.grstctl().read().csrst() {}
self.inner.config_v1();
r.pcgcctl().write(|w| w.0 = 0);
crate::interrupt::bind_handler(crate::peripherals::Interrupt::USB, interrupt_handler);
}
fn disable(&mut self) {
crate::interrupt::disable(Cpu::ProCpu, peripherals::Interrupt::USB);
#[cfg(multi_core)]
crate::interrupt::disable(Cpu::AppCpu, peripherals::Interrupt::USB);
Usb::_disable();
}
}
impl embassy_usb_driver::Bus for Bus<'_> {
async fn poll(&mut self) -> Event {
self.inner.poll().await
}
fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
self.inner.endpoint_set_stalled(ep_addr, stalled)
}
fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
self.inner.endpoint_is_stalled(ep_addr)
}
fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
self.inner.endpoint_set_enabled(ep_addr, enabled)
}
async fn enable(&mut self) {
self.inner.enable().await
}
async fn disable(&mut self) {
self.inner.disable().await
}
async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
self.inner.remote_wakeup().await
}
}
impl Drop for Bus<'_> {
fn drop(&mut self) {
Bus::disable(self);
}
}
#[handler(priority = crate::interrupt::Priority::max())]
fn interrupt_handler() {
unsafe { on_interrupt(Driver::REGISTERS, &STATE, Usb::ENDPOINT_COUNT) }
}
}