- 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:
Dion Dokter 2021-10-13 16:35:05 +02:00 committed by Dario Nieuwenhuis
parent 01e5376b25
commit 65628e1f15
14 changed files with 696 additions and 370 deletions

View File

@ -18,18 +18,20 @@ defmt-info = [ ]
defmt-warn = [ ] defmt-warn = [ ]
defmt-error = [ ] defmt-error = [ ]
nrf52805 = ["nrf52805-pac"] nrf52805 = ["nrf52805-pac", "_ppi"]
nrf52810 = ["nrf52810-pac"] nrf52810 = ["nrf52810-pac", "_ppi"]
nrf52811 = ["nrf52811-pac"] nrf52811 = ["nrf52811-pac", "_ppi"]
nrf52820 = ["nrf52820-pac"] nrf52820 = ["nrf52820-pac", "_ppi"]
nrf52832 = ["nrf52832-pac"] nrf52832 = ["nrf52832-pac", "_ppi"]
nrf52833 = ["nrf52833-pac"] nrf52833 = ["nrf52833-pac", "_ppi"]
nrf52840 = ["nrf52840-pac"] nrf52840 = ["nrf52840-pac", "_ppi"]
nrf9160 = ["nrf9160-pac"] nrf9160 = ["nrf9160-pac", "_dppi"]
# Features starting with `_` are for internal use only. They're not intended # 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. # to be enabled by other crates, and are not covered by semver guarantees.
_time-driver = ["embassy/time-tick-32768hz"] _time-driver = ["embassy/time-tick-32768hz"]
_ppi = []
_dppi = []
gpiote = [] gpiote = []
time-driver-rtc1 = ["_time-driver"] time-driver-rtc1 = ["_time-driver"]

View File

@ -5,7 +5,7 @@ use core::pin::Pin;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy::interrupt::InterruptExt; use embassy::interrupt::InterruptExt;
use embassy::io::{AsyncBufRead, AsyncWrite, Result}; use embassy::io::{AsyncBufRead, AsyncWrite};
use embassy::util::Unborrow; use embassy::util::Unborrow;
use embassy::waitqueue::WakerRegistration; use embassy::waitqueue::WakerRegistration;
use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; 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::sealed::Pin as _;
use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
use crate::pac; use crate::ppi::{AnyChannel, Channel, Event, Ppi, Task};
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
use crate::timer::Instance as TimerInstance; use crate::timer::Instance as TimerInstance;
use crate::timer::{Frequency, Timer}; use crate::timer::{Frequency, Timer};
use crate::uarte::{Config, Instance as UarteInstance}; use crate::uarte::{Config, Instance as UarteInstance};
use crate::{pac, ppi};
// Re-export SVD variants to allow user to directly set values // 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}; 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)] #[derive(Copy, Clone, Debug, PartialEq)]
enum RxState { enum RxState {
Idle, Idle,
@ -45,8 +57,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> {
struct StateInner<'d, U: UarteInstance, T: TimerInstance> { struct StateInner<'d, U: UarteInstance, T: TimerInstance> {
phantom: PhantomData<&'d mut U>, phantom: PhantomData<&'d mut U>,
timer: Timer<'d, T>, timer: Timer<'d, T>,
_ppi_ch1: Ppi<'d, AnyConfigurableChannel>, _ppi_ch1: Ppi<'d, AnyChannel>,
_ppi_ch2: Ppi<'d, AnyConfigurableChannel>, _ppi_ch2: Ppi<'d, AnyChannel>,
rx: RingBuffer<'d>, rx: RingBuffer<'d>,
rx_state: RxState, 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> { impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
/// unsafe: may not leak self or futures /// 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( pub unsafe fn new(
state: &'d mut State<'d, U, T>, state: &'d mut State<'d, U, T>,
_uarte: impl Unborrow<Target = U> + 'd, _uarte: impl Unborrow<Target = U> + 'd,
timer: impl Unborrow<Target = T> + 'd, timer: impl Unborrow<Target = T> + 'd,
ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel> + 'd, ppi_ch1: impl Unborrow<Target = impl Channel> + 'd,
ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel> + 'd, ppi_ch2: impl Unborrow<Target = impl Channel> + 'd,
irq: impl Unborrow<Target = U::Interrupt> + 'd, irq: impl Unborrow<Target = U::Interrupt> + 'd,
rxd: impl Unborrow<Target = impl GpioPin> + 'd, rxd: impl Unborrow<Target = impl GpioPin> + 'd,
txd: 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, config: Config,
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
) -> Self { ) -> Result<Self, Error> {
unborrow!(ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts); unborrow!(ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts);
let r = U::regs(); 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_clear();
timer.cc(0).short_compare_stop(); timer.cc(0).short_compare_stop();
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable()); let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade());
ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); ppi_ch1.publish(Event::from_reg(&r.events_rxdrdy))?;
ppi_ch1.set_task(timer.task_clear()); ppi_ch1.subscribe(timer.task_clear())?;
ppi_ch1.set_fork_task(timer.task_start()); ppi_ch1.subscribe(timer.task_start())?;
ppi_ch1.enable(); ppi_ch1.enable();
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade());
ppi_ch2.set_event(timer.cc(0).event_compare()); ppi_ch2.publish(timer.cc(0).event_compare())?;
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); ppi_ch2.subscribe(Task::from_reg(&r.tasks_stoprx))?;
ppi_ch2.enable(); ppi_ch2.enable();
Self { Ok(Self {
inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
phantom: PhantomData, phantom: PhantomData,
timer, timer,
@ -170,7 +185,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
tx_state: TxState::Idle, tx_state: TxState::Idle,
tx_waker: WakerRegistration::new(), tx_waker: WakerRegistration::new(),
}), }),
} })
} }
pub fn set_baudrate(&mut self, baudrate: Baudrate) { 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> { 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| { self.inner.with(|state| {
// Conservative compiler fence to prevent optimizations that do not // Conservative compiler fence to prevent optimizations that do not
// take in to account actions by DMA. The fence has been placed here, // 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"); trace!(" empty");
state.rx_waker.register(cx.waker()); 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>, mut self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,
buf: &[u8], buf: &[u8],
) -> Poll<Result<usize>> { ) -> Poll<embassy::io::Result<usize>> {
let poll = self.inner.with(|state| { let poll = self.inner.with(|state| {
trace!("poll_write: {:?}", buf.len()); trace!("poll_write: {:?}", buf.len());

View File

@ -167,28 +167,28 @@ impl_pin!(P0_29, 0, 29);
impl_pin!(P0_30, 0, 30); impl_pin!(P0_30, 0, 30);
impl_pin!(P0_31, 0, 31); impl_pin!(P0_31, 0, 31);
impl_ppi_channel!(PPI_CH0, 0, configurable); impl_ppi_channel!(PPI_CH0, 0, 2, 1);
impl_ppi_channel!(PPI_CH1, 1, configurable); impl_ppi_channel!(PPI_CH1, 1, 2, 1);
impl_ppi_channel!(PPI_CH2, 2, configurable); impl_ppi_channel!(PPI_CH2, 2, 2, 1);
impl_ppi_channel!(PPI_CH3, 3, configurable); impl_ppi_channel!(PPI_CH3, 3, 2, 1);
impl_ppi_channel!(PPI_CH4, 4, configurable); impl_ppi_channel!(PPI_CH4, 4, 2, 1);
impl_ppi_channel!(PPI_CH5, 5, configurable); impl_ppi_channel!(PPI_CH5, 5, 2, 1);
impl_ppi_channel!(PPI_CH6, 6, configurable); impl_ppi_channel!(PPI_CH6, 6, 2, 1);
impl_ppi_channel!(PPI_CH7, 7, configurable); impl_ppi_channel!(PPI_CH7, 7, 2, 1);
impl_ppi_channel!(PPI_CH8, 8, configurable); impl_ppi_channel!(PPI_CH8, 8, 2, 1);
impl_ppi_channel!(PPI_CH9, 9, configurable); impl_ppi_channel!(PPI_CH9, 9, 2, 1);
impl_ppi_channel!(PPI_CH20, 20); impl_ppi_channel!(PPI_CH20, 20, 1, 0);
impl_ppi_channel!(PPI_CH21, 21); impl_ppi_channel!(PPI_CH21, 21, 1, 0);
impl_ppi_channel!(PPI_CH22, 22); impl_ppi_channel!(PPI_CH22, 22, 1, 0);
impl_ppi_channel!(PPI_CH23, 23); impl_ppi_channel!(PPI_CH23, 23, 1, 0);
impl_ppi_channel!(PPI_CH24, 24); impl_ppi_channel!(PPI_CH24, 24, 1, 0);
impl_ppi_channel!(PPI_CH25, 25); impl_ppi_channel!(PPI_CH25, 25, 1, 0);
impl_ppi_channel!(PPI_CH26, 26); impl_ppi_channel!(PPI_CH26, 26, 1, 0);
impl_ppi_channel!(PPI_CH27, 27); impl_ppi_channel!(PPI_CH27, 27, 1, 0);
impl_ppi_channel!(PPI_CH28, 28); impl_ppi_channel!(PPI_CH28, 28, 1, 0);
impl_ppi_channel!(PPI_CH29, 29); impl_ppi_channel!(PPI_CH29, 29, 1, 0);
impl_ppi_channel!(PPI_CH30, 30); impl_ppi_channel!(PPI_CH30, 30, 1, 0);
impl_ppi_channel!(PPI_CH31, 31); impl_ppi_channel!(PPI_CH31, 31, 1, 0);
impl_saadc_input!(P0_04, ANALOGINPUT2); impl_saadc_input!(P0_04, ANALOGINPUT2);
impl_saadc_input!(P0_05, ANALOGINPUT3); impl_saadc_input!(P0_05, ANALOGINPUT3);

View File

@ -172,38 +172,38 @@ impl_pin!(P0_29, 0, 29);
impl_pin!(P0_30, 0, 30); impl_pin!(P0_30, 0, 30);
impl_pin!(P0_31, 0, 31); impl_pin!(P0_31, 0, 31);
impl_ppi_channel!(PPI_CH0, 0, configurable); impl_ppi_channel!(PPI_CH0, 0, 2, 1);
impl_ppi_channel!(PPI_CH1, 1, configurable); impl_ppi_channel!(PPI_CH1, 1, 2, 1);
impl_ppi_channel!(PPI_CH2, 2, configurable); impl_ppi_channel!(PPI_CH2, 2, 2, 1);
impl_ppi_channel!(PPI_CH3, 3, configurable); impl_ppi_channel!(PPI_CH3, 3, 2, 1);
impl_ppi_channel!(PPI_CH4, 4, configurable); impl_ppi_channel!(PPI_CH4, 4, 2, 1);
impl_ppi_channel!(PPI_CH5, 5, configurable); impl_ppi_channel!(PPI_CH5, 5, 2, 1);
impl_ppi_channel!(PPI_CH6, 6, configurable); impl_ppi_channel!(PPI_CH6, 6, 2, 1);
impl_ppi_channel!(PPI_CH7, 7, configurable); impl_ppi_channel!(PPI_CH7, 7, 2, 1);
impl_ppi_channel!(PPI_CH8, 8, configurable); impl_ppi_channel!(PPI_CH8, 8, 2, 1);
impl_ppi_channel!(PPI_CH9, 9, configurable); impl_ppi_channel!(PPI_CH9, 9, 2, 1);
impl_ppi_channel!(PPI_CH10, 10, configurable); impl_ppi_channel!(PPI_CH10, 10, 2, 1);
impl_ppi_channel!(PPI_CH11, 11, configurable); impl_ppi_channel!(PPI_CH11, 11, 2, 1);
impl_ppi_channel!(PPI_CH12, 12, configurable); impl_ppi_channel!(PPI_CH12, 12, 2, 1);
impl_ppi_channel!(PPI_CH13, 13, configurable); impl_ppi_channel!(PPI_CH13, 13, 2, 1);
impl_ppi_channel!(PPI_CH14, 14, configurable); impl_ppi_channel!(PPI_CH14, 14, 2, 1);
impl_ppi_channel!(PPI_CH15, 15, configurable); impl_ppi_channel!(PPI_CH15, 15, 2, 1);
impl_ppi_channel!(PPI_CH16, 16, configurable); impl_ppi_channel!(PPI_CH16, 16, 2, 1);
impl_ppi_channel!(PPI_CH17, 17, configurable); impl_ppi_channel!(PPI_CH17, 17, 2, 1);
impl_ppi_channel!(PPI_CH18, 18, configurable); impl_ppi_channel!(PPI_CH18, 18, 2, 1);
impl_ppi_channel!(PPI_CH19, 19, configurable); impl_ppi_channel!(PPI_CH19, 19, 2, 1);
impl_ppi_channel!(PPI_CH20, 20); impl_ppi_channel!(PPI_CH20, 20, 1, 0);
impl_ppi_channel!(PPI_CH21, 21); impl_ppi_channel!(PPI_CH21, 21, 1, 0);
impl_ppi_channel!(PPI_CH22, 22); impl_ppi_channel!(PPI_CH22, 22, 1, 0);
impl_ppi_channel!(PPI_CH23, 23); impl_ppi_channel!(PPI_CH23, 23, 1, 0);
impl_ppi_channel!(PPI_CH24, 24); impl_ppi_channel!(PPI_CH24, 24, 1, 0);
impl_ppi_channel!(PPI_CH25, 25); impl_ppi_channel!(PPI_CH25, 25, 1, 0);
impl_ppi_channel!(PPI_CH26, 26); impl_ppi_channel!(PPI_CH26, 26, 1, 0);
impl_ppi_channel!(PPI_CH27, 27); impl_ppi_channel!(PPI_CH27, 27, 1, 0);
impl_ppi_channel!(PPI_CH28, 28); impl_ppi_channel!(PPI_CH28, 28, 1, 0);
impl_ppi_channel!(PPI_CH29, 29); impl_ppi_channel!(PPI_CH29, 29, 1, 0);
impl_ppi_channel!(PPI_CH30, 30); impl_ppi_channel!(PPI_CH30, 30, 1, 0);
impl_ppi_channel!(PPI_CH31, 31); impl_ppi_channel!(PPI_CH31, 31, 1, 0);
impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_02, ANALOGINPUT0);
impl_saadc_input!(P0_03, ANALOGINPUT1); impl_saadc_input!(P0_03, ANALOGINPUT1);

View File

@ -173,38 +173,38 @@ impl_pin!(P0_29, 0, 29);
impl_pin!(P0_30, 0, 30); impl_pin!(P0_30, 0, 30);
impl_pin!(P0_31, 0, 31); impl_pin!(P0_31, 0, 31);
impl_ppi_channel!(PPI_CH0, 0, configurable); impl_ppi_channel!(PPI_CH0, 0, 2, 1);
impl_ppi_channel!(PPI_CH1, 1, configurable); impl_ppi_channel!(PPI_CH1, 1, 2, 1);
impl_ppi_channel!(PPI_CH2, 2, configurable); impl_ppi_channel!(PPI_CH2, 2, 2, 1);
impl_ppi_channel!(PPI_CH3, 3, configurable); impl_ppi_channel!(PPI_CH3, 3, 2, 1);
impl_ppi_channel!(PPI_CH4, 4, configurable); impl_ppi_channel!(PPI_CH4, 4, 2, 1);
impl_ppi_channel!(PPI_CH5, 5, configurable); impl_ppi_channel!(PPI_CH5, 5, 2, 1);
impl_ppi_channel!(PPI_CH6, 6, configurable); impl_ppi_channel!(PPI_CH6, 6, 2, 1);
impl_ppi_channel!(PPI_CH7, 7, configurable); impl_ppi_channel!(PPI_CH7, 7, 2, 1);
impl_ppi_channel!(PPI_CH8, 8, configurable); impl_ppi_channel!(PPI_CH8, 8, 2, 1);
impl_ppi_channel!(PPI_CH9, 9, configurable); impl_ppi_channel!(PPI_CH9, 9, 2, 1);
impl_ppi_channel!(PPI_CH10, 10, configurable); impl_ppi_channel!(PPI_CH10, 10, 2, 1);
impl_ppi_channel!(PPI_CH11, 11, configurable); impl_ppi_channel!(PPI_CH11, 11, 2, 1);
impl_ppi_channel!(PPI_CH12, 12, configurable); impl_ppi_channel!(PPI_CH12, 12, 2, 1);
impl_ppi_channel!(PPI_CH13, 13, configurable); impl_ppi_channel!(PPI_CH13, 13, 2, 1);
impl_ppi_channel!(PPI_CH14, 14, configurable); impl_ppi_channel!(PPI_CH14, 14, 2, 1);
impl_ppi_channel!(PPI_CH15, 15, configurable); impl_ppi_channel!(PPI_CH15, 15, 2, 1);
impl_ppi_channel!(PPI_CH16, 16, configurable); impl_ppi_channel!(PPI_CH16, 16, 2, 1);
impl_ppi_channel!(PPI_CH17, 17, configurable); impl_ppi_channel!(PPI_CH17, 17, 2, 1);
impl_ppi_channel!(PPI_CH18, 18, configurable); impl_ppi_channel!(PPI_CH18, 18, 2, 1);
impl_ppi_channel!(PPI_CH19, 19, configurable); impl_ppi_channel!(PPI_CH19, 19, 2, 1);
impl_ppi_channel!(PPI_CH20, 20); impl_ppi_channel!(PPI_CH20, 20, 1, 0);
impl_ppi_channel!(PPI_CH21, 21); impl_ppi_channel!(PPI_CH21, 21, 1, 0);
impl_ppi_channel!(PPI_CH22, 22); impl_ppi_channel!(PPI_CH22, 22, 1, 0);
impl_ppi_channel!(PPI_CH23, 23); impl_ppi_channel!(PPI_CH23, 23, 1, 0);
impl_ppi_channel!(PPI_CH24, 24); impl_ppi_channel!(PPI_CH24, 24, 1, 0);
impl_ppi_channel!(PPI_CH25, 25); impl_ppi_channel!(PPI_CH25, 25, 1, 0);
impl_ppi_channel!(PPI_CH26, 26); impl_ppi_channel!(PPI_CH26, 26, 1, 0);
impl_ppi_channel!(PPI_CH27, 27); impl_ppi_channel!(PPI_CH27, 27, 1, 0);
impl_ppi_channel!(PPI_CH28, 28); impl_ppi_channel!(PPI_CH28, 28, 1, 0);
impl_ppi_channel!(PPI_CH29, 29); impl_ppi_channel!(PPI_CH29, 29, 1, 0);
impl_ppi_channel!(PPI_CH30, 30); impl_ppi_channel!(PPI_CH30, 30, 1, 0);
impl_ppi_channel!(PPI_CH31, 31); impl_ppi_channel!(PPI_CH31, 31, 1, 0);
impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_02, ANALOGINPUT0);
impl_saadc_input!(P0_03, ANALOGINPUT1); impl_saadc_input!(P0_03, ANALOGINPUT1);

View File

@ -168,38 +168,38 @@ impl_pin!(P0_29, 0, 29);
impl_pin!(P0_30, 0, 30); impl_pin!(P0_30, 0, 30);
impl_pin!(P0_31, 0, 31); impl_pin!(P0_31, 0, 31);
impl_ppi_channel!(PPI_CH0, 0, configurable); impl_ppi_channel!(PPI_CH0, 0, 2, 1);
impl_ppi_channel!(PPI_CH1, 1, configurable); impl_ppi_channel!(PPI_CH1, 1, 2, 1);
impl_ppi_channel!(PPI_CH2, 2, configurable); impl_ppi_channel!(PPI_CH2, 2, 2, 1);
impl_ppi_channel!(PPI_CH3, 3, configurable); impl_ppi_channel!(PPI_CH3, 3, 2, 1);
impl_ppi_channel!(PPI_CH4, 4, configurable); impl_ppi_channel!(PPI_CH4, 4, 2, 1);
impl_ppi_channel!(PPI_CH5, 5, configurable); impl_ppi_channel!(PPI_CH5, 5, 2, 1);
impl_ppi_channel!(PPI_CH6, 6, configurable); impl_ppi_channel!(PPI_CH6, 6, 2, 1);
impl_ppi_channel!(PPI_CH7, 7, configurable); impl_ppi_channel!(PPI_CH7, 7, 2, 1);
impl_ppi_channel!(PPI_CH8, 8, configurable); impl_ppi_channel!(PPI_CH8, 8, 2, 1);
impl_ppi_channel!(PPI_CH9, 9, configurable); impl_ppi_channel!(PPI_CH9, 9, 2, 1);
impl_ppi_channel!(PPI_CH10, 10, configurable); impl_ppi_channel!(PPI_CH10, 10, 2, 1);
impl_ppi_channel!(PPI_CH11, 11, configurable); impl_ppi_channel!(PPI_CH11, 11, 2, 1);
impl_ppi_channel!(PPI_CH12, 12, configurable); impl_ppi_channel!(PPI_CH12, 12, 2, 1);
impl_ppi_channel!(PPI_CH13, 13, configurable); impl_ppi_channel!(PPI_CH13, 13, 2, 1);
impl_ppi_channel!(PPI_CH14, 14, configurable); impl_ppi_channel!(PPI_CH14, 14, 2, 1);
impl_ppi_channel!(PPI_CH15, 15, configurable); impl_ppi_channel!(PPI_CH15, 15, 2, 1);
impl_ppi_channel!(PPI_CH16, 16, configurable); impl_ppi_channel!(PPI_CH16, 16, 2, 1);
impl_ppi_channel!(PPI_CH17, 17, configurable); impl_ppi_channel!(PPI_CH17, 17, 2, 1);
impl_ppi_channel!(PPI_CH18, 18, configurable); impl_ppi_channel!(PPI_CH18, 18, 2, 1);
impl_ppi_channel!(PPI_CH19, 19, configurable); impl_ppi_channel!(PPI_CH19, 19, 2, 1);
impl_ppi_channel!(PPI_CH20, 20); impl_ppi_channel!(PPI_CH20, 20, 1, 0);
impl_ppi_channel!(PPI_CH21, 21); impl_ppi_channel!(PPI_CH21, 21, 1, 0);
impl_ppi_channel!(PPI_CH22, 22); impl_ppi_channel!(PPI_CH22, 22, 1, 0);
impl_ppi_channel!(PPI_CH23, 23); impl_ppi_channel!(PPI_CH23, 23, 1, 0);
impl_ppi_channel!(PPI_CH24, 24); impl_ppi_channel!(PPI_CH24, 24, 1, 0);
impl_ppi_channel!(PPI_CH25, 25); impl_ppi_channel!(PPI_CH25, 25, 1, 0);
impl_ppi_channel!(PPI_CH26, 26); impl_ppi_channel!(PPI_CH26, 26, 1, 0);
impl_ppi_channel!(PPI_CH27, 27); impl_ppi_channel!(PPI_CH27, 27, 1, 0);
impl_ppi_channel!(PPI_CH28, 28); impl_ppi_channel!(PPI_CH28, 28, 1, 0);
impl_ppi_channel!(PPI_CH29, 29); impl_ppi_channel!(PPI_CH29, 29, 1, 0);
impl_ppi_channel!(PPI_CH30, 30); impl_ppi_channel!(PPI_CH30, 30, 1, 0);
impl_ppi_channel!(PPI_CH31, 31); impl_ppi_channel!(PPI_CH31, 31, 1, 0);
pub mod irqs { pub mod irqs {
use crate::pac::Interrupt as InterruptEnum; use crate::pac::Interrupt as InterruptEnum;

View File

@ -190,38 +190,38 @@ impl_pin!(P0_29, 0, 29);
impl_pin!(P0_30, 0, 30); impl_pin!(P0_30, 0, 30);
impl_pin!(P0_31, 0, 31); impl_pin!(P0_31, 0, 31);
impl_ppi_channel!(PPI_CH0, 0, configurable); impl_ppi_channel!(PPI_CH0, 0, 2, 1);
impl_ppi_channel!(PPI_CH1, 1, configurable); impl_ppi_channel!(PPI_CH1, 1, 2, 1);
impl_ppi_channel!(PPI_CH2, 2, configurable); impl_ppi_channel!(PPI_CH2, 2, 2, 1);
impl_ppi_channel!(PPI_CH3, 3, configurable); impl_ppi_channel!(PPI_CH3, 3, 2, 1);
impl_ppi_channel!(PPI_CH4, 4, configurable); impl_ppi_channel!(PPI_CH4, 4, 2, 1);
impl_ppi_channel!(PPI_CH5, 5, configurable); impl_ppi_channel!(PPI_CH5, 5, 2, 1);
impl_ppi_channel!(PPI_CH6, 6, configurable); impl_ppi_channel!(PPI_CH6, 6, 2, 1);
impl_ppi_channel!(PPI_CH7, 7, configurable); impl_ppi_channel!(PPI_CH7, 7, 2, 1);
impl_ppi_channel!(PPI_CH8, 8, configurable); impl_ppi_channel!(PPI_CH8, 8, 2, 1);
impl_ppi_channel!(PPI_CH9, 9, configurable); impl_ppi_channel!(PPI_CH9, 9, 2, 1);
impl_ppi_channel!(PPI_CH10, 10, configurable); impl_ppi_channel!(PPI_CH10, 10, 2, 1);
impl_ppi_channel!(PPI_CH11, 11, configurable); impl_ppi_channel!(PPI_CH11, 11, 2, 1);
impl_ppi_channel!(PPI_CH12, 12, configurable); impl_ppi_channel!(PPI_CH12, 12, 2, 1);
impl_ppi_channel!(PPI_CH13, 13, configurable); impl_ppi_channel!(PPI_CH13, 13, 2, 1);
impl_ppi_channel!(PPI_CH14, 14, configurable); impl_ppi_channel!(PPI_CH14, 14, 2, 1);
impl_ppi_channel!(PPI_CH15, 15, configurable); impl_ppi_channel!(PPI_CH15, 15, 2, 1);
impl_ppi_channel!(PPI_CH16, 16, configurable); impl_ppi_channel!(PPI_CH16, 16, 2, 1);
impl_ppi_channel!(PPI_CH17, 17, configurable); impl_ppi_channel!(PPI_CH17, 17, 2, 1);
impl_ppi_channel!(PPI_CH18, 18, configurable); impl_ppi_channel!(PPI_CH18, 18, 2, 1);
impl_ppi_channel!(PPI_CH19, 19, configurable); impl_ppi_channel!(PPI_CH19, 19, 2, 1);
impl_ppi_channel!(PPI_CH20, 20); impl_ppi_channel!(PPI_CH20, 20, 1, 0);
impl_ppi_channel!(PPI_CH21, 21); impl_ppi_channel!(PPI_CH21, 21, 1, 0);
impl_ppi_channel!(PPI_CH22, 22); impl_ppi_channel!(PPI_CH22, 22, 1, 0);
impl_ppi_channel!(PPI_CH23, 23); impl_ppi_channel!(PPI_CH23, 23, 1, 0);
impl_ppi_channel!(PPI_CH24, 24); impl_ppi_channel!(PPI_CH24, 24, 1, 0);
impl_ppi_channel!(PPI_CH25, 25); impl_ppi_channel!(PPI_CH25, 25, 1, 0);
impl_ppi_channel!(PPI_CH26, 26); impl_ppi_channel!(PPI_CH26, 26, 1, 0);
impl_ppi_channel!(PPI_CH27, 27); impl_ppi_channel!(PPI_CH27, 27, 1, 0);
impl_ppi_channel!(PPI_CH28, 28); impl_ppi_channel!(PPI_CH28, 28, 1, 0);
impl_ppi_channel!(PPI_CH29, 29); impl_ppi_channel!(PPI_CH29, 29, 1, 0);
impl_ppi_channel!(PPI_CH30, 30); impl_ppi_channel!(PPI_CH30, 30, 1, 0);
impl_ppi_channel!(PPI_CH31, 31); impl_ppi_channel!(PPI_CH31, 31, 1, 0);
impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_02, ANALOGINPUT0);
impl_saadc_input!(P0_03, ANALOGINPUT1); impl_saadc_input!(P0_03, ANALOGINPUT1);

View File

@ -226,38 +226,38 @@ impl_pin!(P1_13, 1, 13);
impl_pin!(P1_14, 1, 14); impl_pin!(P1_14, 1, 14);
impl_pin!(P1_15, 1, 15); impl_pin!(P1_15, 1, 15);
impl_ppi_channel!(PPI_CH0, 0, configurable); impl_ppi_channel!(PPI_CH0, 0, 2, 1);
impl_ppi_channel!(PPI_CH1, 1, configurable); impl_ppi_channel!(PPI_CH1, 1, 2, 1);
impl_ppi_channel!(PPI_CH2, 2, configurable); impl_ppi_channel!(PPI_CH2, 2, 2, 1);
impl_ppi_channel!(PPI_CH3, 3, configurable); impl_ppi_channel!(PPI_CH3, 3, 2, 1);
impl_ppi_channel!(PPI_CH4, 4, configurable); impl_ppi_channel!(PPI_CH4, 4, 2, 1);
impl_ppi_channel!(PPI_CH5, 5, configurable); impl_ppi_channel!(PPI_CH5, 5, 2, 1);
impl_ppi_channel!(PPI_CH6, 6, configurable); impl_ppi_channel!(PPI_CH6, 6, 2, 1);
impl_ppi_channel!(PPI_CH7, 7, configurable); impl_ppi_channel!(PPI_CH7, 7, 2, 1);
impl_ppi_channel!(PPI_CH8, 8, configurable); impl_ppi_channel!(PPI_CH8, 8, 2, 1);
impl_ppi_channel!(PPI_CH9, 9, configurable); impl_ppi_channel!(PPI_CH9, 9, 2, 1);
impl_ppi_channel!(PPI_CH10, 10, configurable); impl_ppi_channel!(PPI_CH10, 10, 2, 1);
impl_ppi_channel!(PPI_CH11, 11, configurable); impl_ppi_channel!(PPI_CH11, 11, 2, 1);
impl_ppi_channel!(PPI_CH12, 12, configurable); impl_ppi_channel!(PPI_CH12, 12, 2, 1);
impl_ppi_channel!(PPI_CH13, 13, configurable); impl_ppi_channel!(PPI_CH13, 13, 2, 1);
impl_ppi_channel!(PPI_CH14, 14, configurable); impl_ppi_channel!(PPI_CH14, 14, 2, 1);
impl_ppi_channel!(PPI_CH15, 15, configurable); impl_ppi_channel!(PPI_CH15, 15, 2, 1);
impl_ppi_channel!(PPI_CH16, 16, configurable); impl_ppi_channel!(PPI_CH16, 16, 2, 1);
impl_ppi_channel!(PPI_CH17, 17, configurable); impl_ppi_channel!(PPI_CH17, 17, 2, 1);
impl_ppi_channel!(PPI_CH18, 18, configurable); impl_ppi_channel!(PPI_CH18, 18, 2, 1);
impl_ppi_channel!(PPI_CH19, 19, configurable); impl_ppi_channel!(PPI_CH19, 19, 2, 1);
impl_ppi_channel!(PPI_CH20, 20); impl_ppi_channel!(PPI_CH20, 20, 1, 0);
impl_ppi_channel!(PPI_CH21, 21); impl_ppi_channel!(PPI_CH21, 21, 1, 0);
impl_ppi_channel!(PPI_CH22, 22); impl_ppi_channel!(PPI_CH22, 22, 1, 0);
impl_ppi_channel!(PPI_CH23, 23); impl_ppi_channel!(PPI_CH23, 23, 1, 0);
impl_ppi_channel!(PPI_CH24, 24); impl_ppi_channel!(PPI_CH24, 24, 1, 0);
impl_ppi_channel!(PPI_CH25, 25); impl_ppi_channel!(PPI_CH25, 25, 1, 0);
impl_ppi_channel!(PPI_CH26, 26); impl_ppi_channel!(PPI_CH26, 26, 1, 0);
impl_ppi_channel!(PPI_CH27, 27); impl_ppi_channel!(PPI_CH27, 27, 1, 0);
impl_ppi_channel!(PPI_CH28, 28); impl_ppi_channel!(PPI_CH28, 28, 1, 0);
impl_ppi_channel!(PPI_CH29, 29); impl_ppi_channel!(PPI_CH29, 29, 1, 0);
impl_ppi_channel!(PPI_CH30, 30); impl_ppi_channel!(PPI_CH30, 30, 1, 0);
impl_ppi_channel!(PPI_CH31, 31); impl_ppi_channel!(PPI_CH31, 31, 1, 0);
impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_02, ANALOGINPUT0);
impl_saadc_input!(P0_03, ANALOGINPUT1); impl_saadc_input!(P0_03, ANALOGINPUT1);

View File

@ -231,38 +231,38 @@ impl_pin!(P1_13, 1, 13);
impl_pin!(P1_14, 1, 14); impl_pin!(P1_14, 1, 14);
impl_pin!(P1_15, 1, 15); impl_pin!(P1_15, 1, 15);
impl_ppi_channel!(PPI_CH0, 0, configurable); impl_ppi_channel!(PPI_CH0, 0, 2, 1);
impl_ppi_channel!(PPI_CH1, 1, configurable); impl_ppi_channel!(PPI_CH1, 1, 2, 1);
impl_ppi_channel!(PPI_CH2, 2, configurable); impl_ppi_channel!(PPI_CH2, 2, 2, 1);
impl_ppi_channel!(PPI_CH3, 3, configurable); impl_ppi_channel!(PPI_CH3, 3, 2, 1);
impl_ppi_channel!(PPI_CH4, 4, configurable); impl_ppi_channel!(PPI_CH4, 4, 2, 1);
impl_ppi_channel!(PPI_CH5, 5, configurable); impl_ppi_channel!(PPI_CH5, 5, 2, 1);
impl_ppi_channel!(PPI_CH6, 6, configurable); impl_ppi_channel!(PPI_CH6, 6, 2, 1);
impl_ppi_channel!(PPI_CH7, 7, configurable); impl_ppi_channel!(PPI_CH7, 7, 2, 1);
impl_ppi_channel!(PPI_CH8, 8, configurable); impl_ppi_channel!(PPI_CH8, 8, 2, 1);
impl_ppi_channel!(PPI_CH9, 9, configurable); impl_ppi_channel!(PPI_CH9, 9, 2, 1);
impl_ppi_channel!(PPI_CH10, 10, configurable); impl_ppi_channel!(PPI_CH10, 10, 2, 1);
impl_ppi_channel!(PPI_CH11, 11, configurable); impl_ppi_channel!(PPI_CH11, 11, 2, 1);
impl_ppi_channel!(PPI_CH12, 12, configurable); impl_ppi_channel!(PPI_CH12, 12, 2, 1);
impl_ppi_channel!(PPI_CH13, 13, configurable); impl_ppi_channel!(PPI_CH13, 13, 2, 1);
impl_ppi_channel!(PPI_CH14, 14, configurable); impl_ppi_channel!(PPI_CH14, 14, 2, 1);
impl_ppi_channel!(PPI_CH15, 15, configurable); impl_ppi_channel!(PPI_CH15, 15, 2, 1);
impl_ppi_channel!(PPI_CH16, 16, configurable); impl_ppi_channel!(PPI_CH16, 16, 2, 1);
impl_ppi_channel!(PPI_CH17, 17, configurable); impl_ppi_channel!(PPI_CH17, 17, 2, 1);
impl_ppi_channel!(PPI_CH18, 18, configurable); impl_ppi_channel!(PPI_CH18, 18, 2, 1);
impl_ppi_channel!(PPI_CH19, 19, configurable); impl_ppi_channel!(PPI_CH19, 19, 2, 1);
impl_ppi_channel!(PPI_CH20, 20); impl_ppi_channel!(PPI_CH20, 20, 1, 0);
impl_ppi_channel!(PPI_CH21, 21); impl_ppi_channel!(PPI_CH21, 21, 1, 0);
impl_ppi_channel!(PPI_CH22, 22); impl_ppi_channel!(PPI_CH22, 22, 1, 0);
impl_ppi_channel!(PPI_CH23, 23); impl_ppi_channel!(PPI_CH23, 23, 1, 0);
impl_ppi_channel!(PPI_CH24, 24); impl_ppi_channel!(PPI_CH24, 24, 1, 0);
impl_ppi_channel!(PPI_CH25, 25); impl_ppi_channel!(PPI_CH25, 25, 1, 0);
impl_ppi_channel!(PPI_CH26, 26); impl_ppi_channel!(PPI_CH26, 26, 1, 0);
impl_ppi_channel!(PPI_CH27, 27); impl_ppi_channel!(PPI_CH27, 27, 1, 0);
impl_ppi_channel!(PPI_CH28, 28); impl_ppi_channel!(PPI_CH28, 28, 1, 0);
impl_ppi_channel!(PPI_CH29, 29); impl_ppi_channel!(PPI_CH29, 29, 1, 0);
impl_ppi_channel!(PPI_CH30, 30); impl_ppi_channel!(PPI_CH30, 30, 1, 0);
impl_ppi_channel!(PPI_CH31, 31); impl_ppi_channel!(PPI_CH31, 31, 1, 0);
impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_02, ANALOGINPUT0);
impl_saadc_input!(P0_03, ANALOGINPUT1); impl_saadc_input!(P0_03, ANALOGINPUT1);

View File

@ -190,7 +190,13 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
/// Returns the IN event, for use with PPI. /// Returns the IN event, for use with PPI.
pub fn event_in(&self) -> Event { pub fn event_in(&self) -> Event {
let g = unsafe { &*pac::GPIOTE::ptr() }; 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. /// Returns the OUT task, for use with PPI.
pub fn task_out(&self) -> Task { pub fn task_out(&self) -> Task {
let g = unsafe { &*pac::GPIOTE::ptr() }; 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. /// Returns the CLR task, for use with PPI.
#[cfg(not(feature = "nrf51"))] #[cfg(not(feature = "nrf51"))]
pub fn task_clr(&self) -> Task { pub fn task_clr(&self) -> Task {
let g = unsafe { &*pac::GPIOTE::ptr() }; 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. /// Returns the SET task, for use with PPI.
#[cfg(not(feature = "nrf51"))] #[cfg(not(feature = "nrf51"))]
pub fn task_set(&self) -> Task { pub fn task_set(&self) -> Task {
let g = unsafe { &*pac::GPIOTE::ptr() }; 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)
} }
} }

View File

@ -20,6 +20,16 @@ use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
// ====================== // ======================
// driver // driver
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum Error {
NoCapacityLeft,
UnknownTask,
TaskAlreadyInUse,
UnknownEvent,
EventAlreadyInUse,
}
pub struct Ppi<'d, C: Channel> { pub struct Ppi<'d, C: Channel> {
ch: C, ch: C,
phantom: PhantomData<&'d mut 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 { pub fn new(ch: impl Unborrow<Target = C> + 'd) -> Self {
unborrow!(ch); unborrow!(ch);
#[allow(unused_mut)] Self {
let mut this = Self {
ch, ch,
phantom: PhantomData, phantom: PhantomData,
}; }
#[cfg(not(any(feature = "nrf51", feature = "nrf9160")))]
this.clear_fork_task();
this
} }
/// Enables the channel. /// Enables the channel.
@ -52,35 +58,279 @@ impl<'d, C: Channel> Ppi<'d, C> {
r.chenclr r.chenclr
.write(|w| unsafe { w.bits(1 << self.ch.number()) }); .write(|w| unsafe { w.bits(1 << self.ch.number()) });
} }
}
#[cfg(not(any(feature = "nrf51", feature = "nrf9160")))] #[cfg(feature = "_ppi")]
/// Sets the fork task that must be triggered when the configured event occurs. The user must impl<'d, C: Channel> Ppi<'d, C> {
/// provide a reference to the task. /// Makes it so that the given task is subscribed to this channel
pub fn set_fork_task(&mut self, task: Task) { 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() }; let r = unsafe { &*pac::PPI::ptr() };
r.fork[self.ch.number()] if let Some(task) = task {
.tep r.ch[self.ch.number()]
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) .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")))] fn get_main_task(&mut self) -> Option<Task> {
/// Clear the fork task endpoint. Previously set task will no longer be triggered.
pub fn clear_fork_task(&mut self) {
let r = unsafe { &*pac::PPI::ptr() }; 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")] fn set_fork_task(&mut self, task: Option<Task>) {
/// Sets the fork task that must be triggered when the configured event occurs. The user must let r = unsafe { &*pac::PPI::ptr() };
/// provide a reference to the task. if let Some(task) = task {
pub fn set_fork_task(&mut self, _task: Task) { r.fork[self.ch.number()]
todo!("Tasks not yet implemented for nrf9160"); .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")] fn get_fork_task(&mut self) -> Option<Task> {
/// Clear the fork task endpoint. Previously set task will no longer be triggered. let r = unsafe { &*pac::PPI::ptr() };
pub fn clear_fork_task(&mut self) {
todo!("Tasks not yet implemented for nrf9160"); 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"))] /// Represents a task that a peripheral can do.
impl<'d, C: ConfigurableChannel> Ppi<'d, C> { /// When a task is subscribed to a PPI channel it will run when the channel is triggered by
/// Sets the task to be triggered when the configured event occurs. /// a published event.
pub fn set_task(&mut self, task: Task) { ///
let r = unsafe { &*pac::PPI::ptr() }; /// The pointer in the task can point to two different kinds of register:
r.ch[self.ch.number()] /// - PPI *(nRF51 & nRF52)*: A pointer to a task register of the task of the peripheral that has
.tep /// to be registered with the PPI to subscribe to a channel
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) /// - 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)]
/// Sets the event that will trigger the chosen task(s). pub struct Task(pub NonNull<u32>);
pub fn set_event(&mut self, event: Event) { impl Task {
let r = unsafe { &*pac::PPI::ptr() }; pub(crate) fn from_reg<T>(reg: &T) -> Self {
r.ch[self.ch.number()] Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
.eep
.write(|w| unsafe { w.bits(event.0.as_ptr() as u32) })
} }
} }
#[cfg(feature = "nrf9160")] /// Represents an event that a peripheral can publish.
impl<'d, C: ConfigurableChannel> Ppi<'d, C> { /// An event can be set to publish on a PPI channel when the event happens.
/// Sets the task to be triggered when the configured event occurs. ///
pub fn set_task(&mut self, _task: Task) { /// The pointer in the event can point to two different kinds of register:
todo!("Tasks not yet implemented for nrf9160") /// - 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
/// Sets the event that will trigger the chosen task(s). /// that has to have the channel number and enable bit written tp it to publish to a channel
pub fn set_event(&mut self, _event: Event) { #[derive(PartialEq, Eq, Clone, Copy)]
todo!("Events not yet implemented for nrf9160") 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 // 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(crate) mod sealed {
pub trait ConfigurableChannel {}
pub trait Channel {} pub trait Channel {}
pub trait Group {} pub trait Group {}
} }
pub trait Channel: sealed::Channel + Sized { pub trait Channel: sealed::Channel + Sized {
fn number(&self) -> usize; fn number(&self) -> usize;
fn task_capacity(&self) -> usize;
fn event_capacity(&self) -> usize;
fn degrade(self) -> AnyChannel { fn degrade(self) -> AnyChannel {
pub trait ConfigurableChannel {}
AnyChannel { AnyChannel {
number: self.number() as u8, number: self.number() as u8,
} task_capacity: self.task_capacity() as _,
} event_capacity: self.event_capacity() as _,
}
pub trait ConfigurableChannel: Channel + sealed::ConfigurableChannel {
fn degrade_configurable(self) -> AnyConfigurableChannel {
AnyConfigurableChannel {
number: self.number() as u8,
} }
} }
} }
@ -175,6 +411,8 @@ pub trait Group: sealed::Group + Sized {
pub struct AnyChannel { pub struct AnyChannel {
number: u8, number: u8,
task_capacity: u8,
event_capacity: u8,
} }
unsafe_impl_unborrow!(AnyChannel); unsafe_impl_unborrow!(AnyChannel);
impl sealed::Channel for AnyChannel {} impl sealed::Channel for AnyChannel {}
@ -182,26 +420,30 @@ impl Channel for AnyChannel {
fn number(&self) -> usize { fn number(&self) -> usize {
self.number as usize self.number as usize
} }
}
pub struct AnyConfigurableChannel { fn task_capacity(&self) -> usize {
number: u8, self.task_capacity as _
} }
unsafe_impl_unborrow!(AnyConfigurableChannel);
impl sealed::Channel for AnyConfigurableChannel {} fn event_capacity(&self) -> usize {
impl sealed::ConfigurableChannel for AnyConfigurableChannel {} self.event_capacity as _
impl ConfigurableChannel for AnyConfigurableChannel {}
impl Channel for AnyConfigurableChannel {
fn number(&self) -> usize {
self.number as usize
} }
} }
macro_rules! impl_ppi_channel { macro_rules! impl_ppi_channel {
($type:ident, $number:expr, configurable) => { ($type:ident, $number:expr, $task_capacity:expr, $event_capacity:expr) => {
impl_ppi_channel!($type, $number); impl crate::ppi::sealed::Channel for peripherals::$type {}
impl crate::ppi::sealed::ConfigurableChannel for peripherals::$type {} impl crate::ppi::Channel for peripherals::$type {
impl crate::ppi::ConfigurableChannel 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) => { ($type:ident, $number:expr) => {
impl crate::ppi::sealed::Channel for peripherals::$type {} impl crate::ppi::sealed::Channel for peripherals::$type {}
@ -209,6 +451,12 @@ macro_rules! impl_ppi_channel {
fn number(&self) -> usize { fn number(&self) -> usize {
$number $number
} }
fn task_capacity(&self) -> usize {
usize::MAX
}
fn event_capacity(&self) -> usize {
usize::MAX
}
} }
}; };
} }

View File

@ -184,21 +184,36 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
/// ///
/// When triggered, this task starts the timer. /// When triggered, this task starts the timer.
pub fn task_start(&self) -> Task { 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. /// Returns the STOP task, for use with PPI.
/// ///
/// When triggered, this task stops the timer. /// When triggered, this task stops the timer.
pub fn task_stop(&self) -> Task { 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. /// Returns the CLEAR task, for use with PPI.
/// ///
/// When triggered, this task resets the timer's counter to 0. /// When triggered, this task resets the timer's counter to 0.
pub fn task_clear(&self) -> Task { 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. /// 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. /// When triggered, this task will capture the current value of the timer's counter in this register.
pub fn task_capture(&self) -> Task { 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. /// 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. /// This event will fire when the timer's counter reaches the value in this CC register.
pub fn event_compare(&self) -> Event { 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. /// Enable the shortcut between this CC register's COMPARE event and the timer's CLEAR task.

View File

@ -7,7 +7,7 @@ use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll; use core::task::Poll;
use embassy::interrupt::InterruptExt; 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::util::Unborrow;
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::unborrow; 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::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin};
use crate::interrupt::Interrupt; use crate::interrupt::Interrupt;
use crate::pac; 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::Instance as TimerInstance;
use crate::timer::{Frequency, Timer}; use crate::timer::{Frequency, Timer};
// Re-export SVD variants to allow user to directly set values. // 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}; 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] #[non_exhaustive]
pub struct Config { pub struct Config {
pub parity: Parity, 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> { impl<'d, T: Instance> Read for Uarte<'d, T> {
#[rustfmt::skip] #[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> { fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
async move { async move {
@ -273,7 +285,7 @@ impl<'d, T: Instance> Read for Uarte<'d, T> {
impl<'d, T: Instance> Write for Uarte<'d, T> { impl<'d, T: Instance> Write for Uarte<'d, T> {
#[rustfmt::skip] #[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> { fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> {
async move { async move {
@ -331,14 +343,17 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
uarte: Uarte<'d, U>, uarte: Uarte<'d, U>,
timer: Timer<'d, T>, timer: Timer<'d, T>,
ppi_ch1: Ppi<'d, AnyConfigurableChannel>, ppi_ch1: Ppi<'d, AnyChannel>,
_ppi_ch2: Ppi<'d, AnyConfigurableChannel>, _ppi_ch2: Ppi<'d, AnyChannel>,
} }
impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
/// Creates the interface to a UARTE instance. /// Creates the interface to a UARTE instance.
/// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. /// 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 /// # Safety
/// ///
/// The returned API is safe unless you use `mem::forget` (or similar safe mechanisms) /// 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( pub unsafe fn new(
uarte: impl Unborrow<Target = U> + 'd, uarte: impl Unborrow<Target = U> + 'd,
timer: impl Unborrow<Target = T> + 'd, timer: impl Unborrow<Target = T> + 'd,
ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel> + 'd, ppi_ch1: impl Unborrow<Target = impl Channel> + 'd,
ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel> + 'd, ppi_ch2: impl Unborrow<Target = impl Channel> + 'd,
irq: impl Unborrow<Target = U::Interrupt> + 'd, irq: impl Unborrow<Target = U::Interrupt> + 'd,
rxd: impl Unborrow<Target = impl GpioPin> + 'd, rxd: impl Unborrow<Target = impl GpioPin> + 'd,
txd: impl Unborrow<Target = impl GpioPin> + 'd, txd: impl Unborrow<Target = impl GpioPin> + 'd,
cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
config: Config, config: Config,
) -> Self { ) -> Result<Self, Error> {
let baudrate = config.baudrate; let baudrate = config.baudrate;
let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config);
let mut timer = Timer::new(timer); 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_clear();
timer.cc(0).short_compare_stop(); timer.cc(0).short_compare_stop();
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable()); let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade());
ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); ppi_ch1.publish(Event::from_reg(&r.events_rxdrdy))?;
ppi_ch1.set_task(timer.task_clear()); ppi_ch1.subscribe(timer.task_clear())?;
ppi_ch1.set_fork_task(timer.task_start()); ppi_ch1.subscribe(timer.task_start())?;
ppi_ch1.enable(); ppi_ch1.enable();
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade());
ppi_ch2.set_event(timer.cc(0).event_compare()); ppi_ch2.publish(timer.cc(0).event_compare())?;
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); ppi_ch2.subscribe(Task::from_reg(&r.tasks_stoprx))?;
ppi_ch2.enable(); ppi_ch2.enable();
Self { Ok(Self {
uarte, uarte,
timer, timer,
ppi_ch1: ppi_ch1, ppi_ch1: ppi_ch1,
_ppi_ch2: ppi_ch2, _ppi_ch2: ppi_ch2,
} })
} }
} }
impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T> { impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T> {
#[rustfmt::skip] #[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> { fn read_until_idle<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> {
async move { async move {
let ptr = rx_buffer.as_ptr(); 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> { impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> {
#[rustfmt::skip] #[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> { fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
async move { async move {
self.ppi_ch1.disable(); 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> { impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> {
#[rustfmt::skip] #[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> { fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> {
self.uarte.write(tx_buffer) self.uarte.write(tx_buffer)

View File

@ -52,24 +52,24 @@ async fn main(_spawner: Spawner, p: Peripherals) {
); );
let mut ppi = Ppi::new(p.PPI_CH0); let mut ppi = Ppi::new(p.PPI_CH0);
ppi.set_event(button1.event_in()); ppi.publish(button1.event_in()).unwrap();
ppi.set_task(led1.task_out()); ppi.subscribe(led1.task_out()).unwrap();
ppi.enable(); ppi.enable();
let mut ppi = Ppi::new(p.PPI_CH1); let mut ppi = Ppi::new(p.PPI_CH1);
ppi.set_event(button2.event_in()); ppi.publish(button2.event_in()).unwrap();
ppi.set_task(led1.task_clr()); ppi.subscribe(led1.task_clr()).unwrap();
ppi.enable(); ppi.enable();
let mut ppi = Ppi::new(p.PPI_CH2); let mut ppi = Ppi::new(p.PPI_CH2);
ppi.set_event(button3.event_in()); ppi.publish(button3.event_in()).unwrap();
ppi.set_task(led1.task_set()); ppi.subscribe(led1.task_set()).unwrap();
ppi.enable(); ppi.enable();
let mut ppi = Ppi::new(p.PPI_CH3); let mut ppi = Ppi::new(p.PPI_CH3);
ppi.set_event(button4.event_in()); ppi.publish(button4.event_in()).unwrap();
ppi.set_task(led1.task_out()); ppi.subscribe(led1.task_out()).unwrap();
ppi.set_fork_task(led2.task_out()); ppi.subscribe(led2.task_out()).unwrap();
ppi.enable(); ppi.enable();
info!("PPI setup!"); info!("PPI setup!");