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:
parent
d66281609b
commit
cc4e527eaf
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user