nrf: impl embedded-hal 1.0 and embedded-hal-async traits.
This commit is contained in:
parent
6eec3d8acc
commit
7997687f3b
@ -12,6 +12,9 @@ edition = "2018"
|
|||||||
# There are no plans to make this stable.
|
# There are no plans to make this stable.
|
||||||
unstable-pac = []
|
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"]
|
nrf52805 = ["nrf52805-pac", "_ppi"]
|
||||||
nrf52810 = ["nrf52810-pac", "_ppi"]
|
nrf52810 = ["nrf52810-pac", "_ppi"]
|
||||||
nrf52811 = ["nrf52811-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-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]}
|
||||||
embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
|
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 }
|
defmt = { version = "0.3", optional = true }
|
||||||
log = { version = "0.4.14", optional = true }
|
log = { version = "0.4.14", optional = true }
|
||||||
cortex-m-rt = ">=0.6.15,<0.8"
|
cortex-m-rt = ">=0.6.15,<0.8"
|
||||||
cortex-m = "0.7.3"
|
cortex-m = "0.7.3"
|
||||||
embedded-hal = "0.2.6"
|
|
||||||
embedded-dma = "0.1.2"
|
embedded-dma = "0.1.2"
|
||||||
futures = { version = "0.3.17", default-features = false }
|
futures = { version = "0.3.17", default-features = false }
|
||||||
critical-section = "0.2.5"
|
critical-section = "0.2.5"
|
||||||
|
@ -213,9 +213,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d,
|
|||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
) -> Poll<embassy::io::Result<&[u8]>> {
|
) -> Poll<embassy::io::Result<&[u8]>> {
|
||||||
self.inner.with(|state| {
|
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);
|
compiler_fence(Ordering::SeqCst);
|
||||||
trace!("poll_read");
|
trace!("poll_read");
|
||||||
|
|
||||||
@ -265,9 +262,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U,
|
|||||||
|
|
||||||
trace!("poll_write: queued {:?}", n);
|
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);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
Poll::Ready(Ok(n))
|
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());
|
trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len());
|
||||||
|
|
||||||
// Start UARTE Receive transaction
|
// Start UARTE Receive transaction
|
||||||
r.tasks_startrx.write(|w|
|
r.tasks_startrx.write(|w| unsafe { w.bits(1) });
|
||||||
// `1` is a valid value to write to task registers.
|
|
||||||
unsafe { w.bits(1) });
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -397,9 +389,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a,
|
|||||||
unsafe { w.maxcnt().bits(buf.len() as _) });
|
unsafe { w.maxcnt().bits(buf.len() as _) });
|
||||||
|
|
||||||
// Start UARTE Transmit transaction
|
// Start UARTE Transmit transaction
|
||||||
r.tasks_starttx.write(|w|
|
r.tasks_starttx.write(|w| unsafe { w.bits(1) });
|
||||||
// `1` is a valid value to write to task registers.
|
|
||||||
unsafe { w.bits(1) });
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ use core::marker::PhantomData;
|
|||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
|
use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
|
||||||
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
|
|
||||||
use gpio::pin_cnf::DRIVE_A;
|
use gpio::pin_cnf::DRIVE_A;
|
||||||
|
|
||||||
use crate::pac;
|
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<bool, Self::Error> {
|
|
||||||
Ok(self.is_high())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
|
||||||
Ok(self.is_low())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Digital input or output level.
|
/// Digital input or output level.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[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<bool, Self::Error> {
|
|
||||||
Ok(self.is_set_high())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
|
||||||
Ok(self.is_set_low())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// GPIO flexible pin.
|
/// GPIO flexible pin.
|
||||||
///
|
///
|
||||||
/// This pin can either be a disconnected, input, or output pin. The level register bit will remain
|
/// 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<bool, Self::Error> {
|
|
||||||
Ok(self.is_high())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
|
||||||
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<bool, Self::Error> {
|
|
||||||
Ok(self.is_set_high())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
|
||||||
Ok(self.is_set_low())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_set_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_set_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_set_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
Ok(self.is_set_high())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
Ok(self.is_set_low())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,7 +5,6 @@ use core::task::{Context, Poll};
|
|||||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy::waitqueue::AtomicWaker;
|
use embassy::waitqueue::AtomicWaker;
|
||||||
use embassy_hal_common::unsafe_impl_unborrow;
|
use embassy_hal_common::unsafe_impl_unborrow;
|
||||||
use embedded_hal::digital::v2::InputPin;
|
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
use crate::gpio::sealed::Pin as _;
|
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<bool, Self::Error> {
|
|
||||||
self.pin.is_high()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
|
||||||
self.pin.is_low()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// GPIOTE channel driver in output mode
|
/// GPIOTE channel driver in output mode
|
||||||
pub struct OutputChannel<'d, C: Channel, T: GpioPin> {
|
pub struct OutputChannel<'d, C: Channel, T: GpioPin> {
|
||||||
ch: C,
|
ch: C,
|
||||||
@ -454,3 +441,137 @@ impl_channel!(GPIOTE_CH4, 4);
|
|||||||
impl_channel!(GPIOTE_CH5, 5);
|
impl_channel!(GPIOTE_CH5, 5);
|
||||||
impl_channel!(GPIOTE_CH6, 6);
|
impl_channel!(GPIOTE_CH6, 6);
|
||||||
impl_channel!(GPIOTE_CH7, 7);
|
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<bool, Self::Error> {
|
||||||
|
self.pin.is_high()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<bool, Self::Error> {
|
||||||
|
self.pin.is_high()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
|
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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
|
fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
|
||||||
|
self.wait_for_any_edge().map(Ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
use core::future::Future;
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
use embassy::interrupt::InterruptExt;
|
use embassy::interrupt::InterruptExt;
|
||||||
use embassy::traits;
|
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
use traits::spi::{FullDuplex, Read, Spi, Write};
|
|
||||||
|
|
||||||
use crate::gpio;
|
use crate::gpio;
|
||||||
use crate::gpio::sealed::Pin as _;
|
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::util::{slice_ptr_parts, slice_ptr_parts_mut};
|
||||||
use crate::{pac, util::slice_in_ram_or};
|
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;
|
pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@ -267,59 +264,6 @@ impl<'d, T: Instance> Drop for Spim<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Spi<u8> for Spim<'d, T> {
|
|
||||||
type Error = Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> Read<u8> for Spim<'d, T> {
|
|
||||||
type ReadFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
|
||||||
|
|
||||||
fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
|
||||||
self.read(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> Write<u8> for Spim<'d, T> {
|
|
||||||
type WriteFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
|
||||||
|
|
||||||
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
|
||||||
self.write(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|
||||||
type WriteReadFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Self::Error>> + '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<u8> 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<u8> for Spim<'d, T> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
self.blocking_write(words)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use embassy::waitqueue::AtomicWaker;
|
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<u8> 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<u8> 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<u8> 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<u8> 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<WI>(&mut self, words: WI) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
WI: IntoIterator<Item = u8>,
|
||||||
|
{
|
||||||
|
for w in words {
|
||||||
|
self.blocking_write(&[w])?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> embedded_hal_1::spi::blocking::ReadWrite<u8> 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<u8> for Spim<'d, T> {
|
||||||
|
type ReadFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<u8> for Spim<'d, T> {
|
||||||
|
type WriteFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
|
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
|
self.write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
type WriteTransactionFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + '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<u8> for Spim<'d, T> {
|
||||||
|
type TransferFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,12 +11,10 @@ use core::marker::PhantomData;
|
|||||||
use core::sync::atomic::{compiler_fence, Ordering::SeqCst};
|
use core::sync::atomic::{compiler_fence, Ordering::SeqCst};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy::traits;
|
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy::waitqueue::AtomicWaker;
|
use embassy::waitqueue::AtomicWaker;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
use traits::i2c::I2c;
|
|
||||||
|
|
||||||
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
||||||
use crate::gpio;
|
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.
|
/// Interface to a TWIM instance.
|
||||||
pub struct Twim<'d, T: Instance> {
|
pub struct Twim<'d, T: Instance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
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<Output = Result<(), Self::Error>> + 'a;
|
|
||||||
type ReadFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
|
||||||
type WriteReadFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Self::Error>> + '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 {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
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<B>(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
B: IntoIterator<Item = u8>,
|
||||||
|
{
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_iter_read<B>(
|
||||||
|
&mut self,
|
||||||
|
_address: u8,
|
||||||
|
_bytes: B,
|
||||||
|
_buffer: &mut [u8],
|
||||||
|
) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
B: IntoIterator<Item = u8>,
|
||||||
|
{
|
||||||
|
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<Item = embedded_hal_async::i2c::Operation<'a>>,
|
||||||
|
{
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
|
||||||
|
type ReadFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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!() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -712,3 +712,206 @@ macro_rules! impl_uarte {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================
|
||||||
|
|
||||||
|
mod eh02 {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> 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<u8> 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<u8>
|
||||||
|
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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
|
fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
|
self.write(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlushFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
|
fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
|
self.write(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlushFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + '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<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
|
fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
|
self.write(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlushFuture<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
|
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||||
|
async move { Ok(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,7 +15,6 @@ defmt-rtt = "0.3"
|
|||||||
|
|
||||||
cortex-m = "0.7.3"
|
cortex-m = "0.7.3"
|
||||||
cortex-m-rt = "0.7.0"
|
cortex-m-rt = "0.7.0"
|
||||||
embedded-hal = "0.2.6"
|
|
||||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||||
rand = { version = "0.8.4", default-features = false }
|
rand = { version = "0.8.4", default-features = false }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user