aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-04-25 20:16:27 +0200
committerpennae <[email protected]>2023-05-01 12:58:57 +0200
commit58e727d3b9aa9d54f7c20f618fada176dcd533a9 (patch)
tree2af5bf9684caa397a0e3bc2c2030c43ef74fddb5
parent4cd5ed81aa7931b8b0ff3e09c3604cf5d65f2107 (diff)
rp/pio: move non-sm-specific methods to PioCommon
pin and irq operations affect the entire pio block. with pins this is not very problematic since pins themselves are resources, but irqs are not treated like that and can thus interfere across state machines. the ability to wait for an irq on a state machine is kept to make synchronization with user code easier, and since we can't inspect loaded programs at build time we wouldn't gain much from disallowing waits from state machines anyway.
-rw-r--r--embassy-rp/src/pio.rs61
-rw-r--r--examples/rp/src/bin/pio_async.rs20
-rw-r--r--examples/rp/src/bin/ws2812-pio.rs11
3 files changed, 47 insertions, 45 deletions
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 088944b66..b43244da2 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -677,26 +677,6 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
677 } 677 }
678 } 678 }
679 679
680 fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> {
681 unsafe {
682 pin.io().ctrl().write(|w| {
683 w.set_funcsel(
684 if Self::Pio::PIO_NO == 1 {
685 pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
686 } else {
687 // PIO == 0
688 pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
689 }
690 .0,
691 );
692 });
693 }
694 PioPin {
695 pin_bank: pin.pin_bank(),
696 pio: PhantomData::default(),
697 }
698 }
699
700 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) { 680 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) {
701 unsafe { 681 unsafe {
702 Self::Pio::PIO 682 Self::Pio::PIO
@@ -815,19 +795,6 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
815 ); 795 );
816 } 796 }
817 797
818 fn is_irq_set(&self, irq_no: u8) -> bool {
819 assert!(irq_no < 8);
820 unsafe {
821 let irq_flags = Self::Pio::PIO.irq();
822 irq_flags.read().0 & (1 << irq_no) != 0
823 }
824 }
825
826 fn clear_irq(&mut self, irq_no: usize) {
827 assert!(irq_no < 8);
828 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
829 }
830
831 fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> { 798 fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> {
832 FifoOutFuture::new(self, value) 799 FifoOutFuture::new(self, value)
833 } 800 }
@@ -990,6 +957,14 @@ pub trait PioCommon: sealed::PioCommon + Sized {
990 write_instr(Self::Pio::PIO, Self::Pio::PIO_NO, start, instrs, MEM_USED_BY_COMMON); 957 write_instr(Self::Pio::PIO, Self::Pio::PIO_NO, start, instrs, MEM_USED_BY_COMMON);
991 } 958 }
992 959
960 fn is_irq_set(&self, irq_no: u8) -> bool {
961 assert!(irq_no < 8);
962 unsafe {
963 let irq_flags = Self::Pio::PIO.irq();
964 irq_flags.read().0 & (1 << irq_no) != 0
965 }
966 }
967
993 fn clear_irq(&mut self, irq_no: usize) { 968 fn clear_irq(&mut self, irq_no: usize) {
994 assert!(irq_no < 8); 969 assert!(irq_no < 8);
995 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) } 970 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
@@ -1015,6 +990,26 @@ pub trait PioCommon: sealed::PioCommon + Sized {
1015 fn get_input_sync_bypass(&self) -> u32 { 990 fn get_input_sync_bypass(&self) -> u32 {
1016 unsafe { Self::Pio::PIO.input_sync_bypass().read() } 991 unsafe { Self::Pio::PIO.input_sync_bypass().read() }
1017 } 992 }
993
994 fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> {
995 unsafe {
996 pin.io().ctrl().write(|w| {
997 w.set_funcsel(
998 if Self::Pio::PIO_NO == 1 {
999 pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
1000 } else {
1001 // PIO == 0
1002 pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
1003 }
1004 .0,
1005 );
1006 });
1007 }
1008 PioPin {
1009 pin_bank: pin.pin_bank(),
1010 pio: PhantomData::default(),
1011 }
1012 }
1018} 1013}
1019 1014
1020// Identifies a specific state machine inside a PIO device 1015// Identifies a specific state machine inside a PIO device
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index e616d8c5a..3cfeec71f 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -4,13 +4,15 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::gpio::{AnyPin, Pin}; 6use embassy_rp::gpio::{AnyPin, Pin};
7use embassy_rp::pio::{Pio0, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2}; 7use embassy_rp::pio::{
8 Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0,
9 Sm1, Sm2,
10};
8use embassy_rp::pio_instr_util; 11use embassy_rp::pio_instr_util;
9use embassy_rp::relocate::RelocatedProgram; 12use embassy_rp::relocate::RelocatedProgram;
10use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
11 14
12#[embassy_executor::task] 15fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
13async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
14 // Setup sm0 16 // Setup sm0
15 17
16 // Send data serially to pin 18 // Send data serially to pin
@@ -23,11 +25,11 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
23 ); 25 );
24 26
25 let relocated = RelocatedProgram::new(&prg.program); 27 let relocated = RelocatedProgram::new(&prg.program);
26 let out_pin = sm.make_pio_pin(pin); 28 let out_pin = pio.make_pio_pin(pin);
27 let pio_pins = [&out_pin]; 29 let pio_pins = [&out_pin];
28 sm.set_out_pins(&pio_pins); 30 sm.set_out_pins(&pio_pins);
29 sm.write_instr(relocated.origin() as usize, relocated.code()); 31 sm.write_instr(relocated.origin() as usize, relocated.code());
30 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 32 pio_instr_util::exec_jmp(sm, relocated.origin());
31 sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); 33 sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32);
32 sm.set_set_range(0, 1); 34 sm.set_set_range(0, 1);
33 let pio::Wrap { source, target } = relocated.wrap(); 35 let pio::Wrap { source, target } = relocated.wrap();
@@ -35,7 +37,10 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
35 37
36 sm.set_autopull(true); 38 sm.set_autopull(true);
37 sm.set_out_shift_dir(ShiftDirection::Left); 39 sm.set_out_shift_dir(ShiftDirection::Left);
40}
38 41
42#[embassy_executor::task]
43async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) {
39 sm.set_enable(true); 44 sm.set_enable(true);
40 45
41 let mut v = 0x0f0caffa; 46 let mut v = 0x0f0caffa;
@@ -104,9 +109,10 @@ async fn main(spawner: Spawner) {
104 let p = embassy_rp::init(Default::default()); 109 let p = embassy_rp::init(Default::default());
105 let pio = p.PIO0; 110 let pio = p.PIO0;
106 111
107 let (_, sm0, sm1, sm2, ..) = pio.split(); 112 let (mut pio0, mut sm0, sm1, sm2, ..) = pio.split();
108 113
109 spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap(); 114 setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade());
115 spawner.spawn(pio_task_sm0(sm0)).unwrap();
110 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 116 spawner.spawn(pio_task_sm1(sm1)).unwrap();
111 spawner.spawn(pio_task_sm2(sm2)).unwrap(); 117 spawner.spawn(pio_task_sm2(sm2)).unwrap();
112} 118}
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs
index 5f8a3baee..211c60c49 100644
--- a/examples/rp/src/bin/ws2812-pio.rs
+++ b/examples/rp/src/bin/ws2812-pio.rs
@@ -6,7 +6,8 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::gpio::{self, Pin}; 7use embassy_rp::gpio::{self, Pin};
8use embassy_rp::pio::{ 8use embassy_rp::pio::{
9 FifoJoin, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, 9 FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance,
10 ShiftDirection, SmInstance,
10}; 11};
11use embassy_rp::pio_instr_util; 12use embassy_rp::pio_instr_util;
12use embassy_rp::relocate::RelocatedProgram; 13use embassy_rp::relocate::RelocatedProgram;
@@ -18,7 +19,7 @@ pub struct Ws2812<P: PioInstance, S: SmInstance> {
18} 19}
19 20
20impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { 21impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
21 pub fn new(mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self { 22 pub fn new(pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self {
22 // Setup sm0 23 // Setup sm0
23 24
24 // prepare the PIO program 25 // prepare the PIO program
@@ -53,7 +54,7 @@ impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
53 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 54 pio_instr_util::exec_jmp(&mut sm, relocated.origin());
54 55
55 // Pin config 56 // Pin config
56 let out_pin = sm.make_pio_pin(pin); 57 let out_pin = pio.make_pio_pin(pin);
57 sm.set_set_pins(&[&out_pin]); 58 sm.set_set_pins(&[&out_pin]);
58 sm.set_sideset_base_pin(&out_pin); 59 sm.set_sideset_base_pin(&out_pin);
59 sm.set_sideset_count(1); 60 sm.set_sideset_count(1);
@@ -115,7 +116,7 @@ async fn main(_spawner: Spawner) {
115 info!("Start"); 116 info!("Start");
116 let p = embassy_rp::init(Default::default()); 117 let p = embassy_rp::init(Default::default());
117 118
118 let (_pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); 119 let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split();
119 120
120 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit 121 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit
121 // feather boards for the 2040 both have one built in. 122 // feather boards for the 2040 both have one built in.
@@ -124,7 +125,7 @@ async fn main(_spawner: Spawner) {
124 125
125 // For the thing plus, use pin 8 126 // For the thing plus, use pin 8
126 // For the feather, use pin 16 127 // For the feather, use pin 16
127 let mut ws2812 = Ws2812::new(sm0, p.PIN_8.degrade()); 128 let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade());
128 129
129 // Loop forever making RGB values and pushing them out to the WS2812. 130 // Loop forever making RGB values and pushing them out to the WS2812.
130 loop { 131 loop {