From 5e383f004a81e864b66f45d5b12774f755edec95 Mon Sep 17 00:00:00 2001 From: ferris Date: Wed, 25 Oct 2023 13:37:24 +0200 Subject: [PATCH] Add tx_frame & add todos --- embassy-nrf/src/lib.rs | 2 +- embassy-nrf/src/nfc.rs | 86 +++++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index f80312c3..c28cc1d4 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -39,8 +39,8 @@ pub mod gpio; pub mod gpiote; #[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))] pub mod i2s; -pub mod nvmc; pub mod nfc; +pub mod nvmc; #[cfg(any( feature = "nrf52810", feature = "nrf52811", diff --git a/embassy-nrf/src/nfc.rs b/embassy-nrf/src/nfc.rs index 02d4b2d2..5a029285 100644 --- a/embassy-nrf/src/nfc.rs +++ b/embassy-nrf/src/nfc.rs @@ -1,4 +1,7 @@ +//! NFC Tag Driver + #![macro_use] + use core::future::poll_fn; use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; @@ -25,25 +28,16 @@ impl interrupt::typelevel::Handler for InterruptHand r.intenclr.write(|w| w.rxframeend().clear()); WAKER.wake(); } + if r.events_rxerror.read().bits() != 0 { r.intenclr.write(|w| w.rxerror().clear()); WAKER.wake(); } - // if r.events_calibratedone.read().bits() != 0 { - // r.intenclr.write(|w| w.calibratedone().clear()); - // WAKER.wake(); - // } - - // if r.events_end.read().bits() != 0 { - // r.intenclr.write(|w| w.end().clear()); - // WAKER.wake(); - // } - - // if r.events_started.read().bits() != 0 { - // r.intenclr.write(|w| w.started().clear()); - // WAKER.wake(); - // } + if r.events_endtx.read().bits() != 0 { + r.intenclr.write(|w| w.endtx().clear()); + WAKER.wake(); + } } } @@ -85,18 +79,71 @@ impl<'d> NfcT<'d> { fn stop_recv_frame() { let r = Self::regs(); + + r.intenclr.write(|w| w.rxframeend().set_bit()); + r.intenclr.write(|w| w.rxerror().set_bit()); + compiler_fence(Ordering::SeqCst); - r.intenset.write(|w| w.rxframeend().clear_bit()); - r.intenset.write(|w| w.rxerror().clear_bit()); + // FIXME: this might take too long, maybe on start we clear? + while r.events_rxframeend.read().bits() == 0 && r.events_rxerror.read().bits() == 0 {} r.events_rxframeend.reset(); r.events_rxerror.reset(); } + fn stop_tx_frame() { + let r = Self::regs(); + r.intenclr.write(|w| w.endtx().set_bit()); + + compiler_fence(Ordering::SeqCst); + + // FIXME: this might take too long, maybe on start we clear? + while r.events_endtx.read().bits() == 0 {} + r.events_endtx.reset(); + } + + /// Transmit an NFC frame + /// `buf` is not pointing to the Data RAM region, an EasyDMA transfer may result in a hard fault or RAM corruption. + pub async fn tx_frame(&mut self, buf: &[u8]) { + // TODO: requires buf slice in ram validation + let r = Self::regs(); + + let on_drop = OnDrop::new(Self::stop_tx_frame); + + //Setup DMA + r.packetptr.write(|w| unsafe { w.bits(buf.as_ptr() as u32) }); + r.maxlen.write(|w| unsafe { w.bits(buf.len() as _) }); + + r.events_endtx.reset(); + r.intenset.write(|w| w.endtx().set()); + + // Start enablerxdata only after configs are finished writing + compiler_fence(Ordering::SeqCst); + + // Enter TX state + r.tasks_starttx.write(|w| w.tasks_starttx().set_bit()); + + // Wait for 'rxframeend'/'rxerror' event. + poll_fn(|cx| { + let r = Self::regs(); + + WAKER.register(cx.waker()); + + if r.events_endtx.read().bits() != 0 { + r.events_endtx.reset(); + return Poll::Ready(()); + } + + Poll::Pending + }) + .await; + + drop(on_drop); + } + /// Waits for a single frame to be loaded into `buf` - /// `buf`` is not pointing to the Data RAM region, an EasyDMA transfer may result in a hard fault or RAM corruption. + /// `buf` is not pointing to the Data RAM region, an EasyDMA transfer may result in a hard fault or RAM corruption. pub async fn recv_frame(&mut self, buf: &mut [u8; N]) -> Result<(), Error> { - // NOTE: Tx variant requires buf slice in ram validation let r = Self::regs(); let on_drop = OnDrop::new(Self::stop_recv_frame); @@ -111,6 +158,9 @@ impl<'d> NfcT<'d> { r.intenset.write(|w| w.rxframeend().set()); r.intenset.write(|w| w.rxerror().set()); + // Start enablerxdata only after configs are finished writing + compiler_fence(Ordering::SeqCst); + // Enter RX state r.tasks_enablerxdata.write(|w| w.tasks_enablerxdata().set_bit());