768: nrf/usb: fix control out transfers getting corrupted due to ep0rcvout sticking from earlier. r=Dirbaio a=Dirbaio

bors r+

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
bors[bot] 2022-05-12 16:46:35 +00:00 committed by GitHub
commit 13bcb5ffb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 27 deletions

View file

@ -9,7 +9,6 @@ use embassy::interrupt::InterruptExt;
use embassy::util::Unborrow; use embassy::util::Unborrow;
use embassy::waitqueue::AtomicWaker; use embassy::waitqueue::AtomicWaker;
use embassy_hal_common::unborrow; use embassy_hal_common::unborrow;
use embassy_usb::control::Request;
use embassy_usb::driver::{self, EndpointError, Event, Unsupported}; use embassy_usb::driver::{self, EndpointError, Event, Unsupported};
use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
use futures::future::poll_fn; use futures::future::poll_fn;
@ -526,10 +525,6 @@ unsafe fn read_dma<T: Instance>(i: usize, buf: &mut [u8]) -> Result<usize, Endpo
return Err(EndpointError::BufferOverflow); return Err(EndpointError::BufferOverflow);
} }
if i == 0 {
regs.events_ep0datadone.reset();
}
let epout = [ let epout = [
&regs.epout0, &regs.epout0,
&regs.epout1, &regs.epout1,
@ -640,7 +635,7 @@ pub struct ControlPipe<'d, T: Instance> {
} }
impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
type SetupFuture<'a> = impl Future<Output = Request> + 'a where Self: 'a; type SetupFuture<'a> = impl Future<Output = [u8;8]> + 'a where Self: 'a;
type DataOutFuture<'a> = impl Future<Output = Result<usize, EndpointError>> + 'a where Self: 'a; type DataOutFuture<'a> = impl Future<Output = Result<usize, EndpointError>> + 'a where Self: 'a;
type DataInFuture<'a> = impl Future<Output = Result<(), EndpointError>> + 'a where Self: 'a; type DataInFuture<'a> = impl Future<Output = Result<(), EndpointError>> + 'a where Self: 'a;
@ -652,11 +647,11 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
async move { async move {
let regs = T::regs(); let regs = T::regs();
// Reset shorts
regs.shorts.write(|w| w);
// Wait for SETUP packet // Wait for SETUP packet
regs.intenset.write(|w| { regs.intenset.write(|w| w.ep0setup().set());
w.ep0setup().set();
w.ep0datadone().set()
});
poll_fn(|cx| { poll_fn(|cx| {
EP0_WAKER.register(cx.waker()); EP0_WAKER.register(cx.waker());
let regs = T::regs(); let regs = T::regs();
@ -668,8 +663,6 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
}) })
.await; .await;
// Reset shorts
regs.shorts.write(|w| w);
regs.events_ep0setup.reset(); regs.events_ep0setup.reset();
let mut buf = [0; 8]; let mut buf = [0; 8];
@ -682,14 +675,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
buf[6] = regs.wlengthl.read().wlengthl().bits(); buf[6] = regs.wlengthl.read().wlengthl().bits();
buf[7] = regs.wlengthh.read().wlengthh().bits(); buf[7] = regs.wlengthh.read().wlengthh().bits();
let req = Request::parse(&buf); buf
if req.direction == UsbDirection::Out {
regs.tasks_ep0rcvout
.write(|w| w.tasks_ep0rcvout().set_bit());
}
req
} }
} }
@ -697,6 +683,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
async move { async move {
let regs = T::regs(); let regs = T::regs();
regs.events_ep0datadone.reset();
// This starts a RX on EP0. events_ep0datadone notifies when done.
regs.tasks_ep0rcvout
.write(|w| w.tasks_ep0rcvout().set_bit());
// Wait until ready // Wait until ready
regs.intenset.write(|w| { regs.intenset.write(|w| {
w.usbreset().set(); w.usbreset().set();
@ -728,13 +720,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
async move { async move {
let regs = T::regs(); let regs = T::regs();
regs.events_ep0datadone.reset(); regs.events_ep0datadone.reset();
unsafe {
write_dma::<T>(0, buf);
}
regs.shorts regs.shorts
.write(|w| w.ep0datadone_ep0status().bit(last_packet)); .write(|w| w.ep0datadone_ep0status().bit(last_packet));
// This starts a TX on EP0. events_ep0datadone notifies when done.
unsafe { write_dma::<T>(0, buf) }
regs.intenset.write(|w| { regs.intenset.write(|w| {
w.usbreset().set(); w.usbreset().set();
w.ep0setup().set(); w.ep0setup().set();

View file

@ -1,7 +1,5 @@
use core::future::Future; use core::future::Future;
use crate::control::Request;
use super::types::*; use super::types::*;
/// Driver for a specific USB peripheral. Implement this to add support for a new hardware /// Driver for a specific USB peripheral. Implement this to add support for a new hardware
@ -146,7 +144,7 @@ pub trait EndpointOut: Endpoint {
} }
pub trait ControlPipe { pub trait ControlPipe {
type SetupFuture<'a>: Future<Output = Request> + 'a type SetupFuture<'a>: Future<Output = [u8; 8]> + 'a
where where
Self: 'a; Self: 'a;
type DataOutFuture<'a>: Future<Output = Result<usize, EndpointError>> + 'a type DataOutFuture<'a>: Future<Output = Result<usize, EndpointError>> + 'a

View file

@ -246,7 +246,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
} }
} }
async fn handle_control(&mut self, req: Request) { async fn handle_control(&mut self, req: [u8; 8]) {
let req = Request::parse(&req);
trace!("control request: {:02x}", req); trace!("control request: {:02x}", req);
match req.direction { match req.direction {