diff options
author | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2022-05-04 20:48:37 +0200 |
---|---|---|
committer | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2022-05-07 01:45:54 +0200 |
commit | 931a137f8c5a760c2e06c437c98d14eff3e3a587 (patch) | |
tree | 7b79ba8397c3eff730f634cbaf77aa5571337191 | |
parent | fc32b3750c448a81b7dd44cf9de98723b8eb4fcf (diff) | |
download | embassy-931a137f8c5a760c2e06c437c98d14eff3e3a587.zip |
Replace embassy::io with embedded_io.
47 files changed, 699 insertions, 1762 deletions
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 2d0116bd..1b2847a0 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -31,12 +31,15 @@ pool-32 = [] pool-64 = [] pool-128 = [] +nightly = ["embedded-io/async"] + [dependencies] defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } embassy = { version = "0.1.0", path = "../embassy" } +embedded-io = "0.2.0" managed = { version = "0.8.0", default-features = false, features = [ "map" ] } heapless = { version = "0.7.5", default-features = false } diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index f66ebc19..1f4fa520 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs @@ -4,7 +4,6 @@ use smoltcp::phy::DeviceCapabilities; use smoltcp::time::Instant as SmolInstant; use crate::packet_pool::PacketBoxExt; -use crate::Result; use crate::{Packet, PacketBox, PacketBuf}; #[derive(PartialEq, Eq, Clone, Copy)] @@ -78,9 +77,9 @@ pub struct RxToken { } impl smoltcp::phy::RxToken for RxToken { - fn consume<R, F>(mut self, _timestamp: SmolInstant, f: F) -> Result<R> + fn consume<R, F>(mut self, _timestamp: SmolInstant, f: F) -> smoltcp::Result<R> where - F: FnOnce(&mut [u8]) -> Result<R>, + F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, { f(&mut self.pkt) } @@ -92,9 +91,9 @@ pub struct TxToken<'a> { } impl<'a> smoltcp::phy::TxToken for TxToken<'a> { - fn consume<R, F>(self, _timestamp: SmolInstant, len: usize, f: F) -> Result<R> + fn consume<R, F>(self, _timestamp: SmolInstant, len: usize, f: F) -> smoltcp::Result<R> where - F: FnOnce(&mut [u8]) -> Result<R>, + F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, { let mut buf = self.pkt.slice(0..len); let r = f(&mut buf)?; diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index ffe786b3..ded84190 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -1,5 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::new_without_default)] +#![cfg_attr( + feature = "nightly", + feature(generic_associated_types, type_alias_impl_trait) +)] // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; @@ -20,9 +24,7 @@ pub use stack::{ }; #[cfg(feature = "tcp")] -mod tcp_socket; -#[cfg(feature = "tcp")] -pub use tcp_socket::TcpSocket; +pub mod tcp; // smoltcp reexports pub use smoltcp::phy::{DeviceCapabilities, Medium}; @@ -32,4 +34,3 @@ pub use smoltcp::time::Instant as SmolInstant; pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; pub type Interface = smoltcp::iface::Interface<'static, device::DeviceAdapter>; -pub use smoltcp::{Error, Result}; diff --git a/embassy-net/src/tcp/io_impl.rs b/embassy-net/src/tcp/io_impl.rs new file mode 100644 index 00000000..15573349 --- /dev/null +++ b/embassy-net/src/tcp/io_impl.rs @@ -0,0 +1,67 @@ +use core::future::Future; +use core::task::Poll; +use futures::future::poll_fn; + +use super::{Error, TcpSocket}; + +impl<'d> embedded_io::asynch::Read for TcpSocket<'d> { + type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + where + Self: 'a; + + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { + poll_fn(move |cx| { + // CAUTION: smoltcp semantics around EOF are different to what you'd expect + // from posix-like IO, so we have to tweak things here. + self.with(|s, _| match s.recv_slice(buf) { + // No data ready + Ok(0) => { + s.register_recv_waker(cx.waker()); + Poll::Pending + } + // Data ready! + Ok(n) => Poll::Ready(Ok(n)), + // EOF + Err(smoltcp::Error::Finished) => Poll::Ready(Ok(0)), + // Connection reset. TODO: this can also be timeouts etc, investigate. + Err(smoltcp::Error::Illegal) => Poll::Ready(Err(Error::ConnectionReset)), + // smoltcp returns no errors other than the above. + Err(_) => unreachable!(), + }) + }) + } +} + +impl<'d> embedded_io::asynch::Write for TcpSocket<'d> { + type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + where + Self: 'a; + + fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { + poll_fn(move |cx| { + self.with(|s, _| match s.send_slice(buf) { + // Not ready to send (no space in the tx buffer) + Ok(0) => { + s.register_send_waker(cx.waker()); + Poll::Pending + } + // Some data sent + Ok(n) => Poll::Ready(Ok(n)), + // Connection reset. TODO: this can also be timeouts etc, investigate. + Err(smoltcp::Error::Illegal) => Poll::Ready(Err(Error::ConnectionReset)), + // smoltcp returns no errors other than the above. + Err(_) => unreachable!(), + }) + }) + } + + type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + where + Self: 'a; + + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + poll_fn(move |_| { + Poll::Ready(Ok(())) // TODO: Is there a better implementation for this? + }) + } +} diff --git a/embassy-net/src/tcp_socket.rs b/embassy-net/src/tcp/mod.rs index 5637505d..3bfd4c7b 100644 --- a/embassy-net/src/tcp_socket.rs +++ b/embassy-net/src/tcp/mod.rs @@ -1,17 +1,46 @@ use core::marker::PhantomData; use core::mem; -use core::pin::Pin; -use core::task::{Context, Poll}; -use embassy::io; -use embassy::io::{AsyncBufRead, AsyncWrite}; +use core::task::Poll; use smoltcp::iface::{Context as SmolContext, SocketHandle}; use smoltcp::socket::TcpSocket as SyncTcpSocket; use smoltcp::socket::{TcpSocketBuffer, TcpState}; use smoltcp::time::Duration; use smoltcp::wire::IpEndpoint; +#[cfg(feature = "nightly")] +mod io_impl; + use super::stack::Stack; -use crate::{Error, Result}; + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + ConnectionReset, +} + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ConnectError { + /// The socket is already connected or listening. + InvalidState, + /// The remote host rejected the connection with a RST packet. + ConnectionReset, + /// Connect timed out. + TimedOut, + /// No route to host. + NoRoute, +} + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum AcceptError { + /// The socket is already connected or listening. + InvalidState, + /// Invalid listen port + InvalidPort, + /// The remote host rejected the connection with a RST packet. + ConnectionReset, +} pub struct TcpSocket<'a> { handle: SocketHandle, @@ -37,17 +66,25 @@ impl<'a> TcpSocket<'a> { } } - pub async fn connect<T>(&mut self, remote_endpoint: T) -> Result<()> + pub async fn connect<T>(&mut self, remote_endpoint: T) -> Result<(), ConnectError> where T: Into<IpEndpoint>, { let local_port = Stack::with(|stack| stack.get_local_port()); - self.with(|s, cx| s.connect(cx, remote_endpoint, local_port))?; + match self.with(|s, cx| s.connect(cx, remote_endpoint, local_port)) { + Ok(()) => {} + Err(smoltcp::Error::Illegal) => return Err(ConnectError::InvalidState), + Err(smoltcp::Error::Unaddressable) => return Err(ConnectError::NoRoute), + // smoltcp returns no errors other than the above. + Err(_) => unreachable!(), + } futures::future::poll_fn(|cx| { self.with(|s, _| match s.state() { - TcpState::Closed | TcpState::TimeWait => Poll::Ready(Err(Error::Unaddressable)), - TcpState::Listen => Poll::Ready(Err(Error::Illegal)), + TcpState::Closed | TcpState::TimeWait => { + Poll::Ready(Err(ConnectError::ConnectionReset)) + } + TcpState::Listen => unreachable!(), TcpState::SynSent | TcpState::SynReceived => { s.register_send_waker(cx.waker()); Poll::Pending @@ -58,11 +95,17 @@ impl<'a> TcpSocket<'a> { .await } - pub async fn accept<T>(&mut self, local_endpoint: T) -> Result<()> + pub async fn accept<T>(&mut self, local_endpoint: T) -> Result<(), AcceptError> where T: Into<IpEndpoint>, { - self.with(|s, _| s.listen(local_endpoint))?; + match self.with(|s, _| s.listen(local_endpoint)) { + Ok(()) => {} + Err(smoltcp::Error::Illegal) => return Err(AcceptError::InvalidState), + Err(smoltcp::Error::Unaddressable) => return Err(AcceptError::InvalidPort), + // smoltcp returns no errors other than the above. + Err(_) => unreachable!(), + } futures::future::poll_fn(|cx| { self.with(|s, _| match s.state() { @@ -130,11 +173,6 @@ impl<'a> TcpSocket<'a> { } } -fn to_ioerr(_err: Error) -> io::Error { - // todo - io::Error::Other -} - impl<'a> Drop for TcpSocket<'a> { fn drop(&mut self) { Stack::with(|stack| { @@ -143,63 +181,12 @@ impl<'a> Drop for TcpSocket<'a> { } } -impl<'a> AsyncBufRead for TcpSocket<'a> { - fn poll_fill_buf<'z>( - self: Pin<&'z mut Self>, - cx: &mut Context<'_>, - ) -> Poll<io::Result<&'z [u8]>> { - self.with(|s, _| match s.peek(1 << 30) { - // No data ready - Ok(buf) if buf.is_empty() => { - s.register_recv_waker(cx.waker()); - Poll::Pending - } - // Data ready! - Ok(buf) => { - // Safety: - // - User can't touch the inner TcpSocket directly at all. - // - The socket itself won't touch these bytes until consume() is called, which - // requires the user to release this borrow. - let buf: &'z [u8] = unsafe { core::mem::transmute(&*buf) }; - Poll::Ready(Ok(buf)) - } - // EOF - Err(Error::Finished) => Poll::Ready(Ok(&[][..])), - // Error - Err(e) => Poll::Ready(Err(to_ioerr(e))), - }) - } - - fn consume(self: Pin<&mut Self>, amt: usize) { - if amt == 0 { - // smoltcp's recv returns Finished if we're at EOF, - // even if we're "reading" 0 bytes. - return; - } - self.with(|s, _| s.recv(|_| (amt, ()))).unwrap() +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + embedded_io::ErrorKind::Other } } -impl<'a> AsyncWrite for TcpSocket<'a> { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll<io::Result<usize>> { - self.with(|s, _| match s.send_slice(buf) { - // Not ready to send (no space in the tx buffer) - Ok(0) => { - s.register_send_waker(cx.waker()); - Poll::Pending - } - // Some data sent - Ok(n) => Poll::Ready(Ok(n)), - // Error - Err(e) => Poll::Ready(Err(to_ioerr(e))), - }) - } - - fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { - Poll::Ready(Ok(())) // TODO: Is there a better implementation for this? - } +impl<'d> embedded_io::Io for TcpSocket<'d> { + type Error = Error; } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index b7c09286..cf61abcc 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -19,10 +19,10 @@ flavors = [ time = ["embassy/time"] -defmt = ["dep:defmt", "embassy/defmt", "embassy-usb?/defmt"] +defmt = ["dep:defmt", "embassy/defmt", "embassy-usb?/defmt", "embedded-io?/defmt"] # Enable nightly-only features -nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async"] +nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io"] # Reexport the PAC for the currently enabled chip at `embassy_nrf::pac`. # This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. @@ -73,6 +73,7 @@ embassy-usb = {version = "0.1.0", path = "../embassy-usb", optional=true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8", optional = true} embedded-hal-async = { version = "0.1.0-alpha.0", optional = true} +embedded-io = { version = "0.2.0", features = ["async"], optional = true } defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index b49c1278..fc4e9c8d 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -14,18 +14,17 @@ //! Please also see [crate::uarte] to understand when [BufferedUarte] should be used. use core::cmp::min; +use core::future::Future; use core::marker::PhantomData; -use core::mem; -use core::pin::Pin; use core::sync::atomic::{compiler_fence, Ordering}; -use core::task::{Context, Poll}; +use core::task::Poll; use embassy::interrupt::InterruptExt; -use embassy::io::{AsyncBufRead, AsyncWrite}; use embassy::util::Unborrow; use embassy::waitqueue::WakerRegistration; use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; use embassy_hal_common::ring_buffer::RingBuffer; use embassy_hal_common::{low_power_wait_until, unborrow}; +use futures::future::poll_fn; use crate::gpio::Pin as GpioPin; use crate::pac; @@ -197,82 +196,99 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { } } -impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, U, T> { - fn poll_fill_buf( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll<embassy::io::Result<&[u8]>> { - self.inner.with(|state| { - compiler_fence(Ordering::SeqCst); - trace!("poll_read"); - - // We have data ready in buffer? Return it. - let buf = state.rx.pop_buf(); - if !buf.is_empty() { - trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len()); - let buf: &[u8] = buf; - let buf: &[u8] = unsafe { mem::transmute(buf) }; - return Poll::Ready(Ok(buf)); +impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarte<'d, U, T> { + type Error = core::convert::Infallible; +} + +impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> { + type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + where + Self: 'a; + + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { + poll_fn(move |cx| { + let mut do_pend = false; + let res = self.inner.with(|state| { + compiler_fence(Ordering::SeqCst); + trace!("poll_read"); + + // We have data ready in buffer? Return it. + let data = state.rx.pop_buf(); + if !data.is_empty() { + trace!(" got {:?} {:?}", data.as_ptr() as u32, data.len()); + let len = data.len().min(data.len()); + buf[..len].copy_from_slice(&data[..len]); + state.rx.pop(len); + do_pend = true; + return Poll::Ready(Ok(len)); + } + + trace!(" empty"); + state.rx_waker.register(cx.waker()); + Poll::Pending + }); + if do_pend { + self.inner.pend(); } - trace!(" empty"); - state.rx_waker.register(cx.waker()); - Poll::<embassy::io::Result<&[u8]>>::Pending + res }) } - - fn consume(mut self: Pin<&mut Self>, amt: usize) { - self.inner.with(|state| { - trace!("consume {:?}", amt); - state.rx.pop(amt); - }); - self.inner.pend(); - } } -impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U, T> { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll<embassy::io::Result<usize>> { - let poll = self.inner.with(|state| { - trace!("poll_write: {:?}", buf.len()); - - let tx_buf = state.tx.push_buf(); - if tx_buf.is_empty() { - trace!("poll_write: pending"); - state.tx_waker.register(cx.waker()); - return Poll::Pending; - } +impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write + for BufferedUarte<'d, U, T> +{ + type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + where + Self: 'a; + + fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { + poll_fn(move |cx| { + let res = self.inner.with(|state| { + trace!("poll_write: {:?}", buf.len()); + + let tx_buf = state.tx.push_buf(); + if tx_buf.is_empty() { + trace!("poll_write: pending"); + state.tx_waker.register(cx.waker()); + return Poll::Pending; + } - let n = min(tx_buf.len(), buf.len()); - tx_buf[..n].copy_from_slice(&buf[..n]); - state.tx.push(n); + let n = min(tx_buf.len(), buf.len()); + tx_buf[..n].copy_from_slice(&buf[..n]); + state.tx.push(n); - trace!("poll_write: queued {:?}", n); + trace!("poll_write: queued {:?}", n); - compiler_fence(Ordering::SeqCst); + compiler_fence(Ordering::SeqCst); - Poll::Ready(Ok(n)) - }); + Poll::Ready(Ok(n)) + }); - self.inner.pend(); + self.inner.pend(); - poll + res + }) } - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<embassy::io::Result<()>> { - self.inner.with(|state| { - trace!("poll_flush"); + type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + where + Self: 'a; - if !state.tx.is_empty() { - trace!("poll_flush: pending"); - state.tx_waker.register(cx.waker()); - return Poll::Pending; - } + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + poll_fn(move |cx| { + self.inner.with(|state| { + trace!("poll_flush"); + + if !state.tx.is_empty() { + trace!("poll_flush: pending"); + state.tx_waker.register(cx.waker()); + return Poll::Pending; + } - Poll::Ready(Ok(())) + Poll::Ready(Ok(())) + }) }) } } diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 3b180902..865f33d7 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -64,6 +64,7 @@ pub(crate) mod util; #[cfg(feature = "_time-driver")] mod time_driver; +#[cfg(feature = "nightly")] pub mod buffered_uarte; pub mod gpio; #[cfg(feature = "gpiote")] diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index ea9ac3b5..9686e016 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -57,12 +57,13 @@ critical-section = "0.2.5" bare-metal = "1.0.0" atomic-polyfill = "0.1.5" stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] } -vcell = { version = "0.1.3", optional = true } +vcell = "0.1.3" bxcan = "0.6.2" nb = "1.0.0" stm32-fmc = "0.2.4" seq-macro = "0.2.2" cfg-if = "1.0.0" +embedded-io = { version = "0.2.0", features = ["async"], optional = true } [build-dependencies] proc-macro2 = "1.0.36" @@ -70,8 +71,9 @@ quote = "1.0.15" stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]} [features] +defmt = ["dep:defmt", "embassy/defmt", "embedded-io?/defmt" ] sdmmc-rs = ["embedded-sdmmc"] -net = ["embassy-net", "vcell"] +net = ["embassy-net" ] memory-x = ["stm32-metapac/memory-x"] subghz = [] exti = [] @@ -88,7 +90,7 @@ time-driver-tim12 = ["_time-driver"] time-driver-tim15 = ["_time-driver"] # Enable nightly-only features -nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async"] +nightly = ["embassy/nightly", "embassy-net?/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io"] # Reexport stm32-metapac at `embassy_stm32::pac`. # This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index db757764..490f2d8f 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -244,200 +244,200 @@ fn main() { #[rustfmt::skip] let signals: HashMap<_, _> = [ - // (kind, signal) => (trait, cfgs) - (("usart", "TX"), (quote!(crate::usart::TxPin), quote!())), - (("usart", "RX"), (quote!(crate::usart::RxPin), quote!())), - (("usart", "CTS"), (quote!(crate::usart::CtsPin), quote!())), - (("usart", "RTS"), (quote!(crate::usart::RtsPin), quote!())), - (("usart", "CK"), (quote!(crate::usart::CkPin), quote!())), - (("usart", "TX"), (quote!(crate::usart::TxPin), quote!())), - (("usart", "RX"), (quote!(crate::usart::RxPin), quote!())), - (("usart", "CTS"), (quote!(crate::usart::CtsPin), quote!())), - (("usart", "RTS"), (quote!(crate::usart::RtsPin), quote!())), - (("usart", "CK"), (quote!(crate::usart::CkPin), quote!())), - (("spi", "SCK"), (quote!(crate::spi::SckPin), quote!())), - (("spi", "MOSI"), (quote!(crate::spi::MosiPin), quote!())), - (("spi", "MISO"), (quote!(crate::spi::MisoPin), quote!())), - (("i2c", "SDA"), (quote!(crate::i2c::SdaPin), quote!())), - (("i2c", "SCL"), (quote!(crate::i2c::SclPin), quote!())), - (("rcc", "MCO_1"), (quote!(crate::rcc::McoPin), quote!())), - (("rcc", "MCO_2"), (quote!(crate::rcc::McoPin), quote!())), - (("dcmi", "D0"), (quote!(crate::dcmi::D0Pin), quote!())), - (("dcmi", "D1"), (quote!(crate::dcmi::D1Pin), quote!())), - (("dcmi", "D2"), (quote!(crate::dcmi::D2Pin), quote!())), - (("dcmi", "D3"), (quote!(crate::dcmi::D3Pin), quote!())), - (("dcmi", "D4"), (quote!(crate::dcmi::D4Pin), quote!())), - (("dcmi", "D5"), (quote!(crate::dcmi::D5Pin), quote!())), - (("dcmi", "D6"), (quote!(crate::dcmi::D6Pin), quote!())), - (("dcmi", "D7"), (quote!(crate::dcmi::D7Pin), quote!())), - (("dcmi", "D8"), (quote!(crate::dcmi::D8Pin), quote!())), - (("dcmi", "D9"), (quote!(crate::dcmi::D9Pin), quote!())), - (("dcmi", "D10"), (quote!(crate::dcmi::D10Pin), quote!())), - (("dcmi", "D11"), (quote!(crate::dcmi::D11Pin), quote!())), - (("dcmi", "D12"), (quote!(crate::dcmi::D12Pin), quote!())), - (("dcmi", "D13"), (quote!(crate::dcmi::D13Pin), quote!())), - (("dcmi", "HSYNC"), (quote!(crate::dcmi::HSyncPin), quote!())), - (("dcmi", "VSYNC"), (quote!(crate::dcmi::VSyncPin), quote!())), - (("dcmi", "PIXCLK"), (quote!(crate::dcmi::PixClkPin), quote!())), - (("otgfs", "DP"), (quote!(crate::usb_otg::DpPin), quote!())), - (("otgfs", "DM"), (quote!(crate::usb_otg::DmPin), quote!())), - (("otghs", "DP"), (quote!(crate::usb_otg::DpPin), quote!())), - (("otghs", "DM"), (quote!(crate::usb_otg::DmPin), quote!())), - (("otghs", "ULPI_CK"), (quote!(crate::usb_otg::UlpiClkPin), quote!())), - (("otghs", "ULPI_DIR"), (quote!(crate::usb_otg::UlpiDirPin), quote!())), - (("otghs", "ULPI_NXT"), (quote!(crate::usb_otg::UlpiNxtPin), quote!())), - (("otghs", "ULPI_STP"), (quote!(crate::usb_otg::UlpiStpPin), quote!())), - (("otghs", "ULPI_D0"), (quote!(crate::usb_otg::UlpiD0Pin), quote!())), - (("otghs", "ULPI_D1"), (quote!(crate::usb_otg::UlpiD1Pin), quote!())), - (("otghs", "ULPI_D2"), (quote!(crate::usb_otg::UlpiD2Pin), quote!())), - (("otghs", "ULPI_D3"), (quote!(crate::usb_otg::UlpiD3Pin), quote!())), - (("otghs", "ULPI_D4"), (quote!(crate::usb_otg::UlpiD4Pin), quote!())), - (("otghs", "ULPI_D5"), (quote!(crate::usb_otg::UlpiD5Pin), quote!())), - (("otghs", "ULPI_D6"), (quote!(crate::usb_otg::UlpiD6Pin), quote!())), - (("otghs", "ULPI_D7"), (quote!(crate::usb_otg::UlpiD7Pin), quote!())), - (("can", "TX"), (quote!(crate::can::TxPin), quote!())), - (("can", "RX"), (quote!(crate::can::RxPin), quote!())), - (("eth", "REF_CLK"), (quote!(crate::eth::RefClkPin), quote!(#[cfg(feature="net")]))), - (("eth", "MDIO"), (quote!(crate::eth::MDIOPin), quote!(#[cfg(feature="net")]))), - (("eth", "MDC"), (quote!(crate::eth::MDCPin), quote!(#[cfg(feature="net")]))), - (("eth", "CRS_DV"), (quote!(crate::eth::CRSPin), quote!(#[cfg(feature="net")]))), - (("eth", "RXD0"), (quote!(crate::eth::RXD0Pin), quote!(#[cfg(feature="net")]))), - (("eth", "RXD1"), (quote!(crate::eth::RXD1Pin), quote!(#[cfg(feature="net")]))), - (("eth", "TXD0"), (quote!(crate::eth::TXD0Pin), quote!(#[cfg(feature="net")]))), - (("eth", "TXD1"), (quote!(crate::eth::TXD1Pin), quote!(#[cfg(feature="net")]))), - (("eth", "TX_EN"), (quote!(crate::eth::TXEnPin), quote!(#[cfg(feature="net")]))), - (("fmc", "A0"), (quote!(crate::fmc::A0Pin), quote!())), - (("fmc", "A1"), (quote!(crate::fmc::A1Pin), quote!())), - (("fmc", "A2"), (quote!(crate::fmc::A2Pin), quote!())), - (("fmc", "A3"), (quote!(crate::fmc::A3Pin), quote!())), - (("fmc", "A4"), (quote!(crate::fmc::A4Pin), quote!())), - (("fmc", "A5"), (quote!(crate::fmc::A5Pin), quote!())), - (("fmc", "A6"), (quote!(crate::fmc::A6Pin), quote!())), - (("fmc", "A7"), (quote!(crate::fmc::A7Pin), quote!())), - (("fmc", "A8"), (quote!(crate::fmc::A8Pin), quote!())), - (("fmc", "A9"), (quote!(crate::fmc::A9Pin), quote!())), - (("fmc", "A10"), (quote!(crate::fmc::A10Pin), quote!())), - (("fmc", "A11"), (quote!(crate::fmc::A11Pin), quote!())), - (("fmc", "A12"), (quote!(crate::fmc::A12Pin), quote!())), - (("fmc", "A13"), (quote!(crate::fmc::A13Pin), quote!())), - (("fmc", "A14"), (quote!(crate::fmc::A14Pin), quote!())), - (("fmc", "A15"), (quote!(crate::fmc::A15Pin), quote!())), - (("fmc", "A16"), (quote!(crate::fmc::A16Pin), quote!())), - (("fmc", "A17"), (quote!(crate::fmc::A17Pin), quote!())), - (("fmc", "A18"), (quote!(crate::fmc::A18Pin), quote!())), - (("fmc", "A19"), (quote!(crate::fmc::A19Pin), quote!())), - (("fmc", "A20"), (quote!(crate::fmc::A20Pin), quote!())), - (("fmc", "A21"), (quote!(crate::fmc::A21Pin), quote!())), - (("fmc", "A22"), (quote!(crate::fmc::A22Pin), quote!())), - (("fmc", "A23"), (quote!(crate::fmc::A23Pin), quote!())), - (("fmc", "A24"), (quote!(crate::fmc::A24Pin), quote!())), - (("fmc", "A25"), (quote!(crate::fmc::A25Pin), quote!())), - (("fmc", "D0"), (quote!(crate::fmc::D0Pin), quote!())), - (("fmc", "D1"), (quote!(crate::fmc::D1Pin), quote!())), - (("fmc", "D2"), (quote!(crate::fmc::D2Pin), quote!())), - (("fmc", "D3"), (quote!(crate::fmc::D3Pin), quote!())), - (("fmc", "D4"), (quote!(crate::fmc::D4Pin), quote!())), - (("fmc", "D5"), (quote!(crate::fmc::D5Pin), quote!())), - (("fmc", "D6"), (quote!(crate::fmc::D6Pin), quote!())), - (("fmc", "D7"), (quote!(crate::fmc::D7Pin), quote!())), - (("fmc", "D8"), (quote!(crate::fmc::D8Pin), quote!())), - (("fmc", "D9"), (quote!(crate::fmc::D9Pin), quote!())), - (("fmc", "D10"), (quote!(crate::fmc::D10Pin), quote!())), - (("fmc", "D11"), (quote!(crate::fmc::D11Pin), quote!())), - (("fmc", "D12"), (quote!(crate::fmc::D12Pin), quote!())), - (("fmc", "D13"), (quote!(crate::fmc::D13Pin), quote!())), - (("fmc", "D14"), (quote!(crate::fmc::D14Pin), quote!())), - (("fmc", "D15"), (quote!(crate::fmc::D15Pin), quote!())), - (("fmc", "D16"), (quote!(crate::fmc::D16Pin), quote!())), - (("fmc", "D17"), (quote!(crate::fmc::D17Pin), quote!())), - (("fmc", "D18"), (quote!(crate::fmc::D18Pin), quote!())), - (("fmc", "D19"), (quote!(crate::fmc::D19Pin), quote!())), - (("fmc", "D20"), (quote!(crate::fmc::D20Pin), quote!())), - (("fmc", "D21"), (quote!(crate::fmc::D21Pin), quote!())), - (("fmc", "D22"), (quote!(crate::fmc::D22Pin), quote!())), - (("fmc", "D23"), (quote!(crate::fmc::D23Pin), quote!())), - (("fmc", "D24"), (quote!(crate::fmc::D24Pin), quote!())), - (("fmc", "D25"), (quote!(crate::fmc::D25Pin), quote!())), - (("fmc", "D26"), (quote!(crate::fmc::D26Pin), quote!())), - (("fmc", "D27"), (quote!(crate::fmc::D27Pin), quote!())), - (("fmc", "D28"), (quote!(crate::fmc::D28Pin), quote!())), - (("fmc", "D29"), (quote!(crate::fmc::D29Pin), quote!())), - (("fmc", "D30"), (quote!(crate::fmc::D30Pin), quote!())), - (("fmc", "D31"), (quote!(crate::fmc::D31Pin), quote!())), - (("fmc", "DA0"), (quote!(crate::fmc::DA0Pin), quote!())), - (("fmc", "DA1"), (quote!(crate::fmc::DA1Pin), quote!())), - (("fmc", "DA2"), (quote!(crate::fmc::DA2Pin), quote!())), - (("fmc", "DA3"), (quote!(crate::fmc::DA3Pin), quote!())), - (("fmc", "DA4"), (quote!(crate::fmc::DA4Pin), quote!())), - (("fmc", "DA5"), (quote!(crate::fmc::DA5Pin), quote!())), - (("fmc", "DA6"), (quote!(crate::fmc::DA6Pin), quote!())), - (("fmc", "DA7"), (quote!(crate::fmc::DA7Pin), quote!())), - (("fmc", "DA8"), (quote!(crate::fmc::DA8Pin), quote!())), - (("fmc", "DA9"), (quote!(crate::fmc::DA9Pin), quote!())), - (("fmc", "DA10"), (quote!(crate::fmc::DA10Pin), quote!())), - (("fmc", "DA11"), (quote!(crate::fmc::DA11Pin), quote!())), - (("fmc", "DA12"), (quote!(crate::fmc::DA12Pin), quote!())), - (("fmc", "DA13"), (quote!(crate::fmc::DA13Pin), quote!())), - (("fmc", "DA14"), (quote!(crate::fmc::DA14Pin), quote!())), - (("fmc", "DA15"), (quote!(crate::fmc::DA15Pin), quote!())), - (("fmc", "SDNWE"), (quote!(crate::fmc::SDNWEPin), quote!())), - (("fmc", "SDNCAS"), (quote!(crate::fmc::SDNCASPin), quote!())), - (("fmc", "SDNRAS"), (quote!(crate::fmc::SDNRASPin), quote!())), - (("fmc", "SDNE0"), (quote!(crate::fmc::SDNE0Pin), quote!())), - (("fmc", "SDNE1"), (quote!(crate::fmc::SDNE1Pin), quote!())), - (("fmc", "SDCKE0"), (quote!(crate::fmc::SDCKE0Pin), quote!())), - (("fmc", "SDCKE1"), (quote!(crate::fmc::SDCKE1Pin), quote!())), - (("fmc", "SDCLK"), (quote!(crate::fmc::SDCLKPin), quote!())), - (("fmc", "NBL0"), (quote!(crate::fmc::NBL0Pin), quote!())), - (("fmc", "NBL1"), (quote!(crate::fmc::NBL1Pin), quote!())), - (("fmc", "NBL2"), (quote!(crate::fmc::NBL2Pin), quote!())), - (("fmc", "NBL3"), (quote!(crate::fmc::NBL3Pin), quote!())), - (("fmc", "INT"), (quote!(crate::fmc::INTPin), quote!())), - (("fmc", "NL"), (quote!(crate::fmc::NLPin), quote!())), - (("fmc", "NWAIT"), (quote!(crate::fmc::NWaitPin), quote!())), - (("fmc", "NE1"), (quote!(crate::fmc::NE1Pin), quote!())), - (("fmc", "NE2"), (quote!(crate::fmc::NE2Pin), quote!())), - (("fmc", "NE3"), (quote!(crate::fmc::NE3Pin), quote!())), - (("fmc", "NE4"), (quote!(crate::fmc::NE4Pin), quote!())), - (("fmc", "NCE"), (quote!(crate::fmc::NCEPin), quote!())), - (("fmc", "NOE"), (quote!(crate::fmc::NOEPin), quote!())), - (("fmc", "NWE"), (quote!(crate::fmc::NWEPin), quote!())), - (("fmc", "Clk"), (quote!(crate::fmc::ClkPin), quote!())), - (("fmc", "BA0"), (quote!(crate::fmc::BA0Pin), quote!())), - (("fmc", "BA1"), (quote!(crate::fmc::BA1Pin), quote!())), - (("timer", "CH1"), (quote!(crate::pwm::Channel1Pin), quote!())), - (("timer", "CH1N"), (quote!(crate::pwm::Channel1ComplementaryPin), quote!())), - (("timer", "CH2"), (quote!(crate::pwm::Channel2Pin), quote!())), - (("timer", "CH2N"), (quote!(crate::pwm::Channel2ComplementaryPin), quote!())), - (("timer", "CH3"), (quote!(crate::pwm::Channel3Pin), quote!())), - (("timer", "CH3N"), (quote!(crate::pwm::Channel3ComplementaryPin), quote!())), - (("timer", "CH4"), (quote!(crate::pwm::Channel4Pin), quote!())), - (("timer", "CH4N"), (quote!(crate::pwm::Channel4ComplementaryPin), quote!())), - (("timer", "ETR"), (quote!(crate::pwm::ExternalTriggerPin), quote!())), - (("timer", "BKIN"), (quote!(crate::pwm::BreakInputPin), quote!())), - (("timer", "BKIN_COMP1"), (quote!(crate::pwm::BreakInputComparator1Pin), quote!())), - (("timer", "BKIN_COMP2"), (quote!(crate::pwm::BreakInputComparator2Pin), quote!())), - (("timer", "BKIN2"), (quote!(crate::pwm::BreakInput2Pin), quote!())), - (("timer", "BKIN2_COMP1"), (quote!(crate::pwm::BreakInput2Comparator1Pin), quote!())), - (("timer", "BKIN2_COMP2"), (quote!(crate::pwm::BreakInput2Comparator2Pin), quote!())), - (("sdmmc", "CK"), (quote!(crate::sdmmc::CkPin), quote!())), - (("sdmmc", "CMD"), (quote!(crate::sdmmc::CmdPin), quote!())), - (("sdmmc", "D0"), (quote!(crate::sdmmc::D0Pin), quote!())), - (("sdmmc", "D1"), (quote!(crate::sdmmc::D1Pin), quote!())), - (("sdmmc", "D2"), (quote!(crate::sdmmc::D2Pin), quote!())), - (("sdmmc", "D3"), (quote!(crate::sdmmc::D3Pin), quote!())), - (("sdmmc", "D4"), (quote!(crate::sdmmc::D4Pin), quote!())), - (("sdmmc", "D5"), (quote!(crate::sdmmc::D5Pin), quote!())), - (("sdmmc", "D6"), (quote!(crate::sdmmc::D6Pin), quote!())), - (("sdmmc", "D6"), (quote!(crate::sdmmc::D7Pin), quote!())), - (("sdmmc", "D8"), (quote!(crate::sdmmc::D8Pin), quote!())), + // (kind, signal) => trait + (("usart", "TX"), quote!(crate::usart::TxPin)), + (("usart", "RX"), quote!(crate::usart::RxPin)), + (("usart", "CTS"), quote!(crate::usart::CtsPin)), + (("usart", "RTS"), quote!(crate::usart::RtsPin)), + (("usart", "CK"), quote!(crate::usart::CkPin)), + (("usart", "TX"), quote!(crate::usart::TxPin)), + (("usart", "RX"), quote!(crate::usart::RxPin)), + (("usart", "CTS"), quote!(crate::usart::CtsPin)), + (("usart", "RTS"), quote!(crate::usart::RtsPin)), + (("usart", "CK"), quote!(crate::usart::CkPin)), + (("spi", "SCK"), quote!(crate::spi::SckPin)), + (("spi", "MOSI"), quote!(crate::spi::MosiPin)), + (("spi", "MISO"), quote!(crate::spi::MisoPin)), + (("i2c", "SDA"), quote!(crate::i2c::SdaPin)), + (("i2c", "SCL"), quote!(crate::i2c::SclPin)), + (("rcc", "MCO_1"), quote!(crate::rcc::McoPin)), + (("rcc", "MCO_2"), quote!(crate::rcc::McoPin)), + (("dcmi", "D0"), quote!(crate::dcmi::D0Pin)), + (("dcmi", "D1"), quote!(crate::dcmi::D1Pin)), + (("dcmi", "D2"), quote!(crate::dcmi::D2Pin)), + (("dcmi", "D3"), quote!(crate::dcmi::D3Pin)), + (("dcmi", "D4"), quote!(crate::dcmi::D4Pin)), + (("dcmi", "D5"), quote!(crate::dcmi::D5Pin)), + (("dcmi", "D6"), quote!(crate::dcmi::D6Pin)), + (("dcmi", "D7"), quote!(crate::dcmi::D7Pin)), + (("dcmi", "D8"), quote!(crate::dcmi::D8Pin)), + (("dcmi", "D9"), quote!(crate::dcmi::D9Pin)), + (("dcmi", "D10"), quote!(crate::dcmi::D10Pin)), + (("dcmi", "D11"), quote!(crate::dcmi::D11Pin)), + (("dcmi", "D12"), quote!(crate::dcmi::D12Pin)), + (("dcmi", "D13"), quote!(crate::dcmi::D13Pin)), + (("dcmi", "HSYNC"), quote!(crate::dcmi::HSyncPin)), + (("dcmi", "VSYNC"), quote!(crate::dcmi::VSyncPin)), + (("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)), + (("otgfs", "DP"), quote!(crate::usb_otg::DpPin)), + (("otgfs", "DM"), quote!(crate::usb_otg::DmPin)), + (("otghs", "DP"), quote!(crate::usb_otg::DpPin)), + (("otghs", "DM"), quote!(crate::usb_otg::DmPin)), + (("otghs", "ULPI_CK"), quote!(crate::usb_otg::UlpiClkPin)), + (("otghs", "ULPI_DIR"), quote!(crate::usb_otg::UlpiDirPin)), + (("otghs", "ULPI_NXT"), quote!(crate::usb_otg::UlpiNxtPin)), + (("otghs", "ULPI_STP"), quote!(crate::usb_otg::UlpiStpPin)), + (("otghs", "ULPI_D0"), quote!(crate::usb_otg::UlpiD0Pin)), + (("otghs", "ULPI_D1"), quote!(crate::usb_otg::UlpiD1Pin)), + (("otghs", "ULPI_D2"), quote!(crate::usb_otg::UlpiD2Pin)), + (("otghs", "ULPI_D3"), quote!(crate::usb_otg::UlpiD3Pin)), + (("otghs", "ULPI_D4"), quote!(crate::usb_otg::UlpiD4Pin)), + (("otghs", "ULPI_D5"), quote!(crate::usb_otg::UlpiD5Pin)), + (("otghs", "ULPI_D6"), quote!(crate::usb_otg::UlpiD6Pin)), + (("otghs", "ULPI_D7"), quote!(crate::usb_otg::UlpiD7Pin)), + (("can", "TX"), quote!(crate::can::TxPin)), + (("can", "RX"), quote!(crate::can::RxPin)), + (("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)), + (("eth", "MDIO"), quote!(crate::eth::MDIOPin)), + (("eth", "MDC"), quote!(crate::eth::MDCPin)), + (("eth", "CRS_DV"), quote!(crate::eth::CRSPin)), + (("eth", "RXD0"), quote!(crate::eth::RXD0Pin)), + (("eth", "RXD1"), quote!(crate::eth::RXD1Pin)), + (("eth", "TXD0"), quote!(crate::eth::TXD0Pin)), + (("eth", "TXD1"), quote!(crate::eth::TXD1Pin)), + (("eth", "TX_EN"), quote!(crate::eth::TXEnPin)), + (("fmc", "A0"), quote!(crate::fmc::A0Pin)), + (("fmc", "A1"), quote!(crate::fmc::A1Pin)), + (("fmc", "A2"), quote!(crate::fmc::A2Pin)), + (("fmc", "A3"), quote!(crate::fmc::A3Pin)), + (("fmc", "A4"), quote!(crate::fmc::A4Pin)), + (("fmc", "A5"), quote!(crate::fmc::A5Pin)), + (("fmc", "A6"), quote!(crate::fmc::A6Pin)), + (("fmc", "A7"), quote!(crate::fmc::A7Pin)), + (("fmc", "A8"), quote!(crate::fmc::A8Pin)), + (("fmc", "A9"), quote!(crate::fmc::A9Pin)), + (("fmc", "A10"), quote!(crate::fmc::A10Pin)), + (("fmc", "A11"), quote!(crate::fmc::A11Pin)), + (("fmc", "A12"), quote!(crate::fmc::A12Pin)), + (("fmc", "A13"), quote!(crate::fmc::A13Pin)), + (("fmc", "A14"), quote!(crate::fmc::A14Pin)), + (("fmc", "A15"), quote!(crate::fmc::A15Pin)), + (("fmc", "A16"), quote!(crate::fmc::A16Pin)), + (("fmc", "A17"), quote!(crate::fmc::A17Pin)), + (("fmc", "A18"), quote!(crate::fmc::A18Pin)), + (("fmc", "A19"), quote!(crate::fmc::A19Pin)), + (("fmc", "A20"), quote!(crate::fmc::A20Pin)), + (("fmc", "A21"), quote!(crate::fmc::A21Pin)), + (("fmc", "A22"), quote!(crate::fmc::A22Pin)), + (("fmc", "A23"), quote!(crate::fmc::A23Pin)), + (("fmc", "A24"), quote!(crate::fmc::A24Pin)), + (("fmc", "A25"), quote!(crate::fmc::A25Pin)), + (("fmc", "D0"), quote!(crate::fmc::D0Pin)), + (("fmc", "D1"), quote!(crate::fmc::D1Pin)), + (("fmc", "D2"), quote!(crate::fmc::D2Pin)), + (("fmc", "D3"), quote!(crate::fmc::D3Pin)), + (("fmc", "D4"), quote!(crate::fmc::D4Pin)), + (("fmc", "D5"), quote!(crate::fmc::D5Pin)), + (("fmc", "D6"), quote!(crate::fmc::D6Pin)), + (("fmc", "D7"), quote!(crate::fmc::D7Pin)), + (("fmc", "D8"), quote!(crate::fmc::D8Pin)), + (("fmc", "D9"), quote!(crate::fmc::D9Pin)), + (("fmc", "D10"), quote!(crate::fmc::D10Pin)), + (("fmc", "D11"), quote!(crate::fmc::D11Pin)), + (("fmc", "D12"), quote!(crate::fmc::D12Pin)), + (("fmc", "D13"), quote!(crate::fmc::D13Pin)), + (("fmc", "D14"), quote!(crate::fmc::D14Pin)), + (("fmc", "D15"), quote!(crate::fmc::D15Pin)), + (("fmc", "D16"), quote!(crate::fmc::D16Pin)), + (("fmc", "D17"), quote!(crate::fmc::D17Pin)), + (("fmc", "D18"), quote!(crate::fmc::D18Pin)), + (("fmc", "D19"), quote!(crate::fmc::D19Pin)), + (("fmc", "D20"), quote!(crate::fmc::D20Pin)), + (("fmc", "D21"), quote!(crate::fmc::D21Pin)), + (("fmc", "D22"), quote!(crate::fmc::D22Pin)), + (("fmc", "D23"), quote!(crate::fmc::D23Pin)), + (("fmc", "D24"), quote!(crate::fmc::D24Pin)), + (("fmc", "D25"), quote!(crate::fmc::D25Pin)), + (("fmc", "D26"), quote!(crate::fmc::D26Pin)), + (("fmc", "D27"), quote!(crate::fmc::D27Pin)), + (("fmc", "D28"), quote!(crate::fmc::D28Pin)), + (("fmc", "D29"), quote!(crate::fmc::D29Pin)), + (("fmc", "D30"), quote!(crate::fmc::D30Pin)), + (("fmc", "D31"), quote!(crate::fmc::D31Pin)), + (("fmc", "DA0"), quote!(crate::fmc::DA0Pin)), + (("fmc", "DA1"), quote!(crate::fmc::DA1Pin)), + (("fmc", "DA2"), quote!(crate::fmc::DA2Pin)), + (("fmc", "DA3"), quote!(crate::fmc::DA3Pin)), + (("fmc", "DA4"), quote!(crate::fmc::DA4Pin)), + (("fmc", "DA5"), quote!(crate::fmc::DA5Pin)), + (("fmc", "DA6"), quote!(crate::fmc::DA6Pin)), + (("fmc", "DA7"), quote!(crate::fmc::DA7Pin)), + (("fmc", "DA8"), quote!(crate::fmc::DA8Pin)), + (("fmc", "DA9"), quote!(crate::fmc::DA9Pin)), + (("fmc", "DA10"), quote!(crate::fmc::DA10Pin)), + (("fmc", "DA11"), quote!(crate::fmc::DA11Pin)), + (("fmc", "DA12"), quote!(crate::fmc::DA12Pin)), + (("fmc", "DA13"), quote!(crate::fmc::DA13Pin)), + (("fmc", "DA14"), quote!(crate::fmc::DA14Pin)), + (("fmc", "DA15"), quote!(crate::fmc::DA15Pin)), + (("fmc", "SDNWE"), quote!(crate::fmc::SDNWEPin)), + (("fmc", "SDNCAS"), quote!(crate::fmc::SDNCASPin)), + (("fmc", "SDNRAS"), quote!(crate::fmc::SDNRASPin)), + (("fmc", "SDNE0"), quote!(crate::fmc::SDNE0Pin)), + (("fmc", "SDNE1"), quote!(crate::fmc::SDNE1Pin)), + (("fmc", "SDCKE0"), quote!(crate::fmc::SDCKE0Pin)), + (("fmc", "SDCKE1"), quote!(crate::fmc::SDCKE1Pin)), + (("fmc", "SDCLK"), quote!(crate::fmc::SDCLKPin)), + (("fmc", "NBL0"), quote!(crate::fmc::NBL0Pin)), + (("fmc", "NBL1"), quote!(crate::fmc::NBL1Pin)), + (("fmc", "NBL2"), quote!(crate::fmc::NBL2Pin)), + (("fmc", "NBL3"), quote!(crate::fmc::NBL3Pin)), + (("fmc", "INT"), quote!(crate::fmc::INTPin)), + (("fmc", "NL"), quote!(crate::fmc::NLPin)), + (("fmc", "NWAIT"), quote!(crate::fmc::NWaitPin)), + (("fmc", "NE1"), quote!(crate::fmc::NE1Pin)), + (("fmc", "NE2"), quote!(crate::fmc::NE2Pin)), + (("fmc", "NE3"), quote!(crate::fmc::NE3Pin)), + (("fmc", "NE4"), quote!(crate::fmc::NE4Pin)), + (("fmc", "NCE"), quote!(crate::fmc::NCEPin)), + (("fmc", "NOE"), quote!(crate::fmc::NOEPin)), + (("fmc", "NWE"), quote!(crate::fmc::NWEPin)), + (("fmc", "Clk"), quote!(crate::fmc::ClkPin)), + (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)), + (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)), + (("timer", "CH1"), quote!(crate::pwm::Channel1Pin)), + (("timer", "CH1N"), quote!(crate::pwm::Channel1ComplementaryPin)), + (("timer", "CH2"), quote!(crate::pwm::Channel2Pin)), + (("timer", "CH2N"), quote!(crate::pwm::Channel2ComplementaryPin)), + (("timer", "CH3"), quote!(crate::pwm::Channel3Pin)), + (("timer", "CH3N"), quote!(crate::pwm::Channel3ComplementaryPin)), + (("timer", "CH4"), quote!(crate::pwm::Channel4Pin)), + (("timer", "CH4N"), quote!(crate::pwm::Channel4ComplementaryPin)), + (("timer", "ETR"), quote!(crate::pwm::ExternalTriggerPin)), + (("timer", "BKIN"), quote!(crate::pwm::BreakInputPin)), + (("timer", "BKIN_COMP1"), quote!(crate::pwm::BreakInputComparator1Pin)), + (("timer", "BKIN_COMP2"), quote!(crate::pwm::BreakInputComparator2Pin)), + (("timer", "BKIN2"), quote!(crate::pwm::BreakInput2Pin)), + (("timer", "BKIN2_COMP1"), quote!(crate::pwm::BreakInput2Comparator1Pin)), + (("timer", "BKIN2_COMP2"), quote!(crate::pwm::BreakInput2Comparator2Pin)), + (("sdmmc", "CK"), quote!(crate::sdmmc::CkPin)), + (("sdmmc", "CMD"), quote!(crate::sdmmc::CmdPin)), + (("sdmmc", "D0"), quote!(crate::sdmmc::D0Pin)), + (("sdmmc", "D1"), quote!(crate::sdmmc::D1Pin)), + (("sdmmc", "D2"), quote!(crate::sdmmc::D2Pin)), + (("sdmmc", "D3"), quote!(crate::sdmmc::D3Pin)), + (("sdmmc", "D4"), quote!(crate::sdmmc::D4Pin)), + (("sdmmc", "D5"), quote!(crate::sdmmc::D5Pin)), + (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), + (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), + (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), ].into(); for p in METADATA.peripherals { if let Some(regs) = &p.registers { for pin in p.pins { let key = (regs.kind, pin.signal); - if let Some((tr, cfgs)) = signals.get(&key) { + if let Some(tr) = signals.get(&key) { let mut peri = format_ident!("{}", p.name); let pin_name = format_ident!("{}", pin.pin); let af = pin.af.unwrap_or(0); @@ -453,7 +453,6 @@ fn main() { } g.extend(quote! { - #cfgs pin_trait_impl!(#tr, #peri, #pin_name, #af); }) } diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 28f0c178..76a3dfab 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -1,10 +1,12 @@ #![macro_use] +#[cfg(feature = "net")] #[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] #[cfg_attr(eth_v2, path = "v2/mod.rs")] mod _version; pub mod generic_smi; +#[cfg(feature = "net")] pub use _version::*; /// Station Management Interface (SMI) on an ethernet PHY diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 6e9077b4..86b3e25d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -39,7 +39,7 @@ pub mod can; pub mod dac; #[cfg(dcmi)] pub mod dcmi; -#[cfg(all(eth, feature = "net"))] +#[cfg(eth)] pub mod eth; #[cfg(feature = "exti")] pub mod exti; diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs new file mode 100644 index 00000000..b2fcb504 --- /dev/null +++ b/embassy-stm32/src/usart/buffered.rs @@ -0,0 +1,238 @@ +use atomic_polyfill::{compiler_fence, Ordering}; +use core::future::Future; +use core::task::Poll; +use embassy::waitqueue::WakerRegistration; +use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; +use embassy_hal_common::ring_buffer::RingBuffer; +use futures::future::poll_fn; + +use super::*; + +pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>); +impl<'d, T: Instance> State<'d, T> { + pub fn new() -> Self { + Self(StateStorage::new()) + } +} + +struct StateInner<'d, T: Instance> { + phantom: PhantomData<&'d mut T>, + + rx_waker: WakerRegistration, + rx: RingBuffer<'d>, + + tx_waker: WakerRegistration, + tx: RingBuffer<'d>, +} + +unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {} +unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {} + +pub struct BufferedUart<'d, T: Instance> { + inner: PeripheralMutex<'d, StateInner<'d, T>>, +} + +impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} + +impl<'d, T: Instance> BufferedUart<'d, T> { + pub unsafe fn new( + state: &'d mut State<'d, T>, + _uart: Uart<'d, T, NoDma, NoDma>, + irq: impl Unborrow<Target = T::Interrupt> + 'd, + tx_buffer: &'d mut [u8], + rx_buffer: &'d mut [u8], + ) -> BufferedUart<'d, T> { + unborrow!(irq); + + let r = T::regs(); + r.cr1().modify(|w| { + w.set_rxneie(true); + w.set_idleie(true); + }); + + Self { + inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { + phantom: PhantomData, + tx: RingBuffer::new(tx_buffer), + tx_waker: WakerRegistration::new(), + + rx: RingBuffer::new(rx_buffer), + rx_waker: WakerRegistration::new(), + }), + } + } +} + +impl<'d, T: Instance> StateInner<'d, T> +where + Self: 'd, +{ + fn on_rx(&mut self) { + let r = T::regs(); + unsafe { + let sr = sr(r).read(); + clear_interrupt_flags(r, sr); + + // This read also clears the error and idle interrupt flags on v1. + let b = rdr(r).read_volatile(); + + if sr.rxne() { + if sr.pe() { + warn!("Parity error"); + } + if sr.fe() { + warn!("Framing error"); + } + if sr.ne() { + warn!("Noise error"); + } + if sr.ore() { + warn!("Overrun error"); + } + + let buf = self.rx.push_buf(); + if !buf.is_empty() { + buf[0] = b; + self.rx.push(1); + } else { + warn!("RX buffer full, discard received byte"); + } + + if self.rx.is_full() { + self.rx_waker.wake(); + } + } + + if sr.idle() { + self.rx_waker.wake(); + }; + } + } + + fn on_tx(&mut self) { + let r = T::regs(); + unsafe { + if sr(r).read().txe() { + let buf = self.tx.pop_buf(); + if !buf.is_empty() { + r.cr1().modify(|w| { + w.set_txeie(true); + }); + tdr(r).write_volatile(buf[0].into()); + self.tx.pop(1); + self.tx_waker.wake(); + } else { + // Disable interrupt until we have something to transmit again + r.cr1().modify(|w| { + w.set_txeie(false); + }); + } + } + } + } +} + +impl<'d, T: Instance> PeripheralState for StateInner<'d, T> +where + Self: 'd, +{ + type Interrupt = T::Interrupt; + fn on_interrupt(&mut self) { + self.on_rx(); + self.on_tx(); + } +} + +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + embedded_io::ErrorKind::Other + } +} + +impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> { + type Error = Error; +} + +impl<'d, T: Instance> embedded_io::asynch::Read for BufferedUart<'d, T> { + type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + where + Self: 'a; + + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { + poll_fn(move |cx| { + let mut do_pend = false; + let res = self.inner.with(|state| { + compiler_fence(Ordering::SeqCst); + + // We have data ready in buffer? Return it. + let data = state.rx.pop_buf(); + if !data.is_empty() { + let len = data.len().min(buf.len()); + buf[..len].copy_from_slice(&data[..len]); + + if state.rx.is_full() { + do_pend = true; + } + state.rx.pop(len); + + return Poll::Ready(Ok(len)); + } + + state.rx_waker.register(cx.waker()); + Poll::Pending + }); + + if do_pend { + self.inner.pend(); + } + + res + }) + } +} + +impl<'d, T: Instance> embedded_io::asynch::Write for BufferedUart<'d, T> { + type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + where + Self: 'a; + + fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { + poll_fn(move |cx| { + let (poll, empty) = self.inner.with(|state| { + let empty = state.tx.is_empty(); + let tx_buf = state.tx.push_buf(); + if tx_buf.is_empty() { + state.tx_waker.register(cx.waker()); + return (Poll::Pending, empty); + } + + let n = core::cmp::min(tx_buf.len(), buf.len()); + tx_buf[..n].copy_from_slice(&buf[..n]); + state.tx.push(n); + + (Poll::Ready(Ok(n)), empty) + }); + if empty { + self.inner.pend(); + } + poll + }) + } + + type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + where + Self: 'a; + + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + poll_fn(move |cx| { + self.inner.with(|state| { + if !state.tx.is_empty() { + state.tx_waker.register(cx.waker()); + return Poll::Pending; + } + + Poll::Ready(Ok(())) + }) + }) + } +} diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 22224215..6feecd18 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -424,227 +424,10 @@ cfg_if::cfg_if! { } } +#[cfg(feature = "nightly")] pub use buffered::*; -mod buffered { - use atomic_polyfill::{compiler_fence, Ordering}; - use core::pin::Pin; - use core::task::Context; - use core::task::Poll; - use embassy::waitqueue::WakerRegistration; - use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; - use embassy_hal_common::ring_buffer::RingBuffer; - - use super::*; - - pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>); - impl<'d, T: Instance> State<'d, T> { - pub fn new() -> Self { - Self(StateStorage::new()) - } - } - - struct StateInner<'d, T: Instance> { - phantom: PhantomData<&'d mut T>, - - rx_waker: WakerRegistration, - rx: RingBuffer<'d>, - - tx_waker: WakerRegistration, - tx: RingBuffer<'d>, - } - - unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {} - unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {} - - pub struct BufferedUart<'d, T: Instance> { - inner: PeripheralMutex<'d, StateInner<'d, T>>, - } - - impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} - - impl<'d, T: Instance> BufferedUart<'d, T> { - pub unsafe fn new( - state: &'d mut State<'d, T>, - _uart: Uart<'d, T, NoDma, NoDma>, - irq: impl Unborrow<Target = T::Interrupt> + 'd, - tx_buffer: &'d mut [u8], - rx_buffer: &'d mut [u8], - ) -> BufferedUart<'d, T> { - unborrow!(irq); - - let r = T::regs(); - r.cr1().modify(|w| { - w.set_rxneie(true); - w.set_idleie(true); - }); - - Self { - inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { - phantom: PhantomData, - tx: RingBuffer::new(tx_buffer), - tx_waker: WakerRegistration::new(), - - rx: RingBuffer::new(rx_buffer), - rx_waker: WakerRegistration::new(), - }), - } - } - } - - impl<'d, T: Instance> StateInner<'d, T> - where - Self: 'd, - { - fn on_rx(&mut self) { - let r = T::regs(); - unsafe { - let sr = sr(r).read(); - clear_interrupt_flags(r, sr); - - // This read also clears the error and idle interrupt flags on v1. - let b = rdr(r).read_volatile(); - - if sr.rxne() { - if sr.pe() { - warn!("Parity error"); - } - if sr.fe() { - warn!("Framing error"); - } - if sr.ne() { - warn!("Noise error"); - } - if sr.ore() { - warn!("Overrun error"); - } - - let buf = self.rx.push_buf(); - if !buf.is_empty() { - buf[0] = b; - self.rx.push(1); - } else { - warn!("RX buffer full, discard received byte"); - } - - if self.rx.is_full() { - self.rx_waker.wake(); - } - } - - if sr.idle() { - self.rx_waker.wake(); - }; - } - } - - fn on_tx(&mut self) { - let r = T::regs(); - unsafe { - if sr(r).read().txe() { - let buf = self.tx.pop_buf(); - if !buf.is_empty() { - r.cr1().modify(|w| { - w.set_txeie(true); - }); - tdr(r).write_volatile(buf[0].into()); - self.tx.pop(1); - self.tx_waker.wake(); - } else { - // Disable interrupt until we have something to transmit again - r.cr1().modify(|w| { - w.set_txeie(false); - }); - } - } - } - } - } - - impl<'d, T: Instance> PeripheralState for StateInner<'d, T> - where - Self: 'd, - { - type Interrupt = T::Interrupt; - fn on_interrupt(&mut self) { - self.on_rx(); - self.on_tx(); - } - } - - impl<'d, T: Instance> embassy::io::AsyncBufRead for BufferedUart<'d, T> { - fn poll_fill_buf( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll<Result<&[u8], embassy::io::Error>> { - self.inner.with(|state| { - compiler_fence(Ordering::SeqCst); - - // We have data ready in buffer? Return it. - let buf = state.rx.pop_buf(); - if !buf.is_empty() { - let buf: &[u8] = buf; - // Safety: buffer lives as long as uart - let buf: &[u8] = unsafe { core::mem::transmute(buf) }; - return Poll::Ready(Ok(buf)); - } - - state.rx_waker.register(cx.waker()); - Poll::<Result<&[u8], embassy::io::Error>>::Pending - }) - } - fn consume(mut self: Pin<&mut Self>, amt: usize) { - let signal = self.inner.with(|state| { - let full = state.rx.is_full(); - state.rx.pop(amt); - full - }); - if signal { - self.inner.pend(); - } - } - } - - impl<'d, T: Instance> embassy::io::AsyncWrite for BufferedUart<'d, T> { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll<Result<usize, embassy::io::Error>> { - let (poll, empty) = self.inner.with(|state| { - let empty = state.tx.is_empty(); - let tx_buf = state.tx.push_buf(); - if tx_buf.is_empty() { - state.tx_waker.register(cx.waker()); - return (Poll::Pending, empty); - } - - let n = core::cmp::min(tx_buf.len(), buf.len()); - tx_buf[..n].copy_from_slice(&buf[..n]); - state.tx.push(n); - - (Poll::Ready(Ok(n)), empty) - }); - if empty { - self.inner.pend(); - } - poll - } - - fn poll_flush( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll<Result<(), embassy::io::Error>> { - self.inner.with(|state| { - if !state.tx.is_empty() { - state.tx_waker.register(cx.waker()); - return Poll::Pending; - } - - Poll::Ready(Ok(())) - }) - } - } -} +#[cfg(feature = "nightly")] +mod buffered; #[cfg(usart_v1)] fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { @@ -662,6 +445,7 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::p } #[cfg(usart_v1)] +#[allow(unused)] unsafe fn clear_interrupt_flags(_r: crate::pac::usart::Usart, _sr: regs::Sr) { // On v1 the flags are cleared implicitly by reads and writes to DR. } @@ -682,6 +466,7 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Ixr, crate:: } #[cfg(usart_v2)] +#[allow(unused)] unsafe fn clear_interrupt_flags(r: crate::pac::usart::Usart, sr: regs::Ixr) { r.icr().write(|w| *w = sr); } diff --git a/embassy/src/io/error.rs b/embassy/src/io/error.rs deleted file mode 100644 index 2092c0d1..00000000 --- a/embassy/src/io/error.rs +++ /dev/null @@ -1,142 +0,0 @@ -/// Categories of errors that can occur. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - /// An entity was not found, often a file. - NotFound, - /// The operation lacked the necessary privileges to complete. - PermissionDenied, - /// The connection was refused by the remote server. - ConnectionRefused, - /// The connection was reset by the remote server. - ConnectionReset, - /// The connection was aborted (terminated) by the remote server. - ConnectionAborted, - /// The network operation failed because it was not connected yet. - NotConnected, - /// A socket address could not be bound because the address is already in - /// use elsewhere. - AddrInUse, - /// A nonexistent interface was requested or the requested address was not - /// local. - AddrNotAvailable, - /// The operation failed because a pipe was closed. - BrokenPipe, - /// An entity already exists, often a file. - AlreadyExists, - /// The operation needs to block to complete, but the blocking operation was - /// requested to not occur. - WouldBlock, - /// A parameter was incorrect. - InvalidInput, - /// Data not valid for the operation were encountered. - /// - /// Unlike [`InvalidInput`], this typically means that the operation - /// parameters were valid, however the error was caused by malformed - /// input data. - /// - /// For example, a function that reads a file into a string will error with - /// `InvalidData` if the file's contents are not valid UTF-8. - /// - /// [`InvalidInput`]: #variant.InvalidInput - InvalidData, - /// The I/O operation's timeout expired, causing it to be canceled. - TimedOut, - /// An error returned when an operation could not be completed because a - /// call to [`write`] returned [`Ok(0)`]. - /// - /// This typically means that an operation could only succeed if it wrote a - /// particular number of bytes but only a smaller number of bytes could be - /// written. - /// - /// [`write`]: ../../std/io/trait.Write.html#tymethod.write - /// [`Ok(0)`]: ../../std/io/type.Result.html - WriteZero, - /// This operation was interrupted. - /// - /// Interrupted operations can typically be retried. - Interrupted, - - /// An error returned when an operation could not be completed because an - /// "end of file" was reached prematurely. - /// - /// This typically means that an operation could only succeed if it read a - /// particular number of bytes but only a smaller number of bytes could be - /// read. - UnexpectedEof, - - /// An operation would have read more data if the given buffer was large. - /// - /// This typically means that the buffer has been filled with the first N bytes - /// of the read data. - Truncated, - - /// Any I/O error not part of this list. - Other, -} - -pub type Result<T> = core::result::Result<T, Error>; - -#[cfg(feature = "std")] -impl From<std::io::Error> for Error { - fn from(err: std::io::Error) -> Error { - match err.kind() { - std::io::ErrorKind::NotFound => Error::NotFound, - std::io::ErrorKind::PermissionDenied => Error::PermissionDenied, - std::io::ErrorKind::ConnectionRefused => Error::ConnectionRefused, - std::io::ErrorKind::ConnectionReset => Error::ConnectionReset, - std::io::ErrorKind::ConnectionAborted => Error::ConnectionAborted, - std::io::ErrorKind::NotConnected => Error::NotConnected, - std::io::ErrorKind::AddrInUse => Error::AddrInUse, - std::io::ErrorKind::AddrNotAvailable => Error::AddrNotAvailable, - std::io::ErrorKind::BrokenPipe => Error::BrokenPipe, - std::io::ErrorKind::AlreadyExists => Error::AlreadyExists, - std::io::ErrorKind::WouldBlock => Error::WouldBlock, - std::io::ErrorKind::InvalidInput => Error::InvalidInput, - std::io::ErrorKind::InvalidData => Error::InvalidData, - std::io::ErrorKind::TimedOut => Error::TimedOut, - std::io::ErrorKind::WriteZero => Error::WriteZero, - std::io::ErrorKind::Interrupted => Error::Interrupted, - std::io::ErrorKind::UnexpectedEof => Error::UnexpectedEof, - _ => Error::Other, - } - } -} - -#[cfg(feature = "std")] -impl From<Error> for std::io::Error { - fn from(e: Error) -> Self { - let kind = match e { - Error::NotFound => std::io::ErrorKind::NotFound, - Error::PermissionDenied => std::io::ErrorKind::PermissionDenied, - Error::ConnectionRefused => std::io::ErrorKind::ConnectionRefused, - Error::ConnectionReset => std::io::ErrorKind::ConnectionReset, - Error::ConnectionAborted => std::io::ErrorKind::ConnectionAborted, - Error::NotConnected => std::io::ErrorKind::NotConnected, - Error::AddrInUse => std::io::ErrorKind::AddrInUse, - Error::AddrNotAvailable => std::io::ErrorKind::AddrNotAvailable, - Error::BrokenPipe => std::io::ErrorKind::BrokenPipe, - Error::AlreadyExists => std::io::ErrorKind::AlreadyExists, - Error::WouldBlock => std::io::ErrorKind::WouldBlock, - Error::InvalidInput => std::io::ErrorKind::InvalidInput, - Error::InvalidData => std::io::ErrorKind::InvalidData, - Error::TimedOut => std::io::ErrorKind::TimedOut, - Error::WriteZero => std::io::ErrorKind::WriteZero, - Error::Interrupted => std::io::ErrorKind::Interrupted, - Error::UnexpectedEof => std::io::ErrorKind::UnexpectedEof, - Error::Truncated => std::io::ErrorKind::Other, - Error::Other => std::io::ErrorKind::Other, - }; - std::io::Error::new(kind, "embassy::io::Error") - } -} - -impl core::fmt::Display for Error { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{:?}", self) - } -} - -#[cfg(feature = "std")] -impl std::error::Error for Error {} diff --git a/embassy/src/io/mod.rs b/embassy/src/io/mod.rs deleted file mode 100644 index 52b05097..00000000 --- a/embassy/src/io/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod error; -#[cfg(feature = "std")] -mod std; -mod traits; -mod util; - -pub use self::error::*; -#[cfg(feature = "std")] -pub use self::std::*; -pub use self::traits::*; -pub use self::util::*; diff --git a/embassy/src/io/std.rs b/embassy/src/io/std.rs deleted file mode 100644 index 580d5289..00000000 --- a/embassy/src/io/std.rs +++ /dev/null @@ -1,41 +0,0 @@ -use core::pin::Pin; -use core::task::{Context, Poll}; -use futures::io as std_io; - -use super::{AsyncBufRead, AsyncWrite, Result}; - -pub struct FromStdIo<T>(T); - -impl<T> FromStdIo<T> { - pub fn new(inner: T) -> Self { - Self(inner) - } -} - -impl<T: std_io::AsyncBufRead> AsyncBufRead for FromStdIo<T> { - fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { - let Self(inner) = unsafe { self.get_unchecked_mut() }; - unsafe { Pin::new_unchecked(inner) } - .poll_fill_buf(cx) - .map_err(|e| e.into()) - } - fn consume(self: Pin<&mut Self>, amt: usize) { - let Self(inner) = unsafe { self.get_unchecked_mut() }; - unsafe { Pin::new_unchecked(inner) }.consume(amt) - } -} - -impl<T: std_io::AsyncWrite> AsyncWrite for FromStdIo<T> { - fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { - let Self(inner) = unsafe { self.get_unchecked_mut() }; - unsafe { Pin::new_unchecked(inner) } - .poll_write(cx, buf) - .map_err(|e| e.into()) - } - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { - let Self(inner) = unsafe { self.get_unchecked_mut() }; - unsafe { Pin::new_unchecked(inner) } - .poll_flush(cx) - .map_err(|e| e.into()) - } -} diff --git a/embassy/src/io/traits.rs b/embassy/src/io/traits.rs deleted file mode 100644 index 06500a68..00000000 --- a/embassy/src/io/traits.rs +++ /dev/null @@ -1,175 +0,0 @@ -use core::ops::DerefMut; -use core::pin::Pin; -use core::task::{Context, Poll}; - -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use super::error::Result; - -/// Read bytes asynchronously. -/// -/// This trait is analogous to the `std::io::BufRead` trait, but integrates -/// with the asynchronous task system. In particular, the `poll_fill_buf` -/// method, unlike `BufRead::fill_buf`, will automatically queue the current task -/// for wakeup and return if data is not yet available, rather than blocking -/// the calling thread. -pub trait AsyncBufRead { - /// Attempt to return the contents of the internal buffer, filling it with more data - /// from the inner reader if it is empty. - /// - /// On success, returns `Poll::Ready(Ok(buf))`. - /// - /// If no data is available for reading, the method returns - /// `Poll::Pending` and arranges for the current task (via - /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes - /// readable or is closed. - /// - /// This function is a lower-level call. It needs to be paired with the - /// [`consume`] method to function properly. When calling this - /// method, none of the contents will be "read" in the sense that later - /// calling [`poll_fill_buf`] may return the same contents. As such, [`consume`] must - /// be called with the number of bytes that are consumed from this buffer to - /// ensure that the bytes are never returned twice. - /// - /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf - /// [`consume`]: AsyncBufRead::consume - /// - /// An empty buffer returned indicates that the stream has reached EOF. - /// - /// # Implementation - /// - /// This function may not return errors of kind `WouldBlock` or - /// `Interrupted`. Implementations must convert `WouldBlock` into - /// `Poll::Pending` and either internally retry or convert - /// `Interrupted` into another error kind. - fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>>; - - /// Tells this buffer that `amt` bytes have been consumed from the buffer, - /// so they should no longer be returned in calls to [`poll_fill_buf`]. - /// - /// This function is a lower-level call. It needs to be paired with the - /// [`poll_fill_buf`] method to function properly. This function does - /// not perform any I/O, it simply informs this object that some amount of - /// its buffer, returned from [`poll_fill_buf`], has been consumed and should - /// no longer be returned. As such, this function may do odd things if - /// [`poll_fill_buf`] isn't called before calling it. - /// - /// The `amt` must be `<=` the number of bytes in the buffer returned by - /// [`poll_fill_buf`]. - /// - /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf - fn consume(self: Pin<&mut Self>, amt: usize); -} - -/// Write bytes asynchronously. -/// -/// This trait is analogous to the `core::io::Write` trait, but integrates -/// with the asynchronous task system. In particular, the `poll_write` -/// method, unlike `Write::write`, will automatically queue the current task -/// for wakeup and return if the writer cannot take more data, rather than blocking -/// the calling thread. -pub trait AsyncWrite { - /// Attempt to write bytes from `buf` into the object. - /// - /// On success, returns `Poll::Ready(Ok(num_bytes_written))`. - /// - /// If the object is not ready for writing, the method returns - /// `Poll::Pending` and arranges for the current task (via - /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes - /// writable or is closed. - /// - /// # Implementation - /// - /// This function may not return errors of kind `WouldBlock` or - /// `Interrupted`. Implementations must convert `WouldBlock` into - /// `Poll::Pending` and either internally retry or convert - /// `Interrupted` into another error kind. - /// - /// `poll_write` must try to make progress by flushing the underlying object if - /// that is the only way the underlying object can become writable again. - fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>>; - - /// Attempt to flush the object, ensuring that any buffered data reach their destination. - /// - /// On success, returns Poll::Ready(Ok(())). - /// - /// If flushing cannot immediately complete, this method returns [Poll::Pending] and arranges for the - /// current task (via cx.waker()) to receive a notification when the object can make progress - /// towards flushing. - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>; -} - -macro_rules! defer_async_read { - () => { - fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { - Pin::new(&mut **self.get_mut()).poll_fill_buf(cx) - } - - fn consume(mut self: Pin<&mut Self>, amt: usize) { - Pin::new(&mut **self).consume(amt) - } - }; -} - -#[cfg(feature = "alloc")] -impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for Box<T> { - defer_async_read!(); -} - -impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for &mut T { - defer_async_read!(); -} - -impl<P> AsyncBufRead for Pin<P> -where - P: DerefMut + Unpin, - P::Target: AsyncBufRead, -{ - fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { - self.get_mut().as_mut().poll_fill_buf(cx) - } - - fn consume(self: Pin<&mut Self>, amt: usize) { - self.get_mut().as_mut().consume(amt) - } -} - -macro_rules! deref_async_write { - () => { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll<Result<usize>> { - Pin::new(&mut **self).poll_write(cx, buf) - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { - Pin::new(&mut **self).poll_flush(cx) - } - }; -} - -#[cfg(feature = "alloc")] -impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for Box<T> { - deref_async_write!(); -} - -impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for &mut T { - deref_async_write!(); -} - -impl<P> AsyncWrite for Pin<P> -where - P: DerefMut + Unpin, - P::Target: AsyncWrite, -{ - fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { - self.get_mut().as_mut().poll_write(cx, buf) - } - - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { - self.get_mut().as_mut().poll_flush(cx) - } -} diff --git a/embassy/src/io/util/copy_buf.rs b/embassy/src/io/util/copy_buf.rs deleted file mode 100644 index 6d7932a0..00000000 --- a/embassy/src/io/util/copy_buf.rs +++ /dev/null @@ -1,80 +0,0 @@ -use core::future::Future; -use core::pin::Pin; -use core::task::{Context, Poll}; -use futures::ready; -use pin_project::pin_project; - -use crate::io::{AsyncBufRead, AsyncWrite, Error, Result}; - -/// Creates a future which copies all the bytes from one object to another. -/// -/// The returned future will copy all the bytes read from this `AsyncBufRead` into the -/// `writer` specified. This future will only complete once the `reader` has hit -/// EOF and all bytes have been written to and flushed from the `writer` -/// provided. -/// -/// On success the number of bytes is returned. -/// -/// # Examples -/// -/// ``` ignore -/// # futures::executor::block_on(async { -/// use futures::io::{self, AsyncWriteExt, Cursor}; -/// -/// let reader = Cursor::new([1, 2, 3, 4]); -/// let mut writer = Cursor::new(vec![0u8; 5]); -/// -/// let bytes = io::copy_buf(reader, &mut writer).await?; -/// writer.close().await?; -/// -/// assert_eq!(bytes, 4); -/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); -/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap(); -/// ``` -pub fn copy_buf<R, W>(reader: R, writer: &mut W) -> CopyBuf<'_, R, W> -where - R: AsyncBufRead, - W: AsyncWrite + Unpin + ?Sized, -{ - CopyBuf { - reader, - writer, - amt: 0, - } -} - -/// Future for the [`copy_buf()`] function. -#[pin_project] -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct CopyBuf<'a, R, W: ?Sized> { - #[pin] - reader: R, - writer: &'a mut W, - amt: usize, -} - -impl<R, W> Future for CopyBuf<'_, R, W> -where - R: AsyncBufRead, - W: AsyncWrite + Unpin + ?Sized, -{ - type Output = Result<usize>; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let mut this = self.project(); - loop { - let buffer = ready!(this.reader.as_mut().poll_fill_buf(cx))?; - if buffer.is_empty() { - return Poll::Ready(Ok(*this.amt)); - } - - let i = ready!(Pin::new(&mut this.writer).poll_write(cx, buffer))?; - if i == 0 { - return Poll::Ready(Err(Error::WriteZero)); - } - *this.amt += i; - this.reader.as_mut().consume(i); - } - } -} diff --git a/embassy/src/io/util/drain.rs b/embassy/src/io/util/drain.rs deleted file mode 100644 index 2542876d..00000000 --- a/embassy/src/io/util/drain.rs +++ /dev/null @@ -1,41 +0,0 @@ -use core::pin::Pin; -use futures::future::Future; -use futures::task::{Context, Poll}; - -use super::super::error::Result; -use super::super::traits::AsyncBufRead; - -pub struct Drain<'a, R: ?Sized> { - reader: &'a mut R, -} - -impl<R: ?Sized + Unpin> Unpin for Drain<'_, R> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> Drain<'a, R> { - pub(super) fn new(reader: &'a mut R) -> Self { - Self { reader } - } -} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for Drain<'a, R> { - type Output = Result<usize>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let Self { reader } = &mut *self; - let mut reader = Pin::new(reader); - - let mut n = 0; - - loop { - match reader.as_mut().poll_fill_buf(cx) { - Poll::Pending => return Poll::Ready(Ok(n)), - Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), - Poll::Ready(Ok(buf)) => { - let len = buf.len(); - n += len; - reader.as_mut().consume(len); - } - } - } - } -} diff --git a/embassy/src/io/util/flush.rs b/embassy/src/io/util/flush.rs deleted file mode 100644 index 966ef10f..00000000 --- a/embassy/src/io/util/flush.rs +++ /dev/null @@ -1,32 +0,0 @@ -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::Result; -use super::super::traits::AsyncWrite; - -/// Future for the [`flush`](super::AsyncWriteExt::flush) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Flush<'a, W: ?Sized> { - writer: &'a mut W, -} - -impl<W: ?Sized + Unpin> Unpin for Flush<'_, W> {} - -impl<'a, W: AsyncWrite + ?Sized + Unpin> Flush<'a, W> { - pub(super) fn new(writer: &'a mut W) -> Self { - Flush { writer } - } -} - -impl<W: AsyncWrite + ?Sized + Unpin> Future for Flush<'_, W> { - type Output = Result<()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { - let this = &mut *self; - let _ = ready!(Pin::new(&mut this.writer).poll_flush(cx))?; - Poll::Ready(Ok(())) - } -} diff --git a/embassy/src/io/util/mod.rs b/embassy/src/io/util/mod.rs deleted file mode 100644 index 49758ba9..00000000 --- a/embassy/src/io/util/mod.rs +++ /dev/null @@ -1,177 +0,0 @@ -use core::cmp::min; -use core::pin::Pin; -use core::task::{Context, Poll}; -use futures::ready; - -mod read; -pub use self::read::Read; - -mod read_buf; -pub use self::read_buf::ReadBuf; - -mod read_byte; -pub use self::read_byte::ReadByte; - -mod read_exact; -pub use self::read_exact::ReadExact; - -mod read_while; -pub use self::read_while::ReadWhile; - -mod read_to_end; -pub use self::read_to_end::ReadToEnd; - -mod skip_while; -pub use self::skip_while::SkipWhile; - -mod drain; -pub use self::drain::Drain; - -mod flush; -pub use self::flush::Flush; - -mod write; -pub use self::write::Write; - -mod write_all; -pub use self::write_all::WriteAll; - -mod write_byte; -pub use self::write_byte::WriteByte; - -#[cfg(feature = "alloc")] -mod split; -#[cfg(feature = "alloc")] -pub use self::split::{split, ReadHalf, WriteHalf}; - -mod copy_buf; -pub use self::copy_buf::{copy_buf, CopyBuf}; - -use super::error::Result; -use super::traits::{AsyncBufRead, AsyncWrite}; - -pub trait AsyncBufReadExt: AsyncBufRead { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll<Result<usize>> - where - Self: Unpin, - { - let mut this = &mut *self; - let rbuf = ready!(Pin::new(&mut this).poll_fill_buf(cx))?; - let n = min(buf.len(), rbuf.len()); - buf[..n].copy_from_slice(&rbuf[..n]); - Pin::new(&mut this).consume(n); - Poll::Ready(Ok(n)) - } - - fn read_while<'a, F: Fn(u8) -> bool>( - &'a mut self, - buf: &'a mut [u8], - f: F, - ) -> ReadWhile<'a, Self, F> - where - Self: Unpin, - { - ReadWhile::new(self, f, buf) - } - - fn skip_while<F: Fn(u8) -> bool>(&mut self, f: F) -> SkipWhile<Self, F> - where - Self: Unpin, - { - SkipWhile::new(self, f) - } - - fn drain(&mut self) -> Drain<Self> - where - Self: Unpin, - { - Drain::new(self) - } - - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self> - where - Self: Unpin, - { - Read::new(self, buf) - } - - fn read_buf(&mut self) -> ReadBuf<Self> - where - Self: Unpin, - { - ReadBuf::new(self) - } - - fn read_byte(&mut self) -> ReadByte<Self> - where - Self: Unpin, - { - ReadByte::new(self) - } - - fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self> - where - Self: Unpin, - { - ReadExact::new(self, buf) - } - - fn read_to_end<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadToEnd<'a, Self> - where - Self: Unpin, - { - ReadToEnd::new(self, buf) - } -} - -impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {} - -pub async fn read_line<R: AsyncBufRead + Unpin + ?Sized>( - r: &mut R, - buf: &mut [u8], -) -> Result<usize> { - r.skip_while(|b| b == b'\r' || b == b'\n').await?; - let n = r.read_while(buf, |b| b != b'\r' && b != b'\n').await?; - r.skip_while(|b| b == b'\r').await?; - //assert_eq!(b'\n', r.read_byte().await?); - r.read_byte().await?; - Ok(n) -} - -pub trait AsyncWriteExt: AsyncWrite { - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAll<'a, Self> - where - Self: Unpin, - { - WriteAll::new(self, buf) - } - - fn write_byte(&mut self, byte: u8) -> WriteByte<Self> - where - Self: Unpin, - { - WriteByte::new(self, byte) - } - - fn write<'a>(&'a mut self, buf: &'a [u8]) -> Write<'a, Self> - where - Self: Unpin, - { - Write::new(self, buf) - } - - /// Awaits until all bytes have actually been written, and - /// not just enqueued as per the other "write" methods. - fn flush<'a>(&mut self) -> Flush<Self> - where - Self: Unpin, - { - Flush::new(self) - } -} - -impl<R: AsyncWrite + ?Sized> AsyncWriteExt for R {} diff --git a/embassy/src/io/util/read.rs b/embassy/src/io/util/read.rs deleted file mode 100644 index 274b43a4..00000000 --- a/embassy/src/io/util/read.rs +++ /dev/null @@ -1,39 +0,0 @@ -use super::super::error::Result; -use super::super::traits::AsyncBufRead; - -use core::cmp::min; - -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -/// Future for the [`read_exact`](super::AsyncBufReadExt::read_exact) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Read<'a, R: ?Sized> { - reader: &'a mut R, - buf: &'a mut [u8], -} - -impl<R: ?Sized + Unpin> Unpin for Read<'_, R> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> Read<'a, R> { - pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { - Read { reader, buf } - } -} - -impl<R: AsyncBufRead + ?Sized + Unpin> Future for Read<'_, R> { - type Output = Result<usize>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let this = &mut *self; - let buf = ready!(Pin::new(&mut this.reader).poll_fill_buf(cx))?; - - let n = min(this.buf.len(), buf.len()); - this.buf[..n].copy_from_slice(&buf[..n]); - Pin::new(&mut this.reader).consume(n); - Poll::Ready(Ok(n)) - } -} diff --git a/embassy/src/io/util/read_buf.rs b/embassy/src/io/util/read_buf.rs deleted file mode 100644 index 71299b05..00000000 --- a/embassy/src/io/util/read_buf.rs +++ /dev/null @@ -1,34 +0,0 @@ -use super::super::error::Result; -use super::super::traits::AsyncBufRead; - -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -pub struct ReadBuf<'a, R: ?Sized> { - reader: Option<&'a mut R>, -} - -impl<R: ?Sized + Unpin> Unpin for ReadBuf<'_, R> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadBuf<'a, R> { - pub(super) fn new(reader: &'a mut R) -> Self { - ReadBuf { - reader: Some(reader), - } - } -} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for ReadBuf<'a, R> { - type Output = Result<&'a [u8]>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let this = &mut *self; - - let buf = ready!(Pin::new(this.reader.as_mut().unwrap()).poll_fill_buf(cx))?; - let buf: &'a [u8] = unsafe { core::mem::transmute(buf) }; - this.reader = None; - Poll::Ready(Ok(buf)) - } -} diff --git a/embassy/src/io/util/read_byte.rs b/embassy/src/io/util/read_byte.rs deleted file mode 100644 index e5bbcb1f..00000000 --- a/embassy/src/io/util/read_byte.rs +++ /dev/null @@ -1,36 +0,0 @@ -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::{Error, Result}; -use super::super::traits::AsyncBufRead; - -pub struct ReadByte<'a, R: ?Sized> { - reader: &'a mut R, -} - -impl<R: ?Sized + Unpin> Unpin for ReadByte<'_, R> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadByte<'a, R> { - pub(super) fn new(reader: &'a mut R) -> Self { - Self { reader } - } -} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for ReadByte<'a, R> { - type Output = Result<u8>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let Self { reader } = &mut *self; - let mut reader = Pin::new(reader); - let rbuf = ready!(reader.as_mut().poll_fill_buf(cx))?; - if rbuf.is_empty() { - return Poll::Ready(Err(Error::UnexpectedEof)); - } - - let r = rbuf[0]; - reader.as_mut().consume(1); - Poll::Ready(Ok(r)) - } -} diff --git a/embassy/src/io/util/read_exact.rs b/embassy/src/io/util/read_exact.rs deleted file mode 100644 index 4eecba4c..00000000 --- a/embassy/src/io/util/read_exact.rs +++ /dev/null @@ -1,48 +0,0 @@ -use super::super::error::{Error, Result}; -use super::super::traits::AsyncBufRead; - -use core::cmp::min; -use core::mem; -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -/// Future for the [`read_exact`](super::AsyncBufReadExt::read_exact) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadExact<'a, R: ?Sized> { - reader: &'a mut R, - buf: &'a mut [u8], -} - -impl<R: ?Sized + Unpin> Unpin for ReadExact<'_, R> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadExact<'a, R> { - pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { - ReadExact { reader, buf } - } -} - -impl<R: AsyncBufRead + ?Sized + Unpin> Future for ReadExact<'_, R> { - type Output = Result<()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let this = &mut *self; - while !this.buf.is_empty() { - let buf = ready!(Pin::new(&mut this.reader).poll_fill_buf(cx))?; - if buf.is_empty() { - return Poll::Ready(Err(Error::UnexpectedEof)); - } - - let n = min(this.buf.len(), buf.len()); - this.buf[..n].copy_from_slice(&buf[..n]); - Pin::new(&mut this.reader).consume(n); - { - let (_, rest) = mem::take(&mut this.buf).split_at_mut(n); - this.buf = rest; - } - } - Poll::Ready(Ok(())) - } -} diff --git a/embassy/src/io/util/read_to_end.rs b/embassy/src/io/util/read_to_end.rs deleted file mode 100644 index d09999ad..00000000 --- a/embassy/src/io/util/read_to_end.rs +++ /dev/null @@ -1,48 +0,0 @@ -use core::cmp::min; -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::{Error, Result}; -use super::super::traits::AsyncBufRead; - -pub struct ReadToEnd<'a, R: ?Sized> { - reader: &'a mut R, - buf: &'a mut [u8], - n: usize, -} - -impl<R: ?Sized + Unpin> Unpin for ReadToEnd<'_, R> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadToEnd<'a, R> { - pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { - Self { reader, buf, n: 0 } - } -} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for ReadToEnd<'a, R> { - type Output = Result<usize>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let Self { reader, buf, n } = &mut *self; - let mut reader = Pin::new(reader); - loop { - let rbuf = ready!(reader.as_mut().poll_fill_buf(cx))?; - if rbuf.is_empty() { - return Poll::Ready(Ok(*n)); - } - - if *n == buf.len() { - return Poll::Ready(Err(Error::Truncated)); - } - - // truncate data if it doesn't fit in buf - let p = min(rbuf.len(), buf.len() - *n); - buf[*n..*n + p].copy_from_slice(&rbuf[..p]); - *n += p; - - reader.as_mut().consume(p); - } - } -} diff --git a/embassy/src/io/util/read_while.rs b/embassy/src/io/util/read_while.rs deleted file mode 100644 index e2463803..00000000 --- a/embassy/src/io/util/read_while.rs +++ /dev/null @@ -1,61 +0,0 @@ -use core::cmp::min; -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::{Error, Result}; -use super::super::traits::AsyncBufRead; - -pub struct ReadWhile<'a, R: ?Sized, F> { - reader: &'a mut R, - buf: &'a mut [u8], - n: usize, - f: F, -} - -impl<R: ?Sized + Unpin, F> Unpin for ReadWhile<'_, R, F> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> ReadWhile<'a, R, F> { - pub(super) fn new(reader: &'a mut R, f: F, buf: &'a mut [u8]) -> Self { - Self { - reader, - f, - buf, - n: 0, - } - } -} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> Future for ReadWhile<'a, R, F> { - type Output = Result<usize>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let Self { reader, f, buf, n } = &mut *self; - let mut reader = Pin::new(reader); - loop { - let rbuf = ready!(reader.as_mut().poll_fill_buf(cx))?; - if rbuf.is_empty() { - return Poll::Ready(Err(Error::UnexpectedEof)); - } - - let (p, done) = match rbuf.iter().position(|&b| !f(b)) { - Some(p) => (p, true), - None => (rbuf.len(), false), - }; - - // truncate data if it doesn't fit in buf - let p2 = min(p, buf.len() - *n); - buf[*n..*n + p2].copy_from_slice(&rbuf[..p2]); - *n += p2; - - // consume it all, even if it doesn't fit. - // Otherwise we can deadlock because we never read to the ending char - reader.as_mut().consume(p); - - if done { - return Poll::Ready(Ok(*n)); - } - } - } -} diff --git a/embassy/src/io/util/skip_while.rs b/embassy/src/io/util/skip_while.rs deleted file mode 100644 index 6f0e167d..00000000 --- a/embassy/src/io/util/skip_while.rs +++ /dev/null @@ -1,45 +0,0 @@ -use core::iter::Iterator; -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::{Error, Result}; -use super::super::traits::AsyncBufRead; - -pub struct SkipWhile<'a, R: ?Sized, F> { - reader: &'a mut R, - f: F, -} - -impl<R: ?Sized + Unpin, F> Unpin for SkipWhile<'_, R, F> {} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> SkipWhile<'a, R, F> { - pub(super) fn new(reader: &'a mut R, f: F) -> Self { - Self { reader, f } - } -} - -impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> Future for SkipWhile<'a, R, F> { - type Output = Result<()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let Self { reader, f } = &mut *self; - let mut reader = Pin::new(reader); - loop { - let buf = ready!(reader.as_mut().poll_fill_buf(cx))?; - if buf.is_empty() { - return Poll::Ready(Err(Error::UnexpectedEof)); - } - - let (p, done) = match buf.iter().position(|b| !f(*b)) { - Some(p) => (p, true), - None => (buf.len(), false), - }; - reader.as_mut().consume(p); - if done { - return Poll::Ready(Ok(())); - } - } - } -} diff --git a/embassy/src/io/util/split.rs b/embassy/src/io/util/split.rs deleted file mode 100644 index cc029aa5..00000000 --- a/embassy/src/io/util/split.rs +++ /dev/null @@ -1,43 +0,0 @@ -use alloc::rc::Rc; -use core::cell::UnsafeCell; -use core::pin::Pin; -use futures::task::{Context, Poll}; - -use super::super::error::Result; -use super::super::traits::{AsyncBufRead, AsyncWrite}; - -/// The readable half of an object returned from `AsyncBufRead::split`. -#[derive(Debug)] -pub struct ReadHalf<T> { - handle: Rc<UnsafeCell<T>>, -} - -/// The writable half of an object returned from `AsyncBufRead::split`. -#[derive(Debug)] -pub struct WriteHalf<T> { - handle: Rc<UnsafeCell<T>>, -} - -impl<T: AsyncBufRead + Unpin> AsyncBufRead for ReadHalf<T> { - fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { - Pin::new(unsafe { &mut *self.handle.get() }).poll_fill_buf(cx) - } - - fn consume(self: Pin<&mut Self>, amt: usize) { - Pin::new(unsafe { &mut *self.handle.get() }).consume(amt) - } -} - -impl<T: AsyncWrite + Unpin> AsyncWrite for WriteHalf<T> { - fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { - Pin::new(unsafe { &mut *self.handle.get() }).poll_write(cx, buf) - } - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { - Pin::new(unsafe { &mut *self.handle.get() }).poll_flush(cx) - } -} - -pub fn split<T: AsyncBufRead + AsyncWrite>(t: T) -> (ReadHalf<T>, WriteHalf<T>) { - let c = Rc::new(UnsafeCell::new(t)); - (ReadHalf { handle: c.clone() }, WriteHalf { handle: c }) -} diff --git a/embassy/src/io/util/write.rs b/embassy/src/io/util/write.rs deleted file mode 100644 index 403cd59f..00000000 --- a/embassy/src/io/util/write.rs +++ /dev/null @@ -1,33 +0,0 @@ -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::Result; -use super::super::traits::AsyncWrite; - -/// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Write<'a, W: ?Sized> { - writer: &'a mut W, - buf: &'a [u8], -} - -impl<W: ?Sized + Unpin> Unpin for Write<'_, W> {} - -impl<'a, W: AsyncWrite + ?Sized + Unpin> Write<'a, W> { - pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { - Write { writer, buf } - } -} - -impl<W: AsyncWrite + ?Sized + Unpin> Future for Write<'_, W> { - type Output = Result<usize>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<usize>> { - let this = &mut *self; - let n = ready!(Pin::new(&mut this.writer).poll_write(cx, this.buf))?; - Poll::Ready(Ok(n)) - } -} diff --git a/embassy/src/io/util/write_all.rs b/embassy/src/io/util/write_all.rs deleted file mode 100644 index 8a7d9984..00000000 --- a/embassy/src/io/util/write_all.rs +++ /dev/null @@ -1,44 +0,0 @@ -use core::mem; -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::Result; -use super::super::traits::AsyncWrite; - -/// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct WriteAll<'a, W: ?Sized> { - writer: &'a mut W, - buf: &'a [u8], -} - -impl<W: ?Sized + Unpin> Unpin for WriteAll<'_, W> {} - -impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAll<'a, W> { - pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { - WriteAll { writer, buf } - } -} - -impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteAll<'_, W> { - type Output = Result<()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { - let this = &mut *self; - while !this.buf.is_empty() { - let n = ready!(Pin::new(&mut this.writer).poll_write(cx, this.buf))?; - { - let (_, rest) = mem::take(&mut this.buf).split_at(n); - this.buf = rest; - } - if n == 0 { - panic!(); - } - } - - Poll::Ready(Ok(())) - } -} diff --git a/embassy/src/io/util/write_byte.rs b/embassy/src/io/util/write_byte.rs deleted file mode 100644 index 659e427b..00000000 --- a/embassy/src/io/util/write_byte.rs +++ /dev/null @@ -1,39 +0,0 @@ -use core::pin::Pin; -use futures::future::Future; -use futures::ready; -use futures::task::{Context, Poll}; - -use super::super::error::Result; -use super::super::traits::AsyncWrite; - -/// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct WriteByte<'a, W: ?Sized> { - writer: &'a mut W, - byte: u8, -} - -impl<W: ?Sized + Unpin> Unpin for WriteByte<'_, W> {} - -impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteByte<'a, W> { - pub(super) fn new(writer: &'a mut W, byte: u8) -> Self { - WriteByte { writer, byte } - } -} - -impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteByte<'_, W> { - type Output = Result<()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { - let this = &mut *self; - let buf = [this.byte; 1]; - let n = ready!(Pin::new(&mut this.writer).poll_write(cx, &buf))?; - if n == 0 { - panic!(); - } - assert!(n == 1); - - Poll::Ready(Ok(())) - } -} diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index ec697b40..087bd357 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs @@ -13,7 +13,6 @@ pub mod channel; pub mod executor; #[cfg(cortex_m)] pub mod interrupt; -pub mod io; pub mod mutex; #[cfg(feature = "time")] pub mod time; diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 4258544f..ffac0a76 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" [features] default = ["nightly"] -nightly = ["embassy-nrf/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm"] +nightly = ["embassy-nrf/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm", "embedded-io/async", "embassy-net/nightly"] [dependencies] embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } @@ -16,6 +16,7 @@ embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defm embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true } embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true } embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true } +embedded-io = "0.2.0" defmt = "0.3" defmt-rtt = "0.3" diff --git a/examples/nrf/src/bin/buffered_uart.rs b/examples/nrf/src/bin/buffered_uart.rs index 2cd163a9..a64c5821 100644 --- a/examples/nrf/src/bin/buffered_uart.rs +++ b/examples/nrf/src/bin/buffered_uart.rs @@ -4,9 +4,9 @@ use defmt::*; use embassy::executor::Spawner; -use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; use embassy_nrf::buffered_uarte::State; use embassy_nrf::{buffered_uarte::BufferedUarte, interrupt, uarte, Peripherals}; +use embedded_io::asynch::{Read, Write}; use futures::pin_mut; use defmt_rtt as _; // global logger diff --git a/examples/nrf/src/bin/usb_ethernet.rs b/examples/nrf/src/bin/usb_ethernet.rs index f14a29c4..843487c0 100644 --- a/examples/nrf/src/bin/usb_ethernet.rs +++ b/examples/nrf/src/bin/usb_ethernet.rs @@ -10,9 +10,9 @@ use defmt::*; use embassy::blocking_mutex::raw::ThreadModeRawMutex; use embassy::channel::Channel; use embassy::executor::Spawner; -use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; use embassy::util::Forever; -use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, TcpSocket}; +use embassy_net::tcp::TcpSocket; +use embassy_net::{PacketBox, PacketBoxExt, PacketBuf}; use embassy_nrf::pac; use embassy_nrf::usb::Driver; use embassy_nrf::Peripherals; @@ -20,7 +20,9 @@ use embassy_nrf::{interrupt, peripherals}; use embassy_usb::{Builder, Config, UsbDevice}; use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; -use defmt_rtt as _; // global logger +use defmt_rtt as _; +use embedded_io::asynch::{Read, Write}; +// global logger use panic_probe as _; type MyDriver = Driver<'static, peripherals::USBD>; diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 0853c323..fa2a98a4 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -6,7 +6,8 @@ version = "0.1.0" [dependencies] embassy = { version = "0.1.0", path = "../../embassy", features = ["log", "std", "time", "nightly"] } -embassy-net = { version = "0.1.0", path = "../../embassy-net", features=["std", "log", "medium-ethernet", "tcp", "dhcpv4", "pool-16"] } +embassy-net = { version = "0.1.0", path = "../../embassy-net", features=["nightly", "std", "log", "medium-ethernet", "tcp", "dhcpv4", "pool-16"] } +embedded-io = { version = "0.2.0", features = ["async", "std"] } async-io = "1.6.0" env_logger = "0.9.0" diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 3b4bc6fe..daedffb0 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -2,12 +2,13 @@ use clap::Parser; use embassy::executor::{Executor, Spawner}; -use embassy::io::AsyncWriteExt; use embassy::util::Forever; +use embassy_net::tcp::TcpSocket; use embassy_net::{ Config, Configurator, DhcpConfigurator, Ipv4Address, Ipv4Cidr, StackResources, - StaticConfigurator, TcpSocket, + StaticConfigurator, }; +use embedded_io::asynch::Write; use heapless::Vec; use log::*; diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs index 129dc209..b1e5b014 100644 --- a/examples/std/src/bin/serial.rs +++ b/examples/std/src/bin/serial.rs @@ -5,8 +5,8 @@ mod serial_port; use async_io::Async; use embassy::executor::Executor; -use embassy::io::AsyncBufReadExt; use embassy::util::Forever; +use embedded_io::asynch::Read; use log::*; use nix::sys::termios; @@ -24,12 +24,12 @@ async fn run() { // Essentially, async_io::Async converts from AsRawFd+Read+Write to futures's AsyncRead+AsyncWrite let port = Async::new(port).unwrap(); - // This implements futures's AsyncBufRead based on futures's AsyncRead - let port = futures::io::BufReader::new(port); - - // We can then use FromStdIo to convert from futures's AsyncBufRead+AsyncWrite - // to embassy's AsyncBufRead+AsyncWrite - let mut port = embassy::io::FromStdIo::new(port); + // We can then use FromStdIo to convert from futures's AsyncRead+AsyncWrite + // to embedded_io's async Read+Write. + // + // This is not really needed, you could write the code below using futures::io directly. + // It's useful if you want to have portable code across embedded and std. + let mut port = embedded_io::adapters::FromFutures::new(port); info!("Serial opened!"); diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 09a06aa7..bbeee179 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -9,6 +9,7 @@ resolver = "2" embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "tcp", "medium-ethernet", "pool-16"] } +embedded-io = { version = "0.2.0", features = ["async"] } defmt = "0.3" defmt-rtt = "0.3" diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 33e41de9..dca9338b 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -5,12 +5,10 @@ use cortex_m_rt::entry; use defmt::*; use embassy::executor::{Executor, Spawner}; -use embassy::io::AsyncWriteExt; use embassy::time::{Duration, Timer}; use embassy::util::Forever; -use embassy_net::{ - Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket, -}; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator}; use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, State}; use embassy_stm32::interrupt; @@ -19,6 +17,7 @@ use embassy_stm32::peripherals::RNG; use embassy_stm32::rng::Rng; use embassy_stm32::time::U32Ext; use embassy_stm32::Config; +use embedded_io::asynch::Write; use heapless::Vec; use defmt_rtt as _; // global logger diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 419bbec3..ff70e6db 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -5,12 +5,11 @@ name = "embassy-stm32h7-examples" version = "0.1.0" resolver = "2" -[features] - [dependencies] embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "tcp", "medium-ethernet", "pool-16"] } +embedded-io = { version = "0.2.0", features = ["async"] } defmt = "0.3" defmt-rtt = "0.3" diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 9a2e7a33..8ece2940 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -8,12 +8,10 @@ use panic_probe as _; use cortex_m_rt::entry; use defmt::*; use embassy::executor::{Executor, Spawner}; -use embassy::io::AsyncWriteExt; use embassy::time::{Duration, Timer}; use embassy::util::Forever; -use embassy_net::{ - Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket, -}; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator}; use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, State}; use embassy_stm32::interrupt; @@ -22,6 +20,7 @@ use embassy_stm32::peripherals::RNG; use embassy_stm32::rng::Rng; use embassy_stm32::time::U32Ext; use embassy_stm32::Config; +use embedded_io::asynch::Write; use heapless::Vec; #[embassy::task] diff --git a/examples/stm32l0/.cargo/config.toml b/examples/stm32l0/.cargo/config.toml index 840faa62..ec0b931f 100644 --- a/examples/stm32l0/.cargo/config.toml +++ b/examples/stm32l0/.cargo/config.toml @@ -1,6 +1,6 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace your chip as listed in `probe-run --list-chips` -runner = "probe-run --chip STM32L072CZTx" +runner = "probe-run --chip STM32L053R8Tx" [build] target = "thumbv6m-none-eabi" diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 1cdb2f37..d6848c27 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -7,12 +7,11 @@ resolver = "2" [features] default = ["nightly"] -nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan"] +nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan", "embedded-io/async"] [dependencies] embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } - embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true} lorawan-device = { version = "0.7.1", default-features = false, features = ["async"], optional = true } @@ -22,6 +21,7 @@ defmt = "0.3" defmt-rtt = "0.3" embedded-storage = "0.3.0" +embedded-io = "0.2.0" cortex-m = "0.7.3" cortex-m-rt = "0.7.0" diff --git a/examples/stm32l0/src/bin/usart_irq.rs b/examples/stm32l0/src/bin/usart_irq.rs index abb27fa4..4413a294 100644 --- a/examples/stm32l0/src/bin/usart_irq.rs +++ b/examples/stm32l0/src/bin/usart_irq.rs @@ -2,13 +2,14 @@ #![no_main] #![feature(type_alias_impl_trait)] -use defmt_rtt as _; // global logger +use defmt_rtt as _; +use embedded_io::asynch::{Read, Write}; +// global logger use panic_probe as _; use defmt::*; use embassy::executor::Spawner; -use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; use embassy_stm32::dma::NoDma; use embassy_stm32::interrupt; use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; @@ -16,19 +17,21 @@ use embassy_stm32::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { + info!("Hi!"); + static mut TX_BUFFER: [u8; 8] = [0; 8]; static mut RX_BUFFER: [u8; 256] = [0; 256]; let mut config = Config::default(); config.baudrate = 9600; - let usart = Uart::new(p.USART1, p.PA10, p.PA9, NoDma, NoDma, config); + let usart = Uart::new(p.USART2, p.PA3, p.PA2, NoDma, NoDma, config); let mut state = State::new(); let mut usart = unsafe { BufferedUart::new( &mut state, usart, - interrupt::take!(USART1), + interrupt::take!(USART2), &mut TX_BUFFER, &mut RX_BUFFER, ) |