diff options
| author | alexmoon <[email protected]> | 2022-04-06 22:10:18 -0400 |
|---|---|---|
| committer | alexmoon <[email protected]> | 2022-04-07 10:51:26 -0400 |
| commit | 6abbfa9a92ec9feb03e30846bccb66272020601d (patch) | |
| tree | 78ab2f5f6ccbb45e108520395252f0e6b45665a2 | |
| parent | a1754ac8a820d9cae97cf214969faf3090b37c76 (diff) | |
Async-ify Driver::enable and UsbDeviceBuilder::build
| -rw-r--r-- | embassy-nrf/src/usb.rs | 58 | ||||
| -rw-r--r-- | embassy-usb/src/builder.rs | 17 | ||||
| -rw-r--r-- | embassy-usb/src/driver.rs | 3 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 8 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_keyboard.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_mouse.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_serial.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_serial_multitask.rs | 2 |
8 files changed, 54 insertions, 40 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs index b5e173078..0fcbe025d 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> { | |||
| 140 | type EndpointIn = Endpoint<'d, T, In>; | 140 | type EndpointIn = Endpoint<'d, T, In>; |
| 141 | type ControlPipe = ControlPipe<'d, T>; | 141 | type ControlPipe = ControlPipe<'d, T>; |
| 142 | type Bus = Bus<'d, T>; | 142 | type Bus = Bus<'d, T>; |
| 143 | type EnableFuture = impl Future<Output = Self::Bus> + 'd; | ||
| 143 | 144 | ||
| 144 | fn alloc_endpoint_in( | 145 | fn alloc_endpoint_in( |
| 145 | &mut self, | 146 | &mut self, |
| @@ -191,35 +192,46 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { | |||
| 191 | }) | 192 | }) |
| 192 | } | 193 | } |
| 193 | 194 | ||
| 194 | fn enable(self) -> Self::Bus { | 195 | fn enable(self) -> Self::EnableFuture { |
| 195 | let regs = T::regs(); | 196 | async move { |
| 196 | 197 | let regs = T::regs(); | |
| 197 | errata::pre_enable(); | ||
| 198 | 198 | ||
| 199 | regs.enable.write(|w| w.enable().enabled()); | 199 | errata::pre_enable(); |
| 200 | 200 | ||
| 201 | // Wait until the peripheral is ready. | 201 | regs.enable.write(|w| w.enable().enabled()); |
| 202 | while !regs.eventcause.read().ready().is_ready() {} | ||
| 203 | regs.eventcause.write(|w| w.ready().set_bit()); // Write 1 to clear. | ||
| 204 | 202 | ||
| 205 | errata::post_enable(); | 203 | // Wait until the peripheral is ready. |
| 204 | regs.intenset.write(|w| w.usbevent().set_bit()); | ||
| 205 | poll_fn(|cx| { | ||
| 206 | BUS_WAKER.register(cx.waker()); | ||
| 207 | if regs.eventcause.read().ready().is_ready() { | ||
| 208 | Poll::Ready(()) | ||
| 209 | } else { | ||
| 210 | Poll::Pending | ||
| 211 | } | ||
| 212 | }) | ||
| 213 | .await; | ||
| 214 | regs.eventcause.write(|w| w.ready().set_bit()); // Write 1 to clear. | ||
| 206 | 215 | ||
| 207 | unsafe { NVIC::unmask(pac::Interrupt::USBD) }; | 216 | errata::post_enable(); |
| 208 | 217 | ||
| 209 | regs.intenset.write(|w| { | 218 | unsafe { NVIC::unmask(pac::Interrupt::USBD) }; |
| 210 | w.usbreset().set_bit(); | ||
| 211 | w.usbevent().set_bit(); | ||
| 212 | w.epdata().set_bit(); | ||
| 213 | w | ||
| 214 | }); | ||
| 215 | // Enable the USB pullup, allowing enumeration. | ||
| 216 | regs.usbpullup.write(|w| w.connect().enabled()); | ||
| 217 | trace!("enabled"); | ||
| 218 | 219 | ||
| 219 | Bus { | 220 | regs.intenset.write(|w| { |
| 220 | phantom: PhantomData, | 221 | w.usbreset().set_bit(); |
| 221 | alloc_in: self.alloc_in, | 222 | w.usbevent().set_bit(); |
| 222 | alloc_out: self.alloc_out, | 223 | w.epdata().set_bit(); |
| 224 | w | ||
| 225 | }); | ||
| 226 | // Enable the USB pullup, allowing enumeration. | ||
| 227 | regs.usbpullup.write(|w| w.connect().enabled()); | ||
| 228 | trace!("enabled"); | ||
| 229 | |||
| 230 | Bus { | ||
| 231 | phantom: PhantomData, | ||
| 232 | alloc_in: self.alloc_in, | ||
| 233 | alloc_out: self.alloc_out, | ||
| 234 | } | ||
| 223 | } | 235 | } |
| 224 | } | 236 | } |
| 225 | } | 237 | } |
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index c8a9db7a4..4bbcd3e56 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs | |||
| @@ -122,7 +122,7 @@ pub struct UsbDeviceBuilder<'d, D: Driver<'d>> { | |||
| 122 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, | 122 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, |
| 123 | control_buf: &'d mut [u8], | 123 | control_buf: &'d mut [u8], |
| 124 | 124 | ||
| 125 | bus: D, | 125 | driver: D, |
| 126 | next_interface_number: u8, | 126 | next_interface_number: u8, |
| 127 | next_string_index: u8, | 127 | next_string_index: u8, |
| 128 | 128 | ||
| @@ -139,7 +139,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 139 | /// large enough for the length of the largest control request (in or out) | 139 | /// large enough for the length of the largest control request (in or out) |
| 140 | /// anticipated by any class added to the device. | 140 | /// anticipated by any class added to the device. |
| 141 | pub fn new( | 141 | pub fn new( |
| 142 | bus: D, | 142 | driver: D, |
| 143 | config: Config<'d>, | 143 | config: Config<'d>, |
| 144 | device_descriptor_buf: &'d mut [u8], | 144 | device_descriptor_buf: &'d mut [u8], |
| 145 | config_descriptor_buf: &'d mut [u8], | 145 | config_descriptor_buf: &'d mut [u8], |
| @@ -173,7 +173,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 173 | bos_descriptor.bos(); | 173 | bos_descriptor.bos(); |
| 174 | 174 | ||
| 175 | UsbDeviceBuilder { | 175 | UsbDeviceBuilder { |
| 176 | bus, | 176 | driver, |
| 177 | config, | 177 | config, |
| 178 | interfaces: Vec::new(), | 178 | interfaces: Vec::new(), |
| 179 | control_buf, | 179 | control_buf, |
| @@ -187,12 +187,12 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | /// Creates the [`UsbDevice`] instance with the configuration in this builder. | 189 | /// Creates the [`UsbDevice`] instance with the configuration in this builder. |
| 190 | pub fn build(mut self) -> UsbDevice<'d, D> { | 190 | pub async fn build(mut self) -> UsbDevice<'d, D> { |
| 191 | self.config_descriptor.end_configuration(); | 191 | self.config_descriptor.end_configuration(); |
| 192 | self.bos_descriptor.end_bos(); | 192 | self.bos_descriptor.end_bos(); |
| 193 | 193 | ||
| 194 | UsbDevice::build( | 194 | UsbDevice::build( |
| 195 | self.bus, | 195 | self.driver, |
| 196 | self.config, | 196 | self.config, |
| 197 | self.device_descriptor.into_buf(), | 197 | self.device_descriptor.into_buf(), |
| 198 | self.config_descriptor.into_buf(), | 198 | self.config_descriptor.into_buf(), |
| @@ -200,6 +200,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 200 | self.interfaces, | 200 | self.interfaces, |
| 201 | self.control_buf, | 201 | self.control_buf, |
| 202 | ) | 202 | ) |
| 203 | .await | ||
| 203 | } | 204 | } |
| 204 | 205 | ||
| 205 | /// Allocates a new interface number. | 206 | /// Allocates a new interface number. |
| @@ -251,7 +252,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 251 | max_packet_size: u16, | 252 | max_packet_size: u16, |
| 252 | interval: u8, | 253 | interval: u8, |
| 253 | ) -> Result<D::EndpointIn, EndpointAllocError> { | 254 | ) -> Result<D::EndpointIn, EndpointAllocError> { |
| 254 | self.bus | 255 | self.driver |
| 255 | .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) | 256 | .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) |
| 256 | } | 257 | } |
| 257 | 258 | ||
| @@ -266,7 +267,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 266 | max_packet_size: u16, | 267 | max_packet_size: u16, |
| 267 | interval: u8, | 268 | interval: u8, |
| 268 | ) -> Result<D::EndpointOut, EndpointAllocError> { | 269 | ) -> Result<D::EndpointOut, EndpointAllocError> { |
| 269 | self.bus | 270 | self.driver |
| 270 | .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) | 271 | .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) |
| 271 | } | 272 | } |
| 272 | 273 | ||
| @@ -306,7 +307,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 306 | /// feasibly recoverable. | 307 | /// feasibly recoverable. |
| 307 | #[inline] | 308 | #[inline] |
| 308 | pub fn alloc_control_pipe(&mut self, max_packet_size: u16) -> D::ControlPipe { | 309 | pub fn alloc_control_pipe(&mut self, max_packet_size: u16) -> D::ControlPipe { |
| 309 | self.bus | 310 | self.driver |
| 310 | .alloc_control_pipe(max_packet_size) | 311 | .alloc_control_pipe(max_packet_size) |
| 311 | .expect("alloc_control_pipe failed") | 312 | .expect("alloc_control_pipe failed") |
| 312 | } | 313 | } |
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs index d3231cb45..01eb3d577 100644 --- a/embassy-usb/src/driver.rs +++ b/embassy-usb/src/driver.rs | |||
| @@ -11,6 +11,7 @@ pub trait Driver<'a> { | |||
| 11 | type EndpointIn: EndpointIn + 'a; | 11 | type EndpointIn: EndpointIn + 'a; |
| 12 | type ControlPipe: ControlPipe + 'a; | 12 | type ControlPipe: ControlPipe + 'a; |
| 13 | type Bus: Bus + 'a; | 13 | type Bus: Bus + 'a; |
| 14 | type EnableFuture: Future<Output = Self::Bus> + 'a; | ||
| 14 | 15 | ||
| 15 | /// Allocates an endpoint and specified endpoint parameters. This method is called by the device | 16 | /// Allocates an endpoint and specified endpoint parameters. This method is called by the device |
| 16 | /// and class implementations to allocate endpoints, and can only be called before | 17 | /// and class implementations to allocate endpoints, and can only be called before |
| @@ -46,7 +47,7 @@ pub trait Driver<'a> { | |||
| 46 | 47 | ||
| 47 | /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so | 48 | /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so |
| 48 | /// there is no need to perform a USB reset in this method. | 49 | /// there is no need to perform a USB reset in this method. |
| 49 | fn enable(self) -> Self::Bus; | 50 | fn enable(self) -> Self::EnableFuture; |
| 50 | 51 | ||
| 51 | /// Indicates that `set_device_address` must be called before accepting the corresponding | 52 | /// Indicates that `set_device_address` must be called before accepting the corresponding |
| 52 | /// control transfer, not after. | 53 | /// control transfer, not after. |
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index f833a86d8..e98cbdee3 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -72,7 +72,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> { | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | 74 | impl<'d, D: Driver<'d>> UsbDevice<'d, D> { |
| 75 | pub(crate) fn build( | 75 | pub(crate) async fn build( |
| 76 | mut driver: D, | 76 | mut driver: D, |
| 77 | config: Config<'d>, | 77 | config: Config<'d>, |
| 78 | device_descriptor: &'d [u8], | 78 | device_descriptor: &'d [u8], |
| @@ -80,17 +80,17 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 80 | bos_descriptor: &'d [u8], | 80 | bos_descriptor: &'d [u8], |
| 81 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, | 81 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, |
| 82 | control_buf: &'d mut [u8], | 82 | control_buf: &'d mut [u8], |
| 83 | ) -> Self { | 83 | ) -> UsbDevice<'d, D> { |
| 84 | let control = driver | 84 | let control = driver |
| 85 | .alloc_control_pipe(config.max_packet_size_0 as u16) | 85 | .alloc_control_pipe(config.max_packet_size_0 as u16) |
| 86 | .expect("failed to alloc control endpoint"); | 86 | .expect("failed to alloc control endpoint"); |
| 87 | 87 | ||
| 88 | // Enable the USB bus. | 88 | // Enable the USB bus. |
| 89 | // This prevent further allocation by consuming the driver. | 89 | // This prevent further allocation by consuming the driver. |
| 90 | let driver = driver.enable(); | 90 | let bus = driver.enable().await; |
| 91 | 91 | ||
| 92 | Self { | 92 | Self { |
| 93 | bus: driver, | 93 | bus, |
| 94 | config, | 94 | config, |
| 95 | control: ControlPipe::new(control), | 95 | control: ControlPipe::new(control), |
| 96 | device_descriptor, | 96 | device_descriptor, |
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs index 51136292f..0812697e4 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) { | |||
| 76 | ); | 76 | ); |
| 77 | 77 | ||
| 78 | // Build the builder. | 78 | // Build the builder. |
| 79 | let mut usb = builder.build(); | 79 | let mut usb = builder.build().await; |
| 80 | 80 | ||
| 81 | // Run the USB device. | 81 | // Run the USB device. |
| 82 | let usb_fut = usb.run(); | 82 | 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 741e234b6..ca9383827 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) { | |||
| 74 | ); | 74 | ); |
| 75 | 75 | ||
| 76 | // Build the builder. | 76 | // Build the builder. |
| 77 | let mut usb = builder.build(); | 77 | let mut usb = builder.build().await; |
| 78 | 78 | ||
| 79 | // Run the USB device. | 79 | // Run the USB device. |
| 80 | let usb_fut = usb.run(); | 80 | let usb_fut = usb.run(); |
diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs index 9437e835f..500be2ce8 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) { | |||
| 60 | let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); | 60 | let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); |
| 61 | 61 | ||
| 62 | // Build the builder. | 62 | // Build the builder. |
| 63 | let mut usb = builder.build(); | 63 | let mut usb = builder.build().await; |
| 64 | 64 | ||
| 65 | // Run the USB device. | 65 | // Run the USB device. |
| 66 | let usb_fut = usb.run(); | 66 | 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 bef704417..1258bc53d 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) { | |||
| 85 | let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64); | 85 | let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64); |
| 86 | 86 | ||
| 87 | // Build the builder. | 87 | // Build the builder. |
| 88 | let usb = builder.build(); | 88 | let usb = builder.build().await; |
| 89 | 89 | ||
| 90 | unwrap!(spawner.spawn(usb_task(usb))); | 90 | unwrap!(spawner.spawn(usb_task(usb))); |
| 91 | unwrap!(spawner.spawn(echo_task(class))); | 91 | unwrap!(spawner.spawn(echo_task(class))); |
