NFC recv frame
This commit is contained in:
parent
f956d19e6e
commit
6d8d50f328
@ -40,6 +40,7 @@ pub mod gpiote;
|
||||
#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
|
||||
pub mod i2s;
|
||||
pub mod nvmc;
|
||||
pub mod nfc;
|
||||
#[cfg(any(
|
||||
feature = "nrf52810",
|
||||
feature = "nrf52811",
|
||||
|
144
embassy-nrf/src/nfc.rs
Normal file
144
embassy-nrf/src/nfc.rs
Normal file
@ -0,0 +1,144 @@
|
||||
#![macro_use]
|
||||
use core::future::poll_fn;
|
||||
use core::marker::PhantomData;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
use embassy_hal_internal::drop::OnDrop;
|
||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
// use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
||||
use pac::{nfct, NFCT};
|
||||
|
||||
use crate::util::slice_in_ram;
|
||||
use crate::{interrupt, pac, peripherals, Peripheral};
|
||||
|
||||
/// Interrupt handler.
|
||||
pub struct InterruptHandler {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl interrupt::typelevel::Handler<interrupt::typelevel::NFCT> for InterruptHandler {
|
||||
unsafe fn on_interrupt() {
|
||||
let r = unsafe { &*NFCT::ptr() };
|
||||
if r.events_rxframeend.read().bits() != 0 {
|
||||
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();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
|
||||
/// NFC error.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// Rx Error received while waiting for frame
|
||||
RxError,
|
||||
/// Rx buffer was overrun, increase your buffer size to resolve this
|
||||
RxOverrun,
|
||||
}
|
||||
|
||||
/// Nfc Tag Read/Writer driver
|
||||
pub struct NfcT<'d> {
|
||||
_p: PeripheralRef<'d, NFCT>,
|
||||
}
|
||||
|
||||
impl<'d> NfcT<'d> {
|
||||
/// Create an Nfc Tag driver
|
||||
pub fn new(
|
||||
_p: impl Peripheral<P = NFCT> + 'd,
|
||||
_irq: impl interrupt::typelevel::Binding<interrupt::typelevel::NFCT, InterruptHandler> + 'd,
|
||||
) -> Self {
|
||||
into_ref!(_p);
|
||||
|
||||
let r = unsafe { &*NFCT::ptr() };
|
||||
r.tasks_activate.write(|w| w.tasks_activate().set_bit());
|
||||
|
||||
Self { _p }
|
||||
}
|
||||
|
||||
fn regs() -> &'static nfct::RegisterBlock {
|
||||
unsafe { &*NFCT::ptr() }
|
||||
}
|
||||
|
||||
fn stop_recv_frame() {
|
||||
let r = Self::regs();
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
r.intenset.write(|w| w.rxframeend().clear_bit());
|
||||
r.intenset.write(|w| w.rxerror().clear_bit());
|
||||
r.events_rxframeend.reset();
|
||||
r.events_rxerror.reset();
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub async fn recv_frame<const N: usize>(&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);
|
||||
|
||||
//Setup DMA
|
||||
r.packetptr.write(|w| unsafe { w.bits(buf.as_mut_ptr() as u32) });
|
||||
r.maxlen.write(|w| unsafe { w.bits(N as _) });
|
||||
|
||||
// Reset and enable the end event
|
||||
r.events_rxframeend.reset();
|
||||
r.events_rxerror.reset();
|
||||
r.intenset.write(|w| w.rxframeend().set());
|
||||
r.intenset.write(|w| w.rxerror().set());
|
||||
|
||||
// Enter RX state
|
||||
r.tasks_enablerxdata.write(|w| w.tasks_enablerxdata().set_bit());
|
||||
|
||||
// Wait for 'rxframeend'/'rxerror' event.
|
||||
poll_fn(|cx| {
|
||||
let r = Self::regs();
|
||||
|
||||
WAKER.register(cx.waker());
|
||||
|
||||
if r.events_rxframeend.read().bits() != 0 {
|
||||
r.events_rxframeend.reset();
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
|
||||
if r.events_rxerror.read().bits() != 0 {
|
||||
r.events_rxerror.reset();
|
||||
// If rx buffer is overrun, rxd.amount will indicate a longer message than maxlen & rxerror will be emitted
|
||||
if r.rxd.amount.read().bits() > r.maxlen.read().bits() {
|
||||
return Poll::Ready(Err(Error::RxOverrun));
|
||||
}
|
||||
return Poll::Ready(Err(Error::RxError));
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
})
|
||||
.await?;
|
||||
|
||||
drop(on_drop);
|
||||
Ok(())
|
||||
}
|
||||
}
|
61
embassy-nrf/src/nfc_parse.rs
Normal file
61
embassy-nrf/src/nfc_parse.rs
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
/// Value indicating that the Type 2 Tag contains NFC Forum defined data.
|
||||
const NFC_T2T_NFC_FORUM_DEFINED_DATA: u8 = 0xE1;
|
||||
|
||||
/// Value used for calculating the first BCC byte of a Type 2 Tag serial number.
|
||||
const NFC_T2T_UID_BCC_CASCADE_BYTE: u8 = 0x88;
|
||||
|
||||
/// Supported major version of the Type 2 Tag specification.
|
||||
const NFC_T2T_SUPPORTED_MAJOR_VERSION: u8 = 1;
|
||||
|
||||
/// Supported minor version of the Type 2 Tag specification.
|
||||
const NFC_T2T_SUPPORTED_MINOR_VERSION: u8 = 0;
|
||||
|
||||
/// Type 2 Tag block size in bytes.
|
||||
const NFC_T2T_BLOCK_SIZE: u8 = 4;
|
||||
|
||||
/// Offset of the Capability Container area in the Type 2 Tag.
|
||||
const NFC_T2T_CC_BLOCK_OFFSET: u8 = 12;
|
||||
|
||||
/// Offset of the data area in the Type 2 Tag.
|
||||
const NFC_T2T_FIRST_DATA_BLOCK_OFFSET: u8 = 16;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NfcType2Capabilities {
|
||||
major_ver: u8,
|
||||
minor_ver: u8,
|
||||
data_area_size: u8,
|
||||
read_access: u8,
|
||||
write_access: u8
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NfcType2TagSerial {
|
||||
manufacturer_id: u8,
|
||||
serial_nr_l: u16,
|
||||
serial_nr_h: u32,
|
||||
check_byte_0: u8,
|
||||
check_byte_1: u8,
|
||||
internal: u8,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NfcType2Tag<const MAX_BLOCKS: usize> {
|
||||
sn: NfcType2TagSerial,
|
||||
lock_bytes: u16,
|
||||
capabilities: NfcType2Capabilities,
|
||||
max_tlv: u16,
|
||||
tlv_block_array: [u8; MAX_BLOCKS],
|
||||
count_tlv: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
VersionNotSupported,
|
||||
}
|
||||
|
||||
pub fn parsee_type2<const N: usize>() -> Result<NfcType2Tag<N> {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user