- Added _ppi and _dppi to distinguish between the new and the old peripheral.
- Removed ConfigurableChannel and added capacity numbers to the channels - Replaced the PPI api with a new one using the DPPI terminology (publish & subscribe) - Updated all tasks and event registers for DPPI
This commit is contained in:
parent
01e5376b25
commit
65628e1f15
14 changed files with 696 additions and 370 deletions
|
@ -18,18 +18,20 @@ defmt-info = [ ]
|
|||
defmt-warn = [ ]
|
||||
defmt-error = [ ]
|
||||
|
||||
nrf52805 = ["nrf52805-pac"]
|
||||
nrf52810 = ["nrf52810-pac"]
|
||||
nrf52811 = ["nrf52811-pac"]
|
||||
nrf52820 = ["nrf52820-pac"]
|
||||
nrf52832 = ["nrf52832-pac"]
|
||||
nrf52833 = ["nrf52833-pac"]
|
||||
nrf52840 = ["nrf52840-pac"]
|
||||
nrf9160 = ["nrf9160-pac"]
|
||||
nrf52805 = ["nrf52805-pac", "_ppi"]
|
||||
nrf52810 = ["nrf52810-pac", "_ppi"]
|
||||
nrf52811 = ["nrf52811-pac", "_ppi"]
|
||||
nrf52820 = ["nrf52820-pac", "_ppi"]
|
||||
nrf52832 = ["nrf52832-pac", "_ppi"]
|
||||
nrf52833 = ["nrf52833-pac", "_ppi"]
|
||||
nrf52840 = ["nrf52840-pac", "_ppi"]
|
||||
nrf9160 = ["nrf9160-pac", "_dppi"]
|
||||
|
||||
# Features starting with `_` are for internal use only. They're not intended
|
||||
# to be enabled by other crates, and are not covered by semver guarantees.
|
||||
_time-driver = ["embassy/time-tick-32768hz"]
|
||||
_ppi = []
|
||||
_dppi = []
|
||||
|
||||
gpiote = []
|
||||
time-driver-rtc1 = ["_time-driver"]
|
||||
|
|
|
@ -5,7 +5,7 @@ use core::pin::Pin;
|
|||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::{Context, Poll};
|
||||
use embassy::interrupt::InterruptExt;
|
||||
use embassy::io::{AsyncBufRead, AsyncWrite, Result};
|
||||
use embassy::io::{AsyncBufRead, AsyncWrite};
|
||||
use embassy::util::Unborrow;
|
||||
use embassy::waitqueue::WakerRegistration;
|
||||
use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
|
||||
|
@ -14,15 +14,27 @@ use embassy_hal_common::{low_power_wait_until, unborrow};
|
|||
|
||||
use crate::gpio::sealed::Pin as _;
|
||||
use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
||||
use crate::pac;
|
||||
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
||||
use crate::ppi::{AnyChannel, Channel, Event, Ppi, Task};
|
||||
use crate::timer::Instance as TimerInstance;
|
||||
use crate::timer::{Frequency, Timer};
|
||||
use crate::uarte::{Config, Instance as UarteInstance};
|
||||
use crate::{pac, ppi};
|
||||
|
||||
// Re-export SVD variants to allow user to directly set values
|
||||
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Error {
|
||||
PpiError(ppi::Error),
|
||||
}
|
||||
|
||||
impl From<ppi::Error> for Error {
|
||||
fn from(e: ppi::Error) -> Self {
|
||||
Self::PpiError(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum RxState {
|
||||
Idle,
|
||||
|
@ -45,8 +57,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> {
|
|||
struct StateInner<'d, U: UarteInstance, T: TimerInstance> {
|
||||
phantom: PhantomData<&'d mut U>,
|
||||
timer: Timer<'d, T>,
|
||||
_ppi_ch1: Ppi<'d, AnyConfigurableChannel>,
|
||||
_ppi_ch2: Ppi<'d, AnyConfigurableChannel>,
|
||||
_ppi_ch1: Ppi<'d, AnyChannel>,
|
||||
_ppi_ch2: Ppi<'d, AnyChannel>,
|
||||
|
||||
rx: RingBuffer<'d>,
|
||||
rx_state: RxState,
|
||||
|
@ -66,12 +78,15 @@ impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {
|
|||
|
||||
impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
||||
/// unsafe: may not leak self or futures
|
||||
///
|
||||
/// - *Note:* ppi_ch1 must have at least 1 free event and 2 free tasks or a PPI error is returned
|
||||
/// - *Note:* ppi_ch2 must have at least 1 free event and 1 free tasks or a PPI error is returned
|
||||
pub unsafe fn new(
|
||||
state: &'d mut State<'d, U, T>,
|
||||
_uarte: impl Unborrow<Target = U> + 'd,
|
||||
timer: impl Unborrow<Target = T> + 'd,
|
||||
ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel> + 'd,
|
||||
ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel> + 'd,
|
||||
ppi_ch1: impl Unborrow<Target = impl Channel> + 'd,
|
||||
ppi_ch2: impl Unborrow<Target = impl Channel> + 'd,
|
||||
irq: impl Unborrow<Target = U::Interrupt> + 'd,
|
||||
rxd: impl Unborrow<Target = impl GpioPin> + 'd,
|
||||
txd: impl Unborrow<Target = impl GpioPin> + 'd,
|
||||
|
@ -80,7 +95,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||
config: Config,
|
||||
rx_buffer: &'d mut [u8],
|
||||
tx_buffer: &'d mut [u8],
|
||||
) -> Self {
|
||||
) -> Result<Self, Error> {
|
||||
unborrow!(ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts);
|
||||
|
||||
let r = U::regs();
|
||||
|
@ -144,18 +159,18 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||
timer.cc(0).short_compare_clear();
|
||||
timer.cc(0).short_compare_stop();
|
||||
|
||||
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable());
|
||||
ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy));
|
||||
ppi_ch1.set_task(timer.task_clear());
|
||||
ppi_ch1.set_fork_task(timer.task_start());
|
||||
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade());
|
||||
ppi_ch1.publish(Event::from_reg(&r.events_rxdrdy))?;
|
||||
ppi_ch1.subscribe(timer.task_clear())?;
|
||||
ppi_ch1.subscribe(timer.task_start())?;
|
||||
ppi_ch1.enable();
|
||||
|
||||
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable());
|
||||
ppi_ch2.set_event(timer.cc(0).event_compare());
|
||||
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
|
||||
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade());
|
||||
ppi_ch2.publish(timer.cc(0).event_compare())?;
|
||||
ppi_ch2.subscribe(Task::from_reg(&r.tasks_stoprx))?;
|
||||
ppi_ch2.enable();
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
|
||||
phantom: PhantomData,
|
||||
timer,
|
||||
|
@ -170,7 +185,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||
tx_state: TxState::Idle,
|
||||
tx_waker: WakerRegistration::new(),
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_baudrate(&mut self, baudrate: Baudrate) {
|
||||
|
@ -187,7 +202,10 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||
}
|
||||
|
||||
impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, U, T> {
|
||||
fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
|
||||
fn poll_fill_buf(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<embassy::io::Result<&[u8]>> {
|
||||
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,
|
||||
|
@ -206,7 +224,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d,
|
|||
|
||||
trace!(" empty");
|
||||
state.rx_waker.register(cx.waker());
|
||||
Poll::<Result<&[u8]>>::Pending
|
||||
Poll::<embassy::io::Result<&[u8]>>::Pending
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -224,7 +242,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U,
|
|||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize>> {
|
||||
) -> Poll<embassy::io::Result<usize>> {
|
||||
let poll = self.inner.with(|state| {
|
||||
trace!("poll_write: {:?}", buf.len());
|
||||
|
||||
|
|
|
@ -167,28 +167,28 @@ impl_pin!(P0_29, 0, 29);
|
|||
impl_pin!(P0_30, 0, 30);
|
||||
impl_pin!(P0_31, 0, 31);
|
||||
|
||||
impl_ppi_channel!(PPI_CH0, 0, configurable);
|
||||
impl_ppi_channel!(PPI_CH1, 1, configurable);
|
||||
impl_ppi_channel!(PPI_CH2, 2, configurable);
|
||||
impl_ppi_channel!(PPI_CH3, 3, configurable);
|
||||
impl_ppi_channel!(PPI_CH4, 4, configurable);
|
||||
impl_ppi_channel!(PPI_CH5, 5, configurable);
|
||||
impl_ppi_channel!(PPI_CH6, 6, configurable);
|
||||
impl_ppi_channel!(PPI_CH7, 7, configurable);
|
||||
impl_ppi_channel!(PPI_CH8, 8, configurable);
|
||||
impl_ppi_channel!(PPI_CH9, 9, configurable);
|
||||
impl_ppi_channel!(PPI_CH20, 20);
|
||||
impl_ppi_channel!(PPI_CH21, 21);
|
||||
impl_ppi_channel!(PPI_CH22, 22);
|
||||
impl_ppi_channel!(PPI_CH23, 23);
|
||||
impl_ppi_channel!(PPI_CH24, 24);
|
||||
impl_ppi_channel!(PPI_CH25, 25);
|
||||
impl_ppi_channel!(PPI_CH26, 26);
|
||||
impl_ppi_channel!(PPI_CH27, 27);
|
||||
impl_ppi_channel!(PPI_CH28, 28);
|
||||
impl_ppi_channel!(PPI_CH29, 29);
|
||||
impl_ppi_channel!(PPI_CH30, 30);
|
||||
impl_ppi_channel!(PPI_CH31, 31);
|
||||
impl_ppi_channel!(PPI_CH0, 0, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH1, 1, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH2, 2, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH3, 3, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH4, 4, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH5, 5, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH6, 6, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH7, 7, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH8, 8, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH9, 9, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH20, 20, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH21, 21, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH22, 22, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH23, 23, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH24, 24, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH25, 25, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH26, 26, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH27, 27, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH28, 28, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH29, 29, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH30, 30, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH31, 31, 1, 0);
|
||||
|
||||
impl_saadc_input!(P0_04, ANALOGINPUT2);
|
||||
impl_saadc_input!(P0_05, ANALOGINPUT3);
|
||||
|
|
|
@ -172,38 +172,38 @@ impl_pin!(P0_29, 0, 29);
|
|||
impl_pin!(P0_30, 0, 30);
|
||||
impl_pin!(P0_31, 0, 31);
|
||||
|
||||
impl_ppi_channel!(PPI_CH0, 0, configurable);
|
||||
impl_ppi_channel!(PPI_CH1, 1, configurable);
|
||||
impl_ppi_channel!(PPI_CH2, 2, configurable);
|
||||
impl_ppi_channel!(PPI_CH3, 3, configurable);
|
||||
impl_ppi_channel!(PPI_CH4, 4, configurable);
|
||||
impl_ppi_channel!(PPI_CH5, 5, configurable);
|
||||
impl_ppi_channel!(PPI_CH6, 6, configurable);
|
||||
impl_ppi_channel!(PPI_CH7, 7, configurable);
|
||||
impl_ppi_channel!(PPI_CH8, 8, configurable);
|
||||
impl_ppi_channel!(PPI_CH9, 9, configurable);
|
||||
impl_ppi_channel!(PPI_CH10, 10, configurable);
|
||||
impl_ppi_channel!(PPI_CH11, 11, configurable);
|
||||
impl_ppi_channel!(PPI_CH12, 12, configurable);
|
||||
impl_ppi_channel!(PPI_CH13, 13, configurable);
|
||||
impl_ppi_channel!(PPI_CH14, 14, configurable);
|
||||
impl_ppi_channel!(PPI_CH15, 15, configurable);
|
||||
impl_ppi_channel!(PPI_CH16, 16, configurable);
|
||||
impl_ppi_channel!(PPI_CH17, 17, configurable);
|
||||
impl_ppi_channel!(PPI_CH18, 18, configurable);
|
||||
impl_ppi_channel!(PPI_CH19, 19, configurable);
|
||||
impl_ppi_channel!(PPI_CH20, 20);
|
||||
impl_ppi_channel!(PPI_CH21, 21);
|
||||
impl_ppi_channel!(PPI_CH22, 22);
|
||||
impl_ppi_channel!(PPI_CH23, 23);
|
||||
impl_ppi_channel!(PPI_CH24, 24);
|
||||
impl_ppi_channel!(PPI_CH25, 25);
|
||||
impl_ppi_channel!(PPI_CH26, 26);
|
||||
impl_ppi_channel!(PPI_CH27, 27);
|
||||
impl_ppi_channel!(PPI_CH28, 28);
|
||||
impl_ppi_channel!(PPI_CH29, 29);
|
||||
impl_ppi_channel!(PPI_CH30, 30);
|
||||
impl_ppi_channel!(PPI_CH31, 31);
|
||||
impl_ppi_channel!(PPI_CH0, 0, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH1, 1, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH2, 2, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH3, 3, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH4, 4, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH5, 5, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH6, 6, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH7, 7, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH8, 8, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH9, 9, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH10, 10, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH11, 11, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH12, 12, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH13, 13, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH14, 14, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH15, 15, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH16, 16, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH17, 17, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH18, 18, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH19, 19, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH20, 20, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH21, 21, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH22, 22, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH23, 23, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH24, 24, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH25, 25, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH26, 26, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH27, 27, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH28, 28, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH29, 29, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH30, 30, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH31, 31, 1, 0);
|
||||
|
||||
impl_saadc_input!(P0_02, ANALOGINPUT0);
|
||||
impl_saadc_input!(P0_03, ANALOGINPUT1);
|
||||
|
|
|
@ -173,38 +173,38 @@ impl_pin!(P0_29, 0, 29);
|
|||
impl_pin!(P0_30, 0, 30);
|
||||
impl_pin!(P0_31, 0, 31);
|
||||
|
||||
impl_ppi_channel!(PPI_CH0, 0, configurable);
|
||||
impl_ppi_channel!(PPI_CH1, 1, configurable);
|
||||
impl_ppi_channel!(PPI_CH2, 2, configurable);
|
||||
impl_ppi_channel!(PPI_CH3, 3, configurable);
|
||||
impl_ppi_channel!(PPI_CH4, 4, configurable);
|
||||
impl_ppi_channel!(PPI_CH5, 5, configurable);
|
||||
impl_ppi_channel!(PPI_CH6, 6, configurable);
|
||||
impl_ppi_channel!(PPI_CH7, 7, configurable);
|
||||
impl_ppi_channel!(PPI_CH8, 8, configurable);
|
||||
impl_ppi_channel!(PPI_CH9, 9, configurable);
|
||||
impl_ppi_channel!(PPI_CH10, 10, configurable);
|
||||
impl_ppi_channel!(PPI_CH11, 11, configurable);
|
||||
impl_ppi_channel!(PPI_CH12, 12, configurable);
|
||||
impl_ppi_channel!(PPI_CH13, 13, configurable);
|
||||
impl_ppi_channel!(PPI_CH14, 14, configurable);
|
||||
impl_ppi_channel!(PPI_CH15, 15, configurable);
|
||||
impl_ppi_channel!(PPI_CH16, 16, configurable);
|
||||
impl_ppi_channel!(PPI_CH17, 17, configurable);
|
||||
impl_ppi_channel!(PPI_CH18, 18, configurable);
|
||||
impl_ppi_channel!(PPI_CH19, 19, configurable);
|
||||
impl_ppi_channel!(PPI_CH20, 20);
|
||||
impl_ppi_channel!(PPI_CH21, 21);
|
||||
impl_ppi_channel!(PPI_CH22, 22);
|
||||
impl_ppi_channel!(PPI_CH23, 23);
|
||||
impl_ppi_channel!(PPI_CH24, 24);
|
||||
impl_ppi_channel!(PPI_CH25, 25);
|
||||
impl_ppi_channel!(PPI_CH26, 26);
|
||||
impl_ppi_channel!(PPI_CH27, 27);
|
||||
impl_ppi_channel!(PPI_CH28, 28);
|
||||
impl_ppi_channel!(PPI_CH29, 29);
|
||||
impl_ppi_channel!(PPI_CH30, 30);
|
||||
impl_ppi_channel!(PPI_CH31, 31);
|
||||
impl_ppi_channel!(PPI_CH0, 0, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH1, 1, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH2, 2, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH3, 3, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH4, 4, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH5, 5, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH6, 6, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH7, 7, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH8, 8, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH9, 9, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH10, 10, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH11, 11, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH12, 12, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH13, 13, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH14, 14, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH15, 15, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH16, 16, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH17, 17, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH18, 18, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH19, 19, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH20, 20, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH21, 21, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH22, 22, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH23, 23, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH24, 24, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH25, 25, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH26, 26, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH27, 27, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH28, 28, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH29, 29, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH30, 30, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH31, 31, 1, 0);
|
||||
|
||||
impl_saadc_input!(P0_02, ANALOGINPUT0);
|
||||
impl_saadc_input!(P0_03, ANALOGINPUT1);
|
||||
|
|
|
@ -168,38 +168,38 @@ impl_pin!(P0_29, 0, 29);
|
|||
impl_pin!(P0_30, 0, 30);
|
||||
impl_pin!(P0_31, 0, 31);
|
||||
|
||||
impl_ppi_channel!(PPI_CH0, 0, configurable);
|
||||
impl_ppi_channel!(PPI_CH1, 1, configurable);
|
||||
impl_ppi_channel!(PPI_CH2, 2, configurable);
|
||||
impl_ppi_channel!(PPI_CH3, 3, configurable);
|
||||
impl_ppi_channel!(PPI_CH4, 4, configurable);
|
||||
impl_ppi_channel!(PPI_CH5, 5, configurable);
|
||||
impl_ppi_channel!(PPI_CH6, 6, configurable);
|
||||
impl_ppi_channel!(PPI_CH7, 7, configurable);
|
||||
impl_ppi_channel!(PPI_CH8, 8, configurable);
|
||||
impl_ppi_channel!(PPI_CH9, 9, configurable);
|
||||
impl_ppi_channel!(PPI_CH10, 10, configurable);
|
||||
impl_ppi_channel!(PPI_CH11, 11, configurable);
|
||||
impl_ppi_channel!(PPI_CH12, 12, configurable);
|
||||
impl_ppi_channel!(PPI_CH13, 13, configurable);
|
||||
impl_ppi_channel!(PPI_CH14, 14, configurable);
|
||||
impl_ppi_channel!(PPI_CH15, 15, configurable);
|
||||
impl_ppi_channel!(PPI_CH16, 16, configurable);
|
||||
impl_ppi_channel!(PPI_CH17, 17, configurable);
|
||||
impl_ppi_channel!(PPI_CH18, 18, configurable);
|
||||
impl_ppi_channel!(PPI_CH19, 19, configurable);
|
||||
impl_ppi_channel!(PPI_CH20, 20);
|
||||
impl_ppi_channel!(PPI_CH21, 21);
|
||||
impl_ppi_channel!(PPI_CH22, 22);
|
||||
impl_ppi_channel!(PPI_CH23, 23);
|
||||
impl_ppi_channel!(PPI_CH24, 24);
|
||||
impl_ppi_channel!(PPI_CH25, 25);
|
||||
impl_ppi_channel!(PPI_CH26, 26);
|
||||
impl_ppi_channel!(PPI_CH27, 27);
|
||||
impl_ppi_channel!(PPI_CH28, 28);
|
||||
impl_ppi_channel!(PPI_CH29, 29);
|
||||
impl_ppi_channel!(PPI_CH30, 30);
|
||||
impl_ppi_channel!(PPI_CH31, 31);
|
||||
impl_ppi_channel!(PPI_CH0, 0, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH1, 1, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH2, 2, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH3, 3, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH4, 4, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH5, 5, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH6, 6, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH7, 7, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH8, 8, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH9, 9, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH10, 10, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH11, 11, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH12, 12, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH13, 13, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH14, 14, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH15, 15, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH16, 16, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH17, 17, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH18, 18, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH19, 19, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH20, 20, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH21, 21, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH22, 22, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH23, 23, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH24, 24, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH25, 25, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH26, 26, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH27, 27, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH28, 28, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH29, 29, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH30, 30, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH31, 31, 1, 0);
|
||||
|
||||
pub mod irqs {
|
||||
use crate::pac::Interrupt as InterruptEnum;
|
||||
|
|
|
@ -190,38 +190,38 @@ impl_pin!(P0_29, 0, 29);
|
|||
impl_pin!(P0_30, 0, 30);
|
||||
impl_pin!(P0_31, 0, 31);
|
||||
|
||||
impl_ppi_channel!(PPI_CH0, 0, configurable);
|
||||
impl_ppi_channel!(PPI_CH1, 1, configurable);
|
||||
impl_ppi_channel!(PPI_CH2, 2, configurable);
|
||||
impl_ppi_channel!(PPI_CH3, 3, configurable);
|
||||
impl_ppi_channel!(PPI_CH4, 4, configurable);
|
||||
impl_ppi_channel!(PPI_CH5, 5, configurable);
|
||||
impl_ppi_channel!(PPI_CH6, 6, configurable);
|
||||
impl_ppi_channel!(PPI_CH7, 7, configurable);
|
||||
impl_ppi_channel!(PPI_CH8, 8, configurable);
|
||||
impl_ppi_channel!(PPI_CH9, 9, configurable);
|
||||
impl_ppi_channel!(PPI_CH10, 10, configurable);
|
||||
impl_ppi_channel!(PPI_CH11, 11, configurable);
|
||||
impl_ppi_channel!(PPI_CH12, 12, configurable);
|
||||
impl_ppi_channel!(PPI_CH13, 13, configurable);
|
||||
impl_ppi_channel!(PPI_CH14, 14, configurable);
|
||||
impl_ppi_channel!(PPI_CH15, 15, configurable);
|
||||
impl_ppi_channel!(PPI_CH16, 16, configurable);
|
||||
impl_ppi_channel!(PPI_CH17, 17, configurable);
|
||||
impl_ppi_channel!(PPI_CH18, 18, configurable);
|
||||
impl_ppi_channel!(PPI_CH19, 19, configurable);
|
||||
impl_ppi_channel!(PPI_CH20, 20);
|
||||
impl_ppi_channel!(PPI_CH21, 21);
|
||||
impl_ppi_channel!(PPI_CH22, 22);
|
||||
impl_ppi_channel!(PPI_CH23, 23);
|
||||
impl_ppi_channel!(PPI_CH24, 24);
|
||||
impl_ppi_channel!(PPI_CH25, 25);
|
||||
impl_ppi_channel!(PPI_CH26, 26);
|
||||
impl_ppi_channel!(PPI_CH27, 27);
|
||||
impl_ppi_channel!(PPI_CH28, 28);
|
||||
impl_ppi_channel!(PPI_CH29, 29);
|
||||
impl_ppi_channel!(PPI_CH30, 30);
|
||||
impl_ppi_channel!(PPI_CH31, 31);
|
||||
impl_ppi_channel!(PPI_CH0, 0, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH1, 1, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH2, 2, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH3, 3, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH4, 4, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH5, 5, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH6, 6, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH7, 7, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH8, 8, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH9, 9, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH10, 10, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH11, 11, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH12, 12, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH13, 13, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH14, 14, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH15, 15, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH16, 16, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH17, 17, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH18, 18, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH19, 19, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH20, 20, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH21, 21, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH22, 22, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH23, 23, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH24, 24, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH25, 25, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH26, 26, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH27, 27, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH28, 28, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH29, 29, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH30, 30, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH31, 31, 1, 0);
|
||||
|
||||
impl_saadc_input!(P0_02, ANALOGINPUT0);
|
||||
impl_saadc_input!(P0_03, ANALOGINPUT1);
|
||||
|
|
|
@ -226,38 +226,38 @@ impl_pin!(P1_13, 1, 13);
|
|||
impl_pin!(P1_14, 1, 14);
|
||||
impl_pin!(P1_15, 1, 15);
|
||||
|
||||
impl_ppi_channel!(PPI_CH0, 0, configurable);
|
||||
impl_ppi_channel!(PPI_CH1, 1, configurable);
|
||||
impl_ppi_channel!(PPI_CH2, 2, configurable);
|
||||
impl_ppi_channel!(PPI_CH3, 3, configurable);
|
||||
impl_ppi_channel!(PPI_CH4, 4, configurable);
|
||||
impl_ppi_channel!(PPI_CH5, 5, configurable);
|
||||
impl_ppi_channel!(PPI_CH6, 6, configurable);
|
||||
impl_ppi_channel!(PPI_CH7, 7, configurable);
|
||||
impl_ppi_channel!(PPI_CH8, 8, configurable);
|
||||
impl_ppi_channel!(PPI_CH9, 9, configurable);
|
||||
impl_ppi_channel!(PPI_CH10, 10, configurable);
|
||||
impl_ppi_channel!(PPI_CH11, 11, configurable);
|
||||
impl_ppi_channel!(PPI_CH12, 12, configurable);
|
||||
impl_ppi_channel!(PPI_CH13, 13, configurable);
|
||||
impl_ppi_channel!(PPI_CH14, 14, configurable);
|
||||
impl_ppi_channel!(PPI_CH15, 15, configurable);
|
||||
impl_ppi_channel!(PPI_CH16, 16, configurable);
|
||||
impl_ppi_channel!(PPI_CH17, 17, configurable);
|
||||
impl_ppi_channel!(PPI_CH18, 18, configurable);
|
||||
impl_ppi_channel!(PPI_CH19, 19, configurable);
|
||||
impl_ppi_channel!(PPI_CH20, 20);
|
||||
impl_ppi_channel!(PPI_CH21, 21);
|
||||
impl_ppi_channel!(PPI_CH22, 22);
|
||||
impl_ppi_channel!(PPI_CH23, 23);
|
||||
impl_ppi_channel!(PPI_CH24, 24);
|
||||
impl_ppi_channel!(PPI_CH25, 25);
|
||||
impl_ppi_channel!(PPI_CH26, 26);
|
||||
impl_ppi_channel!(PPI_CH27, 27);
|
||||
impl_ppi_channel!(PPI_CH28, 28);
|
||||
impl_ppi_channel!(PPI_CH29, 29);
|
||||
impl_ppi_channel!(PPI_CH30, 30);
|
||||
impl_ppi_channel!(PPI_CH31, 31);
|
||||
impl_ppi_channel!(PPI_CH0, 0, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH1, 1, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH2, 2, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH3, 3, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH4, 4, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH5, 5, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH6, 6, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH7, 7, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH8, 8, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH9, 9, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH10, 10, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH11, 11, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH12, 12, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH13, 13, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH14, 14, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH15, 15, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH16, 16, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH17, 17, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH18, 18, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH19, 19, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH20, 20, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH21, 21, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH22, 22, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH23, 23, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH24, 24, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH25, 25, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH26, 26, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH27, 27, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH28, 28, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH29, 29, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH30, 30, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH31, 31, 1, 0);
|
||||
|
||||
impl_saadc_input!(P0_02, ANALOGINPUT0);
|
||||
impl_saadc_input!(P0_03, ANALOGINPUT1);
|
||||
|
|
|
@ -231,38 +231,38 @@ impl_pin!(P1_13, 1, 13);
|
|||
impl_pin!(P1_14, 1, 14);
|
||||
impl_pin!(P1_15, 1, 15);
|
||||
|
||||
impl_ppi_channel!(PPI_CH0, 0, configurable);
|
||||
impl_ppi_channel!(PPI_CH1, 1, configurable);
|
||||
impl_ppi_channel!(PPI_CH2, 2, configurable);
|
||||
impl_ppi_channel!(PPI_CH3, 3, configurable);
|
||||
impl_ppi_channel!(PPI_CH4, 4, configurable);
|
||||
impl_ppi_channel!(PPI_CH5, 5, configurable);
|
||||
impl_ppi_channel!(PPI_CH6, 6, configurable);
|
||||
impl_ppi_channel!(PPI_CH7, 7, configurable);
|
||||
impl_ppi_channel!(PPI_CH8, 8, configurable);
|
||||
impl_ppi_channel!(PPI_CH9, 9, configurable);
|
||||
impl_ppi_channel!(PPI_CH10, 10, configurable);
|
||||
impl_ppi_channel!(PPI_CH11, 11, configurable);
|
||||
impl_ppi_channel!(PPI_CH12, 12, configurable);
|
||||
impl_ppi_channel!(PPI_CH13, 13, configurable);
|
||||
impl_ppi_channel!(PPI_CH14, 14, configurable);
|
||||
impl_ppi_channel!(PPI_CH15, 15, configurable);
|
||||
impl_ppi_channel!(PPI_CH16, 16, configurable);
|
||||
impl_ppi_channel!(PPI_CH17, 17, configurable);
|
||||
impl_ppi_channel!(PPI_CH18, 18, configurable);
|
||||
impl_ppi_channel!(PPI_CH19, 19, configurable);
|
||||
impl_ppi_channel!(PPI_CH20, 20);
|
||||
impl_ppi_channel!(PPI_CH21, 21);
|
||||
impl_ppi_channel!(PPI_CH22, 22);
|
||||
impl_ppi_channel!(PPI_CH23, 23);
|
||||
impl_ppi_channel!(PPI_CH24, 24);
|
||||
impl_ppi_channel!(PPI_CH25, 25);
|
||||
impl_ppi_channel!(PPI_CH26, 26);
|
||||
impl_ppi_channel!(PPI_CH27, 27);
|
||||
impl_ppi_channel!(PPI_CH28, 28);
|
||||
impl_ppi_channel!(PPI_CH29, 29);
|
||||
impl_ppi_channel!(PPI_CH30, 30);
|
||||
impl_ppi_channel!(PPI_CH31, 31);
|
||||
impl_ppi_channel!(PPI_CH0, 0, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH1, 1, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH2, 2, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH3, 3, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH4, 4, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH5, 5, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH6, 6, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH7, 7, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH8, 8, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH9, 9, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH10, 10, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH11, 11, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH12, 12, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH13, 13, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH14, 14, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH15, 15, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH16, 16, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH17, 17, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH18, 18, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH19, 19, 2, 1);
|
||||
impl_ppi_channel!(PPI_CH20, 20, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH21, 21, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH22, 22, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH23, 23, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH24, 24, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH25, 25, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH26, 26, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH27, 27, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH28, 28, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH29, 29, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH30, 30, 1, 0);
|
||||
impl_ppi_channel!(PPI_CH31, 31, 1, 0);
|
||||
|
||||
impl_saadc_input!(P0_02, ANALOGINPUT0);
|
||||
impl_saadc_input!(P0_03, ANALOGINPUT1);
|
||||
|
|
|
@ -190,7 +190,13 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
|
|||
/// Returns the IN event, for use with PPI.
|
||||
pub fn event_in(&self) -> Event {
|
||||
let g = unsafe { &*pac::GPIOTE::ptr() };
|
||||
Event::from_reg(&g.events_in[self.ch.number()])
|
||||
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &g.events_in[self.ch.number()];
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &g.publish_in[self.ch.number()];
|
||||
|
||||
Event::from_reg(reg)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,21 +277,33 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
|
|||
/// Returns the OUT task, for use with PPI.
|
||||
pub fn task_out(&self) -> Task {
|
||||
let g = unsafe { &*pac::GPIOTE::ptr() };
|
||||
Task::from_reg(&g.tasks_out[self.ch.number()])
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &g.tasks_out[self.ch.number()];
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &g.subscribe_out[self.ch.number()];
|
||||
Task::from_reg(reg)
|
||||
}
|
||||
|
||||
/// Returns the CLR task, for use with PPI.
|
||||
#[cfg(not(feature = "nrf51"))]
|
||||
pub fn task_clr(&self) -> Task {
|
||||
let g = unsafe { &*pac::GPIOTE::ptr() };
|
||||
Task::from_reg(&g.tasks_clr[self.ch.number()])
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &g.tasks_clr[self.ch.number()];
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &g.subscribe_clr[self.ch.number()];
|
||||
Task::from_reg(reg)
|
||||
}
|
||||
|
||||
/// Returns the SET task, for use with PPI.
|
||||
#[cfg(not(feature = "nrf51"))]
|
||||
pub fn task_set(&self) -> Task {
|
||||
let g = unsafe { &*pac::GPIOTE::ptr() };
|
||||
Task::from_reg(&g.tasks_set[self.ch.number()])
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &g.tasks_set[self.ch.number()];
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &g.subscribe_set[self.ch.number()];
|
||||
Task::from_reg(reg)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,16 @@ use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
|
|||
// ======================
|
||||
// driver
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Error {
|
||||
NoCapacityLeft,
|
||||
UnknownTask,
|
||||
TaskAlreadyInUse,
|
||||
UnknownEvent,
|
||||
EventAlreadyInUse,
|
||||
}
|
||||
|
||||
pub struct Ppi<'d, C: Channel> {
|
||||
ch: C,
|
||||
phantom: PhantomData<&'d mut C>,
|
||||
|
@ -29,14 +39,10 @@ impl<'d, C: Channel> Ppi<'d, C> {
|
|||
pub fn new(ch: impl Unborrow<Target = C> + 'd) -> Self {
|
||||
unborrow!(ch);
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut this = Self {
|
||||
Self {
|
||||
ch,
|
||||
phantom: PhantomData,
|
||||
};
|
||||
#[cfg(not(any(feature = "nrf51", feature = "nrf9160")))]
|
||||
this.clear_fork_task();
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
/// Enables the channel.
|
||||
|
@ -52,35 +58,279 @@ impl<'d, C: Channel> Ppi<'d, C> {
|
|||
r.chenclr
|
||||
.write(|w| unsafe { w.bits(1 << self.ch.number()) });
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "nrf51", feature = "nrf9160")))]
|
||||
/// Sets the fork task that must be triggered when the configured event occurs. The user must
|
||||
/// provide a reference to the task.
|
||||
pub fn set_fork_task(&mut self, task: Task) {
|
||||
#[cfg(feature = "_ppi")]
|
||||
impl<'d, C: Channel> Ppi<'d, C> {
|
||||
/// Makes it so that the given task is subscribed to this channel
|
||||
pub fn subscribe(&mut self, task: Task) -> Result<(), Error> {
|
||||
if self.is_main_task_free() {
|
||||
self.set_main_task(Some(task));
|
||||
Ok(())
|
||||
} else if self.is_fork_task_free() {
|
||||
self.set_fork_task(Some(task));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::NoCapacityLeft)
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes it so that the given task is not subscribed to this channel
|
||||
pub fn unsubscribe(&mut self, task: Task) -> Result<(), Error> {
|
||||
if self.get_main_task() == Some(task) {
|
||||
// If there is a fork task, we move that to the main task for consistency
|
||||
// If there is no fork task, then the main task is set to 0
|
||||
let fork_task = self.get_fork_task();
|
||||
self.set_main_task(fork_task);
|
||||
|
||||
if self.has_fork_task() {
|
||||
// The fork task was copied to the main task, so reset the fork task
|
||||
self.set_fork_task(None);
|
||||
}
|
||||
Ok(())
|
||||
} else if self.get_fork_task() == Some(task) {
|
||||
// Reset the fork task
|
||||
self.set_fork_task(None);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::UnknownTask)
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes it so that the given event is published on this channel
|
||||
pub fn publish(&mut self, event: Event) -> Result<(), Error> {
|
||||
if self.is_event_free() {
|
||||
self.set_event(Some(event));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::NoCapacityLeft)
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes it so that the given event is not published on this channel
|
||||
pub fn unpublish(&mut self, event: Event) -> Result<(), Error> {
|
||||
if self.get_event() == Some(event) {
|
||||
self.set_event(None);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::UnknownEvent)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_main_task(&mut self, task: Option<Task>) {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
r.fork[self.ch.number()]
|
||||
.tep
|
||||
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
||||
if let Some(task) = task {
|
||||
r.ch[self.ch.number()]
|
||||
.tep
|
||||
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
||||
} else {
|
||||
r.ch[self.ch.number()].tep.write(|w| unsafe { w.bits(0) })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "nrf51", feature = "nrf9160")))]
|
||||
/// Clear the fork task endpoint. Previously set task will no longer be triggered.
|
||||
pub fn clear_fork_task(&mut self) {
|
||||
fn get_main_task(&mut self) -> Option<Task> {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
r.fork[self.ch.number()].tep.write(|w| unsafe { w.bits(0) })
|
||||
|
||||
if !self.has_main_task() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let bits = r.ch[self.ch.number()].tep.read().tep().bits();
|
||||
|
||||
if bits == 0 {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(Task(NonNull::new_unchecked(bits as *mut _))) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nrf9160")]
|
||||
/// Sets the fork task that must be triggered when the configured event occurs. The user must
|
||||
/// provide a reference to the task.
|
||||
pub fn set_fork_task(&mut self, _task: Task) {
|
||||
todo!("Tasks not yet implemented for nrf9160");
|
||||
fn set_fork_task(&mut self, task: Option<Task>) {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
if let Some(task) = task {
|
||||
r.fork[self.ch.number()]
|
||||
.tep
|
||||
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
||||
} else {
|
||||
r.fork[self.ch.number()].tep.write(|w| unsafe { w.bits(0) })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nrf9160")]
|
||||
/// Clear the fork task endpoint. Previously set task will no longer be triggered.
|
||||
pub fn clear_fork_task(&mut self) {
|
||||
todo!("Tasks not yet implemented for nrf9160");
|
||||
fn get_fork_task(&mut self) -> Option<Task> {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
|
||||
if !self.has_fork_task() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let bits = r.fork[self.ch.number()].tep.read().tep().bits();
|
||||
|
||||
if bits == 0 {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(Task(NonNull::new_unchecked(bits as *mut _))) }
|
||||
}
|
||||
}
|
||||
|
||||
fn has_main_task(&self) -> bool {
|
||||
match (self.ch.task_capacity(), self.ch.event_capacity()) {
|
||||
(0, 0) => false, // Static task
|
||||
(1, 0) => false, // Static task with fork
|
||||
(1 | 2, 1) => true, // Configurable task with possibly a fork
|
||||
_ => unreachable!(), // Every PPI config is covered
|
||||
}
|
||||
}
|
||||
|
||||
fn has_fork_task(&self) -> bool {
|
||||
match (self.ch.task_capacity(), self.ch.event_capacity()) {
|
||||
(0, 0) => false, // Static task
|
||||
(1, 0) => true, // Static task with fork
|
||||
(1, 1) => false, // Configurable task without fork
|
||||
(2, 1) => true, // Configurable task with fork
|
||||
_ => unreachable!(), // Every PPI config is covered
|
||||
}
|
||||
}
|
||||
|
||||
fn is_main_task_free(&mut self) -> bool {
|
||||
self.get_main_task().is_none()
|
||||
}
|
||||
|
||||
fn is_fork_task_free(&mut self) -> bool {
|
||||
self.get_fork_task().is_none()
|
||||
}
|
||||
|
||||
fn set_event(&mut self, event: Option<Event>) {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
if let Some(event) = event {
|
||||
r.ch[self.ch.number()]
|
||||
.eep
|
||||
.write(|w| unsafe { w.bits(event.0.as_ptr() as u32) })
|
||||
} else {
|
||||
r.ch[self.ch.number()].eep.write(|w| unsafe { w.bits(0) })
|
||||
}
|
||||
}
|
||||
|
||||
fn get_event(&mut self) -> Option<Event> {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
|
||||
if !self.has_event() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let bits = r.ch[self.ch.number()].eep.read().eep().bits();
|
||||
|
||||
if bits == 0 {
|
||||
None
|
||||
} else {
|
||||
unsafe { Some(Event(NonNull::new_unchecked(bits as *mut _))) }
|
||||
}
|
||||
}
|
||||
|
||||
fn has_event(&self) -> bool {
|
||||
match (self.ch.task_capacity(), self.ch.event_capacity()) {
|
||||
(_, 0) => false, // Static event
|
||||
(_, 1) => true, // Configurable event
|
||||
_ => unreachable!(), // Every PPI config is covered
|
||||
}
|
||||
}
|
||||
|
||||
fn is_event_free(&mut self) -> bool {
|
||||
self.get_event().is_none()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "_dppi")]
|
||||
const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
|
||||
#[cfg(feature = "_dppi")]
|
||||
const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
|
||||
|
||||
#[cfg(feature = "_dppi")]
|
||||
impl<'d, C: Channel> Ppi<'d, C> {
|
||||
/// Makes it so that the given task is subscribed to this channel
|
||||
pub fn subscribe(&mut self, task: Task) -> Result<(), Error> {
|
||||
unsafe {
|
||||
if Self::is_register_enabled(task.0) {
|
||||
Err(Error::TaskAlreadyInUse)
|
||||
} else {
|
||||
Self::set_register_active(task.0, self.ch.number() as u8);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes it so that the given task is not subscribed to this channel
|
||||
pub fn unsubscribe(&mut self, task: Task) -> Result<(), Error> {
|
||||
unsafe {
|
||||
if Self::get_register_channel(task.0) != self.ch.number() as u8 {
|
||||
Err(Error::UnknownTask)
|
||||
} else {
|
||||
Self::set_register_inactive(task.0);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes it so that the given event is published on this channel
|
||||
pub fn publish(&mut self, event: Event) -> Result<(), Error> {
|
||||
unsafe {
|
||||
if Self::is_register_enabled(event.0) {
|
||||
Err(Error::TaskAlreadyInUse)
|
||||
} else {
|
||||
Self::set_register_active(event.0, self.ch.number() as u8);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes it so that the given event is not published on this channel
|
||||
pub fn unpublish(&mut self, event: Event) -> Result<(), Error> {
|
||||
unsafe {
|
||||
if Self::get_register_channel(event.0) != self.ch.number() as u8 {
|
||||
Err(Error::UnknownTask)
|
||||
} else {
|
||||
Self::set_register_inactive(event.0);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the DPPI_ENABLE_BIT is set in the register
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals
|
||||
unsafe fn is_register_enabled(register: NonNull<u32>) -> bool {
|
||||
let bits = register.as_ptr().read_volatile();
|
||||
bits & DPPI_ENABLE_BIT > 0
|
||||
}
|
||||
|
||||
/// Sets the register to the given channel and enables it
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals
|
||||
unsafe fn set_register_active(register: NonNull<u32>, channel: u8) {
|
||||
register
|
||||
.as_ptr()
|
||||
.write_volatile(DPPI_ENABLE_BIT | (channel as u32 & DPPI_CHANNEL_MASK));
|
||||
}
|
||||
|
||||
/// Resets the channel number and disables the register
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals
|
||||
unsafe fn set_register_inactive(register: NonNull<u32>) {
|
||||
register.as_ptr().write_volatile(0);
|
||||
}
|
||||
|
||||
/// Gets the current configured channel number of the register
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals
|
||||
unsafe fn get_register_channel(register: NonNull<u32>) -> u8 {
|
||||
let bits = register.as_ptr().read_volatile();
|
||||
(bits & DPPI_CHANNEL_MASK) as u8
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,73 +340,59 @@ impl<'d, C: Channel> Drop for Ppi<'d, C> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nrf9160"))]
|
||||
impl<'d, C: ConfigurableChannel> Ppi<'d, C> {
|
||||
/// Sets the task to be triggered when the configured event occurs.
|
||||
pub fn set_task(&mut self, task: Task) {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
r.ch[self.ch.number()]
|
||||
.tep
|
||||
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
||||
}
|
||||
|
||||
/// Sets the event that will trigger the chosen task(s).
|
||||
pub fn set_event(&mut self, event: Event) {
|
||||
let r = unsafe { &*pac::PPI::ptr() };
|
||||
r.ch[self.ch.number()]
|
||||
.eep
|
||||
.write(|w| unsafe { w.bits(event.0.as_ptr() as u32) })
|
||||
/// Represents a task that a peripheral can do.
|
||||
/// When a task is subscribed to a PPI channel it will run when the channel is triggered by
|
||||
/// a published event.
|
||||
///
|
||||
/// The pointer in the task can point to two different kinds of register:
|
||||
/// - PPI *(nRF51 & nRF52)*: A pointer to a task register of the task of the peripheral that has
|
||||
/// to be registered with the PPI to subscribe to a channel
|
||||
/// - DPPI *(nRF53 & nRF91)*: A pointer to the subscribe register of the task of the peripheral
|
||||
/// that has to have the channel number and enable bit written tp it to subscribe to a channel
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Task(pub NonNull<u32>);
|
||||
impl Task {
|
||||
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
||||
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nrf9160")]
|
||||
impl<'d, C: ConfigurableChannel> Ppi<'d, C> {
|
||||
/// Sets the task to be triggered when the configured event occurs.
|
||||
pub fn set_task(&mut self, _task: Task) {
|
||||
todo!("Tasks not yet implemented for nrf9160")
|
||||
}
|
||||
|
||||
/// Sets the event that will trigger the chosen task(s).
|
||||
pub fn set_event(&mut self, _event: Event) {
|
||||
todo!("Events not yet implemented for nrf9160")
|
||||
/// Represents an event that a peripheral can publish.
|
||||
/// An event can be set to publish on a PPI channel when the event happens.
|
||||
///
|
||||
/// The pointer in the event can point to two different kinds of register:
|
||||
/// - PPI *(nRF51 & nRF52)*: A pointer to an event register of the event of the peripheral that has
|
||||
/// to be registered with the PPI to publish to a channel
|
||||
/// - DPPI *(nRF53 & nRF91)*: A pointer to the publish register of the event of the peripheral
|
||||
/// that has to have the channel number and enable bit written tp it to publish to a channel
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub struct Event(pub NonNull<u32>);
|
||||
impl Event {
|
||||
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
||||
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
|
||||
}
|
||||
}
|
||||
|
||||
// ======================
|
||||
// traits
|
||||
|
||||
pub struct Task(pub NonNull<()>);
|
||||
impl Task {
|
||||
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
||||
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut ()) })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Event(pub NonNull<()>);
|
||||
impl Event {
|
||||
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
||||
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut ()) })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
pub trait ConfigurableChannel {}
|
||||
pub trait Channel {}
|
||||
pub trait Group {}
|
||||
}
|
||||
|
||||
pub trait Channel: sealed::Channel + Sized {
|
||||
fn number(&self) -> usize;
|
||||
fn task_capacity(&self) -> usize;
|
||||
fn event_capacity(&self) -> usize;
|
||||
|
||||
fn degrade(self) -> AnyChannel {
|
||||
pub trait ConfigurableChannel {}
|
||||
|
||||
AnyChannel {
|
||||
number: self.number() as u8,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub trait ConfigurableChannel: Channel + sealed::ConfigurableChannel {
|
||||
fn degrade_configurable(self) -> AnyConfigurableChannel {
|
||||
AnyConfigurableChannel {
|
||||
number: self.number() as u8,
|
||||
task_capacity: self.task_capacity() as _,
|
||||
event_capacity: self.event_capacity() as _,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,6 +411,8 @@ pub trait Group: sealed::Group + Sized {
|
|||
|
||||
pub struct AnyChannel {
|
||||
number: u8,
|
||||
task_capacity: u8,
|
||||
event_capacity: u8,
|
||||
}
|
||||
unsafe_impl_unborrow!(AnyChannel);
|
||||
impl sealed::Channel for AnyChannel {}
|
||||
|
@ -182,26 +420,30 @@ impl Channel for AnyChannel {
|
|||
fn number(&self) -> usize {
|
||||
self.number as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AnyConfigurableChannel {
|
||||
number: u8,
|
||||
}
|
||||
unsafe_impl_unborrow!(AnyConfigurableChannel);
|
||||
impl sealed::Channel for AnyConfigurableChannel {}
|
||||
impl sealed::ConfigurableChannel for AnyConfigurableChannel {}
|
||||
impl ConfigurableChannel for AnyConfigurableChannel {}
|
||||
impl Channel for AnyConfigurableChannel {
|
||||
fn number(&self) -> usize {
|
||||
self.number as usize
|
||||
fn task_capacity(&self) -> usize {
|
||||
self.task_capacity as _
|
||||
}
|
||||
|
||||
fn event_capacity(&self) -> usize {
|
||||
self.event_capacity as _
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_ppi_channel {
|
||||
($type:ident, $number:expr, configurable) => {
|
||||
impl_ppi_channel!($type, $number);
|
||||
impl crate::ppi::sealed::ConfigurableChannel for peripherals::$type {}
|
||||
impl crate::ppi::ConfigurableChannel for peripherals::$type {}
|
||||
($type:ident, $number:expr, $task_capacity:expr, $event_capacity:expr) => {
|
||||
impl crate::ppi::sealed::Channel for peripherals::$type {}
|
||||
impl crate::ppi::Channel for peripherals::$type {
|
||||
fn number(&self) -> usize {
|
||||
$number
|
||||
}
|
||||
fn task_capacity(&self) -> usize {
|
||||
$task_capacity
|
||||
}
|
||||
fn event_capacity(&self) -> usize {
|
||||
$event_capacity
|
||||
}
|
||||
}
|
||||
};
|
||||
($type:ident, $number:expr) => {
|
||||
impl crate::ppi::sealed::Channel for peripherals::$type {}
|
||||
|
@ -209,6 +451,12 @@ macro_rules! impl_ppi_channel {
|
|||
fn number(&self) -> usize {
|
||||
$number
|
||||
}
|
||||
fn task_capacity(&self) -> usize {
|
||||
usize::MAX
|
||||
}
|
||||
fn event_capacity(&self) -> usize {
|
||||
usize::MAX
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -184,21 +184,36 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
|
|||
///
|
||||
/// When triggered, this task starts the timer.
|
||||
pub fn task_start(&self) -> Task {
|
||||
Task::from_reg(&T::regs().tasks_start)
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &T::regs().tasks_start;
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &T::regs().subscribe_start;
|
||||
|
||||
Task::from_reg(reg)
|
||||
}
|
||||
|
||||
/// Returns the STOP task, for use with PPI.
|
||||
///
|
||||
/// When triggered, this task stops the timer.
|
||||
pub fn task_stop(&self) -> Task {
|
||||
Task::from_reg(&T::regs().tasks_stop)
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &T::regs().tasks_stop;
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &T::regs().subscribe_stop;
|
||||
|
||||
Task::from_reg(reg)
|
||||
}
|
||||
|
||||
/// Returns the CLEAR task, for use with PPI.
|
||||
///
|
||||
/// When triggered, this task resets the timer's counter to 0.
|
||||
pub fn task_clear(&self) -> Task {
|
||||
Task::from_reg(&T::regs().tasks_clear)
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &T::regs().tasks_clear;
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &T::regs().subscribe_clear;
|
||||
|
||||
Task::from_reg(reg)
|
||||
}
|
||||
|
||||
/// Change the timer's frequency.
|
||||
|
@ -319,14 +334,24 @@ impl<'a, T: Instance, I: TimerType> Cc<'a, T, I> {
|
|||
///
|
||||
/// When triggered, this task will capture the current value of the timer's counter in this register.
|
||||
pub fn task_capture(&self) -> Task {
|
||||
Task::from_reg(&T::regs().tasks_capture[self.n])
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &T::regs().tasks_capture;
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &T::regs().subscribe_capture;
|
||||
|
||||
Task::from_reg(reg)
|
||||
}
|
||||
|
||||
/// Returns this CC register's COMPARE event, for use with PPI.
|
||||
///
|
||||
/// This event will fire when the timer's counter reaches the value in this CC register.
|
||||
pub fn event_compare(&self) -> Event {
|
||||
Event::from_reg(&T::regs().events_compare[self.n])
|
||||
#[cfg(feature = "_ppi")]
|
||||
let reg = &T::regs().events_compare[self.n];
|
||||
#[cfg(feature = "_dppi")]
|
||||
let reg = &T::regs().publish_compare[self.n];
|
||||
|
||||
Event::from_reg(reg)
|
||||
}
|
||||
|
||||
/// Enable the shortcut between this CC register's COMPARE event and the timer's CLEAR task.
|
||||
|
|
|
@ -7,7 +7,7 @@ use core::marker::PhantomData;
|
|||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
use embassy::interrupt::InterruptExt;
|
||||
use embassy::traits::uart::{Error, Read, ReadUntilIdle, Write};
|
||||
use embassy::traits::uart::{Error as TraitError, Read, ReadUntilIdle, Write};
|
||||
use embassy::util::Unborrow;
|
||||
use embassy_hal_common::drop::OnDrop;
|
||||
use embassy_hal_common::unborrow;
|
||||
|
@ -18,13 +18,25 @@ use crate::gpio::sealed::Pin as _;
|
|||
use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
||||
use crate::interrupt::Interrupt;
|
||||
use crate::pac;
|
||||
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
||||
use crate::ppi::{AnyChannel, Channel, Event, Ppi, Task};
|
||||
use crate::timer::Instance as TimerInstance;
|
||||
use crate::timer::{Frequency, Timer};
|
||||
|
||||
// Re-export SVD variants to allow user to directly set values.
|
||||
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Error {
|
||||
PpiError(crate::ppi::Error),
|
||||
}
|
||||
|
||||
impl From<crate::ppi::Error> for Error {
|
||||
fn from(e: crate::ppi::Error) -> Self {
|
||||
Self::PpiError(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Config {
|
||||
pub parity: Parity,
|
||||
|
@ -219,7 +231,7 @@ impl<'a, T: Instance> Drop for Uarte<'a, T> {
|
|||
|
||||
impl<'d, T: Instance> Read for Uarte<'d, T> {
|
||||
#[rustfmt::skip]
|
||||
type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
|
||||
type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), TraitError>> + 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
async move {
|
||||
|
@ -273,7 +285,7 @@ impl<'d, T: Instance> Read for Uarte<'d, T> {
|
|||
|
||||
impl<'d, T: Instance> Write for Uarte<'d, T> {
|
||||
#[rustfmt::skip]
|
||||
type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
|
||||
type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), TraitError>> + 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
async move {
|
||||
|
@ -331,14 +343,17 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
|
|||
pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
|
||||
uarte: Uarte<'d, U>,
|
||||
timer: Timer<'d, T>,
|
||||
ppi_ch1: Ppi<'d, AnyConfigurableChannel>,
|
||||
_ppi_ch2: Ppi<'d, AnyConfigurableChannel>,
|
||||
ppi_ch1: Ppi<'d, AnyChannel>,
|
||||
_ppi_ch2: Ppi<'d, AnyChannel>,
|
||||
}
|
||||
|
||||
impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
|
||||
/// Creates the interface to a UARTE instance.
|
||||
/// Sets the baud rate, parity and assigns the pins to the UARTE peripheral.
|
||||
///
|
||||
/// - *Note:* ppi_ch1 must have at least 1 free event and 2 free tasks or a PPI error is returned
|
||||
/// - *Note:* ppi_ch2 must have at least 1 free event and 1 free tasks or a PPI error is returned
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The returned API is safe unless you use `mem::forget` (or similar safe mechanisms)
|
||||
|
@ -348,15 +363,15 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
|
|||
pub unsafe fn new(
|
||||
uarte: impl Unborrow<Target = U> + 'd,
|
||||
timer: impl Unborrow<Target = T> + 'd,
|
||||
ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel> + 'd,
|
||||
ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel> + 'd,
|
||||
ppi_ch1: impl Unborrow<Target = impl Channel> + 'd,
|
||||
ppi_ch2: impl Unborrow<Target = impl Channel> + 'd,
|
||||
irq: impl Unborrow<Target = U::Interrupt> + 'd,
|
||||
rxd: impl Unborrow<Target = impl GpioPin> + 'd,
|
||||
txd: impl Unborrow<Target = impl GpioPin> + 'd,
|
||||
cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||
rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
) -> Result<Self, Error> {
|
||||
let baudrate = config.baudrate;
|
||||
let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config);
|
||||
let mut timer = Timer::new(timer);
|
||||
|
@ -378,29 +393,29 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
|
|||
timer.cc(0).short_compare_clear();
|
||||
timer.cc(0).short_compare_stop();
|
||||
|
||||
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable());
|
||||
ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy));
|
||||
ppi_ch1.set_task(timer.task_clear());
|
||||
ppi_ch1.set_fork_task(timer.task_start());
|
||||
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade());
|
||||
ppi_ch1.publish(Event::from_reg(&r.events_rxdrdy))?;
|
||||
ppi_ch1.subscribe(timer.task_clear())?;
|
||||
ppi_ch1.subscribe(timer.task_start())?;
|
||||
ppi_ch1.enable();
|
||||
|
||||
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable());
|
||||
ppi_ch2.set_event(timer.cc(0).event_compare());
|
||||
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
|
||||
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade());
|
||||
ppi_ch2.publish(timer.cc(0).event_compare())?;
|
||||
ppi_ch2.subscribe(Task::from_reg(&r.tasks_stoprx))?;
|
||||
ppi_ch2.enable();
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
uarte,
|
||||
timer,
|
||||
ppi_ch1: ppi_ch1,
|
||||
_ppi_ch2: ppi_ch2,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T> {
|
||||
#[rustfmt::skip]
|
||||
type ReadUntilIdleFuture<'a> where Self: 'a = impl Future<Output = Result<usize, Error>> + 'a;
|
||||
type ReadUntilIdleFuture<'a> where Self: 'a = impl Future<Output = Result<usize, TraitError>> + 'a;
|
||||
fn read_until_idle<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> {
|
||||
async move {
|
||||
let ptr = rx_buffer.as_ptr();
|
||||
|
@ -460,7 +475,7 @@ impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T
|
|||
|
||||
impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> {
|
||||
#[rustfmt::skip]
|
||||
type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
|
||||
type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), TraitError>> + 'a;
|
||||
fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
async move {
|
||||
self.ppi_ch1.disable();
|
||||
|
@ -473,7 +488,7 @@ impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> {
|
|||
|
||||
impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> {
|
||||
#[rustfmt::skip]
|
||||
type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
|
||||
type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), TraitError>> + 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.uarte.write(tx_buffer)
|
||||
|
|
|
@ -52,24 +52,24 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
|||
);
|
||||
|
||||
let mut ppi = Ppi::new(p.PPI_CH0);
|
||||
ppi.set_event(button1.event_in());
|
||||
ppi.set_task(led1.task_out());
|
||||
ppi.publish(button1.event_in()).unwrap();
|
||||
ppi.subscribe(led1.task_out()).unwrap();
|
||||
ppi.enable();
|
||||
|
||||
let mut ppi = Ppi::new(p.PPI_CH1);
|
||||
ppi.set_event(button2.event_in());
|
||||
ppi.set_task(led1.task_clr());
|
||||
ppi.publish(button2.event_in()).unwrap();
|
||||
ppi.subscribe(led1.task_clr()).unwrap();
|
||||
ppi.enable();
|
||||
|
||||
let mut ppi = Ppi::new(p.PPI_CH2);
|
||||
ppi.set_event(button3.event_in());
|
||||
ppi.set_task(led1.task_set());
|
||||
ppi.publish(button3.event_in()).unwrap();
|
||||
ppi.subscribe(led1.task_set()).unwrap();
|
||||
ppi.enable();
|
||||
|
||||
let mut ppi = Ppi::new(p.PPI_CH3);
|
||||
ppi.set_event(button4.event_in());
|
||||
ppi.set_task(led1.task_out());
|
||||
ppi.set_fork_task(led2.task_out());
|
||||
ppi.publish(button4.event_in()).unwrap();
|
||||
ppi.subscribe(led1.task_out()).unwrap();
|
||||
ppi.subscribe(led2.task_out()).unwrap();
|
||||
ppi.enable();
|
||||
|
||||
info!("PPI setup!");
|
||||
|
|
Loading…
Reference in a new issue