aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-04-27 02:12:49 +0200
committerpennae <[email protected]>2023-05-03 12:57:21 +0200
commit909a5fe2e513ef91129a29ccdd8772824879383c (patch)
tree849028b8188df60507f05acb562d8c607dc76bd8
parent486fe9e59da7474c5162f56d89d5b6c279d02753 (diff)
rp/pio: split irqs from state machines
we can only have one active waiter for any given irq at any given time. allowing waits for irqs on state machines bypasses this limitation and causes lost events for all but the latest waiter for a given irq. splitting this out also allows us to signal from state machines to other parts of the application without monopolizing state machine access for the irq wait, as would be necessary to make irq waiting sound.
-rw-r--r--embassy-rp/src/pio.rs45
-rw-r--r--examples/rp/src/bin/pio_async.rs9
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs7
3 files changed, 37 insertions, 24 deletions
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 52ef89a16..769641ac9 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -180,21 +180,12 @@ impl<'a, 'd, PIO: PioInstance, const SM: usize> Drop for FifoInFuture<'a, 'd, PI
180 180
181/// Future that waits for IRQ 181/// Future that waits for IRQ
182#[must_use = "futures do nothing unless you `.await` or poll them"] 182#[must_use = "futures do nothing unless you `.await` or poll them"]
183pub struct IrqFuture<PIO: PioInstance> { 183pub struct IrqFuture<'a, 'd, PIO: PioInstance> {
184 pio: PhantomData<PIO>, 184 pio: PhantomData<&'a PioIrq<'d, PIO, 0>>,
185 irq_no: u8, 185 irq_no: u8,
186} 186}
187 187
188impl<'a, PIO: PioInstance> IrqFuture<PIO> { 188impl<'a, 'd, PIO: PioInstance> Future for IrqFuture<'a, 'd, PIO> {
189 pub fn new(irq_no: u8) -> Self {
190 IrqFuture {
191 pio: PhantomData::default(),
192 irq_no,
193 }
194 }
195}
196
197impl<'d, PIO: PioInstance> Future for IrqFuture<PIO> {
198 type Output = (); 189 type Output = ();
199 fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 190 fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
200 //debug!("Poll {},{}", PIO::PIO_NO, SM); 191 //debug!("Poll {},{}", PIO::PIO_NO, SM);
@@ -224,7 +215,7 @@ impl<'d, PIO: PioInstance> Future for IrqFuture<PIO> {
224 } 215 }
225} 216}
226 217
227impl<'d, PIO: PioInstance> Drop for IrqFuture<PIO> { 218impl<'a, 'd, PIO: PioInstance> Drop for IrqFuture<'a, 'd, PIO> {
228 fn drop(&mut self) { 219 fn drop(&mut self) {
229 unsafe { 220 unsafe {
230 PIO::PIO.irqs(0).inte().write_clear(|m| { 221 PIO::PIO.irqs(0).inte().write_clear(|m| {
@@ -688,10 +679,6 @@ impl<'d, PIO: PioInstance + 'd, const SM: usize> PioStateMachine<'d, PIO, SM> {
688 FifoInFuture::new(self) 679 FifoInFuture::new(self)
689 } 680 }
690 681
691 pub fn wait_irq(&self, irq_no: u8) -> IrqFuture<PIO> {
692 IrqFuture::new(irq_no)
693 }
694
695 pub fn has_tx_stalled(&self) -> bool { 682 pub fn has_tx_stalled(&self) -> bool {
696 unsafe { 683 unsafe {
697 let fdebug = PIO::PIO.fdebug(); 684 let fdebug = PIO::PIO.fdebug();
@@ -862,7 +849,8 @@ impl<'d, PIO: PioInstance> PioCommon<'d, PIO> {
862 849
863 /// Register a pin for PIO usage. Pins will be released from the PIO block 850 /// Register a pin for PIO usage. Pins will be released from the PIO block
864 /// (i.e., have their `FUNCSEL` reset to `NULL`) when the [`PioCommon`] *and* 851 /// (i.e., have their `FUNCSEL` reset to `NULL`) when the [`PioCommon`] *and*
865 /// all [`PioStateMachine`]s for this block have been dropped. 852 /// all [`PioStateMachine`]s for this block have been dropped. **Other members
853 /// of [`Pio`] do not keep pin registrations alive.**
866 pub fn make_pio_pin(&mut self, pin: impl Peripheral<P = impl PioPin + 'd> + 'd) -> Pin<'d, PIO> { 854 pub fn make_pio_pin(&mut self, pin: impl Peripheral<P = impl PioPin + 'd> + 'd) -> Pin<'d, PIO> {
867 into_ref!(pin); 855 into_ref!(pin);
868 unsafe { 856 unsafe {
@@ -877,8 +865,25 @@ impl<'d, PIO: PioInstance> PioCommon<'d, PIO> {
877 } 865 }
878} 866}
879 867
868pub struct PioIrq<'d, PIO: PioInstance, const N: usize> {
869 pio: PhantomData<&'d PIO>,
870}
871
872impl<'d, PIO: PioInstance, const N: usize> PioIrq<'d, PIO, N> {
873 pub fn wait<'a>(&'a mut self) -> IrqFuture<'a, 'd, PIO> {
874 IrqFuture {
875 pio: PhantomData,
876 irq_no: N as u8,
877 }
878 }
879}
880
880pub struct Pio<'d, PIO: PioInstance> { 881pub struct Pio<'d, PIO: PioInstance> {
881 pub common: PioCommon<'d, PIO>, 882 pub common: PioCommon<'d, PIO>,
883 pub irq0: PioIrq<'d, PIO, 0>,
884 pub irq1: PioIrq<'d, PIO, 1>,
885 pub irq2: PioIrq<'d, PIO, 2>,
886 pub irq3: PioIrq<'d, PIO, 3>,
882 pub sm0: PioStateMachine<'d, PIO, 0>, 887 pub sm0: PioStateMachine<'d, PIO, 0>,
883 pub sm1: PioStateMachine<'d, PIO, 1>, 888 pub sm1: PioStateMachine<'d, PIO, 1>,
884 pub sm2: PioStateMachine<'d, PIO, 2>, 889 pub sm2: PioStateMachine<'d, PIO, 2>,
@@ -894,6 +899,10 @@ impl<'d, PIO: PioInstance> Pio<'d, PIO> {
894 instructions_used: 0, 899 instructions_used: 0,
895 pio: PhantomData, 900 pio: PhantomData,
896 }, 901 },
902 irq0: PioIrq { pio: PhantomData },
903 irq1: PioIrq { pio: PhantomData },
904 irq2: PioIrq { pio: PhantomData },
905 irq3: PioIrq { pio: PhantomData },
897 sm0: PioStateMachine { pio: PhantomData }, 906 sm0: PioStateMachine { pio: PhantomData },
898 sm1: PioStateMachine { pio: PhantomData }, 907 sm1: PioStateMachine { pio: PhantomData },
899 sm2: PioStateMachine { pio: PhantomData }, 908 sm2: PioStateMachine { pio: PhantomData },
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index 11b290869..3d76a7d7b 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -4,7 +4,7 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::peripherals::PIO0; 6use embassy_rp::peripherals::PIO0;
7use embassy_rp::pio::{Pio, PioCommon, PioPin, PioStateMachine, ShiftDirection}; 7use embassy_rp::pio::{Pio, PioCommon, PioIrq, PioPin, PioStateMachine, ShiftDirection};
8use embassy_rp::pio_instr_util; 8use embassy_rp::pio_instr_util;
9use embassy_rp::relocate::RelocatedProgram; 9use embassy_rp::relocate::RelocatedProgram;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -99,10 +99,10 @@ fn setup_pio_task_sm2(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachine<PIO0,
99} 99}
100 100
101#[embassy_executor::task] 101#[embassy_executor::task]
102async fn pio_task_sm2(mut sm: PioStateMachine<'static, PIO0, 2>) { 102async fn pio_task_sm2(mut irq: PioIrq<'static, PIO0, 3>, mut sm: PioStateMachine<'static, PIO0, 2>) {
103 sm.set_enable(true); 103 sm.set_enable(true);
104 loop { 104 loop {
105 sm.wait_irq(3).await; 105 irq.wait().await;
106 info!("IRQ trigged"); 106 info!("IRQ trigged");
107 } 107 }
108} 108}
@@ -114,6 +114,7 @@ async fn main(spawner: Spawner) {
114 114
115 let Pio { 115 let Pio {
116 mut common, 116 mut common,
117 irq3,
117 mut sm0, 118 mut sm0,
118 mut sm1, 119 mut sm1,
119 mut sm2, 120 mut sm2,
@@ -125,5 +126,5 @@ async fn main(spawner: Spawner) {
125 setup_pio_task_sm2(&mut common, &mut sm2); 126 setup_pio_task_sm2(&mut common, &mut sm2);
126 spawner.spawn(pio_task_sm0(sm0)).unwrap(); 127 spawner.spawn(pio_task_sm0(sm0)).unwrap();
127 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 128 spawner.spawn(pio_task_sm1(sm1)).unwrap();
128 spawner.spawn(pio_task_sm2(sm2)).unwrap(); 129 spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap();
129} 130}
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index bc51d43c4..7c1d7acfe 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -85,7 +85,10 @@ impl<'l> HD44780<'l> {
85 85
86 let db7pin = db7.pin(); 86 let db7pin = db7.pin();
87 let Pio { 87 let Pio {
88 mut common, mut sm0, .. 88 mut common,
89 mut irq0,
90 mut sm0,
91 ..
89 } = Pio::new(pio); 92 } = Pio::new(pio);
90 93
91 // takes command words (<wait:24> <command:4> <0:4>) 94 // takes command words (<wait:24> <command:4> <0:4>)
@@ -145,7 +148,7 @@ impl<'l> HD44780<'l> {
145 sm0.push_tx((50 << 8) | 0x20); 148 sm0.push_tx((50 << 8) | 0x20);
146 sm0.push_tx(0b1100_0000); 149 sm0.push_tx(0b1100_0000);
147 150
148 sm0.wait_irq(0).await; 151 irq0.wait().await;
149 sm0.set_enable(false); 152 sm0.set_enable(false);
150 153
151 // takes command sequences (<rs:1> <count:7>, data...) 154 // takes command sequences (<rs:1> <count:7>, data...)