From 866a42f3aeb196e2b0f854a52683ee07cffc4ccd Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 21 Oct 2022 22:02:13 +0800 Subject: [PATCH] rp usb: wait for accept() completion This ensures that the current response has finished being sent before the subsequent set_address() happens. Otherwise connecting a device is intermittent, can fail depending on timing. --- embassy-rp/src/usb.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index 0a904aab3..7a83dcb4a 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -811,8 +811,8 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { async move { trace!("control: accept"); + let bufcontrol = T::dpram().ep_in_buffer_control(0); unsafe { - let bufcontrol = T::dpram().ep_in_buffer_control(0); bufcontrol.write(|w| { w.set_length(0, 0); w.set_pid(0, true); @@ -826,6 +826,18 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { w.set_available(0, true); }); } + + // wait for completion before returning, needed so + // set_address() doesn't happen early. + poll_fn(|cx| { + EP_IN_WAKERS[0].register(cx.waker()); + if unsafe { bufcontrol.read().available(0) } { + Poll::Pending + } else { + Poll::Ready(()) + } + }) + .await; } }