Skip to content

Commit

Permalink
fix(usb): check ep status before transfer
Browse files Browse the repository at this point in the history
Signed-off-by: Haobo Gu <[email protected]>
  • Loading branch information
HaoboGu authored and andelf committed Aug 23, 2024
1 parent 47171a4 commit 50f6e24
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/usb/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use embedded_hal::delay::DelayNs;
use hpm_metapac::usb::regs::*;
use riscv::delay::McycleDelay;

use super::{init_qhd, Instance, ENDPOINT_COUNT};
use super::{init_qhd, Instance, ENDPOINT_COUNT, EP_IN_WAKERS, EP_OUT_WAKERS};
use crate::usb::{reset_dcd_data, EpConfig, BUS_WAKER, DCD_DATA, IRQ_RESET, IRQ_SUSPEND};

/// USB bus
Expand Down Expand Up @@ -75,6 +75,12 @@ impl<T: Instance> embassy_usb_driver::Bus for Bus<T> {
if IRQ_RESET.load(Ordering::Acquire) {
IRQ_RESET.store(false, Ordering::Relaxed);

// Disable all endpoints except ep0
for i in 1..ENDPOINT_COUNT {
self.endpoint_close(EndpointAddress::from_parts(i, Direction::In));
self.endpoint_close(EndpointAddress::from_parts(i, Direction::Out));
}

// Set device addr to 0
self.device_set_address(0);

Expand All @@ -90,6 +96,13 @@ impl<T: Instance> embassy_usb_driver::Bus for Bus<T> {
max_packet_size: 64,
});

for w in &EP_IN_WAKERS {
w.wake()
}
for w in &EP_OUT_WAKERS {
w.wake()
}

// Reset bus
self.device_bus_reset(64);

Expand Down Expand Up @@ -355,6 +368,7 @@ impl<T: Instance> Bus<T> {

/// Open the endpoint
fn endpoint_open(&mut self, ep_config: EpConfig) {
// defmt::info!("Enabling endpoint: {:?}", ep_config.ep_addr);
if ep_config.ep_addr.index() >= ENDPOINT_COUNT {
return;
}
Expand Down
23 changes: 23 additions & 0 deletions src/usb/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,16 @@ impl<'d, T: Instance> Endpoint<'d, T> {
r.endptctrl(self.info.addr.index() as usize).modify(|w| w.set_rxs(true));
}
}

pub(crate) fn enabled(&self) -> bool {
let r = T::info().regs;
let ep_num = self.info.addr.index();
if self.info.addr.is_in() {
r.endptctrl(ep_num).read().txe()
} else {
r.endptctrl(ep_num).read().rxe()
}
}
}

impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T> {
Expand All @@ -156,6 +166,9 @@ impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T> {

/// Wait for the endpoint to be enabled.
async fn wait_enabled(&mut self) {
if self.enabled() {
return;
}
let i = self.info.addr.index();
poll_fn(|cx| {
let r = T::info().regs;
Expand Down Expand Up @@ -183,6 +196,9 @@ impl<'d, T: Instance> EndpointOut for Endpoint<'d, T> {
///
/// This should also clear any NAK flags and prepare the endpoint to receive the next packet.
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, embassy_usb_driver::EndpointError> {
if !self.enabled() {
return Err(embassy_usb_driver::EndpointError::Disabled);
}
let r = T::info().regs;
let ep_num = self.info.addr.index();

Expand All @@ -195,6 +211,8 @@ impl<'d, T: Instance> EndpointOut for Endpoint<'d, T> {
// Clear the flag
r.endptcomplete().modify(|w| w.set_erce(1 << ep_num));
Poll::Ready(())
} else if !r.endptctrl(ep_num).read().rxe() {
Poll::Ready(())
} else {
Poll::Pending
}
Expand All @@ -212,6 +230,9 @@ impl<'d, T: Instance> EndpointOut for Endpoint<'d, T> {
impl<'d, T: Instance> EndpointIn for Endpoint<'d, T> {
/// Write a single packet of data to the endpoint.
async fn write(&mut self, buf: &[u8]) -> Result<(), embassy_usb_driver::EndpointError> {
if !self.enabled() {
return Err(embassy_usb_driver::EndpointError::Disabled);
}
let r = T::info().regs;
let ep_num = self.info.addr.index();

Expand All @@ -223,6 +244,8 @@ impl<'d, T: Instance> EndpointIn for Endpoint<'d, T> {
if r.endptcomplete().read().etce() & (1 << ep_num) != 0 {
r.endptcomplete().modify(|w| w.set_etce(1 << ep_num));
Poll::Ready(())
} else if !r.endptctrl(ep_num).read().txe() {
Poll::Ready(())
} else {
Poll::Pending
}
Expand Down

0 comments on commit 50f6e24

Please sign in to comment.