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();
|
||||||
@ -223,6 +234,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Bus<'d, T: Instance> {
|
pub struct Bus<'d, T: Instance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
@ -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…
Reference in New Issue
Block a user