From 8839f3f62ab85a1abd066fcbfa15693965e6fae8 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 26 Apr 2023 19:43:57 +0200 Subject: [PATCH] rp/pio: PioInstance::split -> Pio::new not requiring a PioInstance for splitting lets us split from a PeripheralRef or borrowed PIO as well, mirroring every other peripheral in embassy_rp. pio pins still have to be constructed from owned pin instances for now. --- embassy-rp/src/pio.rs | 92 +++++++++++++++--------------- examples/rp/src/bin/pio_async.rs | 22 ++++--- examples/rp/src/bin/pio_dma.rs | 10 +++- examples/rp/src/bin/pio_hd44780.rs | 10 ++-- examples/rp/src/bin/ws2812-pio.rs | 18 +++--- 5 files changed, 85 insertions(+), 67 deletions(-) diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 27a6068f..97e97b74 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -5,7 +5,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; -use embassy_hal_common::PeripheralRef; +use embassy_hal_common::{Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::dma::{Channel, Transfer, Word}; @@ -316,16 +316,16 @@ impl SealedPin for PioPin { } } -pub struct PioStateMachineInstance { - pio: PhantomData, +pub struct PioStateMachineInstance<'d, PIO: PioInstance, SM: SmInstance> { + pio: PhantomData<&'d PIO>, sm: PhantomData, } -impl sealed::PioStateMachine for PioStateMachineInstance { +impl<'d, PIO: PioInstance, SM: SmInstance> sealed::PioStateMachine for PioStateMachineInstance<'d, PIO, SM> { type Pio = PIO; type Sm = SM; } -impl PioStateMachine for PioStateMachineInstance {} +impl<'d, PIO: PioInstance, SM: SmInstance> PioStateMachine for PioStateMachineInstance<'d, PIO, SM> {} pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin { fn pio_no(&self) -> u8 { @@ -792,21 +792,21 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin { } } -pub struct PioCommonInstance { +pub struct PioCommonInstance<'d, PIO: PioInstance> { instructions_used: u32, - pio: PhantomData, + pio: PhantomData<&'d PIO>, } -pub struct PioInstanceMemory { +pub struct PioInstanceMemory<'d, PIO: PioInstance> { used_mask: u32, - pio: PhantomData, + pio: PhantomData<&'d PIO>, } -impl sealed::PioCommon for PioCommonInstance { +impl<'d, PIO: PioInstance> sealed::PioCommon for PioCommonInstance<'d, PIO> { type Pio = PIO; } -impl PioCommon for PioCommonInstance { - fn write_instr(&mut self, start: usize, instrs: I) -> PioInstanceMemory +impl<'d, PIO: PioInstance> PioCommon for PioCommonInstance<'d, PIO> { + fn write_instr(&mut self, start: usize, instrs: I) -> PioInstanceMemory<'d, Self::Pio> where I: Iterator, { @@ -903,43 +903,45 @@ impl sealed::SmInstance for SmInstanceBase { } impl SmInstance for SmInstanceBase {} +pub struct Pio<'d, PIO: PioInstance> { + pub common: PioCommonInstance<'d, PIO>, + pub sm0: PioStateMachineInstance<'d, PIO, SmInstanceBase<0>>, + pub sm1: PioStateMachineInstance<'d, PIO, SmInstanceBase<1>>, + pub sm2: PioStateMachineInstance<'d, PIO, SmInstanceBase<2>>, + pub sm3: PioStateMachineInstance<'d, PIO, SmInstanceBase<3>>, +} + +impl<'d, PIO: PioInstance> Pio<'d, PIO> { + pub fn new(_pio: impl Peripheral

+ 'd) -> Self { + Self { + common: PioCommonInstance { + instructions_used: 0, + pio: PhantomData, + }, + sm0: PioStateMachineInstance { + sm: PhantomData, + pio: PhantomData, + }, + sm1: PioStateMachineInstance { + sm: PhantomData, + pio: PhantomData, + }, + sm2: PioStateMachineInstance { + sm: PhantomData, + pio: PhantomData, + }, + sm3: PioStateMachineInstance { + sm: PhantomData, + pio: PhantomData, + }, + } + } +} + pub trait PioInstance: sealed::PioInstance + Sized + Unpin { fn pio(&self) -> u8 { Self::PIO_NO } - - fn split( - self, - ) -> ( - PioCommonInstance, - PioStateMachineInstance>, - PioStateMachineInstance>, - PioStateMachineInstance>, - PioStateMachineInstance>, - ) { - ( - PioCommonInstance { - instructions_used: 0, - pio: PhantomData::default(), - }, - PioStateMachineInstance { - sm: PhantomData::default(), - pio: PhantomData::default(), - }, - PioStateMachineInstance { - sm: PhantomData::default(), - pio: PhantomData::default(), - }, - PioStateMachineInstance { - sm: PhantomData::default(), - pio: PhantomData::default(), - }, - PioStateMachineInstance { - sm: PhantomData::default(), - pio: PhantomData::default(), - }, - ) - } } mod sealed { diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 16a09327..69a22f23 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -6,7 +6,7 @@ use embassy_executor::Spawner; use embassy_rp::gpio::{AnyPin, Pin}; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{ - PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2, + Pio, PioCommon, PioCommonInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; @@ -40,7 +40,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm0(mut sm: PioStateMachineInstance) { +async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, Sm0>) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -70,7 +70,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm1(mut sm: PioStateMachineInstance) { +async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, Sm1>) { sm.set_enable(true); loop { let rx = sm.wait_pull().await; @@ -102,7 +102,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm2(mut sm: PioStateMachineInstance) { +async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, Sm2>) { sm.set_enable(true); loop { sm.wait_irq(3).await; @@ -115,11 +115,17 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); + let Pio { + mut common, + mut sm0, + mut sm1, + mut sm2, + .. + } = Pio::new(pio); - 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); + setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0.degrade()); + setup_pio_task_sm1(&mut common, &mut sm1); + setup_pio_task_sm2(&mut common, &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 ccbc70fe..33c320b8 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::{PioCommon, PioInstance, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; @@ -19,7 +19,11 @@ fn swap_nibbles(v: u32) -> u32 { async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (mut pio0, mut sm, ..) = pio.split(); + let Pio { + mut common, + sm0: mut sm, + .. + } = Pio::new(pio); let prg = pio_proc::pio_asm!( ".origin 0", @@ -34,7 +38,7 @@ async fn main(_spawner: Spawner) { ); let relocated = RelocatedProgram::new(&prg.program); - pio0.write_instr(relocated.origin() as usize, relocated.code()); + common.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/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 1b24897b..994d4600 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -9,7 +9,7 @@ use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::gpio::Pin; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{ - FifoJoin, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase, + FifoJoin, Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase, }; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; @@ -67,14 +67,14 @@ async fn main(_spawner: Spawner) { pub struct HD44780<'l> { dma: PeripheralRef<'l, AnyChannel>, - sm: PioStateMachineInstance>, + sm: PioStateMachineInstance<'l, PIO0, SmInstanceBase<0>>, buf: [u8; 40], } impl<'l> HD44780<'l> { pub async fn new( - pio: PIO0, + pio: impl Peripheral

+ 'l, dma: impl Peripheral

+ 'l, rs: impl Pin, rw: impl Pin, @@ -87,7 +87,9 @@ impl<'l> HD44780<'l> { into_ref!(dma); let db7pin = db7.pin(); - let (mut common, mut sm0, ..) = pio.split(); + let Pio { + mut common, mut sm0, .. + } = Pio::new(pio); // takes command words ( <0:4>) let prg = pio_proc::pio_asm!( diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 592caf24..42c731bd 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, + FifoJoin, Pio, PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, }; use embassy_rp::pio_instr_util; @@ -14,12 +14,16 @@ use embassy_rp::relocate::RelocatedProgram; use embassy_time::{Duration, Timer}; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; -pub struct Ws2812 { - sm: PioStateMachineInstance, +pub struct Ws2812<'d, P: PioInstance, S: SmInstance> { + sm: PioStateMachineInstance<'d, P, S>, } -impl Ws2812 { - pub fn new(mut pio: PioCommonInstance

, mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { +impl<'d, P: PioInstance, S: SmInstance> Ws2812<'d, P, S> { + pub fn new( + mut pio: PioCommonInstance<'d, P>, + mut sm: PioStateMachineInstance<'d, P, S>, + pin: gpio::AnyPin, + ) -> Self { // Setup sm0 // prepare the PIO program @@ -116,7 +120,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 Pio { common, sm0, .. } = Pio::new(p.PIO0); // 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. @@ -125,7 +129,7 @@ async fn main(_spawner: Spawner) { // For the thing plus, use pin 8 // For the feather, use pin 16 - let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade()); + let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8.degrade()); // Loop forever making RGB values and pushing them out to the WS2812. loop {