{
Ok(self.pin.is_high())
}
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index d7bd21702..bc70fc2f6 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -76,6 +76,14 @@ pub mod gpio;
pub mod gpiote;
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
pub mod nvmc;
+#[cfg(any(
+ feature = "nrf52810",
+ feature = "nrf52811",
+ feature = "nrf52833",
+ feature = "nrf52840",
+ feature = "_nrf9160"
+))]
+pub mod pdm;
pub mod ppi;
#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))]
pub mod pwm;
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs
new file mode 100644
index 000000000..b7c7022cf
--- /dev/null
+++ b/embassy-nrf/src/pdm.rs
@@ -0,0 +1,242 @@
+//! PDM mirophone interface
+
+use core::marker::PhantomData;
+use core::sync::atomic::{compiler_fence, Ordering};
+use core::task::Poll;
+
+use embassy_hal_common::drop::OnDrop;
+use embassy_hal_common::{into_ref, PeripheralRef};
+use embassy_sync::waitqueue::AtomicWaker;
+use futures::future::poll_fn;
+
+use crate::chip::EASY_DMA_SIZE;
+use crate::gpio::sealed::Pin;
+use crate::gpio::{AnyPin, Pin as GpioPin};
+use crate::interrupt::{self, InterruptExt};
+use crate::peripherals::PDM;
+use crate::{pac, Peripheral};
+
+/// PDM microphone interface
+pub struct Pdm<'d> {
+ irq: PeripheralRef<'d, interrupt::PDM>,
+ phantom: PhantomData<&'d PDM>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+#[non_exhaustive]
+pub enum Error {
+ BufferTooLong,
+ BufferZeroLength,
+ NotRunning,
+}
+
+static WAKER: AtomicWaker = AtomicWaker::new();
+static DUMMY_BUFFER: [i16; 1] = [0; 1];
+
+impl<'d> Pdm<'d> {
+ /// Create PDM driver
+ pub fn new(
+ pdm: impl Peripheral + 'd,
+ irq: impl Peripheral
+ 'd,
+ clk: impl Peripheral
+ 'd,
+ din: impl Peripheral
+ 'd,
+ config: Config,
+ ) -> Self {
+ into_ref!(clk, din);
+ Self::new_inner(pdm, irq, clk.map_into(), din.map_into(), config)
+ }
+
+ fn new_inner(
+ _pdm: impl Peripheral
+ 'd,
+ irq: impl Peripheral
+ 'd,
+ clk: PeripheralRef<'d, AnyPin>,
+ din: PeripheralRef<'d, AnyPin>,
+ config: Config,
+ ) -> Self {
+ into_ref!(irq);
+
+ let r = Self::regs();
+
+ // setup gpio pins
+ din.conf().write(|w| w.input().set_bit());
+ r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) });
+ clk.set_low();
+ clk.conf().write(|w| w.dir().output());
+ r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) });
+
+ // configure
+ // use default for
+ // - gain right
+ // - gain left
+ // - clk
+ // - ratio
+ r.mode.write(|w| {
+ w.edge().bit(config.edge == Edge::LeftRising);
+ w.operation().bit(config.operation_mode == OperationMode::Mono);
+ w
+ });
+ r.gainl.write(|w| w.gainl().default_gain());
+ r.gainr.write(|w| w.gainr().default_gain());
+
+ // IRQ
+ irq.disable();
+ irq.set_handler(|_| {
+ let r = Self::regs();
+ r.intenclr.write(|w| w.end().clear());
+ WAKER.wake();
+ });
+ irq.enable();
+
+ r.enable.write(|w| w.enable().set_bit());
+
+ Self {
+ phantom: PhantomData,
+ irq,
+ }
+ }
+
+ /// Start sampling microphon data into a dummy buffer
+ /// Usefull to start the microphon and keep it active between recording samples
+ pub async fn start(&mut self) {
+ let r = Self::regs();
+
+ // start dummy sampling because microphon needs some setup time
+ r.sample
+ .ptr
+ .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
+ r.sample
+ .maxcnt
+ .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
+
+ r.tasks_start.write(|w| w.tasks_start().set_bit());
+ }
+
+ /// Stop sampling microphon data inta a dummy buffer
+ pub async fn stop(&mut self) {
+ let r = Self::regs();
+ r.tasks_stop.write(|w| w.tasks_stop().set_bit());
+ r.events_started.reset();
+ }
+
+ pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> {
+ if buffer.len() == 0 {
+ return Err(Error::BufferZeroLength);
+ }
+ if buffer.len() > EASY_DMA_SIZE {
+ return Err(Error::BufferTooLong);
+ }
+
+ let r = Self::regs();
+
+ if r.events_started.read().events_started().bit_is_clear() {
+ return Err(Error::NotRunning);
+ }
+
+ let drop = OnDrop::new(move || {
+ r.intenclr.write(|w| w.end().clear());
+ r.events_stopped.reset();
+
+ // reset to dummy buffer
+ r.sample
+ .ptr
+ .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
+ r.sample
+ .maxcnt
+ .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
+
+ while r.events_stopped.read().bits() == 0 {}
+ });
+
+ // setup user buffer
+ let ptr = buffer.as_ptr();
+ let len = buffer.len();
+ r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) });
+ r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) });
+
+ // wait till the current sample is finished and the user buffer sample is started
+ Self::wait_for_sample().await;
+
+ // reset the buffer back to the dummy buffer
+ r.sample
+ .ptr
+ .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
+ r.sample
+ .maxcnt
+ .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
+
+ // wait till the user buffer is sampled
+ Self::wait_for_sample().await;
+
+ drop.defuse();
+
+ Ok(())
+ }
+
+ async fn wait_for_sample() {
+ let r = Self::regs();
+
+ r.events_end.reset();
+ r.intenset.write(|w| w.end().set());
+
+ compiler_fence(Ordering::SeqCst);
+
+ poll_fn(|cx| {
+ WAKER.register(cx.waker());
+ if r.events_end.read().events_end().bit_is_set() {
+ return Poll::Ready(());
+ }
+ Poll::Pending
+ })
+ .await;
+
+ compiler_fence(Ordering::SeqCst);
+ }
+
+ fn regs() -> &'static pac::pdm::RegisterBlock {
+ unsafe { &*pac::PDM::ptr() }
+ }
+}
+
+/// PDM microphone driver Config
+pub struct Config {
+ /// Use stero or mono operation
+ pub operation_mode: OperationMode,
+ /// On which edge the left channel should be samples
+ pub edge: Edge,
+}
+
+impl Default for Config {
+ fn default() -> Self {
+ Self {
+ operation_mode: OperationMode::Mono,
+ edge: Edge::LeftFalling,
+ }
+ }
+}
+
+#[derive(PartialEq)]
+pub enum OperationMode {
+ Mono,
+ Stereo,
+}
+#[derive(PartialEq)]
+pub enum Edge {
+ LeftRising,
+ LeftFalling,
+}
+
+impl<'d> Drop for Pdm<'d> {
+ fn drop(&mut self) {
+ let r = Self::regs();
+
+ r.tasks_stop.write(|w| w.tasks_stop().set_bit());
+
+ self.irq.disable();
+
+ r.enable.write(|w| w.enable().disabled());
+
+ r.psel.din.reset();
+ r.psel.clk.reset();
+ }
+}
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 51cd73a47..d821d2353 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -446,25 +446,25 @@ mod eh1 {
type Error = Error;
}
- impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusFlush for Spim<'d, T> {
+ impl<'d, T: Instance> embedded_hal_1::spi::SpiBusFlush for Spim<'d, T> {
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
- impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusRead for Spim<'d, T> {
+ impl<'d, T: Instance> embedded_hal_1::spi::SpiBusRead for Spim<'d, T> {
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
self.blocking_transfer(words, &[])
}
}
- impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusWrite for Spim<'d, T> {
+ impl<'d, T: Instance> embedded_hal_1::spi::SpiBusWrite for Spim<'d, T> {
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(words)
}
}
- impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBus for Spim<'d, T> {
+ impl<'d, T: Instance> embedded_hal_1::spi::SpiBus for Spim<'d, T> {
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
self.blocking_transfer(read, write)
}
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 7c6ca1d30..8d6171fac 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -793,7 +793,7 @@ mod eh1 {
type Error = Error;
}
- impl<'d, T: Instance> embedded_hal_1::i2c::blocking::I2c for Twim<'d, T> {
+ impl<'d, T: Instance> embedded_hal_1::i2c::I2c for Twim<'d, T> {
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.blocking_read(address, buffer)
}
@@ -823,14 +823,14 @@ mod eh1 {
fn transaction<'a>(
&mut self,
_address: u8,
- _operations: &mut [embedded_hal_1::i2c::blocking::Operation<'a>],
+ _operations: &mut [embedded_hal_1::i2c::Operation<'a>],
) -> Result<(), Self::Error> {
todo!();
}
fn transaction_iter<'a, O>(&mut self, _address: u8, _operations: O) -> Result<(), Self::Error>
where
- O: IntoIterator- >,
+ O: IntoIterator
- >,
{
todo!();
}
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 5f9c4f17d..636d6c7a3 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -173,6 +173,61 @@ impl<'d, T: Instance> Uarte<'d, T> {
(self.tx, self.rx)
}
+ /// Split the Uarte into a transmitter and receiver that will
+ /// return on idle, which is determined as the time it takes
+ /// for two bytes to be received.
+ pub fn split_with_idle(
+ self,
+ timer: impl Peripheral
+ 'd,
+ ppi_ch1: impl Peripheral
+ 'd,
+ ppi_ch2: impl Peripheral
+ 'd,
+ ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) {
+ let mut timer = Timer::new(timer);
+
+ into_ref!(ppi_ch1, ppi_ch2);
+
+ let r = T::regs();
+
+ // BAUDRATE register values are `baudrate * 2^32 / 16000000`
+ // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
+ //
+ // We want to stop RX if line is idle for 2 bytes worth of time
+ // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
+ // This gives us the amount of 16M ticks for 20 bits.
+ let baudrate = r.baudrate.read().baudrate().variant().unwrap();
+ let timeout = 0x8000_0000 / (baudrate as u32 / 40);
+
+ timer.set_frequency(Frequency::F16MHz);
+ timer.cc(0).write(timeout);
+ timer.cc(0).short_compare_clear();
+ timer.cc(0).short_compare_stop();
+
+ let mut ppi_ch1 = Ppi::new_one_to_two(
+ ppi_ch1.map_into(),
+ Event::from_reg(&r.events_rxdrdy),
+ timer.task_clear(),
+ timer.task_start(),
+ );
+ ppi_ch1.enable();
+
+ let mut ppi_ch2 = Ppi::new_one_to_one(
+ ppi_ch2.map_into(),
+ timer.cc(0).event_compare(),
+ Task::from_reg(&r.tasks_stoprx),
+ );
+ ppi_ch2.enable();
+
+ (
+ self.tx,
+ UarteRxWithIdle {
+ rx: self.rx,
+ timer,
+ ppi_ch1: ppi_ch1,
+ _ppi_ch2: ppi_ch2,
+ },
+ )
+ }
+
/// Return the endtx event for use with PPI
pub fn event_endtx(&self) -> Event {
let r = T::regs();
@@ -597,6 +652,117 @@ impl<'a, T: Instance> Drop for UarteRx<'a, T> {
}
}
+pub struct UarteRxWithIdle<'d, T: Instance, U: TimerInstance> {
+ rx: UarteRx<'d, T>,
+ timer: Timer<'d, U>,
+ ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>,
+ _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>,
+}
+
+impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> {
+ pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
+ self.ppi_ch1.disable();
+ self.rx.read(buffer).await
+ }
+
+ pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
+ self.ppi_ch1.disable();
+ self.rx.blocking_read(buffer)
+ }
+
+ pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
+ if buffer.len() == 0 {
+ return Err(Error::BufferZeroLength);
+ }
+ if buffer.len() > EASY_DMA_SIZE {
+ return Err(Error::BufferTooLong);
+ }
+
+ let ptr = buffer.as_ptr();
+ let len = buffer.len();
+
+ let r = T::regs();
+ let s = T::state();
+
+ self.ppi_ch1.enable();
+
+ let drop = OnDrop::new(|| {
+ self.timer.stop();
+
+ r.intenclr.write(|w| w.endrx().clear());
+ r.events_rxto.reset();
+ r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
+
+ while r.events_endrx.read().bits() == 0 {}
+ });
+
+ r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
+ r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
+
+ r.events_endrx.reset();
+ r.intenset.write(|w| w.endrx().set());
+
+ compiler_fence(Ordering::SeqCst);
+
+ r.tasks_startrx.write(|w| unsafe { w.bits(1) });
+
+ poll_fn(|cx| {
+ s.endrx_waker.register(cx.waker());
+ if r.events_endrx.read().bits() != 0 {
+ return Poll::Ready(());
+ }
+ Poll::Pending
+ })
+ .await;
+
+ compiler_fence(Ordering::SeqCst);
+ let n = r.rxd.amount.read().amount().bits() as usize;
+
+ self.timer.stop();
+ r.events_rxstarted.reset();
+
+ drop.defuse();
+
+ Ok(n)
+ }
+
+ pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
+ if buffer.len() == 0 {
+ return Err(Error::BufferZeroLength);
+ }
+ if buffer.len() > EASY_DMA_SIZE {
+ return Err(Error::BufferTooLong);
+ }
+
+ let ptr = buffer.as_ptr();
+ let len = buffer.len();
+
+ let r = T::regs();
+
+ self.ppi_ch1.enable();
+
+ r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
+ r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
+
+ r.events_endrx.reset();
+ r.intenclr.write(|w| w.endrx().clear());
+
+ compiler_fence(Ordering::SeqCst);
+
+ r.tasks_startrx.write(|w| unsafe { w.bits(1) });
+
+ while r.events_endrx.read().bits() == 0 {}
+
+ compiler_fence(Ordering::SeqCst);
+ let n = r.rxd.amount.read().amount().bits() as usize;
+
+ self.timer.stop();
+ r.events_rxstarted.reset();
+
+ Ok(n)
+ }
+}
+
#[cfg(not(any(feature = "_nrf9160", feature = "nrf5340")))]
pub(crate) fn apply_workaround_for_enable_anomaly(_r: &crate::pac::uarte0::RegisterBlock) {
// Do nothing
@@ -665,270 +831,6 @@ pub(crate) fn drop_tx_rx(r: &pac::uarte0::RegisterBlock, s: &sealed::State) {
}
}
-/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
-/// allowing it to implement the ReadUntilIdle trait.
-pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
- tx: UarteTx<'d, U>,
- rx: UarteRxWithIdle<'d, U, T>,
-}
-
-impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
- /// Create a new UARTE without hardware flow control
- pub fn new(
- uarte: impl Peripheral + 'd,
- timer: impl Peripheral
+ 'd,
- ppi_ch1: impl Peripheral
+ 'd,
- ppi_ch2: impl Peripheral
+ 'd,
- irq: impl Peripheral
+ 'd,
- rxd: impl Peripheral
+ 'd,
- txd: impl Peripheral
+ 'd,
- config: Config,
- ) -> Self {
- into_ref!(rxd, txd);
- Self::new_inner(
- uarte,
- timer,
- ppi_ch1,
- ppi_ch2,
- irq,
- rxd.map_into(),
- txd.map_into(),
- None,
- None,
- config,
- )
- }
-
- /// Create a new UARTE with hardware flow control (RTS/CTS)
- pub fn new_with_rtscts(
- uarte: impl Peripheral
+ 'd,
- timer: impl Peripheral
+ 'd,
- ppi_ch1: impl Peripheral
+ 'd,
- ppi_ch2: impl Peripheral
+ 'd,
- irq: impl Peripheral
+ 'd,
- rxd: impl Peripheral
+ 'd,
- txd: impl Peripheral
+ 'd,
- cts: impl Peripheral
+ 'd,
- rts: impl Peripheral
+ 'd,
- config: Config,
- ) -> Self {
- into_ref!(rxd, txd, cts, rts);
- Self::new_inner(
- uarte,
- timer,
- ppi_ch1,
- ppi_ch2,
- irq,
- rxd.map_into(),
- txd.map_into(),
- Some(cts.map_into()),
- Some(rts.map_into()),
- config,
- )
- }
-
- fn new_inner(
- uarte: impl Peripheral
+ 'd,
- timer: impl Peripheral
+ 'd,
- ppi_ch1: impl Peripheral
+ 'd,
- ppi_ch2: impl Peripheral
+ 'd,
- irq: impl Peripheral
+ 'd,
- rxd: PeripheralRef<'d, AnyPin>,
- txd: PeripheralRef<'d, AnyPin>,
- cts: Option>,
- rts: Option>,
- config: Config,
- ) -> Self {
- let baudrate = config.baudrate;
- let (tx, rx) = Uarte::new_inner(uarte, irq, rxd, txd, cts, rts, config).split();
-
- let mut timer = Timer::new(timer);
-
- into_ref!(ppi_ch1, ppi_ch2);
-
- let r = U::regs();
-
- // BAUDRATE register values are `baudrate * 2^32 / 16000000`
- // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
- //
- // We want to stop RX if line is idle for 2 bytes worth of time
- // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
- // This gives us the amount of 16M ticks for 20 bits.
- let timeout = 0x8000_0000 / (baudrate as u32 / 40);
-
- timer.set_frequency(Frequency::F16MHz);
- timer.cc(0).write(timeout);
- timer.cc(0).short_compare_clear();
- timer.cc(0).short_compare_stop();
-
- let mut ppi_ch1 = Ppi::new_one_to_two(
- ppi_ch1.map_into(),
- Event::from_reg(&r.events_rxdrdy),
- timer.task_clear(),
- timer.task_start(),
- );
- ppi_ch1.enable();
-
- let mut ppi_ch2 = Ppi::new_one_to_one(
- ppi_ch2.map_into(),
- timer.cc(0).event_compare(),
- Task::from_reg(&r.tasks_stoprx),
- );
- ppi_ch2.enable();
-
- Self {
- tx,
- rx: UarteRxWithIdle {
- rx,
- timer,
- ppi_ch1: ppi_ch1,
- _ppi_ch2: ppi_ch2,
- },
- }
- }
-
- /// Split the Uarte into a transmitter and receiver, which is
- /// particuarly useful when having two tasks correlating to
- /// transmitting and receiving.
- pub fn split(self) -> (UarteTx<'d, U>, UarteRxWithIdle<'d, U, T>) {
- (self.tx, self.rx)
- }
-
- pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
- self.rx.read(buffer).await
- }
-
- pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
- self.tx.write(buffer).await
- }
-
- pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
- self.rx.blocking_read(buffer)
- }
-
- pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
- self.tx.blocking_write(buffer)
- }
-
- pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
- self.rx.read_until_idle(buffer).await
- }
-
- pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
- self.rx.blocking_read_until_idle(buffer)
- }
-}
-
-pub struct UarteRxWithIdle<'d, U: Instance, T: TimerInstance> {
- rx: UarteRx<'d, U>,
- timer: Timer<'d, T>,
- ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>,
- _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>,
-}
-
-impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
- pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
- self.ppi_ch1.disable();
- self.rx.read(buffer).await
- }
-
- pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
- self.ppi_ch1.disable();
- self.rx.blocking_read(buffer)
- }
-
- pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
- if buffer.len() == 0 {
- return Err(Error::BufferZeroLength);
- }
- if buffer.len() > EASY_DMA_SIZE {
- return Err(Error::BufferTooLong);
- }
-
- let ptr = buffer.as_ptr();
- let len = buffer.len();
-
- let r = U::regs();
- let s = U::state();
-
- self.ppi_ch1.enable();
-
- let drop = OnDrop::new(|| {
- self.timer.stop();
-
- r.intenclr.write(|w| w.endrx().clear());
- r.events_rxto.reset();
- r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
-
- while r.events_endrx.read().bits() == 0 {}
- });
-
- r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
- r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
-
- r.events_endrx.reset();
- r.intenset.write(|w| w.endrx().set());
-
- compiler_fence(Ordering::SeqCst);
-
- r.tasks_startrx.write(|w| unsafe { w.bits(1) });
-
- poll_fn(|cx| {
- s.endrx_waker.register(cx.waker());
- if r.events_endrx.read().bits() != 0 {
- return Poll::Ready(());
- }
- Poll::Pending
- })
- .await;
-
- compiler_fence(Ordering::SeqCst);
- let n = r.rxd.amount.read().amount().bits() as usize;
-
- self.timer.stop();
- r.events_rxstarted.reset();
-
- drop.defuse();
-
- Ok(n)
- }
-
- pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
- if buffer.len() == 0 {
- return Err(Error::BufferZeroLength);
- }
- if buffer.len() > EASY_DMA_SIZE {
- return Err(Error::BufferTooLong);
- }
-
- let ptr = buffer.as_ptr();
- let len = buffer.len();
-
- let r = U::regs();
-
- self.ppi_ch1.enable();
-
- r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
- r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
-
- r.events_endrx.reset();
- r.intenclr.write(|w| w.endrx().clear());
-
- compiler_fence(Ordering::SeqCst);
-
- r.tasks_startrx.write(|w| unsafe { w.bits(1) });
-
- while r.events_endrx.read().bits() == 0 {}
-
- compiler_fence(Ordering::SeqCst);
- let n = r.rxd.amount.read().amount().bits() as usize;
-
- self.timer.stop();
- r.events_rxstarted.reset();
-
- Ok(n)
- }
-}
pub(crate) mod sealed {
use core::sync::atomic::AtomicU8;
@@ -1006,18 +908,6 @@ mod eh02 {
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")]
@@ -1040,7 +930,7 @@ mod eh1 {
type Error = Error;
}
- impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for Uarte<'d, T> {
+ impl<'d, T: Instance> embedded_hal_1::serial::Write for Uarte<'d, T> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
}
@@ -1054,7 +944,7 @@ mod eh1 {
type Error = Error;
}
- impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for UarteTx<'d, T> {
+ impl<'d, T: Instance> embedded_hal_1::serial::Write for UarteTx<'d, T> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
}
@@ -1067,10 +957,6 @@ mod eh1 {
impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> {
type Error = Error;
}
-
- impl<'d, U: Instance, T: TimerInstance> embedded_hal_1::serial::ErrorType for UarteWithIdle<'d, U, T> {
- type Error = Error;
- }
}
#[cfg(all(
@@ -1126,26 +1012,4 @@ mod eha {
self.read(buffer)
}
}
-
- impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read for UarteWithIdle<'d, U, T> {
- type ReadFuture<'a> = impl Future