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.
@@ -811,8 +811,8 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
async move {
trace!("control: accept");
- unsafe {
let bufcontrol = T::dpram().ep_in_buffer_control(0);
+ unsafe {
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;
}
}
