Fix async USB OTG-FS driver (#2742)

* Use unwrap macro

* Clean up reset

* Better replicate synopsys init

* Fix indentation

* Clean up constructor

* Initialize before poll

* Remove prefix

* Keep the Usb PeripheralGuard around

* Remove example addition
This commit is contained in:
Dániel Buga 2024-12-12 14:16:32 +01:00 committed by GitHub
parent d66281609b
commit cc4e527eaf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 56 deletions

View File

@ -62,15 +62,11 @@ pub struct Usb<'d> {
impl<'d> Usb<'d> { impl<'d> Usb<'d> {
/// Creates a new `Usb` instance. /// Creates a new `Usb` instance.
pub fn new<P, M>( pub fn new(
usb0: impl Peripheral<P = peripherals::USB0> + 'd, usb0: impl Peripheral<P = peripherals::USB0> + 'd,
_usb_dp: impl Peripheral<P = P> + 'd, _usb_dp: impl Peripheral<P = impl UsbDp> + 'd,
_usb_dm: impl Peripheral<P = M> + 'd, _usb_dm: impl Peripheral<P = impl UsbDm> + 'd,
) -> Self ) -> Self {
where
P: UsbDp + Send + Sync,
M: UsbDm + Send + Sync,
{
let guard = GenericPeripheralGuard::new(); let guard = GenericPeripheralGuard::new();
Self { Self {
@ -81,7 +77,7 @@ impl<'d> Usb<'d> {
fn _enable() { fn _enable() {
unsafe { unsafe {
let usb_wrap = &*peripherals::USB_WRAP::PTR; let usb_wrap = peripherals::USB_WRAP::steal();
usb_wrap.otg_conf().modify(|_, w| { usb_wrap.otg_conf().modify(|_, w| {
w.usb_pad_enable().set_bit(); w.usb_pad_enable().set_bit();
w.phy_sel().clear_bit(); w.phy_sel().clear_bit();
@ -89,12 +85,15 @@ impl<'d> Usb<'d> {
w.ahb_clk_force_on().set_bit(); w.ahb_clk_force_on().set_bit();
w.phy_clk_force_on().set_bit() w.phy_clk_force_on().set_bit()
}); });
}
#[cfg(esp32s3)] #[cfg(esp32s3)]
{ unsafe {
let rtc = &*peripherals::LPWR::PTR; let rtc = peripherals::LPWR::steal();
rtc.usb_conf() rtc.usb_conf().modify(|_, w| {
.modify(|_, w| w.sw_hw_usb_phy_sel().set_bit().sw_usb_phy_sel().set_bit()); w.sw_hw_usb_phy_sel().set_bit();
w.sw_usb_phy_sel().set_bit()
});
} }
use crate::gpio::Level; use crate::gpio::Level;
@ -104,7 +103,6 @@ impl<'d> Usb<'d> {
InputSignal::USB_OTG_VBUSVALID.connect_to(Level::High); // receiving a valid Vbus from device InputSignal::USB_OTG_VBUSVALID.connect_to(Level::High); // receiving a valid Vbus from device
InputSignal::USB_OTG_AVALID.connect_to(Level::Low); InputSignal::USB_OTG_AVALID.connect_to(Level::Low);
} }
}
fn _disable() { fn _disable() {
// TODO // TODO
@ -166,6 +164,7 @@ pub mod asynch {
/// Asynchronous USB driver. /// Asynchronous USB driver.
pub struct Driver<'d> { pub struct Driver<'d> {
inner: OtgDriver<'d, MAX_EP_COUNT>, inner: OtgDriver<'d, MAX_EP_COUNT>,
_usb: Usb<'d>,
} }
impl<'d> Driver<'d> { impl<'d> Driver<'d> {
@ -181,7 +180,7 @@ pub mod asynch {
/// ///
/// Must be large enough to fit all OUT endpoint max packet sizes. /// Must be large enough to fit all OUT endpoint max packet sizes.
/// Endpoint allocation will fail if it is too small. /// Endpoint allocation will fail if it is too small.
pub fn new(_peri: Usb<'d>, ep_out_buffer: &'d mut [u8], config: Config) -> Self { pub fn new(peri: Usb<'d>, ep_out_buffer: &'d mut [u8], config: Config) -> Self {
// From `synopsys-usb-otg` crate: // From `synopsys-usb-otg` crate:
// This calculation doesn't correspond to one in a Reference Manual. // This calculation doesn't correspond to one in a Reference Manual.
// In fact, the required number of words is higher than indicated in RM. // In fact, the required number of words is higher than indicated in RM.
@ -199,6 +198,7 @@ pub mod asynch {
}; };
Self { Self {
inner: OtgDriver::new(ep_out_buffer, instance, config), inner: OtgDriver::new(ep_out_buffer, instance, config),
_usb: peri,
} }
} }
} }
@ -232,13 +232,14 @@ pub mod asynch {
fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
let (bus, cp) = self.inner.start(control_max_packet_size); let (bus, cp) = self.inner.start(control_max_packet_size);
( let mut bus = Bus {
Bus {
inner: bus, inner: bus,
inited: false, _usb: self._usb,
}, };
cp,
) bus.init();
(bus, cp)
} }
} }
@ -246,7 +247,7 @@ pub mod asynch {
// We need a custom wrapper implementation to handle custom initialization. // We need a custom wrapper implementation to handle custom initialization.
pub struct Bus<'d> { pub struct Bus<'d> {
inner: OtgBus<'d, MAX_EP_COUNT>, inner: OtgBus<'d, MAX_EP_COUNT>,
inited: bool, _usb: Usb<'d>,
} }
impl<'d> Bus<'d> { impl<'d> Bus<'d> {
@ -259,42 +260,39 @@ pub mod asynch {
while !r.grstctl().read().ahbidl() {} while !r.grstctl().read().ahbidl() {}
// Configure as device. // Configure as device.
r.gusbcfg().write(|w| { r.gusbcfg().modify(|w| {
// Force device mode // Force device mode
w.set_fdmod(true); w.set_fdmod(true);
w.set_srpcap(false); w.set_srpcap(false);
// Enable internal full-speed PHY
w.set_physel(true);
}); });
self.inner.config_v1();
// Perform core soft-reset // Perform core soft-reset
while !r.grstctl().read().ahbidl() {}
r.grstctl().modify(|w| w.set_csrst(true)); r.grstctl().modify(|w| w.set_csrst(true));
while r.grstctl().read().csrst() {} while r.grstctl().read().csrst() {}
r.pcgcctl().modify(|w| { self.inner.config_v1();
// Disable power down
w.set_stppclk(false); // Enable PHY clock
}); r.pcgcctl().write(|w| w.0 = 0);
unsafe { unsafe {
crate::interrupt::bind_interrupt( crate::interrupt::bind_interrupt(
crate::peripherals::Interrupt::USB, crate::peripherals::Interrupt::USB,
interrupt_handler.handler(), interrupt_handler.handler(),
); );
crate::interrupt::enable( }
unwrap!(crate::interrupt::enable(
crate::peripherals::Interrupt::USB, crate::peripherals::Interrupt::USB,
interrupt_handler.priority(), interrupt_handler.priority(),
) ));
.unwrap();
}
} }
fn disable(&mut self) { fn disable(&mut self) {
crate::interrupt::disable(Cpu::ProCpu, crate::peripherals::Interrupt::USB); crate::interrupt::disable(Cpu::ProCpu, peripherals::Interrupt::USB);
#[cfg(multi_core)] #[cfg(multi_core)]
crate::interrupt::disable(Cpu::AppCpu, crate::peripherals::Interrupt::USB); crate::interrupt::disable(Cpu::AppCpu, peripherals::Interrupt::USB);
Usb::_disable(); Usb::_disable();
} }
@ -302,11 +300,6 @@ pub mod asynch {
impl<'d> embassy_usb_driver::Bus for Bus<'d> { impl<'d> embassy_usb_driver::Bus for Bus<'d> {
async fn poll(&mut self) -> Event { async fn poll(&mut self) -> Event {
if !self.inited {
self.init();
self.inited = true;
}
self.inner.poll().await self.inner.poll().await
} }

View File

@ -403,15 +403,15 @@ impl PeripheralClockControl {
/// Resets the given peripheral /// Resets the given peripheral
pub(crate) fn reset(peripheral: Peripheral) { pub(crate) fn reset(peripheral: Peripheral) {
debug!("Reset {:?}", peripheral); debug!("Reset {:?}", peripheral);
let system = unsafe { &*SYSTEM::PTR }; let system = unsafe { SYSTEM::steal() };
#[cfg(esp32)] #[cfg(esp32)]
let (perip_rst_en0, peri_rst_en) = { (&system.perip_rst_en(), &system.peri_rst_en()) }; let (perip_rst_en0, peri_rst_en) = (system.perip_rst_en(), system.peri_rst_en());
#[cfg(not(esp32))] #[cfg(not(esp32))]
let perip_rst_en0 = { &system.perip_rst_en0() }; let perip_rst_en0 = system.perip_rst_en0();
#[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))]
let perip_rst_en1 = { &system.perip_rst_en1() }; let perip_rst_en1 = system.perip_rst_en1();
critical_section::with(|_cs| match peripheral { critical_section::with(|_cs| match peripheral {
#[cfg(spi2)] #[cfg(spi2)]