diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs index b5e17307..9f483d96 100644 --- a/embassy-nrf/src/usb.rs +++ b/embassy-nrf/src/usb.rs @@ -140,6 +140,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { type EndpointIn = Endpoint<'d, T, In>; type ControlPipe = ControlPipe<'d, T>; type Bus = Bus<'d, T>; + type EnableFuture = impl Future + 'd; fn alloc_endpoint_in( &mut self, @@ -191,35 +192,46 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { }) } - fn enable(self) -> Self::Bus { - let regs = T::regs(); + fn enable(self) -> Self::EnableFuture { + async move { + let regs = T::regs(); - errata::pre_enable(); + errata::pre_enable(); - regs.enable.write(|w| w.enable().enabled()); + regs.enable.write(|w| w.enable().enabled()); - // Wait until the peripheral is ready. - while !regs.eventcause.read().ready().is_ready() {} - regs.eventcause.write(|w| w.ready().set_bit()); // Write 1 to clear. + // Wait until the peripheral is ready. + regs.intenset.write(|w| w.usbevent().set_bit()); + poll_fn(|cx| { + BUS_WAKER.register(cx.waker()); + if regs.eventcause.read().ready().is_ready() { + Poll::Ready(()) + } else { + Poll::Pending + } + }) + .await; + regs.eventcause.write(|w| w.ready().set_bit()); // Write 1 to clear. - errata::post_enable(); + errata::post_enable(); - unsafe { NVIC::unmask(pac::Interrupt::USBD) }; + unsafe { NVIC::unmask(pac::Interrupt::USBD) }; - regs.intenset.write(|w| { - w.usbreset().set_bit(); - w.usbevent().set_bit(); - w.epdata().set_bit(); - w - }); - // Enable the USB pullup, allowing enumeration. - regs.usbpullup.write(|w| w.connect().enabled()); - trace!("enabled"); + regs.intenset.write(|w| { + w.usbreset().set_bit(); + w.usbevent().set_bit(); + w.epdata().set_bit(); + w + }); + // Enable the USB pullup, allowing enumeration. + regs.usbpullup.write(|w| w.connect().enabled()); + trace!("enabled"); - Bus { - phantom: PhantomData, - alloc_in: self.alloc_in, - alloc_out: self.alloc_out, + Bus { + phantom: PhantomData, + alloc_in: self.alloc_in, + alloc_out: self.alloc_out, + } } } } @@ -650,14 +662,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { poll_fn(|cx| { EP0_WAKER.register(cx.waker()); let regs = T::regs(); - if regs.events_usbreset.read().bits() != 0 { + if regs.events_ep0datadone.read().bits() != 0 { + Poll::Ready(Ok(())) + } else if regs.events_usbreset.read().bits() != 0 { trace!("aborted control data_out: usb reset"); Poll::Ready(Err(ReadError::Disabled)) } else if regs.events_ep0setup.read().bits() != 0 { trace!("aborted control data_out: received another SETUP"); Poll::Ready(Err(ReadError::Disabled)) - } else if regs.events_ep0datadone.read().bits() != 0 { - Poll::Ready(Ok(())) } else { Poll::Pending } @@ -689,14 +701,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { cx.waker().wake_by_ref(); EP0_WAKER.register(cx.waker()); let regs = T::regs(); - if regs.events_usbreset.read().bits() != 0 { + if regs.events_ep0datadone.read().bits() != 0 { + Poll::Ready(Ok(())) + } else if regs.events_usbreset.read().bits() != 0 { trace!("aborted control data_in: usb reset"); Poll::Ready(Err(WriteError::Disabled)) } else if regs.events_ep0setup.read().bits() != 0 { trace!("aborted control data_in: received another SETUP"); Poll::Ready(Err(WriteError::Disabled)) - } else if regs.events_ep0datadone.read().bits() != 0 { - Poll::Ready(Ok(())) } else { Poll::Pending } diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index c8a9db7a..4bbcd3e5 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs @@ -122,7 +122,7 @@ pub struct UsbDeviceBuilder<'d, D: Driver<'d>> { interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, control_buf: &'d mut [u8], - bus: D, + driver: D, next_interface_number: u8, next_string_index: u8, @@ -139,7 +139,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { /// large enough for the length of the largest control request (in or out) /// anticipated by any class added to the device. pub fn new( - bus: D, + driver: D, config: Config<'d>, device_descriptor_buf: &'d mut [u8], config_descriptor_buf: &'d mut [u8], @@ -173,7 +173,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { bos_descriptor.bos(); UsbDeviceBuilder { - bus, + driver, config, interfaces: Vec::new(), control_buf, @@ -187,12 +187,12 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { } /// Creates the [`UsbDevice`] instance with the configuration in this builder. - pub fn build(mut self) -> UsbDevice<'d, D> { + pub async fn build(mut self) -> UsbDevice<'d, D> { self.config_descriptor.end_configuration(); self.bos_descriptor.end_bos(); UsbDevice::build( - self.bus, + self.driver, self.config, self.device_descriptor.into_buf(), self.config_descriptor.into_buf(), @@ -200,6 +200,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { self.interfaces, self.control_buf, ) + .await } /// Allocates a new interface number. @@ -251,7 +252,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { max_packet_size: u16, interval: u8, ) -> Result { - self.bus + self.driver .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) } @@ -266,7 +267,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { max_packet_size: u16, interval: u8, ) -> Result { - self.bus + self.driver .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) } @@ -306,7 +307,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { /// feasibly recoverable. #[inline] pub fn alloc_control_pipe(&mut self, max_packet_size: u16) -> D::ControlPipe { - self.bus + self.driver .alloc_control_pipe(max_packet_size) .expect("alloc_control_pipe failed") } diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs index d3231cb4..01eb3d57 100644 --- a/embassy-usb/src/driver.rs +++ b/embassy-usb/src/driver.rs @@ -11,6 +11,7 @@ pub trait Driver<'a> { type EndpointIn: EndpointIn + 'a; type ControlPipe: ControlPipe + 'a; type Bus: Bus + 'a; + type EnableFuture: Future + 'a; /// Allocates an endpoint and specified endpoint parameters. This method is called by the device /// and class implementations to allocate endpoints, and can only be called before @@ -46,7 +47,7 @@ pub trait Driver<'a> { /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so /// there is no need to perform a USB reset in this method. - fn enable(self) -> Self::Bus; + fn enable(self) -> Self::EnableFuture; /// Indicates that `set_device_address` must be called before accepting the corresponding /// control transfer, not after. diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index f833a86d..e98cbdee 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs @@ -72,7 +72,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> { } impl<'d, D: Driver<'d>> UsbDevice<'d, D> { - pub(crate) fn build( + pub(crate) async fn build( mut driver: D, config: Config<'d>, device_descriptor: &'d [u8], @@ -80,17 +80,17 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { bos_descriptor: &'d [u8], interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, control_buf: &'d mut [u8], - ) -> Self { + ) -> UsbDevice<'d, D> { let control = driver .alloc_control_pipe(config.max_packet_size_0 as u16) .expect("failed to alloc control endpoint"); // Enable the USB bus. // This prevent further allocation by consuming the driver. - let driver = driver.enable(); + let bus = driver.enable().await; Self { - bus: driver, + bus, config, control: ControlPipe::new(control), device_descriptor, diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs index 51136292..0812697e 100644 --- a/examples/nrf/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf/src/bin/usb_hid_keyboard.rs @@ -76,7 +76,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { ); // Build the builder. - let mut usb = builder.build(); + let mut usb = builder.build().await; // Run the USB device. let usb_fut = usb.run(); diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs index 741e234b..ca938382 100644 --- a/examples/nrf/src/bin/usb_hid_mouse.rs +++ b/examples/nrf/src/bin/usb_hid_mouse.rs @@ -74,7 +74,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { ); // Build the builder. - let mut usb = builder.build(); + let mut usb = builder.build().await; // Run the USB device. let usb_fut = usb.run(); diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs index 9437e835..500be2ce 100644 --- a/examples/nrf/src/bin/usb_serial.rs +++ b/examples/nrf/src/bin/usb_serial.rs @@ -60,7 +60,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); // Build the builder. - let mut usb = builder.build(); + let mut usb = builder.build().await; // Run the USB device. let usb_fut = usb.run(); diff --git a/examples/nrf/src/bin/usb_serial_multitask.rs b/examples/nrf/src/bin/usb_serial_multitask.rs index bef70441..1258bc53 100644 --- a/examples/nrf/src/bin/usb_serial_multitask.rs +++ b/examples/nrf/src/bin/usb_serial_multitask.rs @@ -85,7 +85,7 @@ async fn main(spawner: Spawner, p: Peripherals) { let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64); // Build the builder. - let usb = builder.build(); + let usb = builder.build().await; unwrap!(spawner.spawn(usb_task(usb))); unwrap!(spawner.spawn(echo_task(class)));