diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 3d0c171f..c9bd2bc1 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -12,6 +12,9 @@ edition = "2018" # There are no plans to make this stable. unstable-pac = [] +# Implement embedded-hal 1.0 alpha and embedded-hal-async traits. +unstable-traits = ["embedded-hal-1", "embedded-hal-async"] + nrf52805 = ["nrf52805-pac", "_ppi"] nrf52810 = ["nrf52810-pac", "_ppi"] nrf52811 = ["nrf52811-pac", "_ppi"] @@ -47,11 +50,14 @@ embassy = { version = "0.1.0", path = "../embassy" } embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]} embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } +embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } +embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true} +embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true} + defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" cortex-m = "0.7.3" -embedded-hal = "0.2.6" embedded-dma = "0.1.2" futures = { version = "0.3.17", default-features = false } critical-section = "0.2.5" diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 45e8afc4..2880c84f 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -213,9 +213,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, cx: &mut Context<'_>, ) -> Poll> { self.inner.with(|state| { - // Conservative compiler fence to prevent optimizations that do not - // take in to account actions by DMA. The fence has been placed here, - // before any DMA action has started compiler_fence(Ordering::SeqCst); trace!("poll_read"); @@ -265,9 +262,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U, trace!("poll_write: queued {:?}", n); - // Conservative compiler fence to prevent optimizations that do not - // take in to account actions by DMA. The fence has been placed here, - // before any DMA action has started compiler_fence(Ordering::SeqCst); Poll::Ready(Ok(n)) @@ -347,9 +341,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len()); // Start UARTE Receive transaction - r.tasks_startrx.write(|w| - // `1` is a valid value to write to task registers. - unsafe { w.bits(1) }); + r.tasks_startrx.write(|w| unsafe { w.bits(1) }); } break; } @@ -397,9 +389,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, unsafe { w.maxcnt().bits(buf.len() as _) }); // Start UARTE Transmit transaction - r.tasks_starttx.write(|w| - // `1` is a valid value to write to task registers. - unsafe { w.bits(1) }); + r.tasks_starttx.write(|w| unsafe { w.bits(1) }); } break; } diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index abda909f..3f204d56 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -7,7 +7,6 @@ use core::marker::PhantomData; use cfg_if::cfg_if; use embassy::util::Unborrow; use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; -use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; use gpio::pin_cnf::DRIVE_A; use crate::pac; @@ -57,18 +56,6 @@ impl<'d, T: Pin> Input<'d, T> { } } -impl<'d, T: Pin> InputPin for Input<'d, T> { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - /// Digital input or output level. #[derive(Debug, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -142,28 +129,6 @@ impl<'d, T: Pin> Output<'d, T> { } } -impl<'d, T: Pin> OutputPin for Output<'d, T> { - type Error = Infallible; - - fn set_high(&mut self) -> Result<(), Self::Error> { - Ok(self.set_high()) - } - - fn set_low(&mut self) -> Result<(), Self::Error> { - Ok(self.set_low()) - } -} - -impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> { - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - /// GPIO flexible pin. /// /// This pin can either be a disconnected, input, or output pin. The level register bit will remain @@ -276,43 +241,6 @@ impl<'d, T: Pin> Drop for Flex<'d, T> { } } -/// Implement [`InputPin`] for [`Flex`]; -/// -/// If the pin is not in input mode the result is unspecified. -impl<'d, T: Pin> InputPin for Flex<'d, T> { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(self.is_high()) - } - - fn is_low(&self) -> Result { - Ok(self.is_low()) - } -} - -impl<'d, T: Pin> OutputPin for Flex<'d, T> { - type Error = Infallible; - - fn set_high(&mut self) -> Result<(), Self::Error> { - Ok(self.set_high()) - } - - fn set_low(&mut self) -> Result<(), Self::Error> { - Ok(self.set_low()) - } -} - -impl<'d, T: Pin> StatefulOutputPin for Flex<'d, T> { - fn is_set_high(&self) -> Result { - Ok(self.is_set_high()) - } - - fn is_set_low(&self) -> Result { - Ok(self.is_set_low()) - } -} - pub(crate) mod sealed { use super::*; @@ -491,3 +419,160 @@ macro_rules! impl_pin { } }; } + +// ==================== + +mod eh02 { + use super::*; + + impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Input<'d, T> { + type Error = Infallible; + + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + fn is_low(&self) -> Result { + Ok(self.is_low()) + } + } + + impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Output<'d, T> { + type Error = Infallible; + + fn set_high(&mut self) -> Result<(), Self::Error> { + Ok(self.set_high()) + } + + fn set_low(&mut self) -> Result<(), Self::Error> { + Ok(self.set_low()) + } + } + + impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Output<'d, T> { + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } + } + + /// Implement [`InputPin`] for [`Flex`]; + /// + /// If the pin is not in input mode the result is unspecified. + impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Flex<'d, T> { + type Error = Infallible; + + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + fn is_low(&self) -> Result { + Ok(self.is_low()) + } + } + + impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Flex<'d, T> { + type Error = Infallible; + + fn set_high(&mut self) -> Result<(), Self::Error> { + Ok(self.set_high()) + } + + fn set_low(&mut self) -> Result<(), Self::Error> { + Ok(self.set_low()) + } + } + + impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Flex<'d, T> { + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } + } +} + +#[cfg(feature = "unstable-traits")] +mod eh1 { + use super::*; + + impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> { + type Error = Infallible; + } + + impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Input<'d, T> { + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + fn is_low(&self) -> Result { + Ok(self.is_low()) + } + } + + impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Output<'d, T> { + type Error = Infallible; + } + + impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Output<'d, T> { + fn set_high(&mut self) -> Result<(), Self::Error> { + Ok(self.set_high()) + } + + fn set_low(&mut self) -> Result<(), Self::Error> { + Ok(self.set_low()) + } + } + + impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Output<'d, T> { + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } + } + + impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Flex<'d, T> { + type Error = Infallible; + } + + /// Implement [`InputPin`] for [`Flex`]; + /// + /// If the pin is not in input mode the result is unspecified. + impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Flex<'d, T> { + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + fn is_low(&self) -> Result { + Ok(self.is_low()) + } + } + + impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Flex<'d, T> { + fn set_high(&mut self) -> Result<(), Self::Error> { + Ok(self.set_high()) + } + + fn set_low(&mut self) -> Result<(), Self::Error> { + Ok(self.set_low()) + } + } + + impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Flex<'d, T> { + fn is_set_high(&self) -> Result { + Ok(self.is_set_high()) + } + + fn is_set_low(&self) -> Result { + Ok(self.is_set_low()) + } + } +} diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index f1104904..a4c24058 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -5,7 +5,6 @@ use core::task::{Context, Poll}; use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::waitqueue::AtomicWaker; use embassy_hal_common::unsafe_impl_unborrow; -use embedded_hal::digital::v2::InputPin; use futures::future::poll_fn; use crate::gpio::sealed::Pin as _; @@ -216,18 +215,6 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { } } -impl<'d, C: Channel, T: GpioPin> InputPin for InputChannel<'d, C, T> { - type Error = Infallible; - - fn is_high(&self) -> Result { - self.pin.is_high() - } - - fn is_low(&self) -> Result { - self.pin.is_low() - } -} - /// GPIOTE channel driver in output mode pub struct OutputChannel<'d, C: Channel, T: GpioPin> { ch: C, @@ -454,3 +441,137 @@ impl_channel!(GPIOTE_CH4, 4); impl_channel!(GPIOTE_CH5, 5); impl_channel!(GPIOTE_CH6, 6); impl_channel!(GPIOTE_CH7, 7); + +// ==================== + +mod eh02 { + use super::*; + + impl<'d, C: Channel, T: GpioPin> embedded_hal_02::digital::v2::InputPin for InputChannel<'d, C, T> { + type Error = Infallible; + + fn is_high(&self) -> Result { + self.pin.is_high() + } + + fn is_low(&self) -> Result { + self.pin.is_low() + } + } +} + +#[cfg(feature = "unstable-traits")] +mod eh1 { + use super::*; + use futures::FutureExt; + + impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::ErrorType for InputChannel<'d, C, T> { + type Error = Infallible; + } + + impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::blocking::InputPin + for InputChannel<'d, C, T> + { + fn is_high(&self) -> Result { + self.pin.is_high() + } + + fn is_low(&self) -> Result { + self.pin.is_low() + } + } + + impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> { + type WaitForHighFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> { + self.wait_for_high().map(Ok) + } + + type WaitForLowFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> { + self.wait_for_low().map(Ok) + } + + type WaitForRisingEdgeFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> { + self.wait_for_rising_edge().map(Ok) + } + + type WaitForFallingEdgeFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> { + self.wait_for_falling_edge().map(Ok) + } + + type WaitForAnyEdgeFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> { + self.wait_for_any_edge().map(Ok) + } + } + + impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> { + type WaitForHighFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> { + self.wait_for_high().map(Ok) + } + + type WaitForLowFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> { + self.wait_for_low().map(Ok) + } + + type WaitForRisingEdgeFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> { + self.wait_for_rising_edge().map(Ok) + } + + type WaitForFallingEdgeFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> { + self.wait_for_falling_edge().map(Ok) + } + + type WaitForAnyEdgeFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> { + self.wait_for_any_edge().map(Ok) + } + } +} diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index e767bc70..cd43b26e 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -1,15 +1,12 @@ #![macro_use] -use core::future::Future; use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; use embassy::interrupt::InterruptExt; -use embassy::traits; use embassy::util::Unborrow; use embassy_hal_common::unborrow; use futures::future::poll_fn; -use traits::spi::{FullDuplex, Read, Spi, Write}; use crate::gpio; use crate::gpio::sealed::Pin as _; @@ -18,7 +15,7 @@ use crate::interrupt::Interrupt; use crate::util::{slice_ptr_parts, slice_ptr_parts_mut}; use crate::{pac, util::slice_in_ram_or}; -pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; +pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; pub use pac::spim0::frequency::FREQUENCY_A as Frequency; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -267,59 +264,6 @@ impl<'d, T: Instance> Drop for Spim<'d, T> { } } -impl<'d, T: Instance> Spi for Spim<'d, T> { - type Error = Error; -} - -impl<'d, T: Instance> Read for Spim<'d, T> { - type ReadFuture<'a> - where - Self: 'a, - = impl Future> + 'a; - - fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { - self.read(data) - } -} - -impl<'d, T: Instance> Write for Spim<'d, T> { - type WriteFuture<'a> - where - Self: 'a, - = impl Future> + 'a; - - fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { - self.write(data) - } -} - -impl<'d, T: Instance> FullDuplex for Spim<'d, T> { - type WriteReadFuture<'a> - where - Self: 'a, - = impl Future> + 'a; - - fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> { - self.transfer(rx, tx) - } -} - -impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spim<'d, T> { - type Error = Error; - fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { - self.blocking_transfer_in_place(words)?; - Ok(words) - } -} - -impl<'d, T: Instance> embedded_hal::blocking::spi::Write for Spim<'d, T> { - type Error = Error; - - fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(words) - } -} - pub(crate) mod sealed { use embassy::waitqueue::AtomicWaker; @@ -363,3 +307,209 @@ macro_rules! impl_spim { } }; } + +// ==================== + +mod eh02 { + use super::*; + + impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer for Spim<'d, T> { + type Error = Error; + fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { + self.blocking_transfer_in_place(words)?; + Ok(words) + } + } + + impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write for Spim<'d, T> { + type Error = Error; + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(words) + } + } +} + +#[cfg(feature = "unstable-traits")] +mod eh1 { + use super::*; + use core::future::Future; + + impl embedded_hal_1::spi::Error for Error { + fn kind(&self) -> embedded_hal_1::spi::ErrorKind { + match *self { + Self::TxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other, + Self::RxBufferTooLong => embedded_hal_1::spi::ErrorKind::Other, + Self::DMABufferNotInDataMemory => embedded_hal_1::spi::ErrorKind::Other, + } + } + } + + impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spim<'d, T> { + type Error = Error; + } + + impl<'d, T: Instance> embedded_hal_1::spi::blocking::Read for Spim<'d, T> { + fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_transfer(words, &[]) + } + + fn read_transaction(&mut self, words: &mut [&mut [u8]]) -> Result<(), Self::Error> { + for buf in words { + self.blocking_read(buf)? + } + Ok(()) + } + } + + impl<'d, T: Instance> embedded_hal_1::spi::blocking::Write for Spim<'d, T> { + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(words) + } + + fn write_transaction(&mut self, words: &[&[u8]]) -> Result<(), Self::Error> { + for buf in words { + self.blocking_write(buf)? + } + Ok(()) + } + + fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> + where + WI: IntoIterator, + { + for w in words { + self.blocking_write(&[w])?; + } + Ok(()) + } + } + + impl<'d, T: Instance> embedded_hal_1::spi::blocking::ReadWrite for Spim<'d, T> { + fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { + self.blocking_transfer(read, write) + } + + fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_transfer_in_place(words) + } + + fn transaction<'a>( + &mut self, + operations: &mut [embedded_hal_async::spi::Operation<'a, u8>], + ) -> Result<(), Self::Error> { + use embedded_hal_1::spi::blocking::Operation; + for o in operations { + match o { + Operation::Read(b) => self.blocking_read(b)?, + Operation::Write(b) => self.blocking_write(b)?, + Operation::Transfer(r, w) => self.blocking_transfer(r, w)?, + Operation::TransferInPlace(b) => self.blocking_transfer_in_place(b)?, + } + } + Ok(()) + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::Read for Spim<'d, T> { + type ReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn read<'a>(&'a mut self, words: &'a mut [u8]) -> Self::ReadFuture<'a> { + self.read(words) + } + + type ReadTransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn read_transaction<'a>( + &'a mut self, + words: &'a mut [&'a mut [u8]], + ) -> Self::ReadTransactionFuture<'a> { + async move { + for buf in words { + self.read(buf).await? + } + Ok(()) + } + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::Write for Spim<'d, T> { + type WriteFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { + self.write(data) + } + + type WriteTransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write_transaction<'a>( + &'a mut self, + words: &'a [&'a [u8]], + ) -> Self::WriteTransactionFuture<'a> { + async move { + for buf in words { + self.write(buf).await? + } + Ok(()) + } + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::ReadWrite for Spim<'d, T> { + type TransferFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> { + self.transfer(rx, tx) + } + + type TransferInPlaceFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn transfer_in_place<'a>( + &'a mut self, + words: &'a mut [u8], + ) -> Self::TransferInPlaceFuture<'a> { + self.transfer_in_place(words) + } + + type TransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn transaction<'a>( + &'a mut self, + operations: &'a mut [embedded_hal_async::spi::Operation<'a, u8>], + ) -> Self::TransactionFuture<'a> { + use embedded_hal_1::spi::blocking::Operation; + async move { + for o in operations { + match o { + Operation::Read(b) => self.read(b).await?, + Operation::Write(b) => self.write(b).await?, + Operation::Transfer(r, w) => self.transfer(r, w).await?, + Operation::TransferInPlace(b) => self.transfer_in_place(b).await?, + } + } + Ok(()) + } + } + } +} diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index ab649c47..4cd47c89 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs @@ -11,12 +11,10 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering::SeqCst}; use core::task::Poll; use embassy::interrupt::{Interrupt, InterruptExt}; -use embassy::traits; use embassy::util::Unborrow; use embassy::waitqueue::AtomicWaker; use embassy_hal_common::unborrow; use futures::future::poll_fn; -use traits::i2c::I2c; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::gpio; @@ -50,6 +48,22 @@ impl Default for Config { } } +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + TxBufferTooLong, + RxBufferTooLong, + TxBufferZeroLength, + RxBufferZeroLength, + Transmit, + Receive, + DMABufferNotInDataMemory, + AddressNack, + DataNack, + Overrun, +} + /// Interface to a TWIM instance. pub struct Twim<'d, T: Instance> { phantom: PhantomData<&'d mut T>, @@ -506,101 +520,6 @@ impl<'a, T: Instance> Drop for Twim<'a, T> { } } -impl<'d, T> I2c for Twim<'d, T> -where - T: Instance, -{ - type Error = Error; - - type WriteFuture<'a> - where - Self: 'a, - = impl Future> + 'a; - type ReadFuture<'a> - where - Self: 'a, - = impl Future> + 'a; - type WriteReadFuture<'a> - where - Self: 'a, - = impl Future> + 'a; - - fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { - self.read(address, buffer) - } - - fn write<'a>(&'a mut self, address: u8, buffer: &'a [u8]) -> Self::WriteFuture<'a> { - self.write(address, buffer) - } - - fn write_read<'a>( - &'a mut self, - address: u8, - wr_buffer: &'a [u8], - rd_buffer: &'a mut [u8], - ) -> Self::WriteReadFuture<'a> { - self.write_read(address, wr_buffer, rd_buffer) - } -} - -impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> { - type Error = Error; - - fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Error> { - if slice_in_ram(bytes) { - self.blocking_write(addr, bytes) - } else { - let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..]; - for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) { - buf[..chunk.len()].copy_from_slice(chunk); - self.blocking_write(addr, &buf[..chunk.len()])?; - } - Ok(()) - } - } -} - -impl<'a, T: Instance> embedded_hal::blocking::i2c::Read for Twim<'a, T> { - type Error = Error; - - fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Error> { - self.blocking_read(addr, bytes) - } -} - -impl<'a, T: Instance> embedded_hal::blocking::i2c::WriteRead for Twim<'a, T> { - type Error = Error; - - fn write_read<'w>( - &mut self, - addr: u8, - bytes: &'w [u8], - buffer: &'w mut [u8], - ) -> Result<(), Error> { - if slice_in_ram(bytes) { - self.blocking_write_read(addr, bytes, buffer) - } else { - self.blocking_copy_write_read(addr, bytes, buffer) - } - } -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - TxBufferTooLong, - RxBufferTooLong, - TxBufferZeroLength, - RxBufferZeroLength, - Transmit, - Receive, - DMABufferNotInDataMemory, - AddressNack, - DataNack, - Overrun, -} - pub(crate) mod sealed { use super::*; @@ -642,3 +561,187 @@ macro_rules! impl_twim { } }; } + +// ==================== + +mod eh02 { + use super::*; + + impl<'a, T: Instance> embedded_hal_02::blocking::i2c::Write for Twim<'a, T> { + type Error = Error; + + fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Error> { + if slice_in_ram(bytes) { + self.blocking_write(addr, bytes) + } else { + let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..]; + for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) { + buf[..chunk.len()].copy_from_slice(chunk); + self.blocking_write(addr, &buf[..chunk.len()])?; + } + Ok(()) + } + } + } + + impl<'a, T: Instance> embedded_hal_02::blocking::i2c::Read for Twim<'a, T> { + type Error = Error; + + fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Error> { + self.blocking_read(addr, bytes) + } + } + + impl<'a, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for Twim<'a, T> { + type Error = Error; + + fn write_read<'w>( + &mut self, + addr: u8, + bytes: &'w [u8], + buffer: &'w mut [u8], + ) -> Result<(), Error> { + if slice_in_ram(bytes) { + self.blocking_write_read(addr, bytes, buffer) + } else { + self.blocking_copy_write_read(addr, bytes, buffer) + } + } + } +} + +#[cfg(feature = "unstable-traits")] +mod eh1 { + use super::*; + + impl embedded_hal_1::i2c::Error for Error { + fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { + match *self { + Self::TxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, + Self::RxBufferTooLong => embedded_hal_1::i2c::ErrorKind::Other, + Self::TxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other, + Self::RxBufferZeroLength => embedded_hal_1::i2c::ErrorKind::Other, + Self::Transmit => embedded_hal_1::i2c::ErrorKind::Other, + Self::Receive => embedded_hal_1::i2c::ErrorKind::Other, + Self::DMABufferNotInDataMemory => embedded_hal_1::i2c::ErrorKind::Other, + Self::AddressNack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge( + embedded_hal_1::i2c::NoAcknowledgeSource::Address, + ), + Self::DataNack => embedded_hal_1::i2c::ErrorKind::NoAcknowledge( + embedded_hal_1::i2c::NoAcknowledgeSource::Data, + ), + Self::Overrun => embedded_hal_1::i2c::ErrorKind::Overrun, + } + } + } + + impl<'d, T: Instance> embedded_hal_1::i2c::ErrorType for Twim<'d, T> { + type Error = Error; + } + + impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for Twim<'d, T> { + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.blocking_read(address, buffer) + } + + fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(address, buffer) + } + + fn write_iter(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error> + where + B: IntoIterator, + { + todo!(); + } + + fn write_iter_read( + &mut self, + _address: u8, + _bytes: B, + _buffer: &mut [u8], + ) -> Result<(), Self::Error> + where + B: IntoIterator, + { + todo!(); + } + + fn write_read( + &mut self, + address: u8, + wr_buffer: &[u8], + rd_buffer: &mut [u8], + ) -> Result<(), Self::Error> { + self.blocking_write_read(address, wr_buffer, rd_buffer) + } + + fn transaction<'a>( + &mut self, + _address: u8, + _operations: &mut [embedded_hal_async::i2c::Operation<'a>], + ) -> Result<(), Self::Error> { + todo!(); + } + + fn transaction_iter<'a, O>( + &mut self, + _address: u8, + _operations: O, + ) -> Result<(), Self::Error> + where + O: IntoIterator>, + { + todo!(); + } + } + + impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> { + type ReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { + self.read(address, buffer) + } + + type WriteFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { + self.write(address, bytes) + } + + type WriteReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write_read<'a>( + &'a mut self, + address: u8, + wr_buffer: &'a [u8], + rd_buffer: &'a mut [u8], + ) -> Self::WriteReadFuture<'a> { + self.write_read(address, wr_buffer, rd_buffer) + } + + type TransactionFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn transaction<'a>( + &'a mut self, + address: u8, + operations: &mut [embedded_hal_async::i2c::Operation<'a>], + ) -> Self::TransactionFuture<'a> { + let _ = address; + let _ = operations; + async move { todo!() } + } + } +} diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 07cec5d6..b10e55a0 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -712,3 +712,206 @@ macro_rules! impl_uarte { } }; } + +// ==================== + +mod eh02 { + use super::*; + + impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write for Uarte<'d, T> { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } + + impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write for UarteTx<'d, T> { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } + + impl<'d, U: Instance, T: TimerInstance> embedded_hal_02::blocking::serial::Write + for UarteWithIdle<'d, U, T> + { + type Error = Error; + + fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } +} + +#[cfg(feature = "unstable-traits")] +mod eh1 { + use super::*; + use core::future::Future; + + impl embedded_hal_1::serial::Error for Error { + fn kind(&self) -> embedded_hal_1::serial::ErrorKind { + match *self { + Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other, + Self::BufferZeroLength => embedded_hal_1::serial::ErrorKind::Other, + Self::DMABufferNotInDataMemory => embedded_hal_1::serial::ErrorKind::Other, + } + } + } + + // ===================== + + impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for Uarte<'d, T> { + type Error = Error; + } + + impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for Uarte<'d, T> { + fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } + + impl<'d, T: Instance> embedded_hal_async::serial::Read for Uarte<'d, T> { + type ReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { + self.read(buffer) + } + } + + impl<'d, T: Instance> embedded_hal_async::serial::Write for Uarte<'d, T> { + type WriteFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> { + self.write(buffer) + } + + type FlushFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + async move { Ok(()) } + } + } + + // ===================== + + impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteTx<'d, T> { + type Error = Error; + } + + impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for UarteTx<'d, T> { + fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + self.blocking_write(buffer) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } + + impl<'d, T: Instance> embedded_hal_async::serial::Write for UarteTx<'d, T> { + type WriteFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> { + self.write(buffer) + } + + type FlushFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + async move { Ok(()) } + } + } + + // ===================== + + impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> { + type Error = Error; + } + + impl<'d, T: Instance> embedded_hal_async::serial::Read for UarteRx<'d, T> { + type ReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { + self.read(buffer) + } + } + + // ===================== + + impl<'d, U: Instance, T: TimerInstance> embedded_hal_1::serial::ErrorType + for UarteWithIdle<'d, U, T> + { + type Error = Error; + } + + impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read + for UarteWithIdle<'d, U, T> + { + type ReadFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { + self.read(buffer) + } + } + + impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Write + for UarteWithIdle<'d, U, T> + { + type WriteFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> { + self.write(buffer) + } + + type FlushFuture<'a> + where + Self: 'a, + = impl Future> + 'a; + + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + async move { Ok(()) } + } + } +} diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index ca013f8b..fa728692 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -15,7 +15,6 @@ defmt-rtt = "0.3" cortex-m = "0.7.3" cortex-m-rt = "0.7.0" -embedded-hal = "0.2.6" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } rand = { version = "0.8.4", default-features = false }