Merge pull request #701 from alexmoon/async-usb-stack
Async-ify Driver::enable and UsbDeviceBuilder::build
This commit is contained in:
		
						commit
						d2494486d1
					
				@ -140,6 +140,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
 | 
				
			|||||||
    type EndpointIn = Endpoint<'d, T, In>;
 | 
					    type EndpointIn = Endpoint<'d, T, In>;
 | 
				
			||||||
    type ControlPipe = ControlPipe<'d, T>;
 | 
					    type ControlPipe = ControlPipe<'d, T>;
 | 
				
			||||||
    type Bus = Bus<'d, T>;
 | 
					    type Bus = Bus<'d, T>;
 | 
				
			||||||
 | 
					    type EnableFuture = impl Future<Output = Self::Bus> + 'd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn alloc_endpoint_in(
 | 
					    fn alloc_endpoint_in(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
@ -191,7 +192,8 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn enable(self) -> Self::Bus {
 | 
					    fn enable(self) -> Self::EnableFuture {
 | 
				
			||||||
 | 
					        async move {
 | 
				
			||||||
            let regs = T::regs();
 | 
					            let regs = T::regs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            errata::pre_enable();
 | 
					            errata::pre_enable();
 | 
				
			||||||
@ -199,7 +201,16 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
 | 
				
			|||||||
            regs.enable.write(|w| w.enable().enabled());
 | 
					            regs.enable.write(|w| w.enable().enabled());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Wait until the peripheral is ready.
 | 
					            // Wait until the peripheral is ready.
 | 
				
			||||||
        while !regs.eventcause.read().ready().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.
 | 
					            regs.eventcause.write(|w| w.ready().set_bit()); // Write 1 to clear.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            errata::post_enable();
 | 
					            errata::post_enable();
 | 
				
			||||||
@ -222,6 +233,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
 | 
				
			|||||||
                alloc_out: self.alloc_out,
 | 
					                alloc_out: self.alloc_out,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Bus<'d, T: Instance> {
 | 
					pub struct Bus<'d, T: Instance> {
 | 
				
			||||||
@ -650,14 +662,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
 | 
				
			|||||||
            poll_fn(|cx| {
 | 
					            poll_fn(|cx| {
 | 
				
			||||||
                EP0_WAKER.register(cx.waker());
 | 
					                EP0_WAKER.register(cx.waker());
 | 
				
			||||||
                let regs = T::regs();
 | 
					                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");
 | 
					                    trace!("aborted control data_out: usb reset");
 | 
				
			||||||
                    Poll::Ready(Err(ReadError::Disabled))
 | 
					                    Poll::Ready(Err(ReadError::Disabled))
 | 
				
			||||||
                } else if regs.events_ep0setup.read().bits() != 0 {
 | 
					                } else if regs.events_ep0setup.read().bits() != 0 {
 | 
				
			||||||
                    trace!("aborted control data_out: received another SETUP");
 | 
					                    trace!("aborted control data_out: received another SETUP");
 | 
				
			||||||
                    Poll::Ready(Err(ReadError::Disabled))
 | 
					                    Poll::Ready(Err(ReadError::Disabled))
 | 
				
			||||||
                } else if regs.events_ep0datadone.read().bits() != 0 {
 | 
					 | 
				
			||||||
                    Poll::Ready(Ok(()))
 | 
					 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Poll::Pending
 | 
					                    Poll::Pending
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -689,14 +701,14 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
 | 
				
			|||||||
                cx.waker().wake_by_ref();
 | 
					                cx.waker().wake_by_ref();
 | 
				
			||||||
                EP0_WAKER.register(cx.waker());
 | 
					                EP0_WAKER.register(cx.waker());
 | 
				
			||||||
                let regs = T::regs();
 | 
					                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");
 | 
					                    trace!("aborted control data_in: usb reset");
 | 
				
			||||||
                    Poll::Ready(Err(WriteError::Disabled))
 | 
					                    Poll::Ready(Err(WriteError::Disabled))
 | 
				
			||||||
                } else if regs.events_ep0setup.read().bits() != 0 {
 | 
					                } else if regs.events_ep0setup.read().bits() != 0 {
 | 
				
			||||||
                    trace!("aborted control data_in: received another SETUP");
 | 
					                    trace!("aborted control data_in: received another SETUP");
 | 
				
			||||||
                    Poll::Ready(Err(WriteError::Disabled))
 | 
					                    Poll::Ready(Err(WriteError::Disabled))
 | 
				
			||||||
                } else if regs.events_ep0datadone.read().bits() != 0 {
 | 
					 | 
				
			||||||
                    Poll::Ready(Ok(()))
 | 
					 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Poll::Pending
 | 
					                    Poll::Pending
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -122,7 +122,7 @@ pub struct UsbDeviceBuilder<'d, D: Driver<'d>> {
 | 
				
			|||||||
    interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>,
 | 
					    interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>,
 | 
				
			||||||
    control_buf: &'d mut [u8],
 | 
					    control_buf: &'d mut [u8],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bus: D,
 | 
					    driver: D,
 | 
				
			||||||
    next_interface_number: u8,
 | 
					    next_interface_number: u8,
 | 
				
			||||||
    next_string_index: 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)
 | 
					    /// large enough for the length of the largest control request (in or out)
 | 
				
			||||||
    /// anticipated by any class added to the device.
 | 
					    /// anticipated by any class added to the device.
 | 
				
			||||||
    pub fn new(
 | 
					    pub fn new(
 | 
				
			||||||
        bus: D,
 | 
					        driver: D,
 | 
				
			||||||
        config: Config<'d>,
 | 
					        config: Config<'d>,
 | 
				
			||||||
        device_descriptor_buf: &'d mut [u8],
 | 
					        device_descriptor_buf: &'d mut [u8],
 | 
				
			||||||
        config_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();
 | 
					        bos_descriptor.bos();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        UsbDeviceBuilder {
 | 
					        UsbDeviceBuilder {
 | 
				
			||||||
            bus,
 | 
					            driver,
 | 
				
			||||||
            config,
 | 
					            config,
 | 
				
			||||||
            interfaces: Vec::new(),
 | 
					            interfaces: Vec::new(),
 | 
				
			||||||
            control_buf,
 | 
					            control_buf,
 | 
				
			||||||
@ -187,12 +187,12 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates the [`UsbDevice`] instance with the configuration in this builder.
 | 
					    /// 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.config_descriptor.end_configuration();
 | 
				
			||||||
        self.bos_descriptor.end_bos();
 | 
					        self.bos_descriptor.end_bos();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        UsbDevice::build(
 | 
					        UsbDevice::build(
 | 
				
			||||||
            self.bus,
 | 
					            self.driver,
 | 
				
			||||||
            self.config,
 | 
					            self.config,
 | 
				
			||||||
            self.device_descriptor.into_buf(),
 | 
					            self.device_descriptor.into_buf(),
 | 
				
			||||||
            self.config_descriptor.into_buf(),
 | 
					            self.config_descriptor.into_buf(),
 | 
				
			||||||
@ -200,6 +200,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
 | 
				
			|||||||
            self.interfaces,
 | 
					            self.interfaces,
 | 
				
			||||||
            self.control_buf,
 | 
					            self.control_buf,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Allocates a new interface number.
 | 
					    /// Allocates a new interface number.
 | 
				
			||||||
@ -251,7 +252,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
 | 
				
			|||||||
        max_packet_size: u16,
 | 
					        max_packet_size: u16,
 | 
				
			||||||
        interval: u8,
 | 
					        interval: u8,
 | 
				
			||||||
    ) -> Result<D::EndpointIn, EndpointAllocError> {
 | 
					    ) -> Result<D::EndpointIn, EndpointAllocError> {
 | 
				
			||||||
        self.bus
 | 
					        self.driver
 | 
				
			||||||
            .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval)
 | 
					            .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,
 | 
					        max_packet_size: u16,
 | 
				
			||||||
        interval: u8,
 | 
					        interval: u8,
 | 
				
			||||||
    ) -> Result<D::EndpointOut, EndpointAllocError> {
 | 
					    ) -> Result<D::EndpointOut, EndpointAllocError> {
 | 
				
			||||||
        self.bus
 | 
					        self.driver
 | 
				
			||||||
            .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval)
 | 
					            .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.
 | 
					    /// feasibly recoverable.
 | 
				
			||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    pub fn alloc_control_pipe(&mut self, max_packet_size: u16) -> D::ControlPipe {
 | 
					    pub fn alloc_control_pipe(&mut self, max_packet_size: u16) -> D::ControlPipe {
 | 
				
			||||||
        self.bus
 | 
					        self.driver
 | 
				
			||||||
            .alloc_control_pipe(max_packet_size)
 | 
					            .alloc_control_pipe(max_packet_size)
 | 
				
			||||||
            .expect("alloc_control_pipe failed")
 | 
					            .expect("alloc_control_pipe failed")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ pub trait Driver<'a> {
 | 
				
			|||||||
    type EndpointIn: EndpointIn + 'a;
 | 
					    type EndpointIn: EndpointIn + 'a;
 | 
				
			||||||
    type ControlPipe: ControlPipe + 'a;
 | 
					    type ControlPipe: ControlPipe + 'a;
 | 
				
			||||||
    type Bus: Bus + 'a;
 | 
					    type Bus: Bus + 'a;
 | 
				
			||||||
 | 
					    type EnableFuture: Future<Output = Self::Bus> + 'a;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Allocates an endpoint and specified endpoint parameters. This method is called by the device
 | 
					    /// 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
 | 
					    /// 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
 | 
					    /// 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.
 | 
					    /// 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
 | 
					    /// Indicates that `set_device_address` must be called before accepting the corresponding
 | 
				
			||||||
    /// control transfer, not after.
 | 
					    /// control transfer, not after.
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
					impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			||||||
    pub(crate) fn build(
 | 
					    pub(crate) async fn build(
 | 
				
			||||||
        mut driver: D,
 | 
					        mut driver: D,
 | 
				
			||||||
        config: Config<'d>,
 | 
					        config: Config<'d>,
 | 
				
			||||||
        device_descriptor: &'d [u8],
 | 
					        device_descriptor: &'d [u8],
 | 
				
			||||||
@ -80,17 +80,17 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			|||||||
        bos_descriptor: &'d [u8],
 | 
					        bos_descriptor: &'d [u8],
 | 
				
			||||||
        interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>,
 | 
					        interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>,
 | 
				
			||||||
        control_buf: &'d mut [u8],
 | 
					        control_buf: &'d mut [u8],
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> UsbDevice<'d, D> {
 | 
				
			||||||
        let control = driver
 | 
					        let control = driver
 | 
				
			||||||
            .alloc_control_pipe(config.max_packet_size_0 as u16)
 | 
					            .alloc_control_pipe(config.max_packet_size_0 as u16)
 | 
				
			||||||
            .expect("failed to alloc control endpoint");
 | 
					            .expect("failed to alloc control endpoint");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Enable the USB bus.
 | 
					        // Enable the USB bus.
 | 
				
			||||||
        // This prevent further allocation by consuming the driver.
 | 
					        // This prevent further allocation by consuming the driver.
 | 
				
			||||||
        let driver = driver.enable();
 | 
					        let bus = driver.enable().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            bus: driver,
 | 
					            bus,
 | 
				
			||||||
            config,
 | 
					            config,
 | 
				
			||||||
            control: ControlPipe::new(control),
 | 
					            control: ControlPipe::new(control),
 | 
				
			||||||
            device_descriptor,
 | 
					            device_descriptor,
 | 
				
			||||||
 | 
				
			|||||||
@ -76,7 +76,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Build the builder.
 | 
					    // Build the builder.
 | 
				
			||||||
    let mut usb = builder.build();
 | 
					    let mut usb = builder.build().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Run the USB device.
 | 
					    // Run the USB device.
 | 
				
			||||||
    let usb_fut = usb.run();
 | 
					    let usb_fut = usb.run();
 | 
				
			||||||
 | 
				
			|||||||
@ -74,7 +74,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Build the builder.
 | 
					    // Build the builder.
 | 
				
			||||||
    let mut usb = builder.build();
 | 
					    let mut usb = builder.build().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Run the USB device.
 | 
					    // Run the USB device.
 | 
				
			||||||
    let usb_fut = usb.run();
 | 
					    let usb_fut = usb.run();
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
 | 
					    let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Build the builder.
 | 
					    // Build the builder.
 | 
				
			||||||
    let mut usb = builder.build();
 | 
					    let mut usb = builder.build().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Run the USB device.
 | 
					    // Run the USB device.
 | 
				
			||||||
    let usb_fut = usb.run();
 | 
					    let usb_fut = usb.run();
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ async fn main(spawner: Spawner, p: Peripherals) {
 | 
				
			|||||||
    let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64);
 | 
					    let class = CdcAcmClass::new(&mut builder, &mut res.serial_state, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Build the builder.
 | 
					    // Build the builder.
 | 
				
			||||||
    let usb = builder.build();
 | 
					    let usb = builder.build().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unwrap!(spawner.spawn(usb_task(usb)));
 | 
					    unwrap!(spawner.spawn(usb_task(usb)));
 | 
				
			||||||
    unwrap!(spawner.spawn(echo_task(class)));
 | 
					    unwrap!(spawner.spawn(echo_task(class)));
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user