diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-05-04 20:48:37 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-05-07 01:45:54 +0200 |
| commit | 931a137f8c5a760c2e06c437c98d14eff3e3a587 (patch) | |
| tree | 7b79ba8397c3eff730f634cbaf77aa5571337191 | |
| parent | fc32b3750c448a81b7dd44cf9de98723b8eb4fcf (diff) | |
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 2d0116bd5..1b2847a0d 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml | |||
| @@ -31,12 +31,15 @@ pool-32 = [] | |||
| 31 | pool-64 = [] | 31 | pool-64 = [] |
| 32 | pool-128 = [] | 32 | pool-128 = [] |
| 33 | 33 | ||
| 34 | nightly = ["embedded-io/async"] | ||
| 35 | |||
| 34 | [dependencies] | 36 | [dependencies] |
| 35 | 37 | ||
| 36 | defmt = { version = "0.3", optional = true } | 38 | defmt = { version = "0.3", optional = true } |
| 37 | log = { version = "0.4.14", optional = true } | 39 | log = { version = "0.4.14", optional = true } |
| 38 | 40 | ||
| 39 | embassy = { version = "0.1.0", path = "../embassy" } | 41 | embassy = { version = "0.1.0", path = "../embassy" } |
| 42 | embedded-io = "0.2.0" | ||
| 40 | 43 | ||
| 41 | managed = { version = "0.8.0", default-features = false, features = [ "map" ] } | 44 | managed = { version = "0.8.0", default-features = false, features = [ "map" ] } |
| 42 | heapless = { version = "0.7.5", default-features = false } | 45 | heapless = { version = "0.7.5", default-features = false } |
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index f66ebc193..1f4fa5208 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs | |||
| @@ -4,7 +4,6 @@ use smoltcp::phy::DeviceCapabilities; | |||
| 4 | use smoltcp::time::Instant as SmolInstant; | 4 | use smoltcp::time::Instant as SmolInstant; |
| 5 | 5 | ||
| 6 | use crate::packet_pool::PacketBoxExt; | 6 | use crate::packet_pool::PacketBoxExt; |
| 7 | use crate::Result; | ||
| 8 | use crate::{Packet, PacketBox, PacketBuf}; | 7 | use crate::{Packet, PacketBox, PacketBuf}; |
| 9 | 8 | ||
| 10 | #[derive(PartialEq, Eq, Clone, Copy)] | 9 | #[derive(PartialEq, Eq, Clone, Copy)] |
| @@ -78,9 +77,9 @@ pub struct RxToken { | |||
| 78 | } | 77 | } |
| 79 | 78 | ||
| 80 | impl smoltcp::phy::RxToken for RxToken { | 79 | impl smoltcp::phy::RxToken for RxToken { |
| 81 | fn consume<R, F>(mut self, _timestamp: SmolInstant, f: F) -> Result<R> | 80 | fn consume<R, F>(mut self, _timestamp: SmolInstant, f: F) -> smoltcp::Result<R> |
| 82 | where | 81 | where |
| 83 | F: FnOnce(&mut [u8]) -> Result<R>, | 82 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, |
| 84 | { | 83 | { |
| 85 | f(&mut self.pkt) | 84 | f(&mut self.pkt) |
| 86 | } | 85 | } |
| @@ -92,9 +91,9 @@ pub struct TxToken<'a> { | |||
| 92 | } | 91 | } |
| 93 | 92 | ||
| 94 | impl<'a> smoltcp::phy::TxToken for TxToken<'a> { | 93 | impl<'a> smoltcp::phy::TxToken for TxToken<'a> { |
| 95 | fn consume<R, F>(self, _timestamp: SmolInstant, len: usize, f: F) -> Result<R> | 94 | fn consume<R, F>(self, _timestamp: SmolInstant, len: usize, f: F) -> smoltcp::Result<R> |
| 96 | where | 95 | where |
| 97 | F: FnOnce(&mut [u8]) -> Result<R>, | 96 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, |
| 98 | { | 97 | { |
| 99 | let mut buf = self.pkt.slice(0..len); | 98 | let mut buf = self.pkt.slice(0..len); |
| 100 | let r = f(&mut buf)?; | 99 | let r = f(&mut buf)?; |
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index ffe786b36..ded841909 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -1,5 +1,9 @@ | |||
| 1 | #![cfg_attr(not(feature = "std"), no_std)] | 1 | #![cfg_attr(not(feature = "std"), no_std)] |
| 2 | #![allow(clippy::new_without_default)] | 2 | #![allow(clippy::new_without_default)] |
| 3 | #![cfg_attr( | ||
| 4 | feature = "nightly", | ||
| 5 | feature(generic_associated_types, type_alias_impl_trait) | ||
| 6 | )] | ||
| 3 | 7 | ||
| 4 | // This mod MUST go first, so that the others see its macros. | 8 | // This mod MUST go first, so that the others see its macros. |
| 5 | pub(crate) mod fmt; | 9 | pub(crate) mod fmt; |
| @@ -20,9 +24,7 @@ pub use stack::{ | |||
| 20 | }; | 24 | }; |
| 21 | 25 | ||
| 22 | #[cfg(feature = "tcp")] | 26 | #[cfg(feature = "tcp")] |
| 23 | mod tcp_socket; | 27 | pub mod tcp; |
| 24 | #[cfg(feature = "tcp")] | ||
| 25 | pub use tcp_socket::TcpSocket; | ||
| 26 | 28 | ||
| 27 | // smoltcp reexports | 29 | // smoltcp reexports |
| 28 | pub use smoltcp::phy::{DeviceCapabilities, Medium}; | 30 | pub use smoltcp::phy::{DeviceCapabilities, Medium}; |
| @@ -32,4 +34,3 @@ pub use smoltcp::time::Instant as SmolInstant; | |||
| 32 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; | 34 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; |
| 33 | pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; | 35 | pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; |
| 34 | pub type Interface = smoltcp::iface::Interface<'static, device::DeviceAdapter>; | 36 | pub type Interface = smoltcp::iface::Interface<'static, device::DeviceAdapter>; |
| 35 | 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 000000000..155733497 --- /dev/null +++ b/embassy-net/src/tcp/io_impl.rs | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | use core::future::Future; | ||
| 2 | use core::task::Poll; | ||
| 3 | use futures::future::poll_fn; | ||
| 4 | |||
| 5 | use super::{Error, TcpSocket}; | ||
| 6 | |||
| 7 | impl<'d> embedded_io::asynch::Read for TcpSocket<'d> { | ||
| 8 | type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 9 | where | ||
| 10 | Self: 'a; | ||
| 11 | |||
| 12 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 13 | poll_fn(move |cx| { | ||
| 14 | // CAUTION: smoltcp semantics around EOF are different to what you'd expect | ||
| 15 | // from posix-like IO, so we have to tweak things here. | ||
| 16 | self.with(|s, _| match s.recv_slice(buf) { | ||
| 17 | // No data ready | ||
| 18 | Ok(0) => { | ||
| 19 | s.register_recv_waker(cx.waker()); | ||
| 20 | Poll::Pending | ||
| 21 | } | ||
| 22 | // Data ready! | ||
| 23 | Ok(n) => Poll::Ready(Ok(n)), | ||
| 24 | // EOF | ||
| 25 | Err(smoltcp::Error::Finished) => Poll::Ready(Ok(0)), | ||
| 26 | // Connection reset. TODO: this can also be timeouts etc, investigate. | ||
| 27 | Err(smoltcp::Error::Illegal) => Poll::Ready(Err(Error::ConnectionReset)), | ||
| 28 | // smoltcp returns no errors other than the above. | ||
| 29 | Err(_) => unreachable!(), | ||
| 30 | }) | ||
| 31 | }) | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | impl<'d> embedded_io::asynch::Write for TcpSocket<'d> { | ||
| 36 | type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 37 | where | ||
| 38 | Self: 'a; | ||
| 39 | |||
| 40 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 41 | poll_fn(move |cx| { | ||
| 42 | self.with(|s, _| match s.send_slice(buf) { | ||
| 43 | // Not ready to send (no space in the tx buffer) | ||
| 44 | Ok(0) => { | ||
| 45 | s.register_send_waker(cx.waker()); | ||
| 46 | Poll::Pending | ||
| 47 | } | ||
| 48 | // Some data sent | ||
| 49 | Ok(n) => Poll::Ready(Ok(n)), | ||
| 50 | // Connection reset. TODO: this can also be timeouts etc, investigate. | ||
| 51 | Err(smoltcp::Error::Illegal) => Poll::Ready(Err(Error::ConnectionReset)), | ||
| 52 | // smoltcp returns no errors other than the above. | ||
| 53 | Err(_) => unreachable!(), | ||
| 54 | }) | ||
| 55 | }) | ||
| 56 | } | ||
| 57 | |||
| 58 | type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> | ||
| 59 | where | ||
| 60 | Self: 'a; | ||
| 61 | |||
| 62 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { | ||
| 63 | poll_fn(move |_| { | ||
| 64 | Poll::Ready(Ok(())) // TODO: Is there a better implementation for this? | ||
| 65 | }) | ||
| 66 | } | ||
| 67 | } | ||
diff --git a/embassy-net/src/tcp_socket.rs b/embassy-net/src/tcp/mod.rs index 5637505d4..3bfd4c7b6 100644 --- a/embassy-net/src/tcp_socket.rs +++ b/embassy-net/src/tcp/mod.rs | |||
| @@ -1,17 +1,46 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | use core::mem; | 2 | use core::mem; |
| 3 | use core::pin::Pin; | 3 | use core::task::Poll; |
| 4 | use core::task::{Context, Poll}; | ||
| 5 | use embassy::io; | ||
| 6 | use embassy::io::{AsyncBufRead, AsyncWrite}; | ||
| 7 | use smoltcp::iface::{Context as SmolContext, SocketHandle}; | 4 | use smoltcp::iface::{Context as SmolContext, SocketHandle}; |
| 8 | use smoltcp::socket::TcpSocket as SyncTcpSocket; | 5 | use smoltcp::socket::TcpSocket as SyncTcpSocket; |
| 9 | use smoltcp::socket::{TcpSocketBuffer, TcpState}; | 6 | use smoltcp::socket::{TcpSocketBuffer, TcpState}; |
| 10 | use smoltcp::time::Duration; | 7 | use smoltcp::time::Duration; |
| 11 | use smoltcp::wire::IpEndpoint; | 8 | use smoltcp::wire::IpEndpoint; |
| 12 | 9 | ||
| 10 | #[cfg(feature = "nightly")] | ||
| 11 | mod io_impl; | ||
| 12 | |||
| 13 | use super::stack::Stack; | 13 | use super::stack::Stack; |
| 14 | use crate::{Error, Result}; | 14 | |
| 15 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | ||
| 16 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 17 | pub enum Error { | ||
| 18 | ConnectionReset, | ||
| 19 | } | ||
| 20 | |||
| 21 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | ||
| 22 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 23 | pub enum ConnectError { | ||
| 24 | /// The socket is already connected or listening. | ||
| 25 | InvalidState, | ||
| 26 | /// The remote host rejected the connection with a RST packet. | ||
| 27 | ConnectionReset, | ||
| 28 | /// Connect timed out. | ||
| 29 | TimedOut, | ||
| 30 | /// No route to host. | ||
| 31 | NoRoute, | ||
| 32 | } | ||
| 33 | |||
| 34 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | ||
| 35 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 36 | pub enum AcceptError { | ||
| 37 | /// The socket is already connected or listening. | ||
| 38 | InvalidState, | ||
| 39 | /// Invalid listen port | ||
| 40 | InvalidPort, | ||
| 41 | /// The remote host rejected the connection with a RST packet. | ||
| 42 | ConnectionReset, | ||
| 43 | } | ||
| 15 | 44 | ||
| 16 | pub struct TcpSocket<'a> { | 45 | pub struct TcpSocket<'a> { |
| 17 | handle: SocketHandle, | 46 | handle: SocketHandle, |
| @@ -37,17 +66,25 @@ impl<'a> TcpSocket<'a> { | |||
| 37 | } | 66 | } |
| 38 | } | 67 | } |
| 39 | 68 | ||
| 40 | pub async fn connect<T>(&mut self, remote_endpoint: T) -> Result<()> | 69 | pub async fn connect<T>(&mut self, remote_endpoint: T) -> Result<(), ConnectError> |
| 41 | where | 70 | where |
| 42 | T: Into<IpEndpoint>, | 71 | T: Into<IpEndpoint>, |
| 43 | { | 72 | { |
| 44 | let local_port = Stack::with(|stack| stack.get_local_port()); | 73 | let local_port = Stack::with(|stack| stack.get_local_port()); |
| 45 | self.with(|s, cx| s.connect(cx, remote_endpoint, local_port))?; | 74 | match self.with(|s, cx| s.connect(cx, remote_endpoint, local_port)) { |
| 75 | Ok(()) => {} | ||
| 76 | Err(smoltcp::Error::Illegal) => return Err(ConnectError::InvalidState), | ||
| 77 | Err(smoltcp::Error::Unaddressable) => return Err(ConnectError::NoRoute), | ||
| 78 | // smoltcp returns no errors other than the above. | ||
| 79 | Err(_) => unreachable!(), | ||
| 80 | } | ||
| 46 | 81 | ||
| 47 | futures::future::poll_fn(|cx| { | 82 | futures::future::poll_fn(|cx| { |
| 48 | self.with(|s, _| match s.state() { | 83 | self.with(|s, _| match s.state() { |
| 49 | TcpState::Closed | TcpState::TimeWait => Poll::Ready(Err(Error::Unaddressable)), | 84 | TcpState::Closed | TcpState::TimeWait => { |
| 50 | TcpState::Listen => Poll::Ready(Err(Error::Illegal)), | 85 | Poll::Ready(Err(ConnectError::ConnectionReset)) |
| 86 | } | ||
| 87 | TcpState::Listen => unreachable!(), | ||
| 51 | TcpState::SynSent | TcpState::SynReceived => { | 88 | TcpState::SynSent | TcpState::SynReceived => { |
| 52 | s.register_send_waker(cx.waker()); | 89 | s.register_send_waker(cx.waker()); |
| 53 | Poll::Pending | 90 | Poll::Pending |
| @@ -58,11 +95,17 @@ impl<'a> TcpSocket<'a> { | |||
| 58 | .await | 95 | .await |
| 59 | } | 96 | } |
| 60 | 97 | ||
| 61 | pub async fn accept<T>(&mut self, local_endpoint: T) -> Result<()> | 98 | pub async fn accept<T>(&mut self, local_endpoint: T) -> Result<(), AcceptError> |
| 62 | where | 99 | where |
| 63 | T: Into<IpEndpoint>, | 100 | T: Into<IpEndpoint>, |
| 64 | { | 101 | { |
| 65 | self.with(|s, _| s.listen(local_endpoint))?; | 102 | match self.with(|s, _| s.listen(local_endpoint)) { |
| 103 | Ok(()) => {} | ||
| 104 | Err(smoltcp::Error::Illegal) => return Err(AcceptError::InvalidState), | ||
| 105 | Err(smoltcp::Error::Unaddressable) => return Err(AcceptError::InvalidPort), | ||
| 106 | // smoltcp returns no errors other than the above. | ||
| 107 | Err(_) => unreachable!(), | ||
| 108 | } | ||
| 66 | 109 | ||
| 67 | futures::future::poll_fn(|cx| { | 110 | futures::future::poll_fn(|cx| { |
| 68 | self.with(|s, _| match s.state() { | 111 | self.with(|s, _| match s.state() { |
| @@ -130,11 +173,6 @@ impl<'a> TcpSocket<'a> { | |||
| 130 | } | 173 | } |
| 131 | } | 174 | } |
| 132 | 175 | ||
| 133 | fn to_ioerr(_err: Error) -> io::Error { | ||
| 134 | // todo | ||
| 135 | io::Error::Other | ||
| 136 | } | ||
| 137 | |||
| 138 | impl<'a> Drop for TcpSocket<'a> { | 176 | impl<'a> Drop for TcpSocket<'a> { |
| 139 | fn drop(&mut self) { | 177 | fn drop(&mut self) { |
| 140 | Stack::with(|stack| { | 178 | Stack::with(|stack| { |
| @@ -143,63 +181,12 @@ impl<'a> Drop for TcpSocket<'a> { | |||
| 143 | } | 181 | } |
| 144 | } | 182 | } |
| 145 | 183 | ||
| 146 | impl<'a> AsyncBufRead for TcpSocket<'a> { | 184 | impl embedded_io::Error for Error { |
| 147 | fn poll_fill_buf<'z>( | 185 | fn kind(&self) -> embedded_io::ErrorKind { |
| 148 | self: Pin<&'z mut Self>, | 186 | embedded_io::ErrorKind::Other |
| 149 | cx: &mut Context<'_>, | ||
| 150 | ) -> Poll<io::Result<&'z [u8]>> { | ||
| 151 | self.with(|s, _| match s.peek(1 << 30) { | ||
| 152 | // No data ready | ||
| 153 | Ok(buf) if buf.is_empty() => { | ||
| 154 | s.register_recv_waker(cx.waker()); | ||
| 155 | Poll::Pending | ||
| 156 | } | ||
| 157 | // Data ready! | ||
| 158 | Ok(buf) => { | ||
| 159 | // Safety: | ||
| 160 | // - User can't touch the inner TcpSocket directly at all. | ||
| 161 | // - The socket itself won't touch these bytes until consume() is called, which | ||
| 162 | // requires the user to release this borrow. | ||
| 163 | let buf: &'z [u8] = unsafe { core::mem::transmute(&*buf) }; | ||
| 164 | Poll::Ready(Ok(buf)) | ||
| 165 | } | ||
| 166 | // EOF | ||
| 167 | Err(Error::Finished) => Poll::Ready(Ok(&[][..])), | ||
| 168 | // Error | ||
| 169 | Err(e) => Poll::Ready(Err(to_ioerr(e))), | ||
| 170 | }) | ||
| 171 | } | ||
| 172 | |||
| 173 | fn consume(self: Pin<&mut Self>, amt: usize) { | ||
| 174 | if amt == 0 { | ||
| 175 | // smoltcp's recv returns Finished if we're at EOF, | ||
| 176 | // even if we're "reading" 0 bytes. | ||
| 177 | return; | ||
| 178 | } | ||
| 179 | self.with(|s, _| s.recv(|_| (amt, ()))).unwrap() | ||
| 180 | } | 187 | } |
| 181 | } | 188 | } |
| 182 | 189 | ||
| 183 | impl<'a> AsyncWrite for TcpSocket<'a> { | 190 | impl<'d> embedded_io::Io for TcpSocket<'d> { |
| 184 | fn poll_write( | 191 | type Error = Error; |
| 185 | self: Pin<&mut Self>, | ||
| 186 | cx: &mut Context<'_>, | ||
| 187 | buf: &[u8], | ||
| 188 | ) -> Poll<io::Result<usize>> { | ||
| 189 | self.with(|s, _| match s.send_slice(buf) { | ||
| 190 | // Not ready to send (no space in the tx buffer) | ||
| 191 | Ok(0) => { | ||
| 192 | s.register_send_waker(cx.waker()); | ||
| 193 | Poll::Pending | ||
| 194 | } | ||
| 195 | // Some data sent | ||
| 196 | Ok(n) => Poll::Ready(Ok(n)), | ||
| 197 | // Error | ||
| 198 | Err(e) => Poll::Ready(Err(to_ioerr(e))), | ||
| 199 | }) | ||
| 200 | } | ||
| 201 | |||
| 202 | fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { | ||
| 203 | Poll::Ready(Ok(())) // TODO: Is there a better implementation for this? | ||
| 204 | } | ||
| 205 | } | 192 | } |
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index b7c09286f..cf61abcc8 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -19,10 +19,10 @@ flavors = [ | |||
| 19 | 19 | ||
| 20 | time = ["embassy/time"] | 20 | time = ["embassy/time"] |
| 21 | 21 | ||
| 22 | defmt = ["dep:defmt", "embassy/defmt", "embassy-usb?/defmt"] | 22 | defmt = ["dep:defmt", "embassy/defmt", "embassy-usb?/defmt", "embedded-io?/defmt"] |
| 23 | 23 | ||
| 24 | # Enable nightly-only features | 24 | # Enable nightly-only features |
| 25 | nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async"] | 25 | nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io"] |
| 26 | 26 | ||
| 27 | # Reexport the PAC for the currently enabled chip at `embassy_nrf::pac`. | 27 | # Reexport the PAC for the currently enabled chip at `embassy_nrf::pac`. |
| 28 | # This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. | 28 | # 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 } | |||
| 73 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } | 73 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } |
| 74 | embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8", optional = true} | 74 | embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8", optional = true} |
| 75 | embedded-hal-async = { version = "0.1.0-alpha.0", optional = true} | 75 | embedded-hal-async = { version = "0.1.0-alpha.0", optional = true} |
| 76 | embedded-io = { version = "0.2.0", features = ["async"], optional = true } | ||
| 76 | 77 | ||
| 77 | defmt = { version = "0.3", optional = true } | 78 | defmt = { version = "0.3", optional = true } |
| 78 | log = { version = "0.4.14", optional = true } | 79 | log = { version = "0.4.14", optional = true } |
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index b49c12788..fc4e9c8d0 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -14,18 +14,17 @@ | |||
| 14 | //! Please also see [crate::uarte] to understand when [BufferedUarte] should be used. | 14 | //! Please also see [crate::uarte] to understand when [BufferedUarte] should be used. |
| 15 | 15 | ||
| 16 | use core::cmp::min; | 16 | use core::cmp::min; |
| 17 | use core::future::Future; | ||
| 17 | use core::marker::PhantomData; | 18 | use core::marker::PhantomData; |
| 18 | use core::mem; | ||
| 19 | use core::pin::Pin; | ||
| 20 | use core::sync::atomic::{compiler_fence, Ordering}; | 19 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 21 | use core::task::{Context, Poll}; | 20 | use core::task::Poll; |
| 22 | use embassy::interrupt::InterruptExt; | 21 | use embassy::interrupt::InterruptExt; |
| 23 | use embassy::io::{AsyncBufRead, AsyncWrite}; | ||
| 24 | use embassy::util::Unborrow; | 22 | use embassy::util::Unborrow; |
| 25 | use embassy::waitqueue::WakerRegistration; | 23 | use embassy::waitqueue::WakerRegistration; |
| 26 | use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; | 24 | use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; |
| 27 | use embassy_hal_common::ring_buffer::RingBuffer; | 25 | use embassy_hal_common::ring_buffer::RingBuffer; |
| 28 | use embassy_hal_common::{low_power_wait_until, unborrow}; | 26 | use embassy_hal_common::{low_power_wait_until, unborrow}; |
| 27 | use futures::future::poll_fn; | ||
| 29 | 28 | ||
| 30 | use crate::gpio::Pin as GpioPin; | 29 | use crate::gpio::Pin as GpioPin; |
| 31 | use crate::pac; | 30 | use crate::pac; |
| @@ -197,82 +196,99 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 197 | } | 196 | } |
| 198 | } | 197 | } |
| 199 | 198 | ||
| 200 | impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, U, T> { | 199 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarte<'d, U, T> { |
| 201 | fn poll_fill_buf( | 200 | type Error = core::convert::Infallible; |
| 202 | mut self: Pin<&mut Self>, | 201 | } |
| 203 | cx: &mut Context<'_>, | 202 | |
| 204 | ) -> Poll<embassy::io::Result<&[u8]>> { | 203 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> { |
| 205 | self.inner.with(|state| { | 204 | type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> |
| 206 | compiler_fence(Ordering::SeqCst); | 205 | where |
| 207 | trace!("poll_read"); | 206 | Self: 'a; |
| 208 | 207 | ||
| 209 | // We have data ready in buffer? Return it. | 208 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 210 | let buf = state.rx.pop_buf(); | 209 | poll_fn(move |cx| { |
| 211 | if !buf.is_empty() { | 210 | let mut do_pend = false; |
| 212 | trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len()); | 211 | let res = self.inner.with(|state| { |
| 213 | let buf: &[u8] = buf; | 212 | compiler_fence(Ordering::SeqCst); |
| 214 | let buf: &[u8] = unsafe { mem::transmute(buf) }; | 213 | trace!("poll_read"); |
| 215 | return Poll::Ready(Ok(buf)); | 214 | |
| 215 | // We have data ready in buffer? Return it. | ||
| 216 | let data = state.rx.pop_buf(); | ||
| 217 | if !data.is_empty() { | ||
| 218 | trace!(" got {:?} {:?}", data.as_ptr() as u32, data.len()); | ||
| 219 | let len = data.len().min(data.len()); | ||
| 220 | buf[..len].copy_from_slice(&data[..len]); | ||
| 221 | state.rx.pop(len); | ||
| 222 | do_pend = true; | ||
| 223 | return Poll::Ready(Ok(len)); | ||
| 224 | } | ||
| 225 | |||
| 226 | trace!(" empty"); | ||
| 227 | state.rx_waker.register(cx.waker()); | ||
| 228 | Poll::Pending | ||
| 229 | }); | ||
| 230 | if do_pend { | ||
| 231 | self.inner.pend(); | ||
| 216 | } | 232 | } |
| 217 | 233 | ||
| 218 | trace!(" empty"); | 234 | res |
| 219 | state.rx_waker.register(cx.waker()); | ||
| 220 | Poll::<embassy::io::Result<&[u8]>>::Pending | ||
| 221 | }) | 235 | }) |
| 222 | } | 236 | } |
| 223 | |||
| 224 | fn consume(mut self: Pin<&mut Self>, amt: usize) { | ||
| 225 | self.inner.with(|state| { | ||
| 226 | trace!("consume {:?}", amt); | ||
| 227 | state.rx.pop(amt); | ||
| 228 | }); | ||
| 229 | self.inner.pend(); | ||
| 230 | } | ||
| 231 | } | 237 | } |
| 232 | 238 | ||
| 233 | impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U, T> { | 239 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write |
| 234 | fn poll_write( | 240 | for BufferedUarte<'d, U, T> |
| 235 | mut self: Pin<&mut Self>, | 241 | { |
| 236 | cx: &mut Context<'_>, | 242 | type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> |
| 237 | buf: &[u8], | 243 | where |
| 238 | ) -> Poll<embassy::io::Result<usize>> { | 244 | Self: 'a; |
| 239 | let poll = self.inner.with(|state| { | 245 | |
| 240 | trace!("poll_write: {:?}", buf.len()); | 246 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { |
| 241 | 247 | poll_fn(move |cx| { | |
| 242 | let tx_buf = state.tx.push_buf(); | 248 | let res = self.inner.with(|state| { |
| 243 | if tx_buf.is_empty() { | 249 | trace!("poll_write: {:?}", buf.len()); |
| 244 | trace!("poll_write: pending"); | 250 | |
| 245 | state.tx_waker.register(cx.waker()); | 251 | let tx_buf = state.tx.push_buf(); |
| 246 | return Poll::Pending; | 252 | if tx_buf.is_empty() { |
| 247 | } | 253 | trace!("poll_write: pending"); |
| 254 | state.tx_waker.register(cx.waker()); | ||
| 255 | return Poll::Pending; | ||
| 256 | } | ||
| 248 | 257 | ||
| 249 | let n = min(tx_buf.len(), buf.len()); | 258 | let n = min(tx_buf.len(), buf.len()); |
| 250 | tx_buf[..n].copy_from_slice(&buf[..n]); | 259 | tx_buf[..n].copy_from_slice(&buf[..n]); |
| 251 | state.tx.push(n); | 260 | state.tx.push(n); |
| 252 | 261 | ||
| 253 | trace!("poll_write: queued {:?}", n); | 262 | trace!("poll_write: queued {:?}", n); |
| 254 | 263 | ||
| 255 | compiler_fence(Ordering::SeqCst); | 264 | compiler_fence(Ordering::SeqCst); |
| 256 | 265 | ||
| 257 | Poll::Ready(Ok(n)) | 266 | Poll::Ready(Ok(n)) |
| 258 | }); | 267 | }); |
| 259 | 268 | ||
| 260 | self.inner.pend(); | 269 | self.inner.pend(); |
| 261 | 270 | ||
| 262 | poll | 271 | res |
| 272 | }) | ||
| 263 | } | 273 | } |
| 264 | 274 | ||
| 265 | fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<embassy::io::Result<()>> { | 275 | type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> |
| 266 | self.inner.with(|state| { | 276 | where |
| 267 | trace!("poll_flush"); | 277 | Self: 'a; |
| 268 | 278 | ||
| 269 | if !state.tx.is_empty() { | 279 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { |
| 270 | trace!("poll_flush: pending"); | 280 | poll_fn(move |cx| { |
| 271 | state.tx_waker.register(cx.waker()); | 281 | self.inner.with(|state| { |
| 272 | return Poll::Pending; | 282 | trace!("poll_flush"); |
| 273 | } | 283 | |
| 284 | if !state.tx.is_empty() { | ||
| 285 | trace!("poll_flush: pending"); | ||
| 286 | state.tx_waker.register(cx.waker()); | ||
| 287 | return Poll::Pending; | ||
| 288 | } | ||
| 274 | 289 | ||
| 275 | Poll::Ready(Ok(())) | 290 | Poll::Ready(Ok(())) |
| 291 | }) | ||
| 276 | }) | 292 | }) |
| 277 | } | 293 | } |
| 278 | } | 294 | } |
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 3b1809023..865f33d70 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -64,6 +64,7 @@ pub(crate) mod util; | |||
| 64 | #[cfg(feature = "_time-driver")] | 64 | #[cfg(feature = "_time-driver")] |
| 65 | mod time_driver; | 65 | mod time_driver; |
| 66 | 66 | ||
| 67 | #[cfg(feature = "nightly")] | ||
| 67 | pub mod buffered_uarte; | 68 | pub mod buffered_uarte; |
| 68 | pub mod gpio; | 69 | pub mod gpio; |
| 69 | #[cfg(feature = "gpiote")] | 70 | #[cfg(feature = "gpiote")] |
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index ea9ac3b59..9686e016e 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -57,12 +57,13 @@ critical-section = "0.2.5" | |||
| 57 | bare-metal = "1.0.0" | 57 | bare-metal = "1.0.0" |
| 58 | atomic-polyfill = "0.1.5" | 58 | atomic-polyfill = "0.1.5" |
| 59 | stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] } | 59 | stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] } |
| 60 | vcell = { version = "0.1.3", optional = true } | 60 | vcell = "0.1.3" |
| 61 | bxcan = "0.6.2" | 61 | bxcan = "0.6.2" |
| 62 | nb = "1.0.0" | 62 | nb = "1.0.0" |
| 63 | stm32-fmc = "0.2.4" | 63 | stm32-fmc = "0.2.4" |
| 64 | seq-macro = "0.2.2" | 64 | seq-macro = "0.2.2" |
| 65 | cfg-if = "1.0.0" | 65 | cfg-if = "1.0.0" |
| 66 | embedded-io = { version = "0.2.0", features = ["async"], optional = true } | ||
| 66 | 67 | ||
| 67 | [build-dependencies] | 68 | [build-dependencies] |
| 68 | proc-macro2 = "1.0.36" | 69 | proc-macro2 = "1.0.36" |
| @@ -70,8 +71,9 @@ quote = "1.0.15" | |||
| 70 | stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]} | 71 | stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]} |
| 71 | 72 | ||
| 72 | [features] | 73 | [features] |
| 74 | defmt = ["dep:defmt", "embassy/defmt", "embedded-io?/defmt" ] | ||
| 73 | sdmmc-rs = ["embedded-sdmmc"] | 75 | sdmmc-rs = ["embedded-sdmmc"] |
| 74 | net = ["embassy-net", "vcell"] | 76 | net = ["embassy-net" ] |
| 75 | memory-x = ["stm32-metapac/memory-x"] | 77 | memory-x = ["stm32-metapac/memory-x"] |
| 76 | subghz = [] | 78 | subghz = [] |
| 77 | exti = [] | 79 | exti = [] |
| @@ -88,7 +90,7 @@ time-driver-tim12 = ["_time-driver"] | |||
| 88 | time-driver-tim15 = ["_time-driver"] | 90 | time-driver-tim15 = ["_time-driver"] |
| 89 | 91 | ||
| 90 | # Enable nightly-only features | 92 | # Enable nightly-only features |
| 91 | nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async"] | 93 | nightly = ["embassy/nightly", "embassy-net?/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io"] |
| 92 | 94 | ||
| 93 | # Reexport stm32-metapac at `embassy_stm32::pac`. | 95 | # Reexport stm32-metapac at `embassy_stm32::pac`. |
| 94 | # This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. | 96 | # 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 db757764f..490f2d8f2 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -244,200 +244,200 @@ fn main() { | |||
| 244 | 244 | ||
| 245 | #[rustfmt::skip] | 245 | #[rustfmt::skip] |
| 246 | let signals: HashMap<_, _> = [ | 246 | let signals: HashMap<_, _> = [ |
| 247 | // (kind, signal) => (trait, cfgs) | 247 | // (kind, signal) => trait |
| 248 | (("usart", "TX"), (quote!(crate::usart::TxPin), quote!())), | 248 | (("usart", "TX"), quote!(crate::usart::TxPin)), |
| 249 | (("usart", "RX"), (quote!(crate::usart::RxPin), quote!())), | 249 | (("usart", "RX"), quote!(crate::usart::RxPin)), |
| 250 | (("usart", "CTS"), (quote!(crate::usart::CtsPin), quote!())), | 250 | (("usart", "CTS"), quote!(crate::usart::CtsPin)), |
| 251 | (("usart", "RTS"), (quote!(crate::usart::RtsPin), quote!())), | 251 | (("usart", "RTS"), quote!(crate::usart::RtsPin)), |
| 252 | (("usart", "CK"), (quote!(crate::usart::CkPin), quote!())), | 252 | (("usart", "CK"), quote!(crate::usart::CkPin)), |
| 253 | (("usart", "TX"), (quote!(crate::usart::TxPin), quote!())), | 253 | (("usart", "TX"), quote!(crate::usart::TxPin)), |
| 254 | (("usart", "RX"), (quote!(crate::usart::RxPin), quote!())), | 254 | (("usart", "RX"), quote!(crate::usart::RxPin)), |
| 255 | (("usart", "CTS"), (quote!(crate::usart::CtsPin), quote!())), | 255 | (("usart", "CTS"), quote!(crate::usart::CtsPin)), |
| 256 | (("usart", "RTS"), (quote!(crate::usart::RtsPin), quote!())), | 256 | (("usart", "RTS"), quote!(crate::usart::RtsPin)), |
| 257 | (("usart", "CK"), (quote!(crate::usart::CkPin), quote!())), | 257 | (("usart", "CK"), quote!(crate::usart::CkPin)), |
| 258 | (("spi", "SCK"), (quote!(crate::spi::SckPin), quote!())), | 258 | (("spi", "SCK"), quote!(crate::spi::SckPin)), |
| 259 | (("spi", "MOSI"), (quote!(crate::spi::MosiPin), quote!())), | 259 | (("spi", "MOSI"), quote!(crate::spi::MosiPin)), |
| 260 | (("spi", "MISO"), (quote!(crate::spi::MisoPin), quote!())), | 260 | (("spi", "MISO"), quote!(crate::spi::MisoPin)), |
| 261 | (("i2c", "SDA"), (quote!(crate::i2c::SdaPin), quote!())), | 261 | (("i2c", "SDA"), quote!(crate::i2c::SdaPin)), |
| 262 | (("i2c", "SCL"), (quote!(crate::i2c::SclPin), quote!())), | 262 | (("i2c", "SCL"), quote!(crate::i2c::SclPin)), |
| 263 | (("rcc", "MCO_1"), (quote!(crate::rcc::McoPin), quote!())), | 263 | (("rcc", "MCO_1"), quote!(crate::rcc::McoPin)), |
| 264 | (("rcc", "MCO_2"), (quote!(crate::rcc::McoPin), quote!())), | 264 | (("rcc", "MCO_2"), quote!(crate::rcc::McoPin)), |
| 265 | (("dcmi", "D0"), (quote!(crate::dcmi::D0Pin), quote!())), | 265 | (("dcmi", "D0"), quote!(crate::dcmi::D0Pin)), |
| 266 | (("dcmi", "D1"), (quote!(crate::dcmi::D1Pin), quote!())), | 266 | (("dcmi", "D1"), quote!(crate::dcmi::D1Pin)), |
| 267 | (("dcmi", "D2"), (quote!(crate::dcmi::D2Pin), quote!())), | 267 | (("dcmi", "D2"), quote!(crate::dcmi::D2Pin)), |
| 268 | (("dcmi", "D3"), (quote!(crate::dcmi::D3Pin), quote!())), | 268 | (("dcmi", "D3"), quote!(crate::dcmi::D3Pin)), |
| 269 | (("dcmi", "D4"), (quote!(crate::dcmi::D4Pin), quote!())), | 269 | (("dcmi", "D4"), quote!(crate::dcmi::D4Pin)), |
| 270 | (("dcmi", "D5"), (quote!(crate::dcmi::D5Pin), quote!())), | 270 | (("dcmi", "D5"), quote!(crate::dcmi::D5Pin)), |
| 271 | (("dcmi", "D6"), (quote!(crate::dcmi::D6Pin), quote!())), | 271 | (("dcmi", "D6"), quote!(crate::dcmi::D6Pin)), |
| 272 | (("dcmi", "D7"), (quote!(crate::dcmi::D7Pin), quote!())), | 272 | (("dcmi", "D7"), quote!(crate::dcmi::D7Pin)), |
| 273 | (("dcmi", "D8"), (quote!(crate::dcmi::D8Pin), quote!())), | 273 | (("dcmi", "D8"), quote!(crate::dcmi::D8Pin)), |
| 274 | (("dcmi", "D9"), (quote!(crate::dcmi::D9Pin), quote!())), | 274 | (("dcmi", "D9"), quote!(crate::dcmi::D9Pin)), |
| 275 | (("dcmi", "D10"), (quote!(crate::dcmi::D10Pin), quote!())), | 275 | (("dcmi", "D10"), quote!(crate::dcmi::D10Pin)), |
| 276 | (("dcmi", "D11"), (quote!(crate::dcmi::D11Pin), quote!())), | 276 | (("dcmi", "D11"), quote!(crate::dcmi::D11Pin)), |
| 277 | (("dcmi", "D12"), (quote!(crate::dcmi::D12Pin), quote!())), | 277 | (("dcmi", "D12"), quote!(crate::dcmi::D12Pin)), |
| 278 | (("dcmi", "D13"), (quote!(crate::dcmi::D13Pin), quote!())), | 278 | (("dcmi", "D13"), quote!(crate::dcmi::D13Pin)), |
| 279 | (("dcmi", "HSYNC"), (quote!(crate::dcmi::HSyncPin), quote!())), | 279 | (("dcmi", "HSYNC"), quote!(crate::dcmi::HSyncPin)), |
| 280 | (("dcmi", "VSYNC"), (quote!(crate::dcmi::VSyncPin), quote!())), | 280 | (("dcmi", "VSYNC"), quote!(crate::dcmi::VSyncPin)), |
| 281 | (("dcmi", "PIXCLK"), (quote!(crate::dcmi::PixClkPin), quote!())), | 281 | (("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)), |
| 282 | (("otgfs", "DP"), (quote!(crate::usb_otg::DpPin), quote!())), | 282 | (("otgfs", "DP"), quote!(crate::usb_otg::DpPin)), |
| 283 | (("otgfs", "DM"), (quote!(crate::usb_otg::DmPin), quote!())), | 283 | (("otgfs", "DM"), quote!(crate::usb_otg::DmPin)), |
| 284 | (("otghs", "DP"), (quote!(crate::usb_otg::DpPin), quote!())), | 284 | (("otghs", "DP"), quote!(crate::usb_otg::DpPin)), |
| 285 | (("otghs", "DM"), (quote!(crate::usb_otg::DmPin), quote!())), | 285 | (("otghs", "DM"), quote!(crate::usb_otg::DmPin)), |
| 286 | (("otghs", "ULPI_CK"), (quote!(crate::usb_otg::UlpiClkPin), quote!())), | 286 | (("otghs", "ULPI_CK"), quote!(crate::usb_otg::UlpiClkPin)), |
| 287 | (("otghs", "ULPI_DIR"), (quote!(crate::usb_otg::UlpiDirPin), quote!())), | 287 | (("otghs", "ULPI_DIR"), quote!(crate::usb_otg::UlpiDirPin)), |
| 288 | (("otghs", "ULPI_NXT"), (quote!(crate::usb_otg::UlpiNxtPin), quote!())), | 288 | (("otghs", "ULPI_NXT"), quote!(crate::usb_otg::UlpiNxtPin)), |
| 289 | (("otghs", "ULPI_STP"), (quote!(crate::usb_otg::UlpiStpPin), quote!())), | 289 | (("otghs", "ULPI_STP"), quote!(crate::usb_otg::UlpiStpPin)), |
| 290 | (("otghs", "ULPI_D0"), (quote!(crate::usb_otg::UlpiD0Pin), quote!())), | 290 | (("otghs", "ULPI_D0"), quote!(crate::usb_otg::UlpiD0Pin)), |
| 291 | (("otghs", "ULPI_D1"), (quote!(crate::usb_otg::UlpiD1Pin), quote!())), | 291 | (("otghs", "ULPI_D1"), quote!(crate::usb_otg::UlpiD1Pin)), |
| 292 | (("otghs", "ULPI_D2"), (quote!(crate::usb_otg::UlpiD2Pin), quote!())), | 292 | (("otghs", "ULPI_D2"), quote!(crate::usb_otg::UlpiD2Pin)), |
| 293 | (("otghs", "ULPI_D3"), (quote!(crate::usb_otg::UlpiD3Pin), quote!())), | 293 | (("otghs", "ULPI_D3"), quote!(crate::usb_otg::UlpiD3Pin)), |
| 294 | (("otghs", "ULPI_D4"), (quote!(crate::usb_otg::UlpiD4Pin), quote!())), | 294 | (("otghs", "ULPI_D4"), quote!(crate::usb_otg::UlpiD4Pin)), |
| 295 | (("otghs", "ULPI_D5"), (quote!(crate::usb_otg::UlpiD5Pin), quote!())), | 295 | (("otghs", "ULPI_D5"), quote!(crate::usb_otg::UlpiD5Pin)), |
| 296 | (("otghs", "ULPI_D6"), (quote!(crate::usb_otg::UlpiD6Pin), quote!())), | 296 | (("otghs", "ULPI_D6"), quote!(crate::usb_otg::UlpiD6Pin)), |
| 297 | (("otghs", "ULPI_D7"), (quote!(crate::usb_otg::UlpiD7Pin), quote!())), | 297 | (("otghs", "ULPI_D7"), quote!(crate::usb_otg::UlpiD7Pin)), |
| 298 | (("can", "TX"), (quote!(crate::can::TxPin), quote!())), | 298 | (("can", "TX"), quote!(crate::can::TxPin)), |
| 299 | (("can", "RX"), (quote!(crate::can::RxPin), quote!())), | 299 | (("can", "RX"), quote!(crate::can::RxPin)), |
| 300 | (("eth", "REF_CLK"), (quote!(crate::eth::RefClkPin), quote!(#[cfg(feature="net")]))), | 300 | (("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)), |
| 301 | (("eth", "MDIO"), (quote!(crate::eth::MDIOPin), quote!(#[cfg(feature="net")]))), | 301 | (("eth", "MDIO"), quote!(crate::eth::MDIOPin)), |
| 302 | (("eth", "MDC"), (quote!(crate::eth::MDCPin), quote!(#[cfg(feature="net")]))), | 302 | (("eth", "MDC"), quote!(crate::eth::MDCPin)), |
| 303 | (("eth", "CRS_DV"), (quote!(crate::eth::CRSPin), quote!(#[cfg(feature="net")]))), | 303 | (("eth", "CRS_DV"), quote!(crate::eth::CRSPin)), |
| 304 | (("eth", "RXD0"), (quote!(crate::eth::RXD0Pin), quote!(#[cfg(feature="net")]))), | 304 | (("eth", "RXD0"), quote!(crate::eth::RXD0Pin)), |
| 305 | (("eth", "RXD1"), (quote!(crate::eth::RXD1Pin), quote!(#[cfg(feature="net")]))), | 305 | (("eth", "RXD1"), quote!(crate::eth::RXD1Pin)), |
| 306 | (("eth", "TXD0"), (quote!(crate::eth::TXD0Pin), quote!(#[cfg(feature="net")]))), | 306 | (("eth", "TXD0"), quote!(crate::eth::TXD0Pin)), |
| 307 | (("eth", "TXD1"), (quote!(crate::eth::TXD1Pin), quote!(#[cfg(feature="net")]))), | 307 | (("eth", "TXD1"), quote!(crate::eth::TXD1Pin)), |
| 308 | (("eth", "TX_EN"), (quote!(crate::eth::TXEnPin), quote!(#[cfg(feature="net")]))), | 308 | (("eth", "TX_EN"), quote!(crate::eth::TXEnPin)), |
| 309 | (("fmc", "A0"), (quote!(crate::fmc::A0Pin), quote!())), | 309 | (("fmc", "A0"), quote!(crate::fmc::A0Pin)), |
| 310 | (("fmc", "A1"), (quote!(crate::fmc::A1Pin), quote!())), | 310 | (("fmc", "A1"), quote!(crate::fmc::A1Pin)), |
| 311 | (("fmc", "A2"), (quote!(crate::fmc::A2Pin), quote!())), | 311 | (("fmc", "A2"), quote!(crate::fmc::A2Pin)), |
| 312 | (("fmc", "A3"), (quote!(crate::fmc::A3Pin), quote!())), | 312 | (("fmc", "A3"), quote!(crate::fmc::A3Pin)), |
| 313 | (("fmc", "A4"), (quote!(crate::fmc::A4Pin), quote!())), | 313 | (("fmc", "A4"), quote!(crate::fmc::A4Pin)), |
| 314 | (("fmc", "A5"), (quote!(crate::fmc::A5Pin), quote!())), | 314 | (("fmc", "A5"), quote!(crate::fmc::A5Pin)), |
| 315 | (("fmc", "A6"), (quote!(crate::fmc::A6Pin), quote!())), | 315 | (("fmc", "A6"), quote!(crate::fmc::A6Pin)), |
| 316 | (("fmc", "A7"), (quote!(crate::fmc::A7Pin), quote!())), | 316 | (("fmc", "A7"), quote!(crate::fmc::A7Pin)), |
| 317 | (("fmc", "A8"), (quote!(crate::fmc::A8Pin), quote!())), | 317 | (("fmc", "A8"), quote!(crate::fmc::A8Pin)), |
| 318 | (("fmc", "A9"), (quote!(crate::fmc::A9Pin), quote!())), | 318 | (("fmc", "A9"), quote!(crate::fmc::A9Pin)), |
| 319 | (("fmc", "A10"), (quote!(crate::fmc::A10Pin), quote!())), | 319 | (("fmc", "A10"), quote!(crate::fmc::A10Pin)), |
| 320 | (("fmc", "A11"), (quote!(crate::fmc::A11Pin), quote!())), | 320 | (("fmc", "A11"), quote!(crate::fmc::A11Pin)), |
| 321 | (("fmc", "A12"), (quote!(crate::fmc::A12Pin), quote!())), | 321 | (("fmc", "A12"), quote!(crate::fmc::A12Pin)), |
| 322 | (("fmc", "A13"), (quote!(crate::fmc::A13Pin), quote!())), | 322 | (("fmc", "A13"), quote!(crate::fmc::A13Pin)), |
| 323 | (("fmc", "A14"), (quote!(crate::fmc::A14Pin), quote!())), | 323 | (("fmc", "A14"), quote!(crate::fmc::A14Pin)), |
| 324 | (("fmc", "A15"), (quote!(crate::fmc::A15Pin), quote!())), | 324 | (("fmc", "A15"), quote!(crate::fmc::A15Pin)), |
| 325 | (("fmc", "A16"), (quote!(crate::fmc::A16Pin), quote!())), | 325 | (("fmc", "A16"), quote!(crate::fmc::A16Pin)), |
| 326 | (("fmc", "A17"), (quote!(crate::fmc::A17Pin), quote!())), | 326 | (("fmc", "A17"), quote!(crate::fmc::A17Pin)), |
| 327 | (("fmc", "A18"), (quote!(crate::fmc::A18Pin), quote!())), | 327 | (("fmc", "A18"), quote!(crate::fmc::A18Pin)), |
| 328 | (("fmc", "A19"), (quote!(crate::fmc::A19Pin), quote!())), | 328 | (("fmc", "A19"), quote!(crate::fmc::A19Pin)), |
| 329 | (("fmc", "A20"), (quote!(crate::fmc::A20Pin), quote!())), | 329 | (("fmc", "A20"), quote!(crate::fmc::A20Pin)), |
| 330 | (("fmc", "A21"), (quote!(crate::fmc::A21Pin), quote!())), | 330 | (("fmc", "A21"), quote!(crate::fmc::A21Pin)), |
| 331 | (("fmc", "A22"), (quote!(crate::fmc::A22Pin), quote!())), | 331 | (("fmc", "A22"), quote!(crate::fmc::A22Pin)), |
| 332 | (("fmc", "A23"), (quote!(crate::fmc::A23Pin), quote!())), | 332 | (("fmc", "A23"), quote!(crate::fmc::A23Pin)), |
| 333 | (("fmc", "A24"), (quote!(crate::fmc::A24Pin), quote!())), | 333 | (("fmc", "A24"), quote!(crate::fmc::A24Pin)), |
| 334 | (("fmc", "A25"), (quote!(crate::fmc::A25Pin), quote!())), | 334 | (("fmc", "A25"), quote!(crate::fmc::A25Pin)), |
| 335 | (("fmc", "D0"), (quote!(crate::fmc::D0Pin), quote!())), | 335 | (("fmc", "D0"), quote!(crate::fmc::D0Pin)), |
| 336 | (("fmc", "D1"), (quote!(crate::fmc::D1Pin), quote!())), | 336 | (("fmc", "D1"), quote!(crate::fmc::D1Pin)), |
| 337 | (("fmc", "D2"), (quote!(crate::fmc::D2Pin), quote!())), | 337 | (("fmc", "D2"), quote!(crate::fmc::D2Pin)), |
| 338 | (("fmc", "D3"), (quote!(crate::fmc::D3Pin), quote!())), | 338 | (("fmc", "D3"), quote!(crate::fmc::D3Pin)), |
| 339 | (("fmc", "D4"), (quote!(crate::fmc::D4Pin), quote!())), | 339 | (("fmc", "D4"), quote!(crate::fmc::D4Pin)), |
| 340 | (("fmc", "D5"), (quote!(crate::fmc::D5Pin), quote!())), | 340 | (("fmc", "D5"), quote!(crate::fmc::D5Pin)), |
| 341 | (("fmc", "D6"), (quote!(crate::fmc::D6Pin), quote!())), | 341 | (("fmc", "D6"), quote!(crate::fmc::D6Pin)), |
| 342 | (("fmc", "D7"), (quote!(crate::fmc::D7Pin), quote!())), | 342 | (("fmc", "D7"), quote!(crate::fmc::D7Pin)), |
| 343 | (("fmc", "D8"), (quote!(crate::fmc::D8Pin), quote!())), | 343 | (("fmc", "D8"), quote!(crate::fmc::D8Pin)), |
| 344 | (("fmc", "D9"), (quote!(crate::fmc::D9Pin), quote!())), | 344 | (("fmc", "D9"), quote!(crate::fmc::D9Pin)), |
| 345 | (("fmc", "D10"), (quote!(crate::fmc::D10Pin), quote!())), | 345 | (("fmc", "D10"), quote!(crate::fmc::D10Pin)), |
| 346 | (("fmc", "D11"), (quote!(crate::fmc::D11Pin), quote!())), | 346 | (("fmc", "D11"), quote!(crate::fmc::D11Pin)), |
| 347 | (("fmc", "D12"), (quote!(crate::fmc::D12Pin), quote!())), | 347 | (("fmc", "D12"), quote!(crate::fmc::D12Pin)), |
| 348 | (("fmc", "D13"), (quote!(crate::fmc::D13Pin), quote!())), | 348 | (("fmc", "D13"), quote!(crate::fmc::D13Pin)), |
| 349 | (("fmc", "D14"), (quote!(crate::fmc::D14Pin), quote!())), | 349 | (("fmc", "D14"), quote!(crate::fmc::D14Pin)), |
| 350 | (("fmc", "D15"), (quote!(crate::fmc::D15Pin), quote!())), | 350 | (("fmc", "D15"), quote!(crate::fmc::D15Pin)), |
| 351 | (("fmc", "D16"), (quote!(crate::fmc::D16Pin), quote!())), | 351 | (("fmc", "D16"), quote!(crate::fmc::D16Pin)), |
| 352 | (("fmc", "D17"), (quote!(crate::fmc::D17Pin), quote!())), | 352 | (("fmc", "D17"), quote!(crate::fmc::D17Pin)), |
| 353 | (("fmc", "D18"), (quote!(crate::fmc::D18Pin), quote!())), | 353 | (("fmc", "D18"), quote!(crate::fmc::D18Pin)), |
| 354 | (("fmc", "D19"), (quote!(crate::fmc::D19Pin), quote!())), | 354 | (("fmc", "D19"), quote!(crate::fmc::D19Pin)), |
| 355 | (("fmc", "D20"), (quote!(crate::fmc::D20Pin), quote!())), | 355 | (("fmc", "D20"), quote!(crate::fmc::D20Pin)), |
| 356 | (("fmc", "D21"), (quote!(crate::fmc::D21Pin), quote!())), | 356 | (("fmc", "D21"), quote!(crate::fmc::D21Pin)), |
| 357 | (("fmc", "D22"), (quote!(crate::fmc::D22Pin), quote!())), | 357 | (("fmc", "D22"), quote!(crate::fmc::D22Pin)), |
| 358 | (("fmc", "D23"), (quote!(crate::fmc::D23Pin), quote!())), | 358 | (("fmc", "D23"), quote!(crate::fmc::D23Pin)), |
| 359 | (("fmc", "D24"), (quote!(crate::fmc::D24Pin), quote!())), | 359 | (("fmc", "D24"), quote!(crate::fmc::D24Pin)), |
| 360 | (("fmc", "D25"), (quote!(crate::fmc::D25Pin), quote!())), | 360 | (("fmc", "D25"), quote!(crate::fmc::D25Pin)), |
| 361 | (("fmc", "D26"), (quote!(crate::fmc::D26Pin), quote!())), | 361 | (("fmc", "D26"), quote!(crate::fmc::D26Pin)), |
| 362 | (("fmc", "D27"), (quote!(crate::fmc::D27Pin), quote!())), | 362 | (("fmc", "D27"), quote!(crate::fmc::D27Pin)), |
| 363 | (("fmc", "D28"), (quote!(crate::fmc::D28Pin), quote!())), | 363 | (("fmc", "D28"), quote!(crate::fmc::D28Pin)), |
| 364 | (("fmc", "D29"), (quote!(crate::fmc::D29Pin), quote!())), | 364 | (("fmc", "D29"), quote!(crate::fmc::D29Pin)), |
| 365 | (("fmc", "D30"), (quote!(crate::fmc::D30Pin), quote!())), | 365 | (("fmc", "D30"), quote!(crate::fmc::D30Pin)), |
| 366 | (("fmc", "D31"), (quote!(crate::fmc::D31Pin), quote!())), | 366 | (("fmc", "D31"), quote!(crate::fmc::D31Pin)), |
| 367 | (("fmc", "DA0"), (quote!(crate::fmc::DA0Pin), quote!())), | 367 | (("fmc", "DA0"), quote!(crate::fmc::DA0Pin)), |
| 368 | (("fmc", "DA1"), (quote!(crate::fmc::DA1Pin), quote!())), | 368 | (("fmc", "DA1"), quote!(crate::fmc::DA1Pin)), |
| 369 | (("fmc", "DA2"), (quote!(crate::fmc::DA2Pin), quote!())), | 369 | (("fmc", "DA2"), quote!(crate::fmc::DA2Pin)), |
| 370 | (("fmc", "DA3"), (quote!(crate::fmc::DA3Pin), quote!())), | 370 | (("fmc", "DA3"), quote!(crate::fmc::DA3Pin)), |
| 371 | (("fmc", "DA4"), (quote!(crate::fmc::DA4Pin), quote!())), | 371 | (("fmc", "DA4"), quote!(crate::fmc::DA4Pin)), |
| 372 | (("fmc", "DA5"), (quote!(crate::fmc::DA5Pin), quote!())), | 372 | (("fmc", "DA5"), quote!(crate::fmc::DA5Pin)), |
| 373 | (("fmc", "DA6"), (quote!(crate::fmc::DA6Pin), quote!())), | 373 | (("fmc", "DA6"), quote!(crate::fmc::DA6Pin)), |
| 374 | (("fmc", "DA7"), (quote!(crate::fmc::DA7Pin), quote!())), | 374 | (("fmc", "DA7"), quote!(crate::fmc::DA7Pin)), |
| 375 | (("fmc", "DA8"), (quote!(crate::fmc::DA8Pin), quote!())), | 375 | (("fmc", "DA8"), quote!(crate::fmc::DA8Pin)), |
| 376 | (("fmc", "DA9"), (quote!(crate::fmc::DA9Pin), quote!())), | 376 | (("fmc", "DA9"), quote!(crate::fmc::DA9Pin)), |
| 377 | (("fmc", "DA10"), (quote!(crate::fmc::DA10Pin), quote!())), | 377 | (("fmc", "DA10"), quote!(crate::fmc::DA10Pin)), |
| 378 | (("fmc", "DA11"), (quote!(crate::fmc::DA11Pin), quote!())), | 378 | (("fmc", "DA11"), quote!(crate::fmc::DA11Pin)), |
| 379 | (("fmc", "DA12"), (quote!(crate::fmc::DA12Pin), quote!())), | 379 | (("fmc", "DA12"), quote!(crate::fmc::DA12Pin)), |
| 380 | (("fmc", "DA13"), (quote!(crate::fmc::DA13Pin), quote!())), | 380 | (("fmc", "DA13"), quote!(crate::fmc::DA13Pin)), |
| 381 | (("fmc", "DA14"), (quote!(crate::fmc::DA14Pin), quote!())), | 381 | (("fmc", "DA14"), quote!(crate::fmc::DA14Pin)), |
| 382 | (("fmc", "DA15"), (quote!(crate::fmc::DA15Pin), quote!())), | 382 | (("fmc", "DA15"), quote!(crate::fmc::DA15Pin)), |
| 383 | (("fmc", "SDNWE"), (quote!(crate::fmc::SDNWEPin), quote!())), | 383 | (("fmc", "SDNWE"), quote!(crate::fmc::SDNWEPin)), |
| 384 | (("fmc", "SDNCAS"), (quote!(crate::fmc::SDNCASPin), quote!())), | 384 | (("fmc", "SDNCAS"), quote!(crate::fmc::SDNCASPin)), |
| 385 | (("fmc", "SDNRAS"), (quote!(crate::fmc::SDNRASPin), quote!())), | 385 | (("fmc", "SDNRAS"), quote!(crate::fmc::SDNRASPin)), |
| 386 | (("fmc", "SDNE0"), (quote!(crate::fmc::SDNE0Pin), quote!())), | 386 | (("fmc", "SDNE0"), quote!(crate::fmc::SDNE0Pin)), |
| 387 | (("fmc", "SDNE1"), (quote!(crate::fmc::SDNE1Pin), quote!())), | 387 | (("fmc", "SDNE1"), quote!(crate::fmc::SDNE1Pin)), |
| 388 | (("fmc", "SDCKE0"), (quote!(crate::fmc::SDCKE0Pin), quote!())), | 388 | (("fmc", "SDCKE0"), quote!(crate::fmc::SDCKE0Pin)), |
| 389 | (("fmc", "SDCKE1"), (quote!(crate::fmc::SDCKE1Pin), quote!())), | 389 | (("fmc", "SDCKE1"), quote!(crate::fmc::SDCKE1Pin)), |
| 390 | (("fmc", "SDCLK"), (quote!(crate::fmc::SDCLKPin), quote!())), | 390 | (("fmc", "SDCLK"), quote!(crate::fmc::SDCLKPin)), |
| 391 | (("fmc", "NBL0"), (quote!(crate::fmc::NBL0Pin), quote!())), | 391 | (("fmc", "NBL0"), quote!(crate::fmc::NBL0Pin)), |
| 392 | (("fmc", "NBL1"), (quote!(crate::fmc::NBL1Pin), quote!())), | 392 | (("fmc", "NBL1"), quote!(crate::fmc::NBL1Pin)), |
| 393 | (("fmc", "NBL2"), (quote!(crate::fmc::NBL2Pin), quote!())), | 393 | (("fmc", "NBL2"), quote!(crate::fmc::NBL2Pin)), |
| 394 | (("fmc", "NBL3"), (quote!(crate::fmc::NBL3Pin), quote!())), | 394 | (("fmc", "NBL3"), quote!(crate::fmc::NBL3Pin)), |
| 395 | (("fmc", "INT"), (quote!(crate::fmc::INTPin), quote!())), | 395 | (("fmc", "INT"), quote!(crate::fmc::INTPin)), |
| 396 | (("fmc", "NL"), (quote!(crate::fmc::NLPin), quote!())), | 396 | (("fmc", "NL"), quote!(crate::fmc::NLPin)), |
| 397 | (("fmc", "NWAIT"), (quote!(crate::fmc::NWaitPin), quote!())), | 397 | (("fmc", "NWAIT"), quote!(crate::fmc::NWaitPin)), |
| 398 | (("fmc", "NE1"), (quote!(crate::fmc::NE1Pin), quote!())), | 398 | (("fmc", "NE1"), quote!(crate::fmc::NE1Pin)), |
| 399 | (("fmc", "NE2"), (quote!(crate::fmc::NE2Pin), quote!())), | 399 | (("fmc", "NE2"), quote!(crate::fmc::NE2Pin)), |
| 400 | (("fmc", "NE3"), (quote!(crate::fmc::NE3Pin), quote!())), | 400 | (("fmc", "NE3"), quote!(crate::fmc::NE3Pin)), |
| 401 | (("fmc", "NE4"), (quote!(crate::fmc::NE4Pin), quote!())), | 401 | (("fmc", "NE4"), quote!(crate::fmc::NE4Pin)), |
| 402 | (("fmc", "NCE"), (quote!(crate::fmc::NCEPin), quote!())), | 402 | (("fmc", "NCE"), quote!(crate::fmc::NCEPin)), |
| 403 | (("fmc", "NOE"), (quote!(crate::fmc::NOEPin), quote!())), | 403 | (("fmc", "NOE"), quote!(crate::fmc::NOEPin)), |
| 404 | (("fmc", "NWE"), (quote!(crate::fmc::NWEPin), quote!())), | 404 | (("fmc", "NWE"), quote!(crate::fmc::NWEPin)), |
| 405 | (("fmc", "Clk"), (quote!(crate::fmc::ClkPin), quote!())), | 405 | (("fmc", "Clk"), quote!(crate::fmc::ClkPin)), |
| 406 | (("fmc", "BA0"), (quote!(crate::fmc::BA0Pin), quote!())), | 406 | (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)), |
| 407 | (("fmc", "BA1"), (quote!(crate::fmc::BA1Pin), quote!())), | 407 | (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)), |
| 408 | (("timer", "CH1"), (quote!(crate::pwm::Channel1Pin), quote!())), | 408 | (("timer", "CH1"), quote!(crate::pwm::Channel1Pin)), |
| 409 | (("timer", "CH1N"), (quote!(crate::pwm::Channel1ComplementaryPin), quote!())), | 409 | (("timer", "CH1N"), quote!(crate::pwm::Channel1ComplementaryPin)), |
| 410 | (("timer", "CH2"), (quote!(crate::pwm::Channel2Pin), quote!())), | 410 | (("timer", "CH2"), quote!(crate::pwm::Channel2Pin)), |
| 411 | (("timer", "CH2N"), (quote!(crate::pwm::Channel2ComplementaryPin), quote!())), | 411 | (("timer", "CH2N"), quote!(crate::pwm::Channel2ComplementaryPin)), |
| 412 | (("timer", "CH3"), (quote!(crate::pwm::Channel3Pin), quote!())), | 412 | (("timer", "CH3"), quote!(crate::pwm::Channel3Pin)), |
| 413 | (("timer", "CH3N"), (quote!(crate::pwm::Channel3ComplementaryPin), quote!())), | 413 | (("timer", "CH3N"), quote!(crate::pwm::Channel3ComplementaryPin)), |
| 414 | (("timer", "CH4"), (quote!(crate::pwm::Channel4Pin), quote!())), | 414 | (("timer", "CH4"), quote!(crate::pwm::Channel4Pin)), |
| 415 | (("timer", "CH4N"), (quote!(crate::pwm::Channel4ComplementaryPin), quote!())), | 415 | (("timer", "CH4N"), quote!(crate::pwm::Channel4ComplementaryPin)), |
| 416 | (("timer", "ETR"), (quote!(crate::pwm::ExternalTriggerPin), quote!())), | 416 | (("timer", "ETR"), quote!(crate::pwm::ExternalTriggerPin)), |
| 417 | (("timer", "BKIN"), (quote!(crate::pwm::BreakInputPin), quote!())), | 417 | (("timer", "BKIN"), quote!(crate::pwm::BreakInputPin)), |
| 418 | (("timer", "BKIN_COMP1"), (quote!(crate::pwm::BreakInputComparator1Pin), quote!())), | 418 | (("timer", "BKIN_COMP1"), quote!(crate::pwm::BreakInputComparator1Pin)), |
| 419 | (("timer", "BKIN_COMP2"), (quote!(crate::pwm::BreakInputComparator2Pin), quote!())), | 419 | (("timer", "BKIN_COMP2"), quote!(crate::pwm::BreakInputComparator2Pin)), |
| 420 | (("timer", "BKIN2"), (quote!(crate::pwm::BreakInput2Pin), quote!())), | 420 | (("timer", "BKIN2"), quote!(crate::pwm::BreakInput2Pin)), |
| 421 | (("timer", "BKIN2_COMP1"), (quote!(crate::pwm::BreakInput2Comparator1Pin), quote!())), | 421 | (("timer", "BKIN2_COMP1"), quote!(crate::pwm::BreakInput2Comparator1Pin)), |
| 422 | (("timer", "BKIN2_COMP2"), (quote!(crate::pwm::BreakInput2Comparator2Pin), quote!())), | 422 | (("timer", "BKIN2_COMP2"), quote!(crate::pwm::BreakInput2Comparator2Pin)), |
| 423 | (("sdmmc", "CK"), (quote!(crate::sdmmc::CkPin), quote!())), | 423 | (("sdmmc", "CK"), quote!(crate::sdmmc::CkPin)), |
| 424 | (("sdmmc", "CMD"), (quote!(crate::sdmmc::CmdPin), quote!())), | 424 | (("sdmmc", "CMD"), quote!(crate::sdmmc::CmdPin)), |
| 425 | (("sdmmc", "D0"), (quote!(crate::sdmmc::D0Pin), quote!())), | 425 | (("sdmmc", "D0"), quote!(crate::sdmmc::D0Pin)), |
| 426 | (("sdmmc", "D1"), (quote!(crate::sdmmc::D1Pin), quote!())), | 426 | (("sdmmc", "D1"), quote!(crate::sdmmc::D1Pin)), |
| 427 | (("sdmmc", "D2"), (quote!(crate::sdmmc::D2Pin), quote!())), | 427 | (("sdmmc", "D2"), quote!(crate::sdmmc::D2Pin)), |
| 428 | (("sdmmc", "D3"), (quote!(crate::sdmmc::D3Pin), quote!())), | 428 | (("sdmmc", "D3"), quote!(crate::sdmmc::D3Pin)), |
| 429 | (("sdmmc", "D4"), (quote!(crate::sdmmc::D4Pin), quote!())), | 429 | (("sdmmc", "D4"), quote!(crate::sdmmc::D4Pin)), |
| 430 | (("sdmmc", "D5"), (quote!(crate::sdmmc::D5Pin), quote!())), | 430 | (("sdmmc", "D5"), quote!(crate::sdmmc::D5Pin)), |
| 431 | (("sdmmc", "D6"), (quote!(crate::sdmmc::D6Pin), quote!())), | 431 | (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), |
| 432 | (("sdmmc", "D6"), (quote!(crate::sdmmc::D7Pin), quote!())), | 432 | (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), |
| 433 | (("sdmmc", "D8"), (quote!(crate::sdmmc::D8Pin), quote!())), | 433 | (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), |
| 434 | ].into(); | 434 | ].into(); |
| 435 | 435 | ||
| 436 | for p in METADATA.peripherals { | 436 | for p in METADATA.peripherals { |
| 437 | if let Some(regs) = &p.registers { | 437 | if let Some(regs) = &p.registers { |
| 438 | for pin in p.pins { | 438 | for pin in p.pins { |
| 439 | let key = (regs.kind, pin.signal); | 439 | let key = (regs.kind, pin.signal); |
| 440 | if let Some((tr, cfgs)) = signals.get(&key) { | 440 | if let Some(tr) = signals.get(&key) { |
| 441 | let mut peri = format_ident!("{}", p.name); | 441 | let mut peri = format_ident!("{}", p.name); |
| 442 | let pin_name = format_ident!("{}", pin.pin); | 442 | let pin_name = format_ident!("{}", pin.pin); |
| 443 | let af = pin.af.unwrap_or(0); | 443 | let af = pin.af.unwrap_or(0); |
| @@ -453,7 +453,6 @@ fn main() { | |||
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | g.extend(quote! { | 455 | g.extend(quote! { |
| 456 | #cfgs | ||
| 457 | pin_trait_impl!(#tr, #peri, #pin_name, #af); | 456 | pin_trait_impl!(#tr, #peri, #pin_name, #af); |
| 458 | }) | 457 | }) |
| 459 | } | 458 | } |
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 28f0c178f..76a3dfab4 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs | |||
| @@ -1,10 +1,12 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | #[cfg(feature = "net")] | ||
| 3 | #[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] | 4 | #[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] |
| 4 | #[cfg_attr(eth_v2, path = "v2/mod.rs")] | 5 | #[cfg_attr(eth_v2, path = "v2/mod.rs")] |
| 5 | mod _version; | 6 | mod _version; |
| 6 | pub mod generic_smi; | 7 | pub mod generic_smi; |
| 7 | 8 | ||
| 9 | #[cfg(feature = "net")] | ||
| 8 | pub use _version::*; | 10 | pub use _version::*; |
| 9 | 11 | ||
| 10 | /// Station Management Interface (SMI) on an ethernet PHY | 12 | /// Station Management Interface (SMI) on an ethernet PHY |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 6e9077b4c..86b3e25dc 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -39,7 +39,7 @@ pub mod can; | |||
| 39 | pub mod dac; | 39 | pub mod dac; |
| 40 | #[cfg(dcmi)] | 40 | #[cfg(dcmi)] |
| 41 | pub mod dcmi; | 41 | pub mod dcmi; |
| 42 | #[cfg(all(eth, feature = "net"))] | 42 | #[cfg(eth)] |
| 43 | pub mod eth; | 43 | pub mod eth; |
| 44 | #[cfg(feature = "exti")] | 44 | #[cfg(feature = "exti")] |
| 45 | pub mod exti; | 45 | pub mod exti; |
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs new file mode 100644 index 000000000..b2fcb504e --- /dev/null +++ b/embassy-stm32/src/usart/buffered.rs | |||
| @@ -0,0 +1,238 @@ | |||
| 1 | use atomic_polyfill::{compiler_fence, Ordering}; | ||
| 2 | use core::future::Future; | ||
| 3 | use core::task::Poll; | ||
| 4 | use embassy::waitqueue::WakerRegistration; | ||
| 5 | use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; | ||
| 6 | use embassy_hal_common::ring_buffer::RingBuffer; | ||
| 7 | use futures::future::poll_fn; | ||
| 8 | |||
| 9 | use super::*; | ||
| 10 | |||
| 11 | pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>); | ||
| 12 | impl<'d, T: Instance> State<'d, T> { | ||
| 13 | pub fn new() -> Self { | ||
| 14 | Self(StateStorage::new()) | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | struct StateInner<'d, T: Instance> { | ||
| 19 | phantom: PhantomData<&'d mut T>, | ||
| 20 | |||
| 21 | rx_waker: WakerRegistration, | ||
| 22 | rx: RingBuffer<'d>, | ||
| 23 | |||
| 24 | tx_waker: WakerRegistration, | ||
| 25 | tx: RingBuffer<'d>, | ||
| 26 | } | ||
| 27 | |||
| 28 | unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {} | ||
| 29 | unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {} | ||
| 30 | |||
| 31 | pub struct BufferedUart<'d, T: Instance> { | ||
| 32 | inner: PeripheralMutex<'d, StateInner<'d, T>>, | ||
| 33 | } | ||
| 34 | |||
| 35 | impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} | ||
| 36 | |||
| 37 | impl<'d, T: Instance> BufferedUart<'d, T> { | ||
| 38 | pub unsafe fn new( | ||
| 39 | state: &'d mut State<'d, T>, | ||
| 40 | _uart: Uart<'d, T, NoDma, NoDma>, | ||
| 41 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 42 | tx_buffer: &'d mut [u8], | ||
| 43 | rx_buffer: &'d mut [u8], | ||
| 44 | ) -> BufferedUart<'d, T> { | ||
| 45 | unborrow!(irq); | ||
| 46 | |||
| 47 | let r = T::regs(); | ||
| 48 | r.cr1().modify(|w| { | ||
| 49 | w.set_rxneie(true); | ||
| 50 | w.set_idleie(true); | ||
| 51 | }); | ||
| 52 | |||
| 53 | Self { | ||
| 54 | inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { | ||
| 55 | phantom: PhantomData, | ||
| 56 | tx: RingBuffer::new(tx_buffer), | ||
| 57 | tx_waker: WakerRegistration::new(), | ||
| 58 | |||
| 59 | rx: RingBuffer::new(rx_buffer), | ||
| 60 | rx_waker: WakerRegistration::new(), | ||
| 61 | }), | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | impl<'d, T: Instance> StateInner<'d, T> | ||
| 67 | where | ||
| 68 | Self: 'd, | ||
| 69 | { | ||
| 70 | fn on_rx(&mut self) { | ||
| 71 | let r = T::regs(); | ||
| 72 | unsafe { | ||
| 73 | let sr = sr(r).read(); | ||
| 74 | clear_interrupt_flags(r, sr); | ||
| 75 | |||
| 76 | // This read also clears the error and idle interrupt flags on v1. | ||
| 77 | let b = rdr(r).read_volatile(); | ||
| 78 | |||
| 79 | if sr.rxne() { | ||
| 80 | if sr.pe() { | ||
| 81 | warn!("Parity error"); | ||
| 82 | } | ||
| 83 | if sr.fe() { | ||
| 84 | warn!("Framing error"); | ||
| 85 | } | ||
| 86 | if sr.ne() { | ||
| 87 | warn!("Noise error"); | ||
| 88 | } | ||
| 89 | if sr.ore() { | ||
| 90 | warn!("Overrun error"); | ||
| 91 | } | ||
| 92 | |||
| 93 | let buf = self.rx.push_buf(); | ||
| 94 | if !buf.is_empty() { | ||
| 95 | buf[0] = b; | ||
| 96 | self.rx.push(1); | ||
| 97 | } else { | ||
| 98 | warn!("RX buffer full, discard received byte"); | ||
| 99 | } | ||
| 100 | |||
| 101 | if self.rx.is_full() { | ||
| 102 | self.rx_waker.wake(); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | if sr.idle() { | ||
| 107 | self.rx_waker.wake(); | ||
| 108 | }; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | fn on_tx(&mut self) { | ||
| 113 | let r = T::regs(); | ||
| 114 | unsafe { | ||
| 115 | if sr(r).read().txe() { | ||
| 116 | let buf = self.tx.pop_buf(); | ||
| 117 | if !buf.is_empty() { | ||
| 118 | r.cr1().modify(|w| { | ||
| 119 | w.set_txeie(true); | ||
| 120 | }); | ||
| 121 | tdr(r).write_volatile(buf[0].into()); | ||
| 122 | self.tx.pop(1); | ||
| 123 | self.tx_waker.wake(); | ||
| 124 | } else { | ||
| 125 | // Disable interrupt until we have something to transmit again | ||
| 126 | r.cr1().modify(|w| { | ||
| 127 | w.set_txeie(false); | ||
| 128 | }); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | impl<'d, T: Instance> PeripheralState for StateInner<'d, T> | ||
| 136 | where | ||
| 137 | Self: 'd, | ||
| 138 | { | ||
| 139 | type Interrupt = T::Interrupt; | ||
| 140 | fn on_interrupt(&mut self) { | ||
| 141 | self.on_rx(); | ||
| 142 | self.on_tx(); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | impl embedded_io::Error for Error { | ||
| 147 | fn kind(&self) -> embedded_io::ErrorKind { | ||
| 148 | embedded_io::ErrorKind::Other | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> { | ||
| 153 | type Error = Error; | ||
| 154 | } | ||
| 155 | |||
| 156 | impl<'d, T: Instance> embedded_io::asynch::Read for BufferedUart<'d, T> { | ||
| 157 | type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 158 | where | ||
| 159 | Self: 'a; | ||
| 160 | |||
| 161 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 162 | poll_fn(move |cx| { | ||
| 163 | let mut do_pend = false; | ||
| 164 | let res = self.inner.with(|state| { | ||
| 165 | compiler_fence(Ordering::SeqCst); | ||
| 166 | |||
| 167 | // We have data ready in buffer? Return it. | ||
| 168 | let data = state.rx.pop_buf(); | ||
| 169 | if !data.is_empty() { | ||
| 170 | let len = data.len().min(buf.len()); | ||
| 171 | buf[..len].copy_from_slice(&data[..len]); | ||
| 172 | |||
| 173 | if state.rx.is_full() { | ||
| 174 | do_pend = true; | ||
| 175 | } | ||
| 176 | state.rx.pop(len); | ||
| 177 | |||
| 178 | return Poll::Ready(Ok(len)); | ||
| 179 | } | ||
| 180 | |||
| 181 | state.rx_waker.register(cx.waker()); | ||
| 182 | Poll::Pending | ||
| 183 | }); | ||
| 184 | |||
| 185 | if do_pend { | ||
| 186 | self.inner.pend(); | ||
| 187 | } | ||
| 188 | |||
| 189 | res | ||
| 190 | }) | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | impl<'d, T: Instance> embedded_io::asynch::Write for BufferedUart<'d, T> { | ||
| 195 | type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 196 | where | ||
| 197 | Self: 'a; | ||
| 198 | |||
| 199 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 200 | poll_fn(move |cx| { | ||
| 201 | let (poll, empty) = self.inner.with(|state| { | ||
| 202 | let empty = state.tx.is_empty(); | ||
| 203 | let tx_buf = state.tx.push_buf(); | ||
| 204 | if tx_buf.is_empty() { | ||
| 205 | state.tx_waker.register(cx.waker()); | ||
| 206 | return (Poll::Pending, empty); | ||
| 207 | } | ||
| 208 | |||
| 209 | let n = core::cmp::min(tx_buf.len(), buf.len()); | ||
| 210 | tx_buf[..n].copy_from_slice(&buf[..n]); | ||
| 211 | state.tx.push(n); | ||
| 212 | |||
| 213 | (Poll::Ready(Ok(n)), empty) | ||
| 214 | }); | ||
| 215 | if empty { | ||
| 216 | self.inner.pend(); | ||
| 217 | } | ||
| 218 | poll | ||
| 219 | }) | ||
| 220 | } | ||
| 221 | |||
| 222 | type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> | ||
| 223 | where | ||
| 224 | Self: 'a; | ||
| 225 | |||
| 226 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { | ||
| 227 | poll_fn(move |cx| { | ||
| 228 | self.inner.with(|state| { | ||
| 229 | if !state.tx.is_empty() { | ||
| 230 | state.tx_waker.register(cx.waker()); | ||
| 231 | return Poll::Pending; | ||
| 232 | } | ||
| 233 | |||
| 234 | Poll::Ready(Ok(())) | ||
| 235 | }) | ||
| 236 | }) | ||
| 237 | } | ||
| 238 | } | ||
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 22224215c..6feecd184 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -424,227 +424,10 @@ cfg_if::cfg_if! { | |||
| 424 | } | 424 | } |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | #[cfg(feature = "nightly")] | ||
| 427 | pub use buffered::*; | 428 | pub use buffered::*; |
| 428 | mod buffered { | 429 | #[cfg(feature = "nightly")] |
| 429 | use atomic_polyfill::{compiler_fence, Ordering}; | 430 | mod buffered; |
| 430 | use core::pin::Pin; | ||
| 431 | use core::task::Context; | ||
| 432 | use core::task::Poll; | ||
| 433 | use embassy::waitqueue::WakerRegistration; | ||
| 434 | use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; | ||
| 435 | use embassy_hal_common::ring_buffer::RingBuffer; | ||
| 436 | |||
| 437 | use super::*; | ||
| 438 | |||
| 439 | pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>); | ||
| 440 | impl<'d, T: Instance> State<'d, T> { | ||
| 441 | pub fn new() -> Self { | ||
| 442 | Self(StateStorage::new()) | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 446 | struct StateInner<'d, T: Instance> { | ||
| 447 | phantom: PhantomData<&'d mut T>, | ||
| 448 | |||
| 449 | rx_waker: WakerRegistration, | ||
| 450 | rx: RingBuffer<'d>, | ||
| 451 | |||
| 452 | tx_waker: WakerRegistration, | ||
| 453 | tx: RingBuffer<'d>, | ||
| 454 | } | ||
| 455 | |||
| 456 | unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {} | ||
| 457 | unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {} | ||
| 458 | |||
| 459 | pub struct BufferedUart<'d, T: Instance> { | ||
| 460 | inner: PeripheralMutex<'d, StateInner<'d, T>>, | ||
| 461 | } | ||
| 462 | |||
| 463 | impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} | ||
| 464 | |||
| 465 | impl<'d, T: Instance> BufferedUart<'d, T> { | ||
| 466 | pub unsafe fn new( | ||
| 467 | state: &'d mut State<'d, T>, | ||
| 468 | _uart: Uart<'d, T, NoDma, NoDma>, | ||
| 469 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 470 | tx_buffer: &'d mut [u8], | ||
| 471 | rx_buffer: &'d mut [u8], | ||
| 472 | ) -> BufferedUart<'d, T> { | ||
| 473 | unborrow!(irq); | ||
| 474 | |||
| 475 | let r = T::regs(); | ||
| 476 | r.cr1().modify(|w| { | ||
| 477 | w.set_rxneie(true); | ||
| 478 | w.set_idleie(true); | ||
| 479 | }); | ||
| 480 | |||
| 481 | Self { | ||
| 482 | inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { | ||
| 483 | phantom: PhantomData, | ||
| 484 | tx: RingBuffer::new(tx_buffer), | ||
| 485 | tx_waker: WakerRegistration::new(), | ||
| 486 | |||
| 487 | rx: RingBuffer::new(rx_buffer), | ||
| 488 | rx_waker: WakerRegistration::new(), | ||
| 489 | }), | ||
| 490 | } | ||
| 491 | } | ||
| 492 | } | ||
| 493 | |||
| 494 | impl<'d, T: Instance> StateInner<'d, T> | ||
| 495 | where | ||
| 496 | Self: 'd, | ||
| 497 | { | ||
| 498 | fn on_rx(&mut self) { | ||
| 499 | let r = T::regs(); | ||
| 500 | unsafe { | ||
| 501 | let sr = sr(r).read(); | ||
| 502 | clear_interrupt_flags(r, sr); | ||
| 503 | |||
| 504 | // This read also clears the error and idle interrupt flags on v1. | ||
| 505 | let b = rdr(r).read_volatile(); | ||
| 506 | |||
| 507 | if sr.rxne() { | ||
| 508 | if sr.pe() { | ||
| 509 | warn!("Parity error"); | ||
| 510 | } | ||
| 511 | if sr.fe() { | ||
| 512 | warn!("Framing error"); | ||
| 513 | } | ||
| 514 | if sr.ne() { | ||
| 515 | warn!("Noise error"); | ||
| 516 | } | ||
| 517 | if sr.ore() { | ||
| 518 | warn!("Overrun error"); | ||
| 519 | } | ||
| 520 | |||
| 521 | let buf = self.rx.push_buf(); | ||
| 522 | if !buf.is_empty() { | ||
| 523 | buf[0] = b; | ||
| 524 | self.rx.push(1); | ||
| 525 | } else { | ||
| 526 | warn!("RX buffer full, discard received byte"); | ||
| 527 | } | ||
| 528 | |||
| 529 | if self.rx.is_full() { | ||
| 530 | self.rx_waker.wake(); | ||
| 531 | } | ||
| 532 | } | ||
| 533 | |||
| 534 | if sr.idle() { | ||
| 535 | self.rx_waker.wake(); | ||
| 536 | }; | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | fn on_tx(&mut self) { | ||
| 541 | let r = T::regs(); | ||
| 542 | unsafe { | ||
| 543 | if sr(r).read().txe() { | ||
| 544 | let buf = self.tx.pop_buf(); | ||
| 545 | if !buf.is_empty() { | ||
| 546 | r.cr1().modify(|w| { | ||
| 547 | w.set_txeie(true); | ||
| 548 | }); | ||
| 549 | tdr(r).write_volatile(buf[0].into()); | ||
| 550 | self.tx.pop(1); | ||
| 551 | self.tx_waker.wake(); | ||
| 552 | } else { | ||
| 553 | // Disable interrupt until we have something to transmit again | ||
| 554 | r.cr1().modify(|w| { | ||
| 555 | w.set_txeie(false); | ||
| 556 | }); | ||
| 557 | } | ||
| 558 | } | ||
| 559 | } | ||
| 560 | } | ||
| 561 | } | ||
| 562 | |||
| 563 | impl<'d, T: Instance> PeripheralState for StateInner<'d, T> | ||
| 564 | where | ||
| 565 | Self: 'd, | ||
| 566 | { | ||
| 567 | type Interrupt = T::Interrupt; | ||
| 568 | fn on_interrupt(&mut self) { | ||
| 569 | self.on_rx(); | ||
| 570 | self.on_tx(); | ||
| 571 | } | ||
| 572 | } | ||
| 573 | |||
| 574 | impl<'d, T: Instance> embassy::io::AsyncBufRead for BufferedUart<'d, T> { | ||
| 575 | fn poll_fill_buf( | ||
| 576 | mut self: Pin<&mut Self>, | ||
| 577 | cx: &mut Context<'_>, | ||
| 578 | ) -> Poll<Result<&[u8], embassy::io::Error>> { | ||
| 579 | self.inner.with(|state| { | ||
| 580 | compiler_fence(Ordering::SeqCst); | ||
| 581 | |||
| 582 | // We have data ready in buffer? Return it. | ||
| 583 | let buf = state.rx.pop_buf(); | ||
| 584 | if !buf.is_empty() { | ||
| 585 | let buf: &[u8] = buf; | ||
| 586 | // Safety: buffer lives as long as uart | ||
| 587 | let buf: &[u8] = unsafe { core::mem::transmute(buf) }; | ||
| 588 | return Poll::Ready(Ok(buf)); | ||
| 589 | } | ||
| 590 | |||
| 591 | state.rx_waker.register(cx.waker()); | ||
| 592 | Poll::<Result<&[u8], embassy::io::Error>>::Pending | ||
| 593 | }) | ||
| 594 | } | ||
| 595 | fn consume(mut self: Pin<&mut Self>, amt: usize) { | ||
| 596 | let signal = self.inner.with(|state| { | ||
| 597 | let full = state.rx.is_full(); | ||
| 598 | state.rx.pop(amt); | ||
| 599 | full | ||
| 600 | }); | ||
| 601 | if signal { | ||
| 602 | self.inner.pend(); | ||
| 603 | } | ||
| 604 | } | ||
| 605 | } | ||
| 606 | |||
| 607 | impl<'d, T: Instance> embassy::io::AsyncWrite for BufferedUart<'d, T> { | ||
| 608 | fn poll_write( | ||
| 609 | mut self: Pin<&mut Self>, | ||
| 610 | cx: &mut Context<'_>, | ||
| 611 | buf: &[u8], | ||
| 612 | ) -> Poll<Result<usize, embassy::io::Error>> { | ||
| 613 | let (poll, empty) = self.inner.with(|state| { | ||
| 614 | let empty = state.tx.is_empty(); | ||
| 615 | let tx_buf = state.tx.push_buf(); | ||
| 616 | if tx_buf.is_empty() { | ||
| 617 | state.tx_waker.register(cx.waker()); | ||
| 618 | return (Poll::Pending, empty); | ||
| 619 | } | ||
| 620 | |||
| 621 | let n = core::cmp::min(tx_buf.len(), buf.len()); | ||
| 622 | tx_buf[..n].copy_from_slice(&buf[..n]); | ||
| 623 | state.tx.push(n); | ||
| 624 | |||
| 625 | (Poll::Ready(Ok(n)), empty) | ||
| 626 | }); | ||
| 627 | if empty { | ||
| 628 | self.inner.pend(); | ||
| 629 | } | ||
| 630 | poll | ||
| 631 | } | ||
| 632 | |||
| 633 | fn poll_flush( | ||
| 634 | mut self: Pin<&mut Self>, | ||
| 635 | cx: &mut Context<'_>, | ||
| 636 | ) -> Poll<Result<(), embassy::io::Error>> { | ||
| 637 | self.inner.with(|state| { | ||
| 638 | if !state.tx.is_empty() { | ||
| 639 | state.tx_waker.register(cx.waker()); | ||
| 640 | return Poll::Pending; | ||
| 641 | } | ||
| 642 | |||
| 643 | Poll::Ready(Ok(())) | ||
| 644 | }) | ||
| 645 | } | ||
| 646 | } | ||
| 647 | } | ||
| 648 | 431 | ||
| 649 | #[cfg(usart_v1)] | 432 | #[cfg(usart_v1)] |
| 650 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { | 433 | 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 | |||
| 662 | } | 445 | } |
| 663 | 446 | ||
| 664 | #[cfg(usart_v1)] | 447 | #[cfg(usart_v1)] |
| 448 | #[allow(unused)] | ||
| 665 | unsafe fn clear_interrupt_flags(_r: crate::pac::usart::Usart, _sr: regs::Sr) { | 449 | unsafe fn clear_interrupt_flags(_r: crate::pac::usart::Usart, _sr: regs::Sr) { |
| 666 | // On v1 the flags are cleared implicitly by reads and writes to DR. | 450 | // On v1 the flags are cleared implicitly by reads and writes to DR. |
| 667 | } | 451 | } |
| @@ -682,6 +466,7 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Ixr, crate:: | |||
| 682 | } | 466 | } |
| 683 | 467 | ||
| 684 | #[cfg(usart_v2)] | 468 | #[cfg(usart_v2)] |
| 469 | #[allow(unused)] | ||
| 685 | unsafe fn clear_interrupt_flags(r: crate::pac::usart::Usart, sr: regs::Ixr) { | 470 | unsafe fn clear_interrupt_flags(r: crate::pac::usart::Usart, sr: regs::Ixr) { |
| 686 | r.icr().write(|w| *w = sr); | 471 | r.icr().write(|w| *w = sr); |
| 687 | } | 472 | } |
diff --git a/embassy/src/io/error.rs b/embassy/src/io/error.rs deleted file mode 100644 index 2092c0d18..000000000 --- a/embassy/src/io/error.rs +++ /dev/null | |||
| @@ -1,142 +0,0 @@ | |||
| 1 | /// Categories of errors that can occur. | ||
| 2 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| 3 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 4 | #[non_exhaustive] | ||
| 5 | pub enum Error { | ||
| 6 | /// An entity was not found, often a file. | ||
| 7 | NotFound, | ||
| 8 | /// The operation lacked the necessary privileges to complete. | ||
| 9 | PermissionDenied, | ||
| 10 | /// The connection was refused by the remote server. | ||
| 11 | ConnectionRefused, | ||
| 12 | /// The connection was reset by the remote server. | ||
| 13 | ConnectionReset, | ||
| 14 | /// The connection was aborted (terminated) by the remote server. | ||
| 15 | ConnectionAborted, | ||
| 16 | /// The network operation failed because it was not connected yet. | ||
| 17 | NotConnected, | ||
| 18 | /// A socket address could not be bound because the address is already in | ||
| 19 | /// use elsewhere. | ||
| 20 | AddrInUse, | ||
| 21 | /// A nonexistent interface was requested or the requested address was not | ||
| 22 | /// local. | ||
| 23 | AddrNotAvailable, | ||
| 24 | /// The operation failed because a pipe was closed. | ||
| 25 | BrokenPipe, | ||
| 26 | /// An entity already exists, often a file. | ||
| 27 | AlreadyExists, | ||
| 28 | /// The operation needs to block to complete, but the blocking operation was | ||
| 29 | /// requested to not occur. | ||
| 30 | WouldBlock, | ||
| 31 | /// A parameter was incorrect. | ||
| 32 | InvalidInput, | ||
| 33 | /// Data not valid for the operation were encountered. | ||
| 34 | /// | ||
| 35 | /// Unlike [`InvalidInput`], this typically means that the operation | ||
| 36 | /// parameters were valid, however the error was caused by malformed | ||
| 37 | /// input data. | ||
| 38 | /// | ||
| 39 | /// For example, a function that reads a file into a string will error with | ||
| 40 | /// `InvalidData` if the file's contents are not valid UTF-8. | ||
| 41 | /// | ||
| 42 | /// [`InvalidInput`]: #variant.InvalidInput | ||
| 43 | InvalidData, | ||
| 44 | /// The I/O operation's timeout expired, causing it to be canceled. | ||
| 45 | TimedOut, | ||
| 46 | /// An error returned when an operation could not be completed because a | ||
| 47 | /// call to [`write`] returned [`Ok(0)`]. | ||
| 48 | /// | ||
| 49 | /// This typically means that an operation could only succeed if it wrote a | ||
| 50 | /// particular number of bytes but only a smaller number of bytes could be | ||
| 51 | /// written. | ||
| 52 | /// | ||
| 53 | /// [`write`]: ../../std/io/trait.Write.html#tymethod.write | ||
| 54 | /// [`Ok(0)`]: ../../std/io/type.Result.html | ||
| 55 | WriteZero, | ||
| 56 | /// This operation was interrupted. | ||
| 57 | /// | ||
| 58 | /// Interrupted operations can typically be retried. | ||
| 59 | Interrupted, | ||
| 60 | |||
| 61 | /// An error returned when an operation could not be completed because an | ||
| 62 | /// "end of file" was reached prematurely. | ||
| 63 | /// | ||
| 64 | /// This typically means that an operation could only succeed if it read a | ||
| 65 | /// particular number of bytes but only a smaller number of bytes could be | ||
| 66 | /// read. | ||
| 67 | UnexpectedEof, | ||
| 68 | |||
| 69 | /// An operation would have read more data if the given buffer was large. | ||
| 70 | /// | ||
| 71 | /// This typically means that the buffer has been filled with the first N bytes | ||
| 72 | /// of the read data. | ||
| 73 | Truncated, | ||
| 74 | |||
| 75 | /// Any I/O error not part of this list. | ||
| 76 | Other, | ||
| 77 | } | ||
| 78 | |||
| 79 | pub type Result<T> = core::result::Result<T, Error>; | ||
| 80 | |||
| 81 | #[cfg(feature = "std")] | ||
| 82 | impl From<std::io::Error> for Error { | ||
| 83 | fn from(err: std::io::Error) -> Error { | ||
| 84 | match err.kind() { | ||
| 85 | std::io::ErrorKind::NotFound => Error::NotFound, | ||
| 86 | std::io::ErrorKind::PermissionDenied => Error::PermissionDenied, | ||
| 87 | std::io::ErrorKind::ConnectionRefused => Error::ConnectionRefused, | ||
| 88 | std::io::ErrorKind::ConnectionReset => Error::ConnectionReset, | ||
| 89 | std::io::ErrorKind::ConnectionAborted => Error::ConnectionAborted, | ||
| 90 | std::io::ErrorKind::NotConnected => Error::NotConnected, | ||
| 91 | std::io::ErrorKind::AddrInUse => Error::AddrInUse, | ||
| 92 | std::io::ErrorKind::AddrNotAvailable => Error::AddrNotAvailable, | ||
| 93 | std::io::ErrorKind::BrokenPipe => Error::BrokenPipe, | ||
| 94 | std::io::ErrorKind::AlreadyExists => Error::AlreadyExists, | ||
| 95 | std::io::ErrorKind::WouldBlock => Error::WouldBlock, | ||
| 96 | std::io::ErrorKind::InvalidInput => Error::InvalidInput, | ||
| 97 | std::io::ErrorKind::InvalidData => Error::InvalidData, | ||
| 98 | std::io::ErrorKind::TimedOut => Error::TimedOut, | ||
| 99 | std::io::ErrorKind::WriteZero => Error::WriteZero, | ||
| 100 | std::io::ErrorKind::Interrupted => Error::Interrupted, | ||
| 101 | std::io::ErrorKind::UnexpectedEof => Error::UnexpectedEof, | ||
| 102 | _ => Error::Other, | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | #[cfg(feature = "std")] | ||
| 108 | impl From<Error> for std::io::Error { | ||
| 109 | fn from(e: Error) -> Self { | ||
| 110 | let kind = match e { | ||
| 111 | Error::NotFound => std::io::ErrorKind::NotFound, | ||
| 112 | Error::PermissionDenied => std::io::ErrorKind::PermissionDenied, | ||
| 113 | Error::ConnectionRefused => std::io::ErrorKind::ConnectionRefused, | ||
| 114 | Error::ConnectionReset => std::io::ErrorKind::ConnectionReset, | ||
| 115 | Error::ConnectionAborted => std::io::ErrorKind::ConnectionAborted, | ||
| 116 | Error::NotConnected => std::io::ErrorKind::NotConnected, | ||
| 117 | Error::AddrInUse => std::io::ErrorKind::AddrInUse, | ||
| 118 | Error::AddrNotAvailable => std::io::ErrorKind::AddrNotAvailable, | ||
| 119 | Error::BrokenPipe => std::io::ErrorKind::BrokenPipe, | ||
| 120 | Error::AlreadyExists => std::io::ErrorKind::AlreadyExists, | ||
| 121 | Error::WouldBlock => std::io::ErrorKind::WouldBlock, | ||
| 122 | Error::InvalidInput => std::io::ErrorKind::InvalidInput, | ||
| 123 | Error::InvalidData => std::io::ErrorKind::InvalidData, | ||
| 124 | Error::TimedOut => std::io::ErrorKind::TimedOut, | ||
| 125 | Error::WriteZero => std::io::ErrorKind::WriteZero, | ||
| 126 | Error::Interrupted => std::io::ErrorKind::Interrupted, | ||
| 127 | Error::UnexpectedEof => std::io::ErrorKind::UnexpectedEof, | ||
| 128 | Error::Truncated => std::io::ErrorKind::Other, | ||
| 129 | Error::Other => std::io::ErrorKind::Other, | ||
| 130 | }; | ||
| 131 | std::io::Error::new(kind, "embassy::io::Error") | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | impl core::fmt::Display for Error { | ||
| 136 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
| 137 | write!(f, "{:?}", self) | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | #[cfg(feature = "std")] | ||
| 142 | 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 52b050971..000000000 --- a/embassy/src/io/mod.rs +++ /dev/null | |||
| @@ -1,11 +0,0 @@ | |||
| 1 | mod error; | ||
| 2 | #[cfg(feature = "std")] | ||
| 3 | mod std; | ||
| 4 | mod traits; | ||
| 5 | mod util; | ||
| 6 | |||
| 7 | pub use self::error::*; | ||
| 8 | #[cfg(feature = "std")] | ||
| 9 | pub use self::std::*; | ||
| 10 | pub use self::traits::*; | ||
| 11 | pub use self::util::*; | ||
diff --git a/embassy/src/io/std.rs b/embassy/src/io/std.rs deleted file mode 100644 index 580d52891..000000000 --- a/embassy/src/io/std.rs +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | use core::pin::Pin; | ||
| 2 | use core::task::{Context, Poll}; | ||
| 3 | use futures::io as std_io; | ||
| 4 | |||
| 5 | use super::{AsyncBufRead, AsyncWrite, Result}; | ||
| 6 | |||
| 7 | pub struct FromStdIo<T>(T); | ||
| 8 | |||
| 9 | impl<T> FromStdIo<T> { | ||
| 10 | pub fn new(inner: T) -> Self { | ||
| 11 | Self(inner) | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | impl<T: std_io::AsyncBufRead> AsyncBufRead for FromStdIo<T> { | ||
| 16 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { | ||
| 17 | let Self(inner) = unsafe { self.get_unchecked_mut() }; | ||
| 18 | unsafe { Pin::new_unchecked(inner) } | ||
| 19 | .poll_fill_buf(cx) | ||
| 20 | .map_err(|e| e.into()) | ||
| 21 | } | ||
| 22 | fn consume(self: Pin<&mut Self>, amt: usize) { | ||
| 23 | let Self(inner) = unsafe { self.get_unchecked_mut() }; | ||
| 24 | unsafe { Pin::new_unchecked(inner) }.consume(amt) | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | impl<T: std_io::AsyncWrite> AsyncWrite for FromStdIo<T> { | ||
| 29 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { | ||
| 30 | let Self(inner) = unsafe { self.get_unchecked_mut() }; | ||
| 31 | unsafe { Pin::new_unchecked(inner) } | ||
| 32 | .poll_write(cx, buf) | ||
| 33 | .map_err(|e| e.into()) | ||
| 34 | } | ||
| 35 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { | ||
| 36 | let Self(inner) = unsafe { self.get_unchecked_mut() }; | ||
| 37 | unsafe { Pin::new_unchecked(inner) } | ||
| 38 | .poll_flush(cx) | ||
| 39 | .map_err(|e| e.into()) | ||
| 40 | } | ||
| 41 | } | ||
diff --git a/embassy/src/io/traits.rs b/embassy/src/io/traits.rs deleted file mode 100644 index 06500a687..000000000 --- a/embassy/src/io/traits.rs +++ /dev/null | |||
| @@ -1,175 +0,0 @@ | |||
| 1 | use core::ops::DerefMut; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use core::task::{Context, Poll}; | ||
| 4 | |||
| 5 | #[cfg(feature = "alloc")] | ||
| 6 | use alloc::boxed::Box; | ||
| 7 | |||
| 8 | use super::error::Result; | ||
| 9 | |||
| 10 | /// Read bytes asynchronously. | ||
| 11 | /// | ||
| 12 | /// This trait is analogous to the `std::io::BufRead` trait, but integrates | ||
| 13 | /// with the asynchronous task system. In particular, the `poll_fill_buf` | ||
| 14 | /// method, unlike `BufRead::fill_buf`, will automatically queue the current task | ||
| 15 | /// for wakeup and return if data is not yet available, rather than blocking | ||
| 16 | /// the calling thread. | ||
| 17 | pub trait AsyncBufRead { | ||
| 18 | /// Attempt to return the contents of the internal buffer, filling it with more data | ||
| 19 | /// from the inner reader if it is empty. | ||
| 20 | /// | ||
| 21 | /// On success, returns `Poll::Ready(Ok(buf))`. | ||
| 22 | /// | ||
| 23 | /// If no data is available for reading, the method returns | ||
| 24 | /// `Poll::Pending` and arranges for the current task (via | ||
| 25 | /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes | ||
| 26 | /// readable or is closed. | ||
| 27 | /// | ||
| 28 | /// This function is a lower-level call. It needs to be paired with the | ||
| 29 | /// [`consume`] method to function properly. When calling this | ||
| 30 | /// method, none of the contents will be "read" in the sense that later | ||
| 31 | /// calling [`poll_fill_buf`] may return the same contents. As such, [`consume`] must | ||
| 32 | /// be called with the number of bytes that are consumed from this buffer to | ||
| 33 | /// ensure that the bytes are never returned twice. | ||
| 34 | /// | ||
| 35 | /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf | ||
| 36 | /// [`consume`]: AsyncBufRead::consume | ||
| 37 | /// | ||
| 38 | /// An empty buffer returned indicates that the stream has reached EOF. | ||
| 39 | /// | ||
| 40 | /// # Implementation | ||
| 41 | /// | ||
| 42 | /// This function may not return errors of kind `WouldBlock` or | ||
| 43 | /// `Interrupted`. Implementations must convert `WouldBlock` into | ||
| 44 | /// `Poll::Pending` and either internally retry or convert | ||
| 45 | /// `Interrupted` into another error kind. | ||
| 46 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>>; | ||
| 47 | |||
| 48 | /// Tells this buffer that `amt` bytes have been consumed from the buffer, | ||
| 49 | /// so they should no longer be returned in calls to [`poll_fill_buf`]. | ||
| 50 | /// | ||
| 51 | /// This function is a lower-level call. It needs to be paired with the | ||
| 52 | /// [`poll_fill_buf`] method to function properly. This function does | ||
| 53 | /// not perform any I/O, it simply informs this object that some amount of | ||
| 54 | /// its buffer, returned from [`poll_fill_buf`], has been consumed and should | ||
| 55 | /// no longer be returned. As such, this function may do odd things if | ||
| 56 | /// [`poll_fill_buf`] isn't called before calling it. | ||
| 57 | /// | ||
| 58 | /// The `amt` must be `<=` the number of bytes in the buffer returned by | ||
| 59 | /// [`poll_fill_buf`]. | ||
| 60 | /// | ||
| 61 | /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf | ||
| 62 | fn consume(self: Pin<&mut Self>, amt: usize); | ||
| 63 | } | ||
| 64 | |||
| 65 | /// Write bytes asynchronously. | ||
| 66 | /// | ||
| 67 | /// This trait is analogous to the `core::io::Write` trait, but integrates | ||
| 68 | /// with the asynchronous task system. In particular, the `poll_write` | ||
| 69 | /// method, unlike `Write::write`, will automatically queue the current task | ||
| 70 | /// for wakeup and return if the writer cannot take more data, rather than blocking | ||
| 71 | /// the calling thread. | ||
| 72 | pub trait AsyncWrite { | ||
| 73 | /// Attempt to write bytes from `buf` into the object. | ||
| 74 | /// | ||
| 75 | /// On success, returns `Poll::Ready(Ok(num_bytes_written))`. | ||
| 76 | /// | ||
| 77 | /// If the object is not ready for writing, the method returns | ||
| 78 | /// `Poll::Pending` and arranges for the current task (via | ||
| 79 | /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes | ||
| 80 | /// writable or is closed. | ||
| 81 | /// | ||
| 82 | /// # Implementation | ||
| 83 | /// | ||
| 84 | /// This function may not return errors of kind `WouldBlock` or | ||
| 85 | /// `Interrupted`. Implementations must convert `WouldBlock` into | ||
| 86 | /// `Poll::Pending` and either internally retry or convert | ||
| 87 | /// `Interrupted` into another error kind. | ||
| 88 | /// | ||
| 89 | /// `poll_write` must try to make progress by flushing the underlying object if | ||
| 90 | /// that is the only way the underlying object can become writable again. | ||
| 91 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>>; | ||
| 92 | |||
| 93 | /// Attempt to flush the object, ensuring that any buffered data reach their destination. | ||
| 94 | /// | ||
| 95 | /// On success, returns Poll::Ready(Ok(())). | ||
| 96 | /// | ||
| 97 | /// If flushing cannot immediately complete, this method returns [Poll::Pending] and arranges for the | ||
| 98 | /// current task (via cx.waker()) to receive a notification when the object can make progress | ||
| 99 | /// towards flushing. | ||
| 100 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>; | ||
| 101 | } | ||
| 102 | |||
| 103 | macro_rules! defer_async_read { | ||
| 104 | () => { | ||
| 105 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { | ||
| 106 | Pin::new(&mut **self.get_mut()).poll_fill_buf(cx) | ||
| 107 | } | ||
| 108 | |||
| 109 | fn consume(mut self: Pin<&mut Self>, amt: usize) { | ||
| 110 | Pin::new(&mut **self).consume(amt) | ||
| 111 | } | ||
| 112 | }; | ||
| 113 | } | ||
| 114 | |||
| 115 | #[cfg(feature = "alloc")] | ||
| 116 | impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for Box<T> { | ||
| 117 | defer_async_read!(); | ||
| 118 | } | ||
| 119 | |||
| 120 | impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for &mut T { | ||
| 121 | defer_async_read!(); | ||
| 122 | } | ||
| 123 | |||
| 124 | impl<P> AsyncBufRead for Pin<P> | ||
| 125 | where | ||
| 126 | P: DerefMut + Unpin, | ||
| 127 | P::Target: AsyncBufRead, | ||
| 128 | { | ||
| 129 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { | ||
| 130 | self.get_mut().as_mut().poll_fill_buf(cx) | ||
| 131 | } | ||
| 132 | |||
| 133 | fn consume(self: Pin<&mut Self>, amt: usize) { | ||
| 134 | self.get_mut().as_mut().consume(amt) | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | macro_rules! deref_async_write { | ||
| 139 | () => { | ||
| 140 | fn poll_write( | ||
| 141 | mut self: Pin<&mut Self>, | ||
| 142 | cx: &mut Context<'_>, | ||
| 143 | buf: &[u8], | ||
| 144 | ) -> Poll<Result<usize>> { | ||
| 145 | Pin::new(&mut **self).poll_write(cx, buf) | ||
| 146 | } | ||
| 147 | |||
| 148 | fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { | ||
| 149 | Pin::new(&mut **self).poll_flush(cx) | ||
| 150 | } | ||
| 151 | }; | ||
| 152 | } | ||
| 153 | |||
| 154 | #[cfg(feature = "alloc")] | ||
| 155 | impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for Box<T> { | ||
| 156 | deref_async_write!(); | ||
| 157 | } | ||
| 158 | |||
| 159 | impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for &mut T { | ||
| 160 | deref_async_write!(); | ||
| 161 | } | ||
| 162 | |||
| 163 | impl<P> AsyncWrite for Pin<P> | ||
| 164 | where | ||
| 165 | P: DerefMut + Unpin, | ||
| 166 | P::Target: AsyncWrite, | ||
| 167 | { | ||
| 168 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { | ||
| 169 | self.get_mut().as_mut().poll_write(cx, buf) | ||
| 170 | } | ||
| 171 | |||
| 172 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { | ||
| 173 | self.get_mut().as_mut().poll_flush(cx) | ||
| 174 | } | ||
| 175 | } | ||
diff --git a/embassy/src/io/util/copy_buf.rs b/embassy/src/io/util/copy_buf.rs deleted file mode 100644 index 6d7932a0f..000000000 --- a/embassy/src/io/util/copy_buf.rs +++ /dev/null | |||
| @@ -1,80 +0,0 @@ | |||
| 1 | use core::future::Future; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use core::task::{Context, Poll}; | ||
| 4 | use futures::ready; | ||
| 5 | use pin_project::pin_project; | ||
| 6 | |||
| 7 | use crate::io::{AsyncBufRead, AsyncWrite, Error, Result}; | ||
| 8 | |||
| 9 | /// Creates a future which copies all the bytes from one object to another. | ||
| 10 | /// | ||
| 11 | /// The returned future will copy all the bytes read from this `AsyncBufRead` into the | ||
| 12 | /// `writer` specified. This future will only complete once the `reader` has hit | ||
| 13 | /// EOF and all bytes have been written to and flushed from the `writer` | ||
| 14 | /// provided. | ||
| 15 | /// | ||
| 16 | /// On success the number of bytes is returned. | ||
| 17 | /// | ||
| 18 | /// # Examples | ||
| 19 | /// | ||
| 20 | /// ``` ignore | ||
| 21 | /// # futures::executor::block_on(async { | ||
| 22 | /// use futures::io::{self, AsyncWriteExt, Cursor}; | ||
| 23 | /// | ||
| 24 | /// let reader = Cursor::new([1, 2, 3, 4]); | ||
| 25 | /// let mut writer = Cursor::new(vec![0u8; 5]); | ||
| 26 | /// | ||
| 27 | /// let bytes = io::copy_buf(reader, &mut writer).await?; | ||
| 28 | /// writer.close().await?; | ||
| 29 | /// | ||
| 30 | /// assert_eq!(bytes, 4); | ||
| 31 | /// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); | ||
| 32 | /// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap(); | ||
| 33 | /// ``` | ||
| 34 | pub fn copy_buf<R, W>(reader: R, writer: &mut W) -> CopyBuf<'_, R, W> | ||
| 35 | where | ||
| 36 | R: AsyncBufRead, | ||
| 37 | W: AsyncWrite + Unpin + ?Sized, | ||
| 38 | { | ||
| 39 | CopyBuf { | ||
| 40 | reader, | ||
| 41 | writer, | ||
| 42 | amt: 0, | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | /// Future for the [`copy_buf()`] function. | ||
| 47 | #[pin_project] | ||
| 48 | #[derive(Debug)] | ||
| 49 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 50 | pub struct CopyBuf<'a, R, W: ?Sized> { | ||
| 51 | #[pin] | ||
| 52 | reader: R, | ||
| 53 | writer: &'a mut W, | ||
| 54 | amt: usize, | ||
| 55 | } | ||
| 56 | |||
| 57 | impl<R, W> Future for CopyBuf<'_, R, W> | ||
| 58 | where | ||
| 59 | R: AsyncBufRead, | ||
| 60 | W: AsyncWrite + Unpin + ?Sized, | ||
| 61 | { | ||
| 62 | type Output = Result<usize>; | ||
| 63 | |||
| 64 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 65 | let mut this = self.project(); | ||
| 66 | loop { | ||
| 67 | let buffer = ready!(this.reader.as_mut().poll_fill_buf(cx))?; | ||
| 68 | if buffer.is_empty() { | ||
| 69 | return Poll::Ready(Ok(*this.amt)); | ||
| 70 | } | ||
| 71 | |||
| 72 | let i = ready!(Pin::new(&mut this.writer).poll_write(cx, buffer))?; | ||
| 73 | if i == 0 { | ||
| 74 | return Poll::Ready(Err(Error::WriteZero)); | ||
| 75 | } | ||
| 76 | *this.amt += i; | ||
| 77 | this.reader.as_mut().consume(i); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
diff --git a/embassy/src/io/util/drain.rs b/embassy/src/io/util/drain.rs deleted file mode 100644 index 2542876d8..000000000 --- a/embassy/src/io/util/drain.rs +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | use core::pin::Pin; | ||
| 2 | use futures::future::Future; | ||
| 3 | use futures::task::{Context, Poll}; | ||
| 4 | |||
| 5 | use super::super::error::Result; | ||
| 6 | use super::super::traits::AsyncBufRead; | ||
| 7 | |||
| 8 | pub struct Drain<'a, R: ?Sized> { | ||
| 9 | reader: &'a mut R, | ||
| 10 | } | ||
| 11 | |||
| 12 | impl<R: ?Sized + Unpin> Unpin for Drain<'_, R> {} | ||
| 13 | |||
| 14 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> Drain<'a, R> { | ||
| 15 | pub(super) fn new(reader: &'a mut R) -> Self { | ||
| 16 | Self { reader } | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for Drain<'a, R> { | ||
| 21 | type Output = Result<usize>; | ||
| 22 | |||
| 23 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 24 | let Self { reader } = &mut *self; | ||
| 25 | let mut reader = Pin::new(reader); | ||
| 26 | |||
| 27 | let mut n = 0; | ||
| 28 | |||
| 29 | loop { | ||
| 30 | match reader.as_mut().poll_fill_buf(cx) { | ||
| 31 | Poll::Pending => return Poll::Ready(Ok(n)), | ||
| 32 | Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), | ||
| 33 | Poll::Ready(Ok(buf)) => { | ||
| 34 | let len = buf.len(); | ||
| 35 | n += len; | ||
| 36 | reader.as_mut().consume(len); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | } | ||
diff --git a/embassy/src/io/util/flush.rs b/embassy/src/io/util/flush.rs deleted file mode 100644 index 966ef10fb..000000000 --- a/embassy/src/io/util/flush.rs +++ /dev/null | |||
| @@ -1,32 +0,0 @@ | |||
| 1 | use core::pin::Pin; | ||
| 2 | use futures::future::Future; | ||
| 3 | use futures::ready; | ||
| 4 | use futures::task::{Context, Poll}; | ||
| 5 | |||
| 6 | use super::super::error::Result; | ||
| 7 | use super::super::traits::AsyncWrite; | ||
| 8 | |||
| 9 | /// Future for the [`flush`](super::AsyncWriteExt::flush) method. | ||
| 10 | #[derive(Debug)] | ||
| 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 12 | pub struct Flush<'a, W: ?Sized> { | ||
| 13 | writer: &'a mut W, | ||
| 14 | } | ||
| 15 | |||
| 16 | impl<W: ?Sized + Unpin> Unpin for Flush<'_, W> {} | ||
| 17 | |||
| 18 | impl<'a, W: AsyncWrite + ?Sized + Unpin> Flush<'a, W> { | ||
| 19 | pub(super) fn new(writer: &'a mut W) -> Self { | ||
| 20 | Flush { writer } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | impl<W: AsyncWrite + ?Sized + Unpin> Future for Flush<'_, W> { | ||
| 25 | type Output = Result<()>; | ||
| 26 | |||
| 27 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { | ||
| 28 | let this = &mut *self; | ||
| 29 | let _ = ready!(Pin::new(&mut this.writer).poll_flush(cx))?; | ||
| 30 | Poll::Ready(Ok(())) | ||
| 31 | } | ||
| 32 | } | ||
diff --git a/embassy/src/io/util/mod.rs b/embassy/src/io/util/mod.rs deleted file mode 100644 index 49758ba99..000000000 --- a/embassy/src/io/util/mod.rs +++ /dev/null | |||
| @@ -1,177 +0,0 @@ | |||
| 1 | use core::cmp::min; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use core::task::{Context, Poll}; | ||
| 4 | use futures::ready; | ||
| 5 | |||
| 6 | mod read; | ||
| 7 | pub use self::read::Read; | ||
| 8 | |||
| 9 | mod read_buf; | ||
| 10 | pub use self::read_buf::ReadBuf; | ||
| 11 | |||
| 12 | mod read_byte; | ||
| 13 | pub use self::read_byte::ReadByte; | ||
| 14 | |||
| 15 | mod read_exact; | ||
| 16 | pub use self::read_exact::ReadExact; | ||
| 17 | |||
| 18 | mod read_while; | ||
| 19 | pub use self::read_while::ReadWhile; | ||
| 20 | |||
| 21 | mod read_to_end; | ||
| 22 | pub use self::read_to_end::ReadToEnd; | ||
| 23 | |||
| 24 | mod skip_while; | ||
| 25 | pub use self::skip_while::SkipWhile; | ||
| 26 | |||
| 27 | mod drain; | ||
| 28 | pub use self::drain::Drain; | ||
| 29 | |||
| 30 | mod flush; | ||
| 31 | pub use self::flush::Flush; | ||
| 32 | |||
| 33 | mod write; | ||
| 34 | pub use self::write::Write; | ||
| 35 | |||
| 36 | mod write_all; | ||
| 37 | pub use self::write_all::WriteAll; | ||
| 38 | |||
| 39 | mod write_byte; | ||
| 40 | pub use self::write_byte::WriteByte; | ||
| 41 | |||
| 42 | #[cfg(feature = "alloc")] | ||
| 43 | mod split; | ||
| 44 | #[cfg(feature = "alloc")] | ||
| 45 | pub use self::split::{split, ReadHalf, WriteHalf}; | ||
| 46 | |||
| 47 | mod copy_buf; | ||
| 48 | pub use self::copy_buf::{copy_buf, CopyBuf}; | ||
| 49 | |||
| 50 | use super::error::Result; | ||
| 51 | use super::traits::{AsyncBufRead, AsyncWrite}; | ||
| 52 | |||
| 53 | pub trait AsyncBufReadExt: AsyncBufRead { | ||
| 54 | fn poll_read( | ||
| 55 | mut self: Pin<&mut Self>, | ||
| 56 | cx: &mut Context<'_>, | ||
| 57 | buf: &mut [u8], | ||
| 58 | ) -> Poll<Result<usize>> | ||
| 59 | where | ||
| 60 | Self: Unpin, | ||
| 61 | { | ||
| 62 | let mut this = &mut *self; | ||
| 63 | let rbuf = ready!(Pin::new(&mut this).poll_fill_buf(cx))?; | ||
| 64 | let n = min(buf.len(), rbuf.len()); | ||
| 65 | buf[..n].copy_from_slice(&rbuf[..n]); | ||
| 66 | Pin::new(&mut this).consume(n); | ||
| 67 | Poll::Ready(Ok(n)) | ||
| 68 | } | ||
| 69 | |||
| 70 | fn read_while<'a, F: Fn(u8) -> bool>( | ||
| 71 | &'a mut self, | ||
| 72 | buf: &'a mut [u8], | ||
| 73 | f: F, | ||
| 74 | ) -> ReadWhile<'a, Self, F> | ||
| 75 | where | ||
| 76 | Self: Unpin, | ||
| 77 | { | ||
| 78 | ReadWhile::new(self, f, buf) | ||
| 79 | } | ||
| 80 | |||
| 81 | fn skip_while<F: Fn(u8) -> bool>(&mut self, f: F) -> SkipWhile<Self, F> | ||
| 82 | where | ||
| 83 | Self: Unpin, | ||
| 84 | { | ||
| 85 | SkipWhile::new(self, f) | ||
| 86 | } | ||
| 87 | |||
| 88 | fn drain(&mut self) -> Drain<Self> | ||
| 89 | where | ||
| 90 | Self: Unpin, | ||
| 91 | { | ||
| 92 | Drain::new(self) | ||
| 93 | } | ||
| 94 | |||
| 95 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self> | ||
| 96 | where | ||
| 97 | Self: Unpin, | ||
| 98 | { | ||
| 99 | Read::new(self, buf) | ||
| 100 | } | ||
| 101 | |||
| 102 | fn read_buf(&mut self) -> ReadBuf<Self> | ||
| 103 | where | ||
| 104 | Self: Unpin, | ||
| 105 | { | ||
| 106 | ReadBuf::new(self) | ||
| 107 | } | ||
| 108 | |||
| 109 | fn read_byte(&mut self) -> ReadByte<Self> | ||
| 110 | where | ||
| 111 | Self: Unpin, | ||
| 112 | { | ||
| 113 | ReadByte::new(self) | ||
| 114 | } | ||
| 115 | |||
| 116 | fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self> | ||
| 117 | where | ||
| 118 | Self: Unpin, | ||
| 119 | { | ||
| 120 | ReadExact::new(self, buf) | ||
| 121 | } | ||
| 122 | |||
| 123 | fn read_to_end<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadToEnd<'a, Self> | ||
| 124 | where | ||
| 125 | Self: Unpin, | ||
| 126 | { | ||
| 127 | ReadToEnd::new(self, buf) | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {} | ||
| 132 | |||
| 133 | pub async fn read_line<R: AsyncBufRead + Unpin + ?Sized>( | ||
| 134 | r: &mut R, | ||
| 135 | buf: &mut [u8], | ||
| 136 | ) -> Result<usize> { | ||
| 137 | r.skip_while(|b| b == b'\r' || b == b'\n').await?; | ||
| 138 | let n = r.read_while(buf, |b| b != b'\r' && b != b'\n').await?; | ||
| 139 | r.skip_while(|b| b == b'\r').await?; | ||
| 140 | //assert_eq!(b'\n', r.read_byte().await?); | ||
| 141 | r.read_byte().await?; | ||
| 142 | Ok(n) | ||
| 143 | } | ||
| 144 | |||
| 145 | pub trait AsyncWriteExt: AsyncWrite { | ||
| 146 | fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAll<'a, Self> | ||
| 147 | where | ||
| 148 | Self: Unpin, | ||
| 149 | { | ||
| 150 | WriteAll::new(self, buf) | ||
| 151 | } | ||
| 152 | |||
| 153 | fn write_byte(&mut self, byte: u8) -> WriteByte<Self> | ||
| 154 | where | ||
| 155 | Self: Unpin, | ||
| 156 | { | ||
| 157 | WriteByte::new(self, byte) | ||
| 158 | } | ||
| 159 | |||
| 160 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Write<'a, Self> | ||
| 161 | where | ||
| 162 | Self: Unpin, | ||
| 163 | { | ||
| 164 | Write::new(self, buf) | ||
| 165 | } | ||
| 166 | |||
| 167 | /// Awaits until all bytes have actually been written, and | ||
| 168 | /// not just enqueued as per the other "write" methods. | ||
| 169 | fn flush<'a>(&mut self) -> Flush<Self> | ||
| 170 | where | ||
| 171 | Self: Unpin, | ||
| 172 | { | ||
| 173 | Flush::new(self) | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | 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 274b43a43..000000000 --- a/embassy/src/io/util/read.rs +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | use super::super::error::Result; | ||
| 2 | use super::super::traits::AsyncBufRead; | ||
| 3 | |||
| 4 | use core::cmp::min; | ||
| 5 | |||
| 6 | use core::pin::Pin; | ||
| 7 | use futures::future::Future; | ||
| 8 | use futures::ready; | ||
| 9 | use futures::task::{Context, Poll}; | ||
| 10 | |||
| 11 | /// Future for the [`read_exact`](super::AsyncBufReadExt::read_exact) method. | ||
| 12 | #[derive(Debug)] | ||
| 13 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 14 | pub struct Read<'a, R: ?Sized> { | ||
| 15 | reader: &'a mut R, | ||
| 16 | buf: &'a mut [u8], | ||
| 17 | } | ||
| 18 | |||
| 19 | impl<R: ?Sized + Unpin> Unpin for Read<'_, R> {} | ||
| 20 | |||
| 21 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> Read<'a, R> { | ||
| 22 | pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { | ||
| 23 | Read { reader, buf } | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | impl<R: AsyncBufRead + ?Sized + Unpin> Future for Read<'_, R> { | ||
| 28 | type Output = Result<usize>; | ||
| 29 | |||
| 30 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 31 | let this = &mut *self; | ||
| 32 | let buf = ready!(Pin::new(&mut this.reader).poll_fill_buf(cx))?; | ||
| 33 | |||
| 34 | let n = min(this.buf.len(), buf.len()); | ||
| 35 | this.buf[..n].copy_from_slice(&buf[..n]); | ||
| 36 | Pin::new(&mut this.reader).consume(n); | ||
| 37 | Poll::Ready(Ok(n)) | ||
| 38 | } | ||
| 39 | } | ||
diff --git a/embassy/src/io/util/read_buf.rs b/embassy/src/io/util/read_buf.rs deleted file mode 100644 index 71299b05e..000000000 --- a/embassy/src/io/util/read_buf.rs +++ /dev/null | |||
| @@ -1,34 +0,0 @@ | |||
| 1 | use super::super::error::Result; | ||
| 2 | use super::super::traits::AsyncBufRead; | ||
| 3 | |||
| 4 | use core::pin::Pin; | ||
| 5 | use futures::future::Future; | ||
| 6 | use futures::ready; | ||
| 7 | use futures::task::{Context, Poll}; | ||
| 8 | |||
| 9 | pub struct ReadBuf<'a, R: ?Sized> { | ||
| 10 | reader: Option<&'a mut R>, | ||
| 11 | } | ||
| 12 | |||
| 13 | impl<R: ?Sized + Unpin> Unpin for ReadBuf<'_, R> {} | ||
| 14 | |||
| 15 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadBuf<'a, R> { | ||
| 16 | pub(super) fn new(reader: &'a mut R) -> Self { | ||
| 17 | ReadBuf { | ||
| 18 | reader: Some(reader), | ||
| 19 | } | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for ReadBuf<'a, R> { | ||
| 24 | type Output = Result<&'a [u8]>; | ||
| 25 | |||
| 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 27 | let this = &mut *self; | ||
| 28 | |||
| 29 | let buf = ready!(Pin::new(this.reader.as_mut().unwrap()).poll_fill_buf(cx))?; | ||
| 30 | let buf: &'a [u8] = unsafe { core::mem::transmute(buf) }; | ||
| 31 | this.reader = None; | ||
| 32 | Poll::Ready(Ok(buf)) | ||
| 33 | } | ||
| 34 | } | ||
diff --git a/embassy/src/io/util/read_byte.rs b/embassy/src/io/util/read_byte.rs deleted file mode 100644 index e5bbcb1ff..000000000 --- a/embassy/src/io/util/read_byte.rs +++ /dev/null | |||
| @@ -1,36 +0,0 @@ | |||
| 1 | use core::pin::Pin; | ||
| 2 | use futures::future::Future; | ||
| 3 | use futures::ready; | ||
| 4 | use futures::task::{Context, Poll}; | ||
| 5 | |||
| 6 | use super::super::error::{Error, Result}; | ||
| 7 | use super::super::traits::AsyncBufRead; | ||
| 8 | |||
| 9 | pub struct ReadByte<'a, R: ?Sized> { | ||
| 10 | reader: &'a mut R, | ||
| 11 | } | ||
| 12 | |||
| 13 | impl<R: ?Sized + Unpin> Unpin for ReadByte<'_, R> {} | ||
| 14 | |||
| 15 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadByte<'a, R> { | ||
| 16 | pub(super) fn new(reader: &'a mut R) -> Self { | ||
| 17 | Self { reader } | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for ReadByte<'a, R> { | ||
| 22 | type Output = Result<u8>; | ||
| 23 | |||
| 24 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 25 | let Self { reader } = &mut *self; | ||
| 26 | let mut reader = Pin::new(reader); | ||
| 27 | let rbuf = ready!(reader.as_mut().poll_fill_buf(cx))?; | ||
| 28 | if rbuf.is_empty() { | ||
| 29 | return Poll::Ready(Err(Error::UnexpectedEof)); | ||
| 30 | } | ||
| 31 | |||
| 32 | let r = rbuf[0]; | ||
| 33 | reader.as_mut().consume(1); | ||
| 34 | Poll::Ready(Ok(r)) | ||
| 35 | } | ||
| 36 | } | ||
diff --git a/embassy/src/io/util/read_exact.rs b/embassy/src/io/util/read_exact.rs deleted file mode 100644 index 4eecba4cc..000000000 --- a/embassy/src/io/util/read_exact.rs +++ /dev/null | |||
| @@ -1,48 +0,0 @@ | |||
| 1 | use super::super::error::{Error, Result}; | ||
| 2 | use super::super::traits::AsyncBufRead; | ||
| 3 | |||
| 4 | use core::cmp::min; | ||
| 5 | use core::mem; | ||
| 6 | use core::pin::Pin; | ||
| 7 | use futures::future::Future; | ||
| 8 | use futures::ready; | ||
| 9 | use futures::task::{Context, Poll}; | ||
| 10 | |||
| 11 | /// Future for the [`read_exact`](super::AsyncBufReadExt::read_exact) method. | ||
| 12 | #[derive(Debug)] | ||
| 13 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 14 | pub struct ReadExact<'a, R: ?Sized> { | ||
| 15 | reader: &'a mut R, | ||
| 16 | buf: &'a mut [u8], | ||
| 17 | } | ||
| 18 | |||
| 19 | impl<R: ?Sized + Unpin> Unpin for ReadExact<'_, R> {} | ||
| 20 | |||
| 21 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadExact<'a, R> { | ||
| 22 | pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { | ||
| 23 | ReadExact { reader, buf } | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | impl<R: AsyncBufRead + ?Sized + Unpin> Future for ReadExact<'_, R> { | ||
| 28 | type Output = Result<()>; | ||
| 29 | |||
| 30 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 31 | let this = &mut *self; | ||
| 32 | while !this.buf.is_empty() { | ||
| 33 | let buf = ready!(Pin::new(&mut this.reader).poll_fill_buf(cx))?; | ||
| 34 | if buf.is_empty() { | ||
| 35 | return Poll::Ready(Err(Error::UnexpectedEof)); | ||
| 36 | } | ||
| 37 | |||
| 38 | let n = min(this.buf.len(), buf.len()); | ||
| 39 | this.buf[..n].copy_from_slice(&buf[..n]); | ||
| 40 | Pin::new(&mut this.reader).consume(n); | ||
| 41 | { | ||
| 42 | let (_, rest) = mem::take(&mut this.buf).split_at_mut(n); | ||
| 43 | this.buf = rest; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | Poll::Ready(Ok(())) | ||
| 47 | } | ||
| 48 | } | ||
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 d09999ad0..000000000 --- a/embassy/src/io/util/read_to_end.rs +++ /dev/null | |||
| @@ -1,48 +0,0 @@ | |||
| 1 | use core::cmp::min; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use futures::future::Future; | ||
| 4 | use futures::ready; | ||
| 5 | use futures::task::{Context, Poll}; | ||
| 6 | |||
| 7 | use super::super::error::{Error, Result}; | ||
| 8 | use super::super::traits::AsyncBufRead; | ||
| 9 | |||
| 10 | pub struct ReadToEnd<'a, R: ?Sized> { | ||
| 11 | reader: &'a mut R, | ||
| 12 | buf: &'a mut [u8], | ||
| 13 | n: usize, | ||
| 14 | } | ||
| 15 | |||
| 16 | impl<R: ?Sized + Unpin> Unpin for ReadToEnd<'_, R> {} | ||
| 17 | |||
| 18 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadToEnd<'a, R> { | ||
| 19 | pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { | ||
| 20 | Self { reader, buf, n: 0 } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | impl<'a, R: AsyncBufRead + ?Sized + Unpin> Future for ReadToEnd<'a, R> { | ||
| 25 | type Output = Result<usize>; | ||
| 26 | |||
| 27 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 28 | let Self { reader, buf, n } = &mut *self; | ||
| 29 | let mut reader = Pin::new(reader); | ||
| 30 | loop { | ||
| 31 | let rbuf = ready!(reader.as_mut().poll_fill_buf(cx))?; | ||
| 32 | if rbuf.is_empty() { | ||
| 33 | return Poll::Ready(Ok(*n)); | ||
| 34 | } | ||
| 35 | |||
| 36 | if *n == buf.len() { | ||
| 37 | return Poll::Ready(Err(Error::Truncated)); | ||
| 38 | } | ||
| 39 | |||
| 40 | // truncate data if it doesn't fit in buf | ||
| 41 | let p = min(rbuf.len(), buf.len() - *n); | ||
| 42 | buf[*n..*n + p].copy_from_slice(&rbuf[..p]); | ||
| 43 | *n += p; | ||
| 44 | |||
| 45 | reader.as_mut().consume(p); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
diff --git a/embassy/src/io/util/read_while.rs b/embassy/src/io/util/read_while.rs deleted file mode 100644 index e24638039..000000000 --- a/embassy/src/io/util/read_while.rs +++ /dev/null | |||
| @@ -1,61 +0,0 @@ | |||
| 1 | use core::cmp::min; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use futures::future::Future; | ||
| 4 | use futures::ready; | ||
| 5 | use futures::task::{Context, Poll}; | ||
| 6 | |||
| 7 | use super::super::error::{Error, Result}; | ||
| 8 | use super::super::traits::AsyncBufRead; | ||
| 9 | |||
| 10 | pub struct ReadWhile<'a, R: ?Sized, F> { | ||
| 11 | reader: &'a mut R, | ||
| 12 | buf: &'a mut [u8], | ||
| 13 | n: usize, | ||
| 14 | f: F, | ||
| 15 | } | ||
| 16 | |||
| 17 | impl<R: ?Sized + Unpin, F> Unpin for ReadWhile<'_, R, F> {} | ||
| 18 | |||
| 19 | impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> ReadWhile<'a, R, F> { | ||
| 20 | pub(super) fn new(reader: &'a mut R, f: F, buf: &'a mut [u8]) -> Self { | ||
| 21 | Self { | ||
| 22 | reader, | ||
| 23 | f, | ||
| 24 | buf, | ||
| 25 | n: 0, | ||
| 26 | } | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> Future for ReadWhile<'a, R, F> { | ||
| 31 | type Output = Result<usize>; | ||
| 32 | |||
| 33 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 34 | let Self { reader, f, buf, n } = &mut *self; | ||
| 35 | let mut reader = Pin::new(reader); | ||
| 36 | loop { | ||
| 37 | let rbuf = ready!(reader.as_mut().poll_fill_buf(cx))?; | ||
| 38 | if rbuf.is_empty() { | ||
| 39 | return Poll::Ready(Err(Error::UnexpectedEof)); | ||
| 40 | } | ||
| 41 | |||
| 42 | let (p, done) = match rbuf.iter().position(|&b| !f(b)) { | ||
| 43 | Some(p) => (p, true), | ||
| 44 | None => (rbuf.len(), false), | ||
| 45 | }; | ||
| 46 | |||
| 47 | // truncate data if it doesn't fit in buf | ||
| 48 | let p2 = min(p, buf.len() - *n); | ||
| 49 | buf[*n..*n + p2].copy_from_slice(&rbuf[..p2]); | ||
| 50 | *n += p2; | ||
| 51 | |||
| 52 | // consume it all, even if it doesn't fit. | ||
| 53 | // Otherwise we can deadlock because we never read to the ending char | ||
| 54 | reader.as_mut().consume(p); | ||
| 55 | |||
| 56 | if done { | ||
| 57 | return Poll::Ready(Ok(*n)); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | } | ||
| 61 | } | ||
diff --git a/embassy/src/io/util/skip_while.rs b/embassy/src/io/util/skip_while.rs deleted file mode 100644 index 6f0e167df..000000000 --- a/embassy/src/io/util/skip_while.rs +++ /dev/null | |||
| @@ -1,45 +0,0 @@ | |||
| 1 | use core::iter::Iterator; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use futures::future::Future; | ||
| 4 | use futures::ready; | ||
| 5 | use futures::task::{Context, Poll}; | ||
| 6 | |||
| 7 | use super::super::error::{Error, Result}; | ||
| 8 | use super::super::traits::AsyncBufRead; | ||
| 9 | |||
| 10 | pub struct SkipWhile<'a, R: ?Sized, F> { | ||
| 11 | reader: &'a mut R, | ||
| 12 | f: F, | ||
| 13 | } | ||
| 14 | |||
| 15 | impl<R: ?Sized + Unpin, F> Unpin for SkipWhile<'_, R, F> {} | ||
| 16 | |||
| 17 | impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> SkipWhile<'a, R, F> { | ||
| 18 | pub(super) fn new(reader: &'a mut R, f: F) -> Self { | ||
| 19 | Self { reader, f } | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | impl<'a, R: AsyncBufRead + ?Sized + Unpin, F: Fn(u8) -> bool> Future for SkipWhile<'a, R, F> { | ||
| 24 | type Output = Result<()>; | ||
| 25 | |||
| 26 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 27 | let Self { reader, f } = &mut *self; | ||
| 28 | let mut reader = Pin::new(reader); | ||
| 29 | loop { | ||
| 30 | let buf = ready!(reader.as_mut().poll_fill_buf(cx))?; | ||
| 31 | if buf.is_empty() { | ||
| 32 | return Poll::Ready(Err(Error::UnexpectedEof)); | ||
| 33 | } | ||
| 34 | |||
| 35 | let (p, done) = match buf.iter().position(|b| !f(*b)) { | ||
| 36 | Some(p) => (p, true), | ||
| 37 | None => (buf.len(), false), | ||
| 38 | }; | ||
| 39 | reader.as_mut().consume(p); | ||
| 40 | if done { | ||
| 41 | return Poll::Ready(Ok(())); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
diff --git a/embassy/src/io/util/split.rs b/embassy/src/io/util/split.rs deleted file mode 100644 index cc029aa53..000000000 --- a/embassy/src/io/util/split.rs +++ /dev/null | |||
| @@ -1,43 +0,0 @@ | |||
| 1 | use alloc::rc::Rc; | ||
| 2 | use core::cell::UnsafeCell; | ||
| 3 | use core::pin::Pin; | ||
| 4 | use futures::task::{Context, Poll}; | ||
| 5 | |||
| 6 | use super::super::error::Result; | ||
| 7 | use super::super::traits::{AsyncBufRead, AsyncWrite}; | ||
| 8 | |||
| 9 | /// The readable half of an object returned from `AsyncBufRead::split`. | ||
| 10 | #[derive(Debug)] | ||
| 11 | pub struct ReadHalf<T> { | ||
| 12 | handle: Rc<UnsafeCell<T>>, | ||
| 13 | } | ||
| 14 | |||
| 15 | /// The writable half of an object returned from `AsyncBufRead::split`. | ||
| 16 | #[derive(Debug)] | ||
| 17 | pub struct WriteHalf<T> { | ||
| 18 | handle: Rc<UnsafeCell<T>>, | ||
| 19 | } | ||
| 20 | |||
| 21 | impl<T: AsyncBufRead + Unpin> AsyncBufRead for ReadHalf<T> { | ||
| 22 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { | ||
| 23 | Pin::new(unsafe { &mut *self.handle.get() }).poll_fill_buf(cx) | ||
| 24 | } | ||
| 25 | |||
| 26 | fn consume(self: Pin<&mut Self>, amt: usize) { | ||
| 27 | Pin::new(unsafe { &mut *self.handle.get() }).consume(amt) | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | impl<T: AsyncWrite + Unpin> AsyncWrite for WriteHalf<T> { | ||
| 32 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { | ||
| 33 | Pin::new(unsafe { &mut *self.handle.get() }).poll_write(cx, buf) | ||
| 34 | } | ||
| 35 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { | ||
| 36 | Pin::new(unsafe { &mut *self.handle.get() }).poll_flush(cx) | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | pub fn split<T: AsyncBufRead + AsyncWrite>(t: T) -> (ReadHalf<T>, WriteHalf<T>) { | ||
| 41 | let c = Rc::new(UnsafeCell::new(t)); | ||
| 42 | (ReadHalf { handle: c.clone() }, WriteHalf { handle: c }) | ||
| 43 | } | ||
diff --git a/embassy/src/io/util/write.rs b/embassy/src/io/util/write.rs deleted file mode 100644 index 403cd59fe..000000000 --- a/embassy/src/io/util/write.rs +++ /dev/null | |||
| @@ -1,33 +0,0 @@ | |||
| 1 | use core::pin::Pin; | ||
| 2 | use futures::future::Future; | ||
| 3 | use futures::ready; | ||
| 4 | use futures::task::{Context, Poll}; | ||
| 5 | |||
| 6 | use super::super::error::Result; | ||
| 7 | use super::super::traits::AsyncWrite; | ||
| 8 | |||
| 9 | /// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. | ||
| 10 | #[derive(Debug)] | ||
| 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 12 | pub struct Write<'a, W: ?Sized> { | ||
| 13 | writer: &'a mut W, | ||
| 14 | buf: &'a [u8], | ||
| 15 | } | ||
| 16 | |||
| 17 | impl<W: ?Sized + Unpin> Unpin for Write<'_, W> {} | ||
| 18 | |||
| 19 | impl<'a, W: AsyncWrite + ?Sized + Unpin> Write<'a, W> { | ||
| 20 | pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { | ||
| 21 | Write { writer, buf } | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | impl<W: AsyncWrite + ?Sized + Unpin> Future for Write<'_, W> { | ||
| 26 | type Output = Result<usize>; | ||
| 27 | |||
| 28 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<usize>> { | ||
| 29 | let this = &mut *self; | ||
| 30 | let n = ready!(Pin::new(&mut this.writer).poll_write(cx, this.buf))?; | ||
| 31 | Poll::Ready(Ok(n)) | ||
| 32 | } | ||
| 33 | } | ||
diff --git a/embassy/src/io/util/write_all.rs b/embassy/src/io/util/write_all.rs deleted file mode 100644 index 8a7d9984c..000000000 --- a/embassy/src/io/util/write_all.rs +++ /dev/null | |||
| @@ -1,44 +0,0 @@ | |||
| 1 | use core::mem; | ||
| 2 | use core::pin::Pin; | ||
| 3 | use futures::future::Future; | ||
| 4 | use futures::ready; | ||
| 5 | use futures::task::{Context, Poll}; | ||
| 6 | |||
| 7 | use super::super::error::Result; | ||
| 8 | use super::super::traits::AsyncWrite; | ||
| 9 | |||
| 10 | /// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. | ||
| 11 | #[derive(Debug)] | ||
| 12 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 13 | pub struct WriteAll<'a, W: ?Sized> { | ||
| 14 | writer: &'a mut W, | ||
| 15 | buf: &'a [u8], | ||
| 16 | } | ||
| 17 | |||
| 18 | impl<W: ?Sized + Unpin> Unpin for WriteAll<'_, W> {} | ||
| 19 | |||
| 20 | impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAll<'a, W> { | ||
| 21 | pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { | ||
| 22 | WriteAll { writer, buf } | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteAll<'_, W> { | ||
| 27 | type Output = Result<()>; | ||
| 28 | |||
| 29 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { | ||
| 30 | let this = &mut *self; | ||
| 31 | while !this.buf.is_empty() { | ||
| 32 | let n = ready!(Pin::new(&mut this.writer).poll_write(cx, this.buf))?; | ||
| 33 | { | ||
| 34 | let (_, rest) = mem::take(&mut this.buf).split_at(n); | ||
| 35 | this.buf = rest; | ||
| 36 | } | ||
| 37 | if n == 0 { | ||
| 38 | panic!(); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | Poll::Ready(Ok(())) | ||
| 43 | } | ||
| 44 | } | ||
diff --git a/embassy/src/io/util/write_byte.rs b/embassy/src/io/util/write_byte.rs deleted file mode 100644 index 659e427b1..000000000 --- a/embassy/src/io/util/write_byte.rs +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | use core::pin::Pin; | ||
| 2 | use futures::future::Future; | ||
| 3 | use futures::ready; | ||
| 4 | use futures::task::{Context, Poll}; | ||
| 5 | |||
| 6 | use super::super::error::Result; | ||
| 7 | use super::super::traits::AsyncWrite; | ||
| 8 | |||
| 9 | /// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. | ||
| 10 | #[derive(Debug)] | ||
| 11 | #[must_use = "futures do nothing unless you `.await` or poll them"] | ||
| 12 | pub struct WriteByte<'a, W: ?Sized> { | ||
| 13 | writer: &'a mut W, | ||
| 14 | byte: u8, | ||
| 15 | } | ||
| 16 | |||
| 17 | impl<W: ?Sized + Unpin> Unpin for WriteByte<'_, W> {} | ||
| 18 | |||
| 19 | impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteByte<'a, W> { | ||
| 20 | pub(super) fn new(writer: &'a mut W, byte: u8) -> Self { | ||
| 21 | WriteByte { writer, byte } | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteByte<'_, W> { | ||
| 26 | type Output = Result<()>; | ||
| 27 | |||
| 28 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { | ||
| 29 | let this = &mut *self; | ||
| 30 | let buf = [this.byte; 1]; | ||
| 31 | let n = ready!(Pin::new(&mut this.writer).poll_write(cx, &buf))?; | ||
| 32 | if n == 0 { | ||
| 33 | panic!(); | ||
| 34 | } | ||
| 35 | assert!(n == 1); | ||
| 36 | |||
| 37 | Poll::Ready(Ok(())) | ||
| 38 | } | ||
| 39 | } | ||
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index ec697b40a..087bd357a 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs | |||
| @@ -13,7 +13,6 @@ pub mod channel; | |||
| 13 | pub mod executor; | 13 | pub mod executor; |
| 14 | #[cfg(cortex_m)] | 14 | #[cfg(cortex_m)] |
| 15 | pub mod interrupt; | 15 | pub mod interrupt; |
| 16 | pub mod io; | ||
| 17 | pub mod mutex; | 16 | pub mod mutex; |
| 18 | #[cfg(feature = "time")] | 17 | #[cfg(feature = "time")] |
| 19 | pub mod time; | 18 | pub mod time; |
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 4258544f0..ffac0a769 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml | |||
| @@ -6,7 +6,7 @@ version = "0.1.0" | |||
| 6 | 6 | ||
| 7 | [features] | 7 | [features] |
| 8 | default = ["nightly"] | 8 | default = ["nightly"] |
| 9 | nightly = ["embassy-nrf/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm"] | 9 | 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"] |
| 10 | 10 | ||
| 11 | [dependencies] | 11 | [dependencies] |
| 12 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } | 12 | 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 | |||
| 16 | embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true } | 16 | embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true } |
| 17 | embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true } | 17 | embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true } |
| 18 | embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true } | 18 | embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true } |
| 19 | embedded-io = "0.2.0" | ||
| 19 | 20 | ||
| 20 | defmt = "0.3" | 21 | defmt = "0.3" |
| 21 | defmt-rtt = "0.3" | 22 | defmt-rtt = "0.3" |
diff --git a/examples/nrf/src/bin/buffered_uart.rs b/examples/nrf/src/bin/buffered_uart.rs index 2cd163a9f..a64c5821b 100644 --- a/examples/nrf/src/bin/buffered_uart.rs +++ b/examples/nrf/src/bin/buffered_uart.rs | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy::executor::Spawner; | 6 | use embassy::executor::Spawner; |
| 7 | use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; | ||
| 8 | use embassy_nrf::buffered_uarte::State; | 7 | use embassy_nrf::buffered_uarte::State; |
| 9 | use embassy_nrf::{buffered_uarte::BufferedUarte, interrupt, uarte, Peripherals}; | 8 | use embassy_nrf::{buffered_uarte::BufferedUarte, interrupt, uarte, Peripherals}; |
| 9 | use embedded_io::asynch::{Read, Write}; | ||
| 10 | use futures::pin_mut; | 10 | use futures::pin_mut; |
| 11 | 11 | ||
| 12 | use defmt_rtt as _; // global logger | 12 | 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 f14a29c49..843487c03 100644 --- a/examples/nrf/src/bin/usb_ethernet.rs +++ b/examples/nrf/src/bin/usb_ethernet.rs | |||
| @@ -10,9 +10,9 @@ use defmt::*; | |||
| 10 | use embassy::blocking_mutex::raw::ThreadModeRawMutex; | 10 | use embassy::blocking_mutex::raw::ThreadModeRawMutex; |
| 11 | use embassy::channel::Channel; | 11 | use embassy::channel::Channel; |
| 12 | use embassy::executor::Spawner; | 12 | use embassy::executor::Spawner; |
| 13 | use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; | ||
| 14 | use embassy::util::Forever; | 13 | use embassy::util::Forever; |
| 15 | use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, TcpSocket}; | 14 | use embassy_net::tcp::TcpSocket; |
| 15 | use embassy_net::{PacketBox, PacketBoxExt, PacketBuf}; | ||
| 16 | use embassy_nrf::pac; | 16 | use embassy_nrf::pac; |
| 17 | use embassy_nrf::usb::Driver; | 17 | use embassy_nrf::usb::Driver; |
| 18 | use embassy_nrf::Peripherals; | 18 | use embassy_nrf::Peripherals; |
| @@ -20,7 +20,9 @@ use embassy_nrf::{interrupt, peripherals}; | |||
| 20 | use embassy_usb::{Builder, Config, UsbDevice}; | 20 | use embassy_usb::{Builder, Config, UsbDevice}; |
| 21 | use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; | 21 | use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; |
| 22 | 22 | ||
| 23 | use defmt_rtt as _; // global logger | 23 | use defmt_rtt as _; |
| 24 | use embedded_io::asynch::{Read, Write}; | ||
| 25 | // global logger | ||
| 24 | use panic_probe as _; | 26 | use panic_probe as _; |
| 25 | 27 | ||
| 26 | type MyDriver = Driver<'static, peripherals::USBD>; | 28 | type MyDriver = Driver<'static, peripherals::USBD>; |
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 0853c323e..fa2a98a49 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml | |||
| @@ -6,7 +6,8 @@ version = "0.1.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy = { version = "0.1.0", path = "../../embassy", features = ["log", "std", "time", "nightly"] } | 8 | embassy = { version = "0.1.0", path = "../../embassy", features = ["log", "std", "time", "nightly"] } |
| 9 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features=["std", "log", "medium-ethernet", "tcp", "dhcpv4", "pool-16"] } | 9 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features=["nightly", "std", "log", "medium-ethernet", "tcp", "dhcpv4", "pool-16"] } |
| 10 | embedded-io = { version = "0.2.0", features = ["async", "std"] } | ||
| 10 | 11 | ||
| 11 | async-io = "1.6.0" | 12 | async-io = "1.6.0" |
| 12 | env_logger = "0.9.0" | 13 | env_logger = "0.9.0" |
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 3b4bc6fea..daedffb0f 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs | |||
| @@ -2,12 +2,13 @@ | |||
| 2 | 2 | ||
| 3 | use clap::Parser; | 3 | use clap::Parser; |
| 4 | use embassy::executor::{Executor, Spawner}; | 4 | use embassy::executor::{Executor, Spawner}; |
| 5 | use embassy::io::AsyncWriteExt; | ||
| 6 | use embassy::util::Forever; | 5 | use embassy::util::Forever; |
| 6 | use embassy_net::tcp::TcpSocket; | ||
| 7 | use embassy_net::{ | 7 | use embassy_net::{ |
| 8 | Config, Configurator, DhcpConfigurator, Ipv4Address, Ipv4Cidr, StackResources, | 8 | Config, Configurator, DhcpConfigurator, Ipv4Address, Ipv4Cidr, StackResources, |
| 9 | StaticConfigurator, TcpSocket, | 9 | StaticConfigurator, |
| 10 | }; | 10 | }; |
| 11 | use embedded_io::asynch::Write; | ||
| 11 | use heapless::Vec; | 12 | use heapless::Vec; |
| 12 | use log::*; | 13 | use log::*; |
| 13 | 14 | ||
diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs index 129dc2090..b1e5b0142 100644 --- a/examples/std/src/bin/serial.rs +++ b/examples/std/src/bin/serial.rs | |||
| @@ -5,8 +5,8 @@ mod serial_port; | |||
| 5 | 5 | ||
| 6 | use async_io::Async; | 6 | use async_io::Async; |
| 7 | use embassy::executor::Executor; | 7 | use embassy::executor::Executor; |
| 8 | use embassy::io::AsyncBufReadExt; | ||
| 9 | use embassy::util::Forever; | 8 | use embassy::util::Forever; |
| 9 | use embedded_io::asynch::Read; | ||
| 10 | use log::*; | 10 | use log::*; |
| 11 | use nix::sys::termios; | 11 | use nix::sys::termios; |
| 12 | 12 | ||
| @@ -24,12 +24,12 @@ async fn run() { | |||
| 24 | // Essentially, async_io::Async converts from AsRawFd+Read+Write to futures's AsyncRead+AsyncWrite | 24 | // Essentially, async_io::Async converts from AsRawFd+Read+Write to futures's AsyncRead+AsyncWrite |
| 25 | let port = Async::new(port).unwrap(); | 25 | let port = Async::new(port).unwrap(); |
| 26 | 26 | ||
| 27 | // This implements futures's AsyncBufRead based on futures's AsyncRead | 27 | // We can then use FromStdIo to convert from futures's AsyncRead+AsyncWrite |
| 28 | let port = futures::io::BufReader::new(port); | 28 | // to embedded_io's async Read+Write. |
| 29 | 29 | // | |
| 30 | // We can then use FromStdIo to convert from futures's AsyncBufRead+AsyncWrite | 30 | // This is not really needed, you could write the code below using futures::io directly. |
| 31 | // to embassy's AsyncBufRead+AsyncWrite | 31 | // It's useful if you want to have portable code across embedded and std. |
| 32 | let mut port = embassy::io::FromStdIo::new(port); | 32 | let mut port = embedded_io::adapters::FromFutures::new(port); |
| 33 | 33 | ||
| 34 | info!("Serial opened!"); | 34 | info!("Serial opened!"); |
| 35 | 35 | ||
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 09a06aa7f..bbeee179d 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml | |||
| @@ -9,6 +9,7 @@ resolver = "2" | |||
| 9 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } | 9 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } |
| 10 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } | 10 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } |
| 11 | embassy-net = { path = "../../embassy-net", features = ["defmt", "tcp", "medium-ethernet", "pool-16"] } | 11 | embassy-net = { path = "../../embassy-net", features = ["defmt", "tcp", "medium-ethernet", "pool-16"] } |
| 12 | embedded-io = { version = "0.2.0", features = ["async"] } | ||
| 12 | 13 | ||
| 13 | defmt = "0.3" | 14 | defmt = "0.3" |
| 14 | defmt-rtt = "0.3" | 15 | defmt-rtt = "0.3" |
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 33e41de9c..dca9338b2 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs | |||
| @@ -5,12 +5,10 @@ | |||
| 5 | use cortex_m_rt::entry; | 5 | use cortex_m_rt::entry; |
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy::executor::{Executor, Spawner}; | 7 | use embassy::executor::{Executor, Spawner}; |
| 8 | use embassy::io::AsyncWriteExt; | ||
| 9 | use embassy::time::{Duration, Timer}; | 8 | use embassy::time::{Duration, Timer}; |
| 10 | use embassy::util::Forever; | 9 | use embassy::util::Forever; |
| 11 | use embassy_net::{ | 10 | use embassy_net::tcp::TcpSocket; |
| 12 | Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket, | 11 | use embassy_net::{Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator}; |
| 13 | }; | ||
| 14 | use embassy_stm32::eth::generic_smi::GenericSMI; | 12 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 15 | use embassy_stm32::eth::{Ethernet, State}; | 13 | use embassy_stm32::eth::{Ethernet, State}; |
| 16 | use embassy_stm32::interrupt; | 14 | use embassy_stm32::interrupt; |
| @@ -19,6 +17,7 @@ use embassy_stm32::peripherals::RNG; | |||
| 19 | use embassy_stm32::rng::Rng; | 17 | use embassy_stm32::rng::Rng; |
| 20 | use embassy_stm32::time::U32Ext; | 18 | use embassy_stm32::time::U32Ext; |
| 21 | use embassy_stm32::Config; | 19 | use embassy_stm32::Config; |
| 20 | use embedded_io::asynch::Write; | ||
| 22 | use heapless::Vec; | 21 | use heapless::Vec; |
| 23 | 22 | ||
| 24 | use defmt_rtt as _; // global logger | 23 | use defmt_rtt as _; // global logger |
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 419bbec31..ff70e6db6 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml | |||
| @@ -5,12 +5,11 @@ name = "embassy-stm32h7-examples" | |||
| 5 | version = "0.1.0" | 5 | version = "0.1.0" |
| 6 | resolver = "2" | 6 | resolver = "2" |
| 7 | 7 | ||
| 8 | [features] | ||
| 9 | |||
| 10 | [dependencies] | 8 | [dependencies] |
| 11 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits"] } | 9 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits"] } |
| 12 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } | 10 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } |
| 13 | embassy-net = { path = "../../embassy-net", features = ["defmt", "tcp", "medium-ethernet", "pool-16"] } | 11 | embassy-net = { path = "../../embassy-net", features = ["defmt", "tcp", "medium-ethernet", "pool-16"] } |
| 12 | embedded-io = { version = "0.2.0", features = ["async"] } | ||
| 14 | 13 | ||
| 15 | defmt = "0.3" | 14 | defmt = "0.3" |
| 16 | defmt-rtt = "0.3" | 15 | defmt-rtt = "0.3" |
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 9a2e7a33d..8ece29403 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -8,12 +8,10 @@ use panic_probe as _; | |||
| 8 | use cortex_m_rt::entry; | 8 | use cortex_m_rt::entry; |
| 9 | use defmt::*; | 9 | use defmt::*; |
| 10 | use embassy::executor::{Executor, Spawner}; | 10 | use embassy::executor::{Executor, Spawner}; |
| 11 | use embassy::io::AsyncWriteExt; | ||
| 12 | use embassy::time::{Duration, Timer}; | 11 | use embassy::time::{Duration, Timer}; |
| 13 | use embassy::util::Forever; | 12 | use embassy::util::Forever; |
| 14 | use embassy_net::{ | 13 | use embassy_net::tcp::TcpSocket; |
| 15 | Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket, | 14 | use embassy_net::{Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator}; |
| 16 | }; | ||
| 17 | use embassy_stm32::eth::generic_smi::GenericSMI; | 15 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 18 | use embassy_stm32::eth::{Ethernet, State}; | 16 | use embassy_stm32::eth::{Ethernet, State}; |
| 19 | use embassy_stm32::interrupt; | 17 | use embassy_stm32::interrupt; |
| @@ -22,6 +20,7 @@ use embassy_stm32::peripherals::RNG; | |||
| 22 | use embassy_stm32::rng::Rng; | 20 | use embassy_stm32::rng::Rng; |
| 23 | use embassy_stm32::time::U32Ext; | 21 | use embassy_stm32::time::U32Ext; |
| 24 | use embassy_stm32::Config; | 22 | use embassy_stm32::Config; |
| 23 | use embedded_io::asynch::Write; | ||
| 25 | use heapless::Vec; | 24 | use heapless::Vec; |
| 26 | 25 | ||
| 27 | #[embassy::task] | 26 | #[embassy::task] |
diff --git a/examples/stm32l0/.cargo/config.toml b/examples/stm32l0/.cargo/config.toml index 840faa62e..ec0b931f2 100644 --- a/examples/stm32l0/.cargo/config.toml +++ b/examples/stm32l0/.cargo/config.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | # replace your chip as listed in `probe-run --list-chips` | 2 | # replace your chip as listed in `probe-run --list-chips` |
| 3 | runner = "probe-run --chip STM32L072CZTx" | 3 | runner = "probe-run --chip STM32L053R8Tx" |
| 4 | 4 | ||
| 5 | [build] | 5 | [build] |
| 6 | target = "thumbv6m-none-eabi" | 6 | target = "thumbv6m-none-eabi" |
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 1cdb2f374..d6848c27a 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml | |||
| @@ -7,12 +7,11 @@ resolver = "2" | |||
| 7 | 7 | ||
| 8 | [features] | 8 | [features] |
| 9 | default = ["nightly"] | 9 | default = ["nightly"] |
| 10 | nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan"] | 10 | nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan", "embedded-io/async"] |
| 11 | 11 | ||
| 12 | [dependencies] | 12 | [dependencies] |
| 13 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } | 13 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-timestamp-uptime"] } |
| 14 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } | 14 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } |
| 15 | |||
| 16 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true} | 15 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true} |
| 17 | 16 | ||
| 18 | lorawan-device = { version = "0.7.1", default-features = false, features = ["async"], optional = true } | 17 | lorawan-device = { version = "0.7.1", default-features = false, features = ["async"], optional = true } |
| @@ -22,6 +21,7 @@ defmt = "0.3" | |||
| 22 | defmt-rtt = "0.3" | 21 | defmt-rtt = "0.3" |
| 23 | 22 | ||
| 24 | embedded-storage = "0.3.0" | 23 | embedded-storage = "0.3.0" |
| 24 | embedded-io = "0.2.0" | ||
| 25 | 25 | ||
| 26 | cortex-m = "0.7.3" | 26 | cortex-m = "0.7.3" |
| 27 | cortex-m-rt = "0.7.0" | 27 | 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 abb27fa4f..4413a2945 100644 --- a/examples/stm32l0/src/bin/usart_irq.rs +++ b/examples/stm32l0/src/bin/usart_irq.rs | |||
| @@ -2,13 +2,14 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use defmt_rtt as _; // global logger | 5 | use defmt_rtt as _; |
| 6 | use embedded_io::asynch::{Read, Write}; | ||
| 7 | // global logger | ||
| 6 | use panic_probe as _; | 8 | use panic_probe as _; |
| 7 | 9 | ||
| 8 | use defmt::*; | 10 | use defmt::*; |
| 9 | 11 | ||
| 10 | use embassy::executor::Spawner; | 12 | use embassy::executor::Spawner; |
| 11 | use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; | ||
| 12 | use embassy_stm32::dma::NoDma; | 13 | use embassy_stm32::dma::NoDma; |
| 13 | use embassy_stm32::interrupt; | 14 | use embassy_stm32::interrupt; |
| 14 | use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; | 15 | use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; |
| @@ -16,19 +17,21 @@ use embassy_stm32::Peripherals; | |||
| 16 | 17 | ||
| 17 | #[embassy::main] | 18 | #[embassy::main] |
| 18 | async fn main(_spawner: Spawner, p: Peripherals) { | 19 | async fn main(_spawner: Spawner, p: Peripherals) { |
| 20 | info!("Hi!"); | ||
| 21 | |||
| 19 | static mut TX_BUFFER: [u8; 8] = [0; 8]; | 22 | static mut TX_BUFFER: [u8; 8] = [0; 8]; |
| 20 | static mut RX_BUFFER: [u8; 256] = [0; 256]; | 23 | static mut RX_BUFFER: [u8; 256] = [0; 256]; |
| 21 | 24 | ||
| 22 | let mut config = Config::default(); | 25 | let mut config = Config::default(); |
| 23 | config.baudrate = 9600; | 26 | config.baudrate = 9600; |
| 24 | 27 | ||
| 25 | let usart = Uart::new(p.USART1, p.PA10, p.PA9, NoDma, NoDma, config); | 28 | let usart = Uart::new(p.USART2, p.PA3, p.PA2, NoDma, NoDma, config); |
| 26 | let mut state = State::new(); | 29 | let mut state = State::new(); |
| 27 | let mut usart = unsafe { | 30 | let mut usart = unsafe { |
| 28 | BufferedUart::new( | 31 | BufferedUart::new( |
| 29 | &mut state, | 32 | &mut state, |
| 30 | usart, | 33 | usart, |
| 31 | interrupt::take!(USART1), | 34 | interrupt::take!(USART2), |
| 32 | &mut TX_BUFFER, | 35 | &mut TX_BUFFER, |
| 33 | &mut RX_BUFFER, | 36 | &mut RX_BUFFER, |
| 34 | ) | 37 | ) |
