diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 697f4308..d69d12a3 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -156,6 +156,7 @@ pub fn init(_config: config::Config) -> Peripherals { #[cfg(feature = "time-driver")] timer::init(); dma::init(); + pio::init(); } peripherals diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 3c7abea2..7faec10b 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -8,18 +8,33 @@ use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_hal_common::PeripheralRef; use embassy_sync::waitqueue::AtomicWaker; -use crate::dma::{self, Channel, Transfer}; +use crate::dma::{Channel, Transfer}; use crate::gpio::sealed::Pin as SealedPin; use crate::gpio::{Drive, Pin, Pull, SlewRate}; use crate::pac::dma::vals::{DataSize, TreqSel}; -use crate::{interrupt, pac, peripherals}; +use crate::pio::sealed::{PioInstance as _, SmInstance as _}; +use crate::{interrupt, pac, peripherals, RegExt}; + +struct Wakers([AtomicWaker; 12]); + +impl Wakers { + #[inline(always)] + fn fifo_in(&self) -> &[AtomicWaker] { + &self.0[0..4] + } + #[inline(always)] + fn fifo_out(&self) -> &[AtomicWaker] { + &self.0[4..8] + } + #[inline(always)] + fn irq(&self) -> &[AtomicWaker] { + &self.0[8..12] + } +} -const PIOS: [&pac::pio::Pio; 2] = [&pac::PIO0, &pac::PIO1]; const NEW_AW: AtomicWaker = AtomicWaker::new(); -const PIO_WAKERS_INIT: [AtomicWaker; 4] = [NEW_AW; 4]; -static FIFO_OUT_WAKERS: [[AtomicWaker; 4]; 2] = [PIO_WAKERS_INIT; 2]; -static FIFO_IN_WAKERS: [[AtomicWaker; 4]; 2] = [PIO_WAKERS_INIT; 2]; -static IRQ_WAKERS: [[AtomicWaker; 4]; 2] = [PIO_WAKERS_INIT; 2]; +const PIO_WAKERS_INIT: Wakers = Wakers([NEW_AW; 12]); +static WAKERS: [Wakers; 2] = [PIO_WAKERS_INIT; 2]; pub enum FifoJoin { /// Both TX and RX fifo is enabled @@ -40,83 +55,42 @@ const RXNEMPTY_MASK: u32 = 1 << 0; const TXNFULL_MASK: u32 = 1 << 4; const SMIRQ_MASK: u32 = 1 << 8; -#[interrupt] -unsafe fn PIO0_IRQ_1() { - use crate::pac; - let ints = pac::PIO0.irqs(1).ints().read().0; - let inte = pac::PIO0.irqs(1).inte(); - for i in 0..4 { - // Check RXNEMPTY - if ints & (RXNEMPTY_MASK << i) != 0 { - inte.modify(|m| { - m.0 &= !(RXNEMPTY_MASK << i); - }); - FIFO_IN_WAKERS[0][i].wake(); - } - // Check IRQ flgs - if ints & (SMIRQ_MASK << i) != 0 { - inte.modify(|m| { - m.0 &= !(SMIRQ_MASK << i); - }); - IRQ_WAKERS[0][i].wake(); - } - } -} - -#[interrupt] -unsafe fn PIO1_IRQ_1() { - use crate::pac; - let ints = pac::PIO1.irqs(1).ints().read().0; - let inte = pac::PIO1.irqs(1).inte(); - for i in 0..4 { - // Check all RXNEMPTY - if ints & (RXNEMPTY_MASK << i) != 0 { - inte.modify(|m| { - m.0 &= !(RXNEMPTY_MASK << i); - }); - FIFO_IN_WAKERS[1][i].wake(); - } - // Check IRQ flgs - if ints & (SMIRQ_MASK << i) != 0 { - inte.modify(|m| { - m.0 &= !(SMIRQ_MASK << i); - }); - IRQ_WAKERS[1][i].wake(); - } - } -} - #[interrupt] unsafe fn PIO0_IRQ_0() { use crate::pac; let ints = pac::PIO0.irqs(0).ints().read().0; - let inte = pac::PIO0.irqs(0).inte(); - //debug!("!{:04x}",ints); - // Check all TXNFULL - for i in 0..4 { - if ints & (TXNFULL_MASK << i) != 0 { - inte.modify(|m| { - m.0 &= !(TXNFULL_MASK << i); - }); - FIFO_OUT_WAKERS[0][i].wake(); + for bit in 0..12 { + if ints & (1 << bit) != 0 { + WAKERS[0].0[bit].wake(); } } + pac::PIO0.irqs(0).inte().write_clear(|m| m.0 = ints); } #[interrupt] unsafe fn PIO1_IRQ_0() { use crate::pac; let ints = pac::PIO1.irqs(0).ints().read().0; - let inte = pac::PIO1.irqs(0).inte(); - // Check all TXNFULL - for i in 0..4 { - if ints & (TXNFULL_MASK << i) != 0 { - inte.modify(|m| { - m.0 &= !(TXNFULL_MASK << i); - }); - FIFO_OUT_WAKERS[1][i].wake(); + for bit in 0..12 { + if ints & (1 << bit) != 0 { + WAKERS[1].0[bit].wake(); } } + pac::PIO1.irqs(0).inte().write_clear(|m| m.0 = ints); +} + +pub(crate) unsafe fn init() { + let irq = interrupt::PIO0_IRQ_0::steal(); + irq.disable(); + irq.set_priority(interrupt::Priority::P3); + pac::PIO0.irqs(0).inte().write(|m| m.0 = 0); + irq.enable(); + + let irq = interrupt::PIO1_IRQ_0::steal(); + irq.disable(); + irq.set_priority(interrupt::Priority::P3); + pac::PIO1.irqs(0).inte().write(|m| m.0 = 0); + irq.enable(); } /// Future that waits for TX-FIFO to become writable @@ -129,14 +103,6 @@ pub struct FifoOutFuture<'a, PIO: PioInstance, SM: PioStateMachine + Unpin> { impl<'a, PIO: PioInstance, SM: PioStateMachine + Unpin> FifoOutFuture<'a, PIO, SM> { pub fn new(sm: &'a mut SM, value: u32) -> Self { - unsafe { - critical_section::with(|_| { - let irq = PIO::IrqOut::steal(); - irq.set_priority(interrupt::Priority::P3); - - irq.enable(); - }); - } FifoOutFuture { sm, pio: PhantomData::default(), @@ -153,16 +119,11 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Future for FifoOutFuture if self.get_mut().sm.try_push_tx(value) { Poll::Ready(()) } else { - FIFO_OUT_WAKERS[PIO::PIO_NO as usize][SM::Sm::SM_NO as usize].register(cx.waker()); + WAKERS[PIO::PIO_NO as usize].fifo_out()[SM::Sm::SM_NO as usize].register(cx.waker()); unsafe { - let irq = PIO::IrqOut::steal(); - irq.disable(); - critical_section::with(|_| { - PIOS[PIO::PIO_NO as usize].irqs(0).inte().modify(|m| { - m.0 |= TXNFULL_MASK << SM::Sm::SM_NO; - }); + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = TXNFULL_MASK << SM::Sm::SM_NO; }); - irq.enable(); } // debug!("Pending"); Poll::Pending @@ -173,10 +134,8 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Future for FifoOutFuture impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Drop for FifoOutFuture<'d, PIO, SM> { fn drop(&mut self) { unsafe { - critical_section::with(|_| { - PIOS[PIO::PIO_NO as usize].irqs(0).inte().modify(|m| { - m.0 &= !(TXNFULL_MASK << SM::Sm::SM_NO); - }); + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = TXNFULL_MASK << SM::Sm::SM_NO; }); } } @@ -191,14 +150,6 @@ pub struct FifoInFuture<'a, PIO: PioInstance, SM: PioStateMachine> { impl<'a, PIO: PioInstance, SM: PioStateMachine> FifoInFuture<'a, PIO, SM> { pub fn new(sm: &'a mut SM) -> Self { - unsafe { - critical_section::with(|_| { - let irq = PIO::IrqIn::steal(); - irq.set_priority(interrupt::Priority::P3); - - irq.enable(); - }); - } FifoInFuture { sm, pio: PhantomData::default(), @@ -213,16 +164,11 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Future for FifoInFuture<'d, PIO, if let Some(v) = self.sm.try_pull_rx() { Poll::Ready(v) } else { - FIFO_IN_WAKERS[PIO::PIO_NO as usize][SM::Sm::SM_NO as usize].register(cx.waker()); + WAKERS[PIO::PIO_NO as usize].fifo_in()[SM::Sm::SM_NO as usize].register(cx.waker()); unsafe { - let irq = PIO::IrqIn::steal(); - irq.disable(); - critical_section::with(|_| { - PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| { - m.0 |= RXNEMPTY_MASK << SM::Sm::SM_NO; - }); + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO; }); - irq.enable(); } //debug!("Pending"); Poll::Pending @@ -233,10 +179,8 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Future for FifoInFuture<'d, PIO, impl<'d, PIO: PioInstance, SM: PioStateMachine> Drop for FifoInFuture<'d, PIO, SM> { fn drop(&mut self) { unsafe { - critical_section::with(|_| { - PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| { - m.0 &= !(RXNEMPTY_MASK << SM::Sm::SM_NO); - }); + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO; }); } } @@ -251,14 +195,6 @@ pub struct IrqFuture { impl<'a, PIO: PioInstance> IrqFuture { pub fn new(irq_no: u8) -> Self { - unsafe { - critical_section::with(|_| { - let irq = PIO::IrqSm::steal(); - irq.set_priority(interrupt::Priority::P3); - - irq.enable(); - }); - } IrqFuture { pio: PhantomData::default(), irq_no, @@ -273,7 +209,7 @@ impl<'d, PIO: PioInstance> Future for IrqFuture { // Check if IRQ flag is already set if critical_section::with(|_| unsafe { - let irq_flags = PIOS[PIO::PIO_NO as usize].irq(); + let irq_flags = PIO::PIO.irq(); if irq_flags.read().0 & (1 << self.irq_no) != 0 { irq_flags.write(|m| { m.0 = 1 << self.irq_no; @@ -286,16 +222,11 @@ impl<'d, PIO: PioInstance> Future for IrqFuture { return Poll::Ready(()); } - IRQ_WAKERS[PIO::PIO_NO as usize][self.irq_no as usize].register(cx.waker()); + WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker()); unsafe { - let irq = PIO::IrqSm::steal(); - irq.disable(); - critical_section::with(|_| { - PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| { - m.0 |= SMIRQ_MASK << self.irq_no; - }); + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = SMIRQ_MASK << self.irq_no; }); - irq.enable(); } Poll::Pending } @@ -304,10 +235,8 @@ impl<'d, PIO: PioInstance> Future for IrqFuture { impl<'d, PIO: PioInstance> Drop for IrqFuture { fn drop(&mut self) { unsafe { - critical_section::with(|_| { - PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| { - m.0 &= !(SMIRQ_MASK << self.irq_no); - }); + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = SMIRQ_MASK << self.irq_no; }); } } @@ -369,7 +298,7 @@ impl PioPin { pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { let mask = 1 << self.pin(); unsafe { - PIOS[PIO::PIO_NO as usize] + PIO::PIO .input_sync_bypass() .modify(|w| *w = if bypass { *w & !mask } else { *w | mask }); } @@ -391,16 +320,14 @@ pub struct PioStateMachineInstance { sm: PhantomData, } -impl PioStateMachine for PioStateMachineInstance { +impl sealed::PioStateMachine for PioStateMachineInstance { type Pio = PIO; type Sm = SM; } +impl PioStateMachine for PioStateMachineInstance {} -pub trait PioStateMachine: Sized + Unpin { - type Pio: PioInstance; - type Sm: SmInstance; +pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin { fn pio_no(&self) -> u8 { - let _ = self; Self::Pio::PIO_NO } @@ -409,65 +336,56 @@ pub trait PioStateMachine: Sized + Unpin { } fn restart(&mut self) { - let _ = self; unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .ctrl() .modify(|w| w.set_sm_restart(1u8 << Self::Sm::SM_NO)); } } fn set_enable(&mut self, enable: bool) { - let _ = self; let mask = 1u8 << Self::Sm::SM_NO; unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .ctrl() .modify(|w| w.set_sm_enable((w.sm_enable() & !mask) | (if enable { mask } else { 0 }))); } } fn is_enabled(&self) -> bool { - let _ = self; - unsafe { PIOS[Self::Pio::PIO_NO as usize].ctrl().read().sm_enable() & (1u8 << Self::Sm::SM_NO) != 0 } + unsafe { Self::Pio::PIO.ctrl().read().sm_enable() & (1u8 << Self::Sm::SM_NO) != 0 } } fn is_tx_empty(&self) -> bool { - let _ = self; - unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().txempty() & (1u8 << Self::Sm::SM_NO) != 0 } + unsafe { Self::Pio::PIO.fstat().read().txempty() & (1u8 << Self::Sm::SM_NO) != 0 } } fn is_tx_full(&self) -> bool { - let _ = self; - unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().txfull() & (1u8 << Self::Sm::SM_NO) != 0 } + unsafe { Self::Pio::PIO.fstat().read().txfull() & (1u8 << Self::Sm::SM_NO) != 0 } } fn is_rx_empty(&self) -> bool { - let _ = self; - unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().rxempty() & (1u8 << Self::Sm::SM_NO) != 0 } + unsafe { Self::Pio::PIO.fstat().read().rxempty() & (1u8 << Self::Sm::SM_NO) != 0 } } fn is_rx_full(&self) -> bool { - let _ = self; - unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().rxfull() & (1u8 << Self::Sm::SM_NO) != 0 } + unsafe { Self::Pio::PIO.fstat().read().rxfull() & (1u8 << Self::Sm::SM_NO) != 0 } } fn tx_level(&self) -> u8 { unsafe { - let flevel = PIOS[Self::Pio::PIO_NO as usize].flevel().read().0; + let flevel = Self::Pio::PIO.flevel().read().0; (flevel >> (Self::Sm::SM_NO * 8)) as u8 & 0x0f } } fn rx_level(&self) -> u8 { unsafe { - let flevel = PIOS[Self::Pio::PIO_NO as usize].flevel().read().0; + let flevel = Self::Pio::PIO.flevel().read().0; (flevel >> (Self::Sm::SM_NO * 8 + 4)) as u8 & 0x0f } } fn push_tx(&mut self, v: u32) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .txf(Self::Sm::SM_NO as usize) - .write_value(v); + Self::Pio::PIO.txf(Self::Sm::SM_NO as usize).write_value(v); } } @@ -480,7 +398,7 @@ pub trait PioStateMachine: Sized + Unpin { } fn pull_rx(&mut self) -> u32 { - unsafe { PIOS[Self::Pio::PIO_NO as usize].rxf(Self::Sm::SM_NO as usize).read() } + unsafe { Self::Pio::PIO.rxf(Self::Sm::SM_NO as usize).read() } } fn try_pull_rx(&mut self) -> Option { @@ -492,7 +410,7 @@ pub trait PioStateMachine: Sized + Unpin { fn set_clkdiv(&mut self, div_x_256: u32) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .clkdiv() .write(|w| w.0 = div_x_256 << 8); @@ -500,20 +418,12 @@ pub trait PioStateMachine: Sized + Unpin { } fn get_clkdiv(&self) -> u32 { - unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .clkdiv() - .read() - .0 - >> 8 - } + unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).clkdiv().read().0 >> 8 } } fn clkdiv_restart(&mut self) { - let _ = self; unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .ctrl() .modify(|w| w.set_clkdiv_restart(1u8 << Self::Sm::SM_NO)); } @@ -521,7 +431,7 @@ pub trait PioStateMachine: Sized + Unpin { fn set_side_enable(&self, enable: bool) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .execctrl() .modify(|w| w.set_side_en(enable)); @@ -529,18 +439,12 @@ pub trait PioStateMachine: Sized + Unpin { } fn is_side_enabled(&self) -> bool { - unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .execctrl() - .read() - .side_en() - } + unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().side_en() } } fn set_side_pindir(&mut self, pindir: bool) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .execctrl() .modify(|w| w.set_side_pindir(pindir)); @@ -549,7 +453,7 @@ pub trait PioStateMachine: Sized + Unpin { fn is_side_pindir(&self) -> bool { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .execctrl() .read() @@ -559,7 +463,7 @@ pub trait PioStateMachine: Sized + Unpin { fn set_jmp_pin(&mut self, pin: u8) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .execctrl() .modify(|w| w.set_jmp_pin(pin)); @@ -567,34 +471,22 @@ pub trait PioStateMachine: Sized + Unpin { } fn get_jmp_pin(&mut self) -> u8 { - unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .execctrl() - .read() - .jmp_pin() - } + unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().jmp_pin() } } fn set_wrap(&self, source: u8, target: u8) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .execctrl() - .modify(|w| { - w.set_wrap_top(source); - w.set_wrap_bottom(target) - }); + Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().modify(|w| { + w.set_wrap_top(source); + w.set_wrap_bottom(target) + }); } } /// Get wrapping addresses. Returns (source, target). fn get_wrap(&self) -> (u8, u8) { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .execctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read(); (r.wrap_top(), r.wrap_bottom()) } } @@ -606,21 +498,15 @@ pub trait PioStateMachine: Sized + Unpin { FifoJoin::TxOnly => (false, true), }; unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .shiftctrl() - .modify(|w| { - w.set_fjoin_rx(rx); - w.set_fjoin_tx(tx) - }); + Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().modify(|w| { + w.set_fjoin_rx(rx); + w.set_fjoin_tx(tx) + }); } } fn get_fifo_join(&self) -> FifoJoin { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .shiftctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read(); // Ignores the invalid state when both bits are set if r.fjoin_rx() { FifoJoin::RxOnly @@ -635,9 +521,7 @@ pub trait PioStateMachine: Sized + Unpin { fn clear_fifos(&mut self) { // Toggle FJOIN_RX to flush FIFOs unsafe { - let shiftctrl = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .shiftctrl(); + let shiftctrl = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl(); shiftctrl.modify(|w| { w.set_fjoin_rx(!w.fjoin_rx()); }); @@ -649,7 +533,7 @@ pub trait PioStateMachine: Sized + Unpin { fn set_pull_threshold(&mut self, threshold: u8) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .modify(|w| w.set_pull_thresh(threshold)); @@ -658,16 +542,13 @@ pub trait PioStateMachine: Sized + Unpin { fn get_pull_threshold(&self) -> u8 { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .shiftctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read(); r.pull_thresh() } } fn set_push_threshold(&mut self, threshold: u8) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .modify(|w| w.set_push_thresh(threshold)); @@ -676,17 +557,14 @@ pub trait PioStateMachine: Sized + Unpin { fn get_push_threshold(&self) -> u8 { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .shiftctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read(); r.push_thresh() } } fn set_out_shift_dir(&mut self, dir: ShiftDirection) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .modify(|w| w.set_out_shiftdir(dir == ShiftDirection::Right)); @@ -694,7 +572,7 @@ pub trait PioStateMachine: Sized + Unpin { } fn get_out_shiftdir(&self) -> ShiftDirection { unsafe { - if PIOS[Self::Pio::PIO_NO as usize] + if Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .read() @@ -709,7 +587,7 @@ pub trait PioStateMachine: Sized + Unpin { fn set_in_shift_dir(&mut self, dir: ShiftDirection) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .modify(|w| w.set_in_shiftdir(dir == ShiftDirection::Right)); @@ -717,7 +595,7 @@ pub trait PioStateMachine: Sized + Unpin { } fn get_in_shiftdir(&self) -> ShiftDirection { unsafe { - if PIOS[Self::Pio::PIO_NO as usize] + if Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .read() @@ -732,7 +610,7 @@ pub trait PioStateMachine: Sized + Unpin { fn set_autopull(&mut self, auto: bool) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .modify(|w| w.set_autopull(auto)); @@ -741,7 +619,7 @@ pub trait PioStateMachine: Sized + Unpin { fn is_autopull(&self) -> bool { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .read() @@ -751,7 +629,7 @@ pub trait PioStateMachine: Sized + Unpin { fn set_autopush(&mut self, auto: bool) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .modify(|w| w.set_autopush(auto)); @@ -760,7 +638,7 @@ pub trait PioStateMachine: Sized + Unpin { fn is_autopush(&self) -> bool { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .shiftctrl() .read() @@ -770,16 +648,13 @@ pub trait PioStateMachine: Sized + Unpin { fn get_addr(&self) -> u8 { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .addr() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).addr().read(); r.addr() } } fn set_sideset_count(&mut self, count: u8) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .pinctrl() .modify(|w| w.set_sideset_count(count)); @@ -788,37 +663,14 @@ pub trait PioStateMachine: Sized + Unpin { fn get_sideset_count(&self) -> u8 { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .pinctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); r.sideset_count() } } - fn make_pio_pin(&self, pin: impl Pin) -> PioPin { - unsafe { - pin.io().ctrl().write(|w| { - w.set_funcsel( - if Self::Pio::PIO_NO == 1 { - pac::io::vals::Gpio0ctrlFuncsel::PIO1_0 - } else { - // PIO == 0 - pac::io::vals::Gpio0ctrlFuncsel::PIO0_0 - } - .0, - ); - }); - } - PioPin { - pin_bank: pin.pin_bank(), - pio: PhantomData::default(), - } - } - fn set_sideset_base_pin(&mut self, base_pin: &PioPin) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .pinctrl() .modify(|w| w.set_sideset_base(base_pin.pin())); @@ -827,10 +679,7 @@ pub trait PioStateMachine: Sized + Unpin { fn get_sideset_base(&self) -> u8 { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .pinctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); r.sideset_base() } } @@ -839,30 +688,24 @@ pub trait PioStateMachine: Sized + Unpin { fn set_set_range(&mut self, base: u8, count: u8) { assert!(base + count < 32); unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .pinctrl() - .modify(|w| { - w.set_set_base(base); - w.set_set_count(count) - }); + Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| { + w.set_set_base(base); + w.set_set_count(count) + }); } } /// Get the range of out pins affected by a set instruction. Returns (base, count). fn get_set_range(&self) -> (u8, u8) { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .pinctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); (r.set_base(), r.set_count()) } } fn set_in_base_pin(&mut self, base: &PioPin) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .pinctrl() .modify(|w| w.set_in_base(base.pin())); @@ -871,10 +714,7 @@ pub trait PioStateMachine: Sized + Unpin { fn get_in_base(&self) -> u8 { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .pinctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); r.in_base() } } @@ -882,23 +722,17 @@ pub trait PioStateMachine: Sized + Unpin { fn set_out_range(&mut self, base: u8, count: u8) { assert!(base + count < 32); unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .pinctrl() - .modify(|w| { - w.set_out_base(base); - w.set_out_count(count) - }); + Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| { + w.set_out_base(base); + w.set_out_count(count) + }); } } /// Get the range of out pins affected by a set instruction. Returns (base, count). fn get_out_range(&self) -> (u8, u8) { unsafe { - let r = PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .pinctrl() - .read(); + let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); (r.out_base(), r.out_count()) } } @@ -926,50 +760,18 @@ pub trait PioStateMachine: Sized + Unpin { } fn get_current_instr() -> u32 { - unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .sm(Self::Sm::SM_NO as usize) - .instr() - .read() - .0 - } + unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).instr().read().0 } } fn exec_instr(&mut self, instr: u16) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .sm(Self::Sm::SM_NO as usize) .instr() .write(|w| w.set_instr(instr)); } } - fn write_instr(&mut self, start: usize, instrs: I) - where - I: Iterator, - { - let _ = self; - write_instr( - Self::Pio::PIO_NO, - start, - instrs, - MEM_USED_BY_STATEMACHINE | Self::Sm::SM_NO as u32, - ); - } - - fn is_irq_set(&self, irq_no: u8) -> bool { - assert!(irq_no < 8); - unsafe { - let irq_flags = PIOS[Self::Pio::PIO_NO as usize].irq(); - irq_flags.read().0 & (1 << irq_no) != 0 - } - } - - fn clear_irq(&mut self, irq_no: usize) { - assert!(irq_no < 8); - unsafe { PIOS[Self::Pio::PIO_NO as usize].irq().write(|w| w.set_irq(1 << irq_no)) } - } - fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> { FifoOutFuture::new(self, value) } @@ -984,7 +786,7 @@ pub trait PioStateMachine: Sized + Unpin { fn has_tx_stalled(&self) -> bool { unsafe { - let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); + let fdebug = Self::Pio::PIO.fdebug(); let ret = fdebug.read().txstall() & (1 << Self::Sm::SM_NO) != 0; fdebug.write(|w| w.set_txstall(1 << Self::Sm::SM_NO)); ret @@ -993,7 +795,7 @@ pub trait PioStateMachine: Sized + Unpin { fn has_tx_overflowed(&self) -> bool { unsafe { - let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); + let fdebug = Self::Pio::PIO.fdebug(); let ret = fdebug.read().txover() & (1 << Self::Sm::SM_NO) != 0; fdebug.write(|w| w.set_txover(1 << Self::Sm::SM_NO)); ret @@ -1002,7 +804,7 @@ pub trait PioStateMachine: Sized + Unpin { fn has_rx_stalled(&self) -> bool { unsafe { - let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); + let fdebug = Self::Pio::PIO.fdebug(); let ret = fdebug.read().rxstall() & (1 << Self::Sm::SM_NO) != 0; fdebug.write(|w| w.set_rxstall(1 << Self::Sm::SM_NO)); ret @@ -1011,7 +813,7 @@ pub trait PioStateMachine: Sized + Unpin { fn has_rx_underflowed(&self) -> bool { unsafe { - let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); + let fdebug = Self::Pio::PIO.fdebug(); let ret = fdebug.read().rxunder() & (1 << Self::Sm::SM_NO) != 0; fdebug.write(|w| w.set_rxunder(1 << Self::Sm::SM_NO)); ret @@ -1020,13 +822,12 @@ pub trait PioStateMachine: Sized + Unpin { fn dma_push<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [u32]) -> Transfer<'a, C> { unsafe { - dma::init(); let pio_no = Self::Pio::PIO_NO; let sm_no = Self::Sm::SM_NO; let p = ch.regs(); p.read_addr().write_value(data.as_ptr() as u32); p.write_addr() - .write_value(PIOS[pio_no as usize].txf(sm_no as usize).ptr() as u32); + .write_value(Self::Pio::PIO.txf(sm_no as usize).ptr() as u32); p.trans_count().write_value(data.len() as u32); p.ctrl_trig().write(|w| { // Set TX DREQ for this statemachine @@ -1044,13 +845,12 @@ pub trait PioStateMachine: Sized + Unpin { fn dma_pull<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [u32]) -> Transfer<'a, C> { unsafe { - dma::init(); let pio_no = Self::Pio::PIO_NO; let sm_no = Self::Sm::SM_NO; let p = ch.regs(); p.write_addr().write_value(data.as_ptr() as u32); p.read_addr() - .write_value(PIOS[pio_no as usize].rxf(sm_no as usize).ptr() as u32); + .write_value(Self::Pio::PIO.rxf(sm_no as usize).ptr() as u32); p.trans_count().write_value(data.len() as u32); p.ctrl_trig().write(|w| { // Set TX DREQ for this statemachine @@ -1067,120 +867,127 @@ pub trait PioStateMachine: Sized + Unpin { } } -/* -This is a bit array containing 4 bits for every word in the PIO instruction memory. -*/ -// Bit 3-2 -//const MEM_USE_MASK: u32 = 0b1100; -const MEM_NOT_USED: u32 = 0b0000; -const MEM_USED_BY_STATEMACHINE: u32 = 0b0100; -const MEM_USED_BY_COMMON: u32 = 0b1000; - -// Bit 1-0 is the number of the state machine -//const MEM_STATE_MASK: u32 = 0b0011; - -// Should use mutex if running on multiple cores -static mut INSTR_MEM_STATUS: &'static mut [[u32; 4]; 2] = &mut [[0; 4]; 2]; - -fn instr_mem_get_status(pio_no: u8, addr: u8) -> u32 { - ((unsafe { INSTR_MEM_STATUS[pio_no as usize][(addr >> 3) as usize] }) >> ((addr & 0x07) * 4)) & 0xf -} - -fn instr_mem_set_status(pio_no: u8, addr: u8, status: u32) { - let w = unsafe { &mut INSTR_MEM_STATUS[pio_no as usize][(addr >> 3) as usize] }; - let shift = (addr & 0x07) * 4; - *w = (*w & !(0xf << shift)) | (status << shift); -} - -fn instr_mem_is_free(pio_no: u8, addr: u8) -> bool { - instr_mem_get_status(pio_no, addr) == MEM_NOT_USED -} - pub struct PioCommonInstance { + instructions_used: u32, pio: PhantomData, } -impl PioCommon for PioCommonInstance { +pub struct PioInstanceMemory { + used_mask: u32, + pio: PhantomData, +} + +impl sealed::PioCommon for PioCommonInstance { type Pio = PIO; } - -fn write_instr(pio_no: u8, start: usize, instrs: I, mem_user: u32) -where - I: Iterator, -{ - for (i, instr) in instrs.enumerate() { - let addr = (i + start) as u8; - assert!( - instr_mem_is_free(pio_no, addr), - "Trying to write already used PIO instruction memory at {}", - addr - ); - unsafe { - PIOS[pio_no as usize].instr_mem(addr as usize).write(|w| { - w.set_instr_mem(instr); - }); - instr_mem_set_status(pio_no, addr, mem_user); - } - } -} - -pub trait PioCommon: Sized { - type Pio: PioInstance; - - fn write_instr(&mut self, start: usize, instrs: I) +impl PioCommon for PioCommonInstance { + fn write_instr(&mut self, start: usize, instrs: I) -> PioInstanceMemory where I: Iterator, { - let _ = self; - write_instr(Self::Pio::PIO_NO, start, instrs, MEM_USED_BY_COMMON); + let mut used_mask = 0; + for (i, instr) in instrs.enumerate() { + let addr = (i + start) as u8; + let mask = 1 << (addr as usize); + assert!( + self.instructions_used & mask == 0, + "Trying to write already used PIO instruction memory at {}", + addr + ); + unsafe { + PIO::PIO.instr_mem(addr as usize).write(|w| { + w.set_instr_mem(instr); + }); + } + used_mask |= mask; + } + self.instructions_used |= used_mask; + PioInstanceMemory { + used_mask, + pio: PhantomData, + } + } + + fn free_instr(&mut self, instrs: PioInstanceMemory) { + self.instructions_used &= !instrs.used_mask; + } +} + +pub trait PioCommon: sealed::PioCommon + Sized { + fn write_instr(&mut self, start: usize, instrs: I) -> PioInstanceMemory + where + I: Iterator; + + // TODO make instruction memory that is currently in use unfreeable + fn free_instr(&mut self, instrs: PioInstanceMemory); + + fn is_irq_set(&self, irq_no: u8) -> bool { + assert!(irq_no < 8); + unsafe { + let irq_flags = Self::Pio::PIO.irq(); + irq_flags.read().0 & (1 << irq_no) != 0 + } } fn clear_irq(&mut self, irq_no: usize) { assert!(irq_no < 8); - unsafe { PIOS[Self::Pio::PIO_NO as usize].irq().write(|w| w.set_irq(1 << irq_no)) } + unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) } } fn clear_irqs(&mut self, mask: u8) { - unsafe { PIOS[Self::Pio::PIO_NO as usize].irq().write(|w| w.set_irq(mask)) } + unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(mask)) } } fn force_irq(&mut self, irq_no: usize) { assert!(irq_no < 8); - unsafe { - PIOS[Self::Pio::PIO_NO as usize] - .irq_force() - .write(|w| w.set_irq_force(1 << irq_no)) - } + unsafe { Self::Pio::PIO.irq_force().write(|w| w.set_irq_force(1 << irq_no)) } } fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { unsafe { - PIOS[Self::Pio::PIO_NO as usize] + Self::Pio::PIO .input_sync_bypass() .modify(|w| *w = (*w & !mask) | (bypass & mask)); } } fn get_input_sync_bypass(&self) -> u32 { - unsafe { PIOS[Self::Pio::PIO_NO as usize].input_sync_bypass().read() } + unsafe { Self::Pio::PIO.input_sync_bypass().read() } + } + + fn make_pio_pin(&self, pin: impl Pin) -> PioPin { + unsafe { + pin.io().ctrl().write(|w| { + w.set_funcsel( + if Self::Pio::PIO_NO == 1 { + pac::io::vals::Gpio0ctrlFuncsel::PIO1_0 + } else { + // PIO == 0 + pac::io::vals::Gpio0ctrlFuncsel::PIO0_0 + } + .0, + ); + }); + } + PioPin { + pin_bank: pin.pin_bank(), + pio: PhantomData::default(), + } } } // Identifies a specific state machine inside a PIO device pub struct SmInstanceBase {} -pub trait SmInstance: Unpin { - const SM_NO: u8; -} +pub trait SmInstance: sealed::SmInstance + Unpin {} -impl SmInstance for SmInstanceBase { +impl sealed::SmInstance for SmInstanceBase { const SM_NO: u8 = SM_NO; } +impl SmInstance for SmInstanceBase {} -pub trait PioPeripheral: Sized { - type Pio: PioInstance; +pub trait PioPeripheral: sealed::PioPeripheral + Sized { fn pio(&self) -> u8 { - let _ = self; Self::Pio::PIO_NO } @@ -1193,9 +1000,9 @@ pub trait PioPeripheral: Sized { PioStateMachineInstance>, PioStateMachineInstance>, ) { - let _ = self; ( PioCommonInstance { + instructions_used: 0, pio: PhantomData::default(), }, PioStateMachineInstance { @@ -1218,29 +1025,46 @@ pub trait PioPeripheral: Sized { } } +mod sealed { + pub trait PioInstance { + const PIO_NO: u8; + const PIO: &'static crate::pac::pio::Pio; + } + + pub trait PioCommon { + type Pio: super::PioInstance; + } + + pub trait PioStateMachine { + type Pio: super::PioInstance; + type Sm: super::SmInstance; + } + + pub trait SmInstance { + const SM_NO: u8; + } + + pub trait PioPeripheral { + type Pio: super::PioInstance; + } +} + // Identifies a specific PIO device pub struct PioInstanceBase {} -pub trait PioInstance: Unpin { - const PIO_NO: u8; - type IrqOut: Interrupt; - type IrqIn: Interrupt; - type IrqSm: Interrupt; -} +pub trait PioInstance: sealed::PioInstance + Unpin {} -impl PioInstance for PioInstanceBase<0> { +impl sealed::PioInstance for PioInstanceBase<0> { const PIO_NO: u8 = 0; - type IrqOut = interrupt::PIO0_IRQ_0; - type IrqIn = interrupt::PIO0_IRQ_1; - type IrqSm = interrupt::PIO0_IRQ_1; + const PIO: &'static pac::pio::Pio = &pac::PIO0; } +impl PioInstance for PioInstanceBase<0> {} -impl PioInstance for PioInstanceBase<1> { +impl sealed::PioInstance for PioInstanceBase<1> { const PIO_NO: u8 = 1; - type IrqOut = interrupt::PIO1_IRQ_0; - type IrqIn = interrupt::PIO1_IRQ_1; - type IrqSm = interrupt::PIO1_IRQ_1; + const PIO: &'static pac::pio::Pio = &pac::PIO1; } +impl PioInstance for PioInstanceBase<1> {} pub type Pio0 = PioInstanceBase<0>; pub type Pio1 = PioInstanceBase<1>; @@ -1252,9 +1076,10 @@ pub type Sm3 = SmInstanceBase<3>; macro_rules! impl_pio_sm { ($name:ident, $pio:expr) => { - impl PioPeripheral for peripherals::$name { + impl sealed::PioPeripheral for peripherals::$name { type Pio = PioInstanceBase<$pio>; } + impl PioPeripheral for peripherals::$name {} }; } diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index e616d8c5..1b075b8f 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -4,13 +4,15 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::gpio::{AnyPin, Pin}; -use embassy_rp::pio::{Pio0, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2}; +use embassy_rp::pio::{ + Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, + Sm1, Sm2, +}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -#[embassy_executor::task] -async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { +fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance, pin: AnyPin) { // Setup sm0 // Send data serially to pin @@ -23,11 +25,11 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { ); let relocated = RelocatedProgram::new(&prg.program); - let out_pin = sm.make_pio_pin(pin); + let out_pin = pio.make_pio_pin(pin); let pio_pins = [&out_pin]; sm.set_out_pins(&pio_pins); - sm.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + pio.write_instr(relocated.origin() as usize, relocated.code()); + pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); sm.set_set_range(0, 1); let pio::Wrap { source, target } = relocated.wrap(); @@ -35,7 +37,10 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { sm.set_autopull(true); sm.set_out_shift_dir(ShiftDirection::Left); +} +#[embassy_executor::task] +async fn pio_task_sm0(mut sm: PioStateMachineInstance) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -46,16 +51,15 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { } } -#[embassy_executor::task] -async fn pio_task_sm1(mut sm: PioStateMachineInstance) { +fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); let relocated = RelocatedProgram::new(&prg.program); - sm.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + pio.write_instr(relocated.origin() as usize, relocated.code()); + pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); sm.set_set_range(0, 0); let pio::Wrap { source, target } = relocated.wrap(); @@ -63,6 +67,10 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance) { sm.set_autopush(true); sm.set_in_shift_dir(ShiftDirection::Right); +} + +#[embassy_executor::task] +async fn pio_task_sm1(mut sm: PioStateMachineInstance) { sm.set_enable(true); loop { let rx = sm.wait_pull().await; @@ -70,8 +78,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance) { } } -#[embassy_executor::task] -async fn pio_task_sm2(mut sm: PioStateMachineInstance) { +fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { // Setup sm2 // Repeatedly trigger IRQ 3 @@ -85,13 +92,17 @@ async fn pio_task_sm2(mut sm: PioStateMachineInstance) { ".wrap", ); let relocated = RelocatedProgram::new(&prg.program); - sm.write_instr(relocated.origin() as usize, relocated.code()); + pio.write_instr(relocated.origin() as usize, relocated.code()); let pio::Wrap { source, target } = relocated.wrap(); sm.set_wrap(source, target); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); +} + +#[embassy_executor::task] +async fn pio_task_sm2(mut sm: PioStateMachineInstance) { sm.set_enable(true); loop { sm.wait_irq(3).await; @@ -104,9 +115,12 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (_, sm0, sm1, sm2, ..) = pio.split(); + let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); - spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap(); + setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); + setup_pio_task_sm1(&mut pio0, &mut sm1); + setup_pio_task_sm2(&mut pio0, &mut sm2); + spawner.spawn(pio_task_sm0(sm0)).unwrap(); spawner.spawn(pio_task_sm1(sm1)).unwrap(); spawner.spawn(pio_task_sm2(sm2)).unwrap(); } diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 145e4a65..7d4919f7 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{PioPeripheral, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; @@ -19,7 +19,7 @@ fn swap_nibbles(v: u32) -> u32 { async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (_, mut sm, ..) = pio.split(); + let (mut pio0, mut sm, ..) = pio.split(); let prg = pio_proc::pio_asm!( ".origin 0", @@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) { ); let relocated = RelocatedProgram::new(&prg.program); - sm.write_instr(relocated.origin() as usize, relocated.code()); + pio0.write_instr(relocated.origin() as usize, relocated.code()); pio_instr_util::exec_jmp(&mut sm, relocated.origin()); sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); let pio::Wrap { source, target } = relocated.wrap(); diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 5f8a3bae..041e8ae1 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, + FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, + ShiftDirection, SmInstance, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; @@ -18,7 +19,7 @@ pub struct Ws2812 { } impl Ws2812 { - pub fn new(mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { + pub fn new(mut pio: PioCommonInstance

, mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { // Setup sm0 // prepare the PIO program @@ -49,11 +50,11 @@ impl Ws2812 { let prg = a.assemble_with_wrap(wrap_source, wrap_target); let relocated = RelocatedProgram::new(&prg); - sm.write_instr(relocated.origin() as usize, relocated.code()); + pio.write_instr(relocated.origin() as usize, relocated.code()); pio_instr_util::exec_jmp(&mut sm, relocated.origin()); // Pin config - let out_pin = sm.make_pio_pin(pin); + let out_pin = pio.make_pio_pin(pin); sm.set_set_pins(&[&out_pin]); sm.set_sideset_base_pin(&out_pin); sm.set_sideset_count(1); @@ -115,7 +116,7 @@ async fn main(_spawner: Spawner) { info!("Start"); let p = embassy_rp::init(Default::default()); - let (_pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); + let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit // feather boards for the 2040 both have one built in. @@ -124,7 +125,7 @@ async fn main(_spawner: Spawner) { // For the thing plus, use pin 8 // For the feather, use pin 16 - let mut ws2812 = Ws2812::new(sm0, p.PIN_8.degrade()); + let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade()); // Loop forever making RGB values and pushing them out to the WS2812. loop {