embassy_nrf/radio/
mod.rs

1//! Integrated 2.4 GHz Radio
2//!
3//! The 2.4 GHz radio transceiver is compatible with multiple radio standards
4//! such as 1Mbps, 2Mbps and Long Range Bluetooth Low Energy.
5
6#![macro_use]
7
8/// Bluetooth Low Energy Radio driver.
9#[cfg(any(
10    feature = "nrf52811",
11    feature = "nrf52820",
12    feature = "nrf52833",
13    feature = "nrf52840",
14    feature = "_nrf5340-net"
15))]
16/// IEEE 802.15.4
17pub mod ieee802154;
18
19use core::marker::PhantomData;
20
21use embassy_hal_internal::PeripheralType;
22use embassy_sync::waitqueue::AtomicWaker;
23pub use pac::radio::vals::Txpower as TxPower;
24
25use crate::{interrupt, pac};
26
27/// RADIO error.
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30#[non_exhaustive]
31pub enum Error {
32    /// Buffer was too long.
33    BufferTooLong,
34    /// Buffer was too short.
35    BufferTooShort,
36    /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
37    BufferNotInRAM,
38    /// Clear channel assessment reported channel in use
39    ChannelInUse,
40    /// CRC check failed
41    CrcFailed(u16),
42}
43
44/// Interrupt handler
45pub struct InterruptHandler<T: Instance> {
46    _phantom: PhantomData<T>,
47}
48
49impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
50    unsafe fn on_interrupt() {
51        let r = T::regs();
52        let s = T::state();
53        // clear all interrupts
54        r.intenclr().write(|w| w.0 = 0xffff_ffff);
55        s.event_waker.wake();
56    }
57}
58
59pub(crate) struct State {
60    /// end packet transmission or reception
61    event_waker: AtomicWaker,
62}
63impl State {
64    pub(crate) const fn new() -> Self {
65        Self {
66            event_waker: AtomicWaker::new(),
67        }
68    }
69}
70
71pub(crate) trait SealedInstance {
72    fn regs() -> crate::pac::radio::Radio;
73    fn state() -> &'static State;
74}
75
76macro_rules! impl_radio {
77    ($type:ident, $pac_type:ident, $irq:ident) => {
78        impl crate::radio::SealedInstance for peripherals::$type {
79            fn regs() -> crate::pac::radio::Radio {
80                pac::$pac_type
81            }
82
83            #[allow(unused)]
84            fn state() -> &'static crate::radio::State {
85                static STATE: crate::radio::State = crate::radio::State::new();
86                &STATE
87            }
88        }
89        impl crate::radio::Instance for peripherals::$type {
90            type Interrupt = crate::interrupt::typelevel::$irq;
91        }
92    };
93}
94
95/// Radio peripheral instance.
96#[allow(private_bounds)]
97pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
98    /// Interrupt for this peripheral.
99    type Interrupt: interrupt::typelevel::Interrupt;
100}