diff --git a/embassy-stm32f4-examples/src/bin/usb_serial.rs b/embassy-stm32f4-examples/src/bin/usb_serial.rs index d2ccb4b2..cf04c772 100644 --- a/embassy-stm32f4-examples/src/bin/usb_serial.rs +++ b/embassy-stm32f4-examples/src/bin/usb_serial.rs @@ -10,12 +10,11 @@ use cortex_m_rt::entry; use defmt::panic; use embassy::executor::{task, Executor}; use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; -use embassy::time::{Duration, Timer}; use embassy::util::Forever; use embassy_stm32f4::interrupt::OwnedInterrupt; use embassy_stm32f4::usb::Usb; use embassy_stm32f4::usb_serial::UsbSerial; -use embassy_stm32f4::{interrupt, pac, rtc}; +use embassy_stm32f4::{interrupt, pac}; use futures::future::{select, Either}; use futures::pin_mut; use stm32f4xx_hal::otg_fs::{UsbBus, USB}; @@ -27,44 +26,81 @@ use usb_device::prelude::*; async fn run1(bus: &'static mut UsbBusAllocator>) { info!("Async task"); - let mut read_buf = [0u8; 128]; - let mut write_buf = [0u8; 128]; - let serial = UsbSerial::new(bus, &mut read_buf, &mut write_buf); + let mut read_buf1 = [0u8; 128]; + let mut write_buf1 = [0u8; 128]; + let serial1 = UsbSerial::new(bus, &mut read_buf1, &mut write_buf1); + + let mut read_buf2 = [0u8; 128]; + let mut write_buf2 = [0u8; 128]; + let serial2 = UsbSerial::new(bus, &mut read_buf2, &mut write_buf2); let device = UsbDeviceBuilder::new(bus, UsbVidPid(0x16c0, 0x27dd)) .manufacturer("Fake company") .product("Serial port") .serial_number("TEST") - .device_class(0x02) + //.device_class(0x02) .build(); let irq = interrupt::take!(OTG_FS); irq.set_priority(interrupt::Priority::Level3); - let usb = Usb::new(device, serial, irq); + let usb = Usb::new(device, (serial1, serial2), irq); pin_mut!(usb); - let (mut read_interface, mut write_interface) = usb.as_mut().into_ref().take_serial(); + let (mut read_interface1, mut write_interface1) = usb.as_ref().take_serial_0(); + let (mut read_interface2, mut write_interface2) = usb.as_ref().take_serial_1(); + + let mut buf1 = [0u8; 64]; + let mut buf2 = [0u8; 64]; - let mut buf = [0u8; 5]; loop { - let recv_fut = read_interface.read(&mut buf); - let timeout = Timer::after(Duration::from_ticks(32768 * 3)); + let mut n1 = 0; + let mut n2 = 0; + let left = { + let read_line1 = async { + loop { + let byte = unwrap!(read_interface1.read_byte().await); + unwrap!(write_interface1.write_byte(byte).await); + buf1[n1] = byte; - match select(recv_fut, timeout).await { - Either::Left((recv, _)) => { - let recv = unwrap!(recv); - unwrap!(write_interface.write_all(&buf[..recv]).await); - } - Either::Right(_) => { - unwrap!(write_interface.write_all(b"Hello\r\n").await); + n1 += 1; + if byte == b'\n' || n1 == buf1.len() { + break; + } + } + }; + pin_mut!(read_line1); + + let read_line2 = async { + loop { + let byte = unwrap!(read_interface2.read_byte().await); + unwrap!(write_interface2.write_byte(byte).await); + buf2[n2] = byte; + + n2 += 1; + if byte == b'\n' || n2 == buf2.len() { + break; + } + } + }; + pin_mut!(read_line2); + + match select(read_line1, read_line2).await { + Either::Left(_) => true, + Either::Right(_) => false, } + }; + + if left { + unwrap!(write_interface2.write_all(b"\r\n").await); + unwrap!(write_interface2.write_all(&buf1[..n1]).await); + } else { + unwrap!(write_interface1.write_all(b"\r\n").await); + unwrap!(write_interface1.write_all(&buf2[..n2]).await); } } } -static RTC: Forever> = Forever::new(); -static ALARM: Forever> = Forever::new(); static EXECUTOR: Forever = Forever::new(); static USB_BUS: Forever>> = Forever::new(); @@ -91,14 +127,7 @@ fn main() -> ! { w.dbg_stop().set_bit() }); - let rtc = RTC.put(rtc::RTC::new(p.TIM2, interrupt::take!(TIM2), clocks)); - rtc.start(); - - unsafe { embassy::time::set_clock(rtc) }; - - let alarm = ALARM.put(rtc.alarm1()); let executor = EXECUTOR.put(Executor::new()); - executor.set_alarm(alarm); let gpioa = p.GPIOA.split(); let usb = USB { diff --git a/embassy-stm32f4/src/usb.rs b/embassy-stm32f4/src/usb.rs index 613b9ecb..9e741156 100644 --- a/embassy-stm32f4/src/usb.rs +++ b/embassy-stm32f4/src/usb.rs @@ -10,12 +10,20 @@ use crate::interrupt; use crate::usb_serial::{ReadInterface, UsbSerial, WriteInterface}; use crate::util::peripheral::{PeripheralMutex, PeripheralState}; -pub struct State<'bus, B: UsbBus, T: ClassSet> { +pub struct State<'bus, B, T> +where + B: UsbBus, + T: ClassSet, +{ device: UsbDevice<'bus, B>, pub(crate) classes: T, } -pub struct Usb<'bus, B: UsbBus, T: ClassSet> { +pub struct Usb<'bus, B, T> +where + B: UsbBus, + T: ClassSet, +{ // Don't you dare moving out `PeripheralMutex` inner: RefCell>>, } @@ -53,24 +61,54 @@ where impl<'bus, 'c, B, T> Usb<'bus, B, T> where B: UsbBus, - T: ClassSet + SerialState<'bus, 'c, B>, + T: ClassSet + SerialState<'bus, 'c, B, Index0>, { - pub fn take_serial<'a>( + pub fn take_serial_0<'a>( self: Pin<&'a Self>, ) -> ( - ReadInterface<'a, 'bus, 'c, B, T>, - WriteInterface<'a, 'bus, 'c, B, T>, + ReadInterface<'a, 'bus, 'c, Index0, B, T>, + WriteInterface<'a, 'bus, 'c, Index0, B, T>, ) { let this = self.get_ref(); let r = ReadInterface { inner: &this.inner, _buf_lifetime: PhantomData, + _index: PhantomData, }; let w = WriteInterface { inner: &this.inner, _buf_lifetime: PhantomData, + _index: PhantomData, + }; + (r, w) + } +} + +impl<'bus, 'c, B, T> Usb<'bus, B, T> +where + B: UsbBus, + T: ClassSet + SerialState<'bus, 'c, B, Index1>, +{ + pub fn take_serial_1<'a>( + self: Pin<&'a Self>, + ) -> ( + ReadInterface<'a, 'bus, 'c, Index1, B, T>, + WriteInterface<'a, 'bus, 'c, Index1, B, T>, + ) { + let this = self.get_ref(); + + let r = ReadInterface { + inner: &this.inner, + _buf_lifetime: PhantomData, + _index: PhantomData, + }; + + let w = WriteInterface { + inner: &this.inner, + _buf_lifetime: PhantomData, + _index: PhantomData, }; (r, w) } @@ -95,23 +133,56 @@ pub trait IntoClassSet> { fn into_class_set(self) -> C; } -pub struct ClassSet1> { - class: T, +pub struct ClassSet1 +where + B: UsbBus, + C1: UsbClass, +{ + class: C1, _bus: PhantomData, } -impl ClassSet for ClassSet1 +pub struct ClassSet2 where B: UsbBus, - T: UsbClass, + C1: UsbClass, + C2: UsbClass, +{ + class1: C1, + class2: C2, + _bus: PhantomData, +} + +pub struct Index0; +pub struct Index1; + +impl ClassSet for ClassSet1 +where + B: UsbBus, + C1: UsbClass, { fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool { device.poll(&mut [&mut self.class]) } } -impl> IntoClassSet> for T { - fn into_class_set(self) -> ClassSet1 { +impl ClassSet for ClassSet2 +where + B: UsbBus, + C1: UsbClass, + C2: UsbClass, +{ + fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool { + device.poll(&mut [&mut self.class1, &mut self.class2]) + } +} + +impl IntoClassSet> for C1 +where + B: UsbBus, + C1: UsbClass, +{ + fn into_class_set(self) -> ClassSet1 { ClassSet1 { class: self, _bus: PhantomData, @@ -119,12 +190,49 @@ impl> IntoClassSet> for T { } } -pub trait SerialState<'bus, 'a, B: UsbBus> { +impl IntoClassSet> for (C1, C2) +where + B: UsbBus, + C1: UsbClass, + C2: UsbClass, +{ + fn into_class_set(self) -> ClassSet2 { + ClassSet2 { + class1: self.0, + class2: self.1, + _bus: PhantomData, + } + } +} + +pub trait SerialState<'bus, 'a, B: UsbBus, I> { fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B>; } -impl<'bus, 'a, B: UsbBus> SerialState<'bus, 'a, B> for ClassSet1> { +impl<'bus, 'a, B: UsbBus> SerialState<'bus, 'a, B, Index0> + for ClassSet1> +{ fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B> { &mut self.class } } + +impl<'bus, 'a, B, C2> SerialState<'bus, 'a, B, Index0> for ClassSet2, C2> +where + B: UsbBus, + C2: UsbClass, +{ + fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B> { + &mut self.class1 + } +} + +impl<'bus, 'a, B, C1> SerialState<'bus, 'a, B, Index1> for ClassSet2> +where + B: UsbBus, + C1: UsbClass, +{ + fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B> { + &mut self.class2 + } +} diff --git a/embassy-stm32f4/src/usb_serial.rs b/embassy-stm32f4/src/usb_serial.rs index 284d7e5f..bacc886d 100644 --- a/embassy-stm32f4/src/usb_serial.rs +++ b/embassy-stm32f4/src/usb_serial.rs @@ -1,5 +1,5 @@ use core::cell::RefCell; -use core::marker::{PhantomData, PhantomPinned}; +use core::marker::{PhantomData, Unpin}; use core::pin::Pin; use core::task::{Context, Poll}; @@ -14,26 +14,39 @@ use crate::usb::{ClassSet, SerialState, State}; use crate::util::peripheral::PeripheralMutex; use crate::util::ring_buffer::RingBuffer; -pub struct ReadInterface<'a, 'bus, 'c, B: UsbBus, T: SerialState<'bus, 'c, B> + ClassSet> { +pub struct ReadInterface<'a, 'bus, 'c, I, B, T> +where + I: Unpin, + B: UsbBus, + T: SerialState<'bus, 'c, B, I> + ClassSet, +{ // Don't you dare moving out `PeripheralMutex` pub(crate) inner: &'a RefCell>>, pub(crate) _buf_lifetime: PhantomData<&'c T>, + pub(crate) _index: PhantomData, } /// Write interface for USB CDC_ACM /// /// This interface is buffered, meaning that after the write returns the bytes might not be fully /// on the wire just yet -pub struct WriteInterface<'a, 'bus, 'c, B: UsbBus, T: SerialState<'bus, 'c, B> + ClassSet> { +pub struct WriteInterface<'a, 'bus, 'c, I, B, T> +where + I: Unpin, + B: UsbBus, + T: SerialState<'bus, 'c, B, I> + ClassSet, +{ // Don't you dare moving out `PeripheralMutex` pub(crate) inner: &'a RefCell>>, pub(crate) _buf_lifetime: PhantomData<&'c T>, + pub(crate) _index: PhantomData, } -impl<'a, 'bus, 'c, B, T> AsyncBufRead for ReadInterface<'a, 'bus, 'c, B, T> +impl<'a, 'bus, 'c, I, B, T> AsyncBufRead for ReadInterface<'a, 'bus, 'c, I, B, T> where + I: Unpin, B: UsbBus, - T: SerialState<'bus, 'c, B> + ClassSet, + T: SerialState<'bus, 'c, B, I> + ClassSet, { fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.get_mut(); @@ -68,10 +81,11 @@ where } } -impl<'a, 'bus, 'c, B, T> AsyncWrite for WriteInterface<'a, 'bus, 'c, B, T> +impl<'a, 'bus, 'c, I, B, T> AsyncWrite for WriteInterface<'a, 'bus, 'c, I, B, T> where + I: Unpin, B: UsbBus, - T: SerialState<'bus, 'c, B> + ClassSet, + T: SerialState<'bus, 'c, B, I> + ClassSet, { fn poll_write( self: Pin<&mut Self>,