aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-05-01 11:00:48 +0000
committerGitHub <[email protected]>2023-05-01 11:00:48 +0000
commitac0ea406f91a5b630811accd0c97a622a020c700 (patch)
tree08ae76de328feabf6406e6ad7f79b7d23bbe035e
parentce04b732d131f488967846f6f593e10d7721ca86 (diff)
parentf4ade6af8bb2571ce2de0531d9c9715a7b8b941c (diff)
Merge #1395
1395: rp/pio: bit of a rework r=Dirbaio a=pennae the pio module is currently in a Bit of a State. this is far from all that's needed to make it more useful, but it's a start. Co-authored-by: pennae <[email protected]>
-rw-r--r--embassy-rp/src/lib.rs1
-rw-r--r--embassy-rp/src/pio.rs661
-rw-r--r--examples/rp/src/bin/pio_async.rs46
-rw-r--r--examples/rp/src/bin/pio_dma.rs6
-rw-r--r--examples/rp/src/bin/ws2812-pio.rs13
5 files changed, 284 insertions, 443 deletions
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 697f4308b..d69d12a30 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -156,6 +156,7 @@ pub fn init(_config: config::Config) -> Peripherals {
156 #[cfg(feature = "time-driver")] 156 #[cfg(feature = "time-driver")]
157 timer::init(); 157 timer::init();
158 dma::init(); 158 dma::init();
159 pio::init();
159 } 160 }
160 161
161 peripherals 162 peripherals
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 3c7abea25..7faec10b5 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -8,18 +8,33 @@ use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
8use embassy_hal_common::PeripheralRef; 8use embassy_hal_common::PeripheralRef;
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10 10
11use crate::dma::{self, Channel, Transfer}; 11use crate::dma::{Channel, Transfer};
12use crate::gpio::sealed::Pin as SealedPin; 12use crate::gpio::sealed::Pin as SealedPin;
13use crate::gpio::{Drive, Pin, Pull, SlewRate}; 13use crate::gpio::{Drive, Pin, Pull, SlewRate};
14use crate::pac::dma::vals::{DataSize, TreqSel}; 14use crate::pac::dma::vals::{DataSize, TreqSel};
15use crate::{interrupt, pac, peripherals}; 15use crate::pio::sealed::{PioInstance as _, SmInstance as _};
16use crate::{interrupt, pac, peripherals, RegExt};
17
18struct Wakers([AtomicWaker; 12]);
19
20impl Wakers {
21 #[inline(always)]
22 fn fifo_in(&self) -> &[AtomicWaker] {
23 &self.0[0..4]
24 }
25 #[inline(always)]
26 fn fifo_out(&self) -> &[AtomicWaker] {
27 &self.0[4..8]
28 }
29 #[inline(always)]
30 fn irq(&self) -> &[AtomicWaker] {
31 &self.0[8..12]
32 }
33}
16 34
17const PIOS: [&pac::pio::Pio; 2] = [&pac::PIO0, &pac::PIO1];
18const NEW_AW: AtomicWaker = AtomicWaker::new(); 35const NEW_AW: AtomicWaker = AtomicWaker::new();
19const PIO_WAKERS_INIT: [AtomicWaker; 4] = [NEW_AW; 4]; 36const PIO_WAKERS_INIT: Wakers = Wakers([NEW_AW; 12]);
20static FIFO_OUT_WAKERS: [[AtomicWaker; 4]; 2] = [PIO_WAKERS_INIT; 2]; 37static WAKERS: [Wakers; 2] = [PIO_WAKERS_INIT; 2];
21static FIFO_IN_WAKERS: [[AtomicWaker; 4]; 2] = [PIO_WAKERS_INIT; 2];
22static IRQ_WAKERS: [[AtomicWaker; 4]; 2] = [PIO_WAKERS_INIT; 2];
23 38
24pub enum FifoJoin { 39pub enum FifoJoin {
25 /// Both TX and RX fifo is enabled 40 /// Both TX and RX fifo is enabled
@@ -41,82 +56,41 @@ const TXNFULL_MASK: u32 = 1 << 4;
41const SMIRQ_MASK: u32 = 1 << 8; 56const SMIRQ_MASK: u32 = 1 << 8;
42 57
43#[interrupt] 58#[interrupt]
44unsafe fn PIO0_IRQ_1() {
45 use crate::pac;
46 let ints = pac::PIO0.irqs(1).ints().read().0;
47 let inte = pac::PIO0.irqs(1).inte();
48 for i in 0..4 {
49 // Check RXNEMPTY
50 if ints & (RXNEMPTY_MASK << i) != 0 {
51 inte.modify(|m| {
52 m.0 &= !(RXNEMPTY_MASK << i);
53 });
54 FIFO_IN_WAKERS[0][i].wake();
55 }
56 // Check IRQ flgs
57 if ints & (SMIRQ_MASK << i) != 0 {
58 inte.modify(|m| {
59 m.0 &= !(SMIRQ_MASK << i);
60 });
61 IRQ_WAKERS[0][i].wake();
62 }
63 }
64}
65
66#[interrupt]
67unsafe fn PIO1_IRQ_1() {
68 use crate::pac;
69 let ints = pac::PIO1.irqs(1).ints().read().0;
70 let inte = pac::PIO1.irqs(1).inte();
71 for i in 0..4 {
72 // Check all RXNEMPTY
73 if ints & (RXNEMPTY_MASK << i) != 0 {
74 inte.modify(|m| {
75 m.0 &= !(RXNEMPTY_MASK << i);
76 });
77 FIFO_IN_WAKERS[1][i].wake();
78 }
79 // Check IRQ flgs
80 if ints & (SMIRQ_MASK << i) != 0 {
81 inte.modify(|m| {
82 m.0 &= !(SMIRQ_MASK << i);
83 });
84 IRQ_WAKERS[1][i].wake();
85 }
86 }
87}
88
89#[interrupt]
90unsafe fn PIO0_IRQ_0() { 59unsafe fn PIO0_IRQ_0() {
91 use crate::pac; 60 use crate::pac;
92 let ints = pac::PIO0.irqs(0).ints().read().0; 61 let ints = pac::PIO0.irqs(0).ints().read().0;
93 let inte = pac::PIO0.irqs(0).inte(); 62 for bit in 0..12 {
94 //debug!("!{:04x}",ints); 63 if ints & (1 << bit) != 0 {
95 // Check all TXNFULL 64 WAKERS[0].0[bit].wake();
96 for i in 0..4 {
97 if ints & (TXNFULL_MASK << i) != 0 {
98 inte.modify(|m| {
99 m.0 &= !(TXNFULL_MASK << i);
100 });
101 FIFO_OUT_WAKERS[0][i].wake();
102 } 65 }
103 } 66 }
67 pac::PIO0.irqs(0).inte().write_clear(|m| m.0 = ints);
104} 68}
105 69
106#[interrupt] 70#[interrupt]
107unsafe fn PIO1_IRQ_0() { 71unsafe fn PIO1_IRQ_0() {
108 use crate::pac; 72 use crate::pac;
109 let ints = pac::PIO1.irqs(0).ints().read().0; 73 let ints = pac::PIO1.irqs(0).ints().read().0;
110 let inte = pac::PIO1.irqs(0).inte(); 74 for bit in 0..12 {
111 // Check all TXNFULL 75 if ints & (1 << bit) != 0 {
112 for i in 0..4 { 76 WAKERS[1].0[bit].wake();
113 if ints & (TXNFULL_MASK << i) != 0 {
114 inte.modify(|m| {
115 m.0 &= !(TXNFULL_MASK << i);
116 });
117 FIFO_OUT_WAKERS[1][i].wake();
118 } 77 }
119 } 78 }
79 pac::PIO1.irqs(0).inte().write_clear(|m| m.0 = ints);
80}
81
82pub(crate) unsafe fn init() {
83 let irq = interrupt::PIO0_IRQ_0::steal();
84 irq.disable();
85 irq.set_priority(interrupt::Priority::P3);
86 pac::PIO0.irqs(0).inte().write(|m| m.0 = 0);
87 irq.enable();
88
89 let irq = interrupt::PIO1_IRQ_0::steal();
90 irq.disable();
91 irq.set_priority(interrupt::Priority::P3);
92 pac::PIO1.irqs(0).inte().write(|m| m.0 = 0);
93 irq.enable();
120} 94}
121 95
122/// Future that waits for TX-FIFO to become writable 96/// Future that waits for TX-FIFO to become writable
@@ -129,14 +103,6 @@ pub struct FifoOutFuture<'a, PIO: PioInstance, SM: PioStateMachine + Unpin> {
129 103
130impl<'a, PIO: PioInstance, SM: PioStateMachine + Unpin> FifoOutFuture<'a, PIO, SM> { 104impl<'a, PIO: PioInstance, SM: PioStateMachine + Unpin> FifoOutFuture<'a, PIO, SM> {
131 pub fn new(sm: &'a mut SM, value: u32) -> Self { 105 pub fn new(sm: &'a mut SM, value: u32) -> Self {
132 unsafe {
133 critical_section::with(|_| {
134 let irq = PIO::IrqOut::steal();
135 irq.set_priority(interrupt::Priority::P3);
136
137 irq.enable();
138 });
139 }
140 FifoOutFuture { 106 FifoOutFuture {
141 sm, 107 sm,
142 pio: PhantomData::default(), 108 pio: PhantomData::default(),
@@ -153,16 +119,11 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Future for FifoOutFuture
153 if self.get_mut().sm.try_push_tx(value) { 119 if self.get_mut().sm.try_push_tx(value) {
154 Poll::Ready(()) 120 Poll::Ready(())
155 } else { 121 } else {
156 FIFO_OUT_WAKERS[PIO::PIO_NO as usize][SM::Sm::SM_NO as usize].register(cx.waker()); 122 WAKERS[PIO::PIO_NO as usize].fifo_out()[SM::Sm::SM_NO as usize].register(cx.waker());
157 unsafe { 123 unsafe {
158 let irq = PIO::IrqOut::steal(); 124 PIO::PIO.irqs(0).inte().write_set(|m| {
159 irq.disable(); 125 m.0 = TXNFULL_MASK << SM::Sm::SM_NO;
160 critical_section::with(|_| {
161 PIOS[PIO::PIO_NO as usize].irqs(0).inte().modify(|m| {
162 m.0 |= TXNFULL_MASK << SM::Sm::SM_NO;
163 });
164 }); 126 });
165 irq.enable();
166 } 127 }
167 // debug!("Pending"); 128 // debug!("Pending");
168 Poll::Pending 129 Poll::Pending
@@ -173,10 +134,8 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Future for FifoOutFuture
173impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Drop for FifoOutFuture<'d, PIO, SM> { 134impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Drop for FifoOutFuture<'d, PIO, SM> {
174 fn drop(&mut self) { 135 fn drop(&mut self) {
175 unsafe { 136 unsafe {
176 critical_section::with(|_| { 137 PIO::PIO.irqs(0).inte().write_clear(|m| {
177 PIOS[PIO::PIO_NO as usize].irqs(0).inte().modify(|m| { 138 m.0 = TXNFULL_MASK << SM::Sm::SM_NO;
178 m.0 &= !(TXNFULL_MASK << SM::Sm::SM_NO);
179 });
180 }); 139 });
181 } 140 }
182 } 141 }
@@ -191,14 +150,6 @@ pub struct FifoInFuture<'a, PIO: PioInstance, SM: PioStateMachine> {
191 150
192impl<'a, PIO: PioInstance, SM: PioStateMachine> FifoInFuture<'a, PIO, SM> { 151impl<'a, PIO: PioInstance, SM: PioStateMachine> FifoInFuture<'a, PIO, SM> {
193 pub fn new(sm: &'a mut SM) -> Self { 152 pub fn new(sm: &'a mut SM) -> Self {
194 unsafe {
195 critical_section::with(|_| {
196 let irq = PIO::IrqIn::steal();
197 irq.set_priority(interrupt::Priority::P3);
198
199 irq.enable();
200 });
201 }
202 FifoInFuture { 153 FifoInFuture {
203 sm, 154 sm,
204 pio: PhantomData::default(), 155 pio: PhantomData::default(),
@@ -213,16 +164,11 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Future for FifoInFuture<'d, PIO,
213 if let Some(v) = self.sm.try_pull_rx() { 164 if let Some(v) = self.sm.try_pull_rx() {
214 Poll::Ready(v) 165 Poll::Ready(v)
215 } else { 166 } else {
216 FIFO_IN_WAKERS[PIO::PIO_NO as usize][SM::Sm::SM_NO as usize].register(cx.waker()); 167 WAKERS[PIO::PIO_NO as usize].fifo_in()[SM::Sm::SM_NO as usize].register(cx.waker());
217 unsafe { 168 unsafe {
218 let irq = PIO::IrqIn::steal(); 169 PIO::PIO.irqs(0).inte().write_set(|m| {
219 irq.disable(); 170 m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO;
220 critical_section::with(|_| {
221 PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| {
222 m.0 |= RXNEMPTY_MASK << SM::Sm::SM_NO;
223 });
224 }); 171 });
225 irq.enable();
226 } 172 }
227 //debug!("Pending"); 173 //debug!("Pending");
228 Poll::Pending 174 Poll::Pending
@@ -233,10 +179,8 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Future for FifoInFuture<'d, PIO,
233impl<'d, PIO: PioInstance, SM: PioStateMachine> Drop for FifoInFuture<'d, PIO, SM> { 179impl<'d, PIO: PioInstance, SM: PioStateMachine> Drop for FifoInFuture<'d, PIO, SM> {
234 fn drop(&mut self) { 180 fn drop(&mut self) {
235 unsafe { 181 unsafe {
236 critical_section::with(|_| { 182 PIO::PIO.irqs(0).inte().write_clear(|m| {
237 PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| { 183 m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO;
238 m.0 &= !(RXNEMPTY_MASK << SM::Sm::SM_NO);
239 });
240 }); 184 });
241 } 185 }
242 } 186 }
@@ -251,14 +195,6 @@ pub struct IrqFuture<PIO: PioInstance> {
251 195
252impl<'a, PIO: PioInstance> IrqFuture<PIO> { 196impl<'a, PIO: PioInstance> IrqFuture<PIO> {
253 pub fn new(irq_no: u8) -> Self { 197 pub fn new(irq_no: u8) -> Self {
254 unsafe {
255 critical_section::with(|_| {
256 let irq = PIO::IrqSm::steal();
257 irq.set_priority(interrupt::Priority::P3);
258
259 irq.enable();
260 });
261 }
262 IrqFuture { 198 IrqFuture {
263 pio: PhantomData::default(), 199 pio: PhantomData::default(),
264 irq_no, 200 irq_no,
@@ -273,7 +209,7 @@ impl<'d, PIO: PioInstance> Future for IrqFuture<PIO> {
273 209
274 // Check if IRQ flag is already set 210 // Check if IRQ flag is already set
275 if critical_section::with(|_| unsafe { 211 if critical_section::with(|_| unsafe {
276 let irq_flags = PIOS[PIO::PIO_NO as usize].irq(); 212 let irq_flags = PIO::PIO.irq();
277 if irq_flags.read().0 & (1 << self.irq_no) != 0 { 213 if irq_flags.read().0 & (1 << self.irq_no) != 0 {
278 irq_flags.write(|m| { 214 irq_flags.write(|m| {
279 m.0 = 1 << self.irq_no; 215 m.0 = 1 << self.irq_no;
@@ -286,16 +222,11 @@ impl<'d, PIO: PioInstance> Future for IrqFuture<PIO> {
286 return Poll::Ready(()); 222 return Poll::Ready(());
287 } 223 }
288 224
289 IRQ_WAKERS[PIO::PIO_NO as usize][self.irq_no as usize].register(cx.waker()); 225 WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker());
290 unsafe { 226 unsafe {
291 let irq = PIO::IrqSm::steal(); 227 PIO::PIO.irqs(0).inte().write_set(|m| {
292 irq.disable(); 228 m.0 = SMIRQ_MASK << self.irq_no;
293 critical_section::with(|_| {
294 PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| {
295 m.0 |= SMIRQ_MASK << self.irq_no;
296 });
297 }); 229 });
298 irq.enable();
299 } 230 }
300 Poll::Pending 231 Poll::Pending
301 } 232 }
@@ -304,10 +235,8 @@ impl<'d, PIO: PioInstance> Future for IrqFuture<PIO> {
304impl<'d, PIO: PioInstance> Drop for IrqFuture<PIO> { 235impl<'d, PIO: PioInstance> Drop for IrqFuture<PIO> {
305 fn drop(&mut self) { 236 fn drop(&mut self) {
306 unsafe { 237 unsafe {
307 critical_section::with(|_| { 238 PIO::PIO.irqs(0).inte().write_clear(|m| {
308 PIOS[PIO::PIO_NO as usize].irqs(1).inte().modify(|m| { 239 m.0 = SMIRQ_MASK << self.irq_no;
309 m.0 &= !(SMIRQ_MASK << self.irq_no);
310 });
311 }); 240 });
312 } 241 }
313 } 242 }
@@ -369,7 +298,7 @@ impl<PIO: PioInstance> PioPin<PIO> {
369 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { 298 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) {
370 let mask = 1 << self.pin(); 299 let mask = 1 << self.pin();
371 unsafe { 300 unsafe {
372 PIOS[PIO::PIO_NO as usize] 301 PIO::PIO
373 .input_sync_bypass() 302 .input_sync_bypass()
374 .modify(|w| *w = if bypass { *w & !mask } else { *w | mask }); 303 .modify(|w| *w = if bypass { *w & !mask } else { *w | mask });
375 } 304 }
@@ -391,16 +320,14 @@ pub struct PioStateMachineInstance<PIO: PioInstance, SM: SmInstance> {
391 sm: PhantomData<SM>, 320 sm: PhantomData<SM>,
392} 321}
393 322
394impl<PIO: PioInstance, SM: SmInstance> PioStateMachine for PioStateMachineInstance<PIO, SM> { 323impl<PIO: PioInstance, SM: SmInstance> sealed::PioStateMachine for PioStateMachineInstance<PIO, SM> {
395 type Pio = PIO; 324 type Pio = PIO;
396 type Sm = SM; 325 type Sm = SM;
397} 326}
327impl<PIO: PioInstance, SM: SmInstance> PioStateMachine for PioStateMachineInstance<PIO, SM> {}
398 328
399pub trait PioStateMachine: Sized + Unpin { 329pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
400 type Pio: PioInstance;
401 type Sm: SmInstance;
402 fn pio_no(&self) -> u8 { 330 fn pio_no(&self) -> u8 {
403 let _ = self;
404 Self::Pio::PIO_NO 331 Self::Pio::PIO_NO
405 } 332 }
406 333
@@ -409,65 +336,56 @@ pub trait PioStateMachine: Sized + Unpin {
409 } 336 }
410 337
411 fn restart(&mut self) { 338 fn restart(&mut self) {
412 let _ = self;
413 unsafe { 339 unsafe {
414 PIOS[Self::Pio::PIO_NO as usize] 340 Self::Pio::PIO
415 .ctrl() 341 .ctrl()
416 .modify(|w| w.set_sm_restart(1u8 << Self::Sm::SM_NO)); 342 .modify(|w| w.set_sm_restart(1u8 << Self::Sm::SM_NO));
417 } 343 }
418 } 344 }
419 fn set_enable(&mut self, enable: bool) { 345 fn set_enable(&mut self, enable: bool) {
420 let _ = self;
421 let mask = 1u8 << Self::Sm::SM_NO; 346 let mask = 1u8 << Self::Sm::SM_NO;
422 unsafe { 347 unsafe {
423 PIOS[Self::Pio::PIO_NO as usize] 348 Self::Pio::PIO
424 .ctrl() 349 .ctrl()
425 .modify(|w| w.set_sm_enable((w.sm_enable() & !mask) | (if enable { mask } else { 0 }))); 350 .modify(|w| w.set_sm_enable((w.sm_enable() & !mask) | (if enable { mask } else { 0 })));
426 } 351 }
427 } 352 }
428 353
429 fn is_enabled(&self) -> bool { 354 fn is_enabled(&self) -> bool {
430 let _ = self; 355 unsafe { Self::Pio::PIO.ctrl().read().sm_enable() & (1u8 << Self::Sm::SM_NO) != 0 }
431 unsafe { PIOS[Self::Pio::PIO_NO as usize].ctrl().read().sm_enable() & (1u8 << Self::Sm::SM_NO) != 0 }
432 } 356 }
433 357
434 fn is_tx_empty(&self) -> bool { 358 fn is_tx_empty(&self) -> bool {
435 let _ = self; 359 unsafe { Self::Pio::PIO.fstat().read().txempty() & (1u8 << Self::Sm::SM_NO) != 0 }
436 unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().txempty() & (1u8 << Self::Sm::SM_NO) != 0 }
437 } 360 }
438 fn is_tx_full(&self) -> bool { 361 fn is_tx_full(&self) -> bool {
439 let _ = self; 362 unsafe { Self::Pio::PIO.fstat().read().txfull() & (1u8 << Self::Sm::SM_NO) != 0 }
440 unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().txfull() & (1u8 << Self::Sm::SM_NO) != 0 }
441 } 363 }
442 364
443 fn is_rx_empty(&self) -> bool { 365 fn is_rx_empty(&self) -> bool {
444 let _ = self; 366 unsafe { Self::Pio::PIO.fstat().read().rxempty() & (1u8 << Self::Sm::SM_NO) != 0 }
445 unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().rxempty() & (1u8 << Self::Sm::SM_NO) != 0 }
446 } 367 }
447 fn is_rx_full(&self) -> bool { 368 fn is_rx_full(&self) -> bool {
448 let _ = self; 369 unsafe { Self::Pio::PIO.fstat().read().rxfull() & (1u8 << Self::Sm::SM_NO) != 0 }
449 unsafe { PIOS[Self::Pio::PIO_NO as usize].fstat().read().rxfull() & (1u8 << Self::Sm::SM_NO) != 0 }
450 } 370 }
451 371
452 fn tx_level(&self) -> u8 { 372 fn tx_level(&self) -> u8 {
453 unsafe { 373 unsafe {
454 let flevel = PIOS[Self::Pio::PIO_NO as usize].flevel().read().0; 374 let flevel = Self::Pio::PIO.flevel().read().0;
455 (flevel >> (Self::Sm::SM_NO * 8)) as u8 & 0x0f 375 (flevel >> (Self::Sm::SM_NO * 8)) as u8 & 0x0f
456 } 376 }
457 } 377 }
458 378
459 fn rx_level(&self) -> u8 { 379 fn rx_level(&self) -> u8 {
460 unsafe { 380 unsafe {
461 let flevel = PIOS[Self::Pio::PIO_NO as usize].flevel().read().0; 381 let flevel = Self::Pio::PIO.flevel().read().0;
462 (flevel >> (Self::Sm::SM_NO * 8 + 4)) as u8 & 0x0f 382 (flevel >> (Self::Sm::SM_NO * 8 + 4)) as u8 & 0x0f
463 } 383 }
464 } 384 }
465 385
466 fn push_tx(&mut self, v: u32) { 386 fn push_tx(&mut self, v: u32) {
467 unsafe { 387 unsafe {
468 PIOS[Self::Pio::PIO_NO as usize] 388 Self::Pio::PIO.txf(Self::Sm::SM_NO as usize).write_value(v);
469 .txf(Self::Sm::SM_NO as usize)
470 .write_value(v);
471 } 389 }
472 } 390 }
473 391
@@ -480,7 +398,7 @@ pub trait PioStateMachine: Sized + Unpin {
480 } 398 }
481 399
482 fn pull_rx(&mut self) -> u32 { 400 fn pull_rx(&mut self) -> u32 {
483 unsafe { PIOS[Self::Pio::PIO_NO as usize].rxf(Self::Sm::SM_NO as usize).read() } 401 unsafe { Self::Pio::PIO.rxf(Self::Sm::SM_NO as usize).read() }
484 } 402 }
485 403
486 fn try_pull_rx(&mut self) -> Option<u32> { 404 fn try_pull_rx(&mut self) -> Option<u32> {
@@ -492,7 +410,7 @@ pub trait PioStateMachine: Sized + Unpin {
492 410
493 fn set_clkdiv(&mut self, div_x_256: u32) { 411 fn set_clkdiv(&mut self, div_x_256: u32) {
494 unsafe { 412 unsafe {
495 PIOS[Self::Pio::PIO_NO as usize] 413 Self::Pio::PIO
496 .sm(Self::Sm::SM_NO as usize) 414 .sm(Self::Sm::SM_NO as usize)
497 .clkdiv() 415 .clkdiv()
498 .write(|w| w.0 = div_x_256 << 8); 416 .write(|w| w.0 = div_x_256 << 8);
@@ -500,20 +418,12 @@ pub trait PioStateMachine: Sized + Unpin {
500 } 418 }
501 419
502 fn get_clkdiv(&self) -> u32 { 420 fn get_clkdiv(&self) -> u32 {
503 unsafe { 421 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).clkdiv().read().0 >> 8 }
504 PIOS[Self::Pio::PIO_NO as usize]
505 .sm(Self::Sm::SM_NO as usize)
506 .clkdiv()
507 .read()
508 .0
509 >> 8
510 }
511 } 422 }
512 423
513 fn clkdiv_restart(&mut self) { 424 fn clkdiv_restart(&mut self) {
514 let _ = self;
515 unsafe { 425 unsafe {
516 PIOS[Self::Pio::PIO_NO as usize] 426 Self::Pio::PIO
517 .ctrl() 427 .ctrl()
518 .modify(|w| w.set_clkdiv_restart(1u8 << Self::Sm::SM_NO)); 428 .modify(|w| w.set_clkdiv_restart(1u8 << Self::Sm::SM_NO));
519 } 429 }
@@ -521,7 +431,7 @@ pub trait PioStateMachine: Sized + Unpin {
521 431
522 fn set_side_enable(&self, enable: bool) { 432 fn set_side_enable(&self, enable: bool) {
523 unsafe { 433 unsafe {
524 PIOS[Self::Pio::PIO_NO as usize] 434 Self::Pio::PIO
525 .sm(Self::Sm::SM_NO as usize) 435 .sm(Self::Sm::SM_NO as usize)
526 .execctrl() 436 .execctrl()
527 .modify(|w| w.set_side_en(enable)); 437 .modify(|w| w.set_side_en(enable));
@@ -529,18 +439,12 @@ pub trait PioStateMachine: Sized + Unpin {
529 } 439 }
530 440
531 fn is_side_enabled(&self) -> bool { 441 fn is_side_enabled(&self) -> bool {
532 unsafe { 442 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().side_en() }
533 PIOS[Self::Pio::PIO_NO as usize]
534 .sm(Self::Sm::SM_NO as usize)
535 .execctrl()
536 .read()
537 .side_en()
538 }
539 } 443 }
540 444
541 fn set_side_pindir(&mut self, pindir: bool) { 445 fn set_side_pindir(&mut self, pindir: bool) {
542 unsafe { 446 unsafe {
543 PIOS[Self::Pio::PIO_NO as usize] 447 Self::Pio::PIO
544 .sm(Self::Sm::SM_NO as usize) 448 .sm(Self::Sm::SM_NO as usize)
545 .execctrl() 449 .execctrl()
546 .modify(|w| w.set_side_pindir(pindir)); 450 .modify(|w| w.set_side_pindir(pindir));
@@ -549,7 +453,7 @@ pub trait PioStateMachine: Sized + Unpin {
549 453
550 fn is_side_pindir(&self) -> bool { 454 fn is_side_pindir(&self) -> bool {
551 unsafe { 455 unsafe {
552 PIOS[Self::Pio::PIO_NO as usize] 456 Self::Pio::PIO
553 .sm(Self::Sm::SM_NO as usize) 457 .sm(Self::Sm::SM_NO as usize)
554 .execctrl() 458 .execctrl()
555 .read() 459 .read()
@@ -559,7 +463,7 @@ pub trait PioStateMachine: Sized + Unpin {
559 463
560 fn set_jmp_pin(&mut self, pin: u8) { 464 fn set_jmp_pin(&mut self, pin: u8) {
561 unsafe { 465 unsafe {
562 PIOS[Self::Pio::PIO_NO as usize] 466 Self::Pio::PIO
563 .sm(Self::Sm::SM_NO as usize) 467 .sm(Self::Sm::SM_NO as usize)
564 .execctrl() 468 .execctrl()
565 .modify(|w| w.set_jmp_pin(pin)); 469 .modify(|w| w.set_jmp_pin(pin));
@@ -567,34 +471,22 @@ pub trait PioStateMachine: Sized + Unpin {
567 } 471 }
568 472
569 fn get_jmp_pin(&mut self) -> u8 { 473 fn get_jmp_pin(&mut self) -> u8 {
570 unsafe { 474 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().jmp_pin() }
571 PIOS[Self::Pio::PIO_NO as usize]
572 .sm(Self::Sm::SM_NO as usize)
573 .execctrl()
574 .read()
575 .jmp_pin()
576 }
577 } 475 }
578 476
579 fn set_wrap(&self, source: u8, target: u8) { 477 fn set_wrap(&self, source: u8, target: u8) {
580 unsafe { 478 unsafe {
581 PIOS[Self::Pio::PIO_NO as usize] 479 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().modify(|w| {
582 .sm(Self::Sm::SM_NO as usize) 480 w.set_wrap_top(source);
583 .execctrl() 481 w.set_wrap_bottom(target)
584 .modify(|w| { 482 });
585 w.set_wrap_top(source);
586 w.set_wrap_bottom(target)
587 });
588 } 483 }
589 } 484 }
590 485
591 /// Get wrapping addresses. Returns (source, target). 486 /// Get wrapping addresses. Returns (source, target).
592 fn get_wrap(&self) -> (u8, u8) { 487 fn get_wrap(&self) -> (u8, u8) {
593 unsafe { 488 unsafe {
594 let r = PIOS[Self::Pio::PIO_NO as usize] 489 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read();
595 .sm(Self::Sm::SM_NO as usize)
596 .execctrl()
597 .read();
598 (r.wrap_top(), r.wrap_bottom()) 490 (r.wrap_top(), r.wrap_bottom())
599 } 491 }
600 } 492 }
@@ -606,21 +498,15 @@ pub trait PioStateMachine: Sized + Unpin {
606 FifoJoin::TxOnly => (false, true), 498 FifoJoin::TxOnly => (false, true),
607 }; 499 };
608 unsafe { 500 unsafe {
609 PIOS[Self::Pio::PIO_NO as usize] 501 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().modify(|w| {
610 .sm(Self::Sm::SM_NO as usize) 502 w.set_fjoin_rx(rx);
611 .shiftctrl() 503 w.set_fjoin_tx(tx)
612 .modify(|w| { 504 });
613 w.set_fjoin_rx(rx);
614 w.set_fjoin_tx(tx)
615 });
616 } 505 }
617 } 506 }
618 fn get_fifo_join(&self) -> FifoJoin { 507 fn get_fifo_join(&self) -> FifoJoin {
619 unsafe { 508 unsafe {
620 let r = PIOS[Self::Pio::PIO_NO as usize] 509 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read();
621 .sm(Self::Sm::SM_NO as usize)
622 .shiftctrl()
623 .read();
624 // Ignores the invalid state when both bits are set 510 // Ignores the invalid state when both bits are set
625 if r.fjoin_rx() { 511 if r.fjoin_rx() {
626 FifoJoin::RxOnly 512 FifoJoin::RxOnly
@@ -635,9 +521,7 @@ pub trait PioStateMachine: Sized + Unpin {
635 fn clear_fifos(&mut self) { 521 fn clear_fifos(&mut self) {
636 // Toggle FJOIN_RX to flush FIFOs 522 // Toggle FJOIN_RX to flush FIFOs
637 unsafe { 523 unsafe {
638 let shiftctrl = PIOS[Self::Pio::PIO_NO as usize] 524 let shiftctrl = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl();
639 .sm(Self::Sm::SM_NO as usize)
640 .shiftctrl();
641 shiftctrl.modify(|w| { 525 shiftctrl.modify(|w| {
642 w.set_fjoin_rx(!w.fjoin_rx()); 526 w.set_fjoin_rx(!w.fjoin_rx());
643 }); 527 });
@@ -649,7 +533,7 @@ pub trait PioStateMachine: Sized + Unpin {
649 533
650 fn set_pull_threshold(&mut self, threshold: u8) { 534 fn set_pull_threshold(&mut self, threshold: u8) {
651 unsafe { 535 unsafe {
652 PIOS[Self::Pio::PIO_NO as usize] 536 Self::Pio::PIO
653 .sm(Self::Sm::SM_NO as usize) 537 .sm(Self::Sm::SM_NO as usize)
654 .shiftctrl() 538 .shiftctrl()
655 .modify(|w| w.set_pull_thresh(threshold)); 539 .modify(|w| w.set_pull_thresh(threshold));
@@ -658,16 +542,13 @@ pub trait PioStateMachine: Sized + Unpin {
658 542
659 fn get_pull_threshold(&self) -> u8 { 543 fn get_pull_threshold(&self) -> u8 {
660 unsafe { 544 unsafe {
661 let r = PIOS[Self::Pio::PIO_NO as usize] 545 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read();
662 .sm(Self::Sm::SM_NO as usize)
663 .shiftctrl()
664 .read();
665 r.pull_thresh() 546 r.pull_thresh()
666 } 547 }
667 } 548 }
668 fn set_push_threshold(&mut self, threshold: u8) { 549 fn set_push_threshold(&mut self, threshold: u8) {
669 unsafe { 550 unsafe {
670 PIOS[Self::Pio::PIO_NO as usize] 551 Self::Pio::PIO
671 .sm(Self::Sm::SM_NO as usize) 552 .sm(Self::Sm::SM_NO as usize)
672 .shiftctrl() 553 .shiftctrl()
673 .modify(|w| w.set_push_thresh(threshold)); 554 .modify(|w| w.set_push_thresh(threshold));
@@ -676,17 +557,14 @@ pub trait PioStateMachine: Sized + Unpin {
676 557
677 fn get_push_threshold(&self) -> u8 { 558 fn get_push_threshold(&self) -> u8 {
678 unsafe { 559 unsafe {
679 let r = PIOS[Self::Pio::PIO_NO as usize] 560 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read();
680 .sm(Self::Sm::SM_NO as usize)
681 .shiftctrl()
682 .read();
683 r.push_thresh() 561 r.push_thresh()
684 } 562 }
685 } 563 }
686 564
687 fn set_out_shift_dir(&mut self, dir: ShiftDirection) { 565 fn set_out_shift_dir(&mut self, dir: ShiftDirection) {
688 unsafe { 566 unsafe {
689 PIOS[Self::Pio::PIO_NO as usize] 567 Self::Pio::PIO
690 .sm(Self::Sm::SM_NO as usize) 568 .sm(Self::Sm::SM_NO as usize)
691 .shiftctrl() 569 .shiftctrl()
692 .modify(|w| w.set_out_shiftdir(dir == ShiftDirection::Right)); 570 .modify(|w| w.set_out_shiftdir(dir == ShiftDirection::Right));
@@ -694,7 +572,7 @@ pub trait PioStateMachine: Sized + Unpin {
694 } 572 }
695 fn get_out_shiftdir(&self) -> ShiftDirection { 573 fn get_out_shiftdir(&self) -> ShiftDirection {
696 unsafe { 574 unsafe {
697 if PIOS[Self::Pio::PIO_NO as usize] 575 if Self::Pio::PIO
698 .sm(Self::Sm::SM_NO as usize) 576 .sm(Self::Sm::SM_NO as usize)
699 .shiftctrl() 577 .shiftctrl()
700 .read() 578 .read()
@@ -709,7 +587,7 @@ pub trait PioStateMachine: Sized + Unpin {
709 587
710 fn set_in_shift_dir(&mut self, dir: ShiftDirection) { 588 fn set_in_shift_dir(&mut self, dir: ShiftDirection) {
711 unsafe { 589 unsafe {
712 PIOS[Self::Pio::PIO_NO as usize] 590 Self::Pio::PIO
713 .sm(Self::Sm::SM_NO as usize) 591 .sm(Self::Sm::SM_NO as usize)
714 .shiftctrl() 592 .shiftctrl()
715 .modify(|w| w.set_in_shiftdir(dir == ShiftDirection::Right)); 593 .modify(|w| w.set_in_shiftdir(dir == ShiftDirection::Right));
@@ -717,7 +595,7 @@ pub trait PioStateMachine: Sized + Unpin {
717 } 595 }
718 fn get_in_shiftdir(&self) -> ShiftDirection { 596 fn get_in_shiftdir(&self) -> ShiftDirection {
719 unsafe { 597 unsafe {
720 if PIOS[Self::Pio::PIO_NO as usize] 598 if Self::Pio::PIO
721 .sm(Self::Sm::SM_NO as usize) 599 .sm(Self::Sm::SM_NO as usize)
722 .shiftctrl() 600 .shiftctrl()
723 .read() 601 .read()
@@ -732,7 +610,7 @@ pub trait PioStateMachine: Sized + Unpin {
732 610
733 fn set_autopull(&mut self, auto: bool) { 611 fn set_autopull(&mut self, auto: bool) {
734 unsafe { 612 unsafe {
735 PIOS[Self::Pio::PIO_NO as usize] 613 Self::Pio::PIO
736 .sm(Self::Sm::SM_NO as usize) 614 .sm(Self::Sm::SM_NO as usize)
737 .shiftctrl() 615 .shiftctrl()
738 .modify(|w| w.set_autopull(auto)); 616 .modify(|w| w.set_autopull(auto));
@@ -741,7 +619,7 @@ pub trait PioStateMachine: Sized + Unpin {
741 619
742 fn is_autopull(&self) -> bool { 620 fn is_autopull(&self) -> bool {
743 unsafe { 621 unsafe {
744 PIOS[Self::Pio::PIO_NO as usize] 622 Self::Pio::PIO
745 .sm(Self::Sm::SM_NO as usize) 623 .sm(Self::Sm::SM_NO as usize)
746 .shiftctrl() 624 .shiftctrl()
747 .read() 625 .read()
@@ -751,7 +629,7 @@ pub trait PioStateMachine: Sized + Unpin {
751 629
752 fn set_autopush(&mut self, auto: bool) { 630 fn set_autopush(&mut self, auto: bool) {
753 unsafe { 631 unsafe {
754 PIOS[Self::Pio::PIO_NO as usize] 632 Self::Pio::PIO
755 .sm(Self::Sm::SM_NO as usize) 633 .sm(Self::Sm::SM_NO as usize)
756 .shiftctrl() 634 .shiftctrl()
757 .modify(|w| w.set_autopush(auto)); 635 .modify(|w| w.set_autopush(auto));
@@ -760,7 +638,7 @@ pub trait PioStateMachine: Sized + Unpin {
760 638
761 fn is_autopush(&self) -> bool { 639 fn is_autopush(&self) -> bool {
762 unsafe { 640 unsafe {
763 PIOS[Self::Pio::PIO_NO as usize] 641 Self::Pio::PIO
764 .sm(Self::Sm::SM_NO as usize) 642 .sm(Self::Sm::SM_NO as usize)
765 .shiftctrl() 643 .shiftctrl()
766 .read() 644 .read()
@@ -770,16 +648,13 @@ pub trait PioStateMachine: Sized + Unpin {
770 648
771 fn get_addr(&self) -> u8 { 649 fn get_addr(&self) -> u8 {
772 unsafe { 650 unsafe {
773 let r = PIOS[Self::Pio::PIO_NO as usize] 651 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).addr().read();
774 .sm(Self::Sm::SM_NO as usize)
775 .addr()
776 .read();
777 r.addr() 652 r.addr()
778 } 653 }
779 } 654 }
780 fn set_sideset_count(&mut self, count: u8) { 655 fn set_sideset_count(&mut self, count: u8) {
781 unsafe { 656 unsafe {
782 PIOS[Self::Pio::PIO_NO as usize] 657 Self::Pio::PIO
783 .sm(Self::Sm::SM_NO as usize) 658 .sm(Self::Sm::SM_NO as usize)
784 .pinctrl() 659 .pinctrl()
785 .modify(|w| w.set_sideset_count(count)); 660 .modify(|w| w.set_sideset_count(count));
@@ -788,37 +663,14 @@ pub trait PioStateMachine: Sized + Unpin {
788 663
789 fn get_sideset_count(&self) -> u8 { 664 fn get_sideset_count(&self) -> u8 {
790 unsafe { 665 unsafe {
791 let r = PIOS[Self::Pio::PIO_NO as usize] 666 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read();
792 .sm(Self::Sm::SM_NO as usize)
793 .pinctrl()
794 .read();
795 r.sideset_count() 667 r.sideset_count()
796 } 668 }
797 } 669 }
798 670
799 fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> {
800 unsafe {
801 pin.io().ctrl().write(|w| {
802 w.set_funcsel(
803 if Self::Pio::PIO_NO == 1 {
804 pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
805 } else {
806 // PIO == 0
807 pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
808 }
809 .0,
810 );
811 });
812 }
813 PioPin {
814 pin_bank: pin.pin_bank(),
815 pio: PhantomData::default(),
816 }
817 }
818
819 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) { 671 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) {
820 unsafe { 672 unsafe {
821 PIOS[Self::Pio::PIO_NO as usize] 673 Self::Pio::PIO
822 .sm(Self::Sm::SM_NO as usize) 674 .sm(Self::Sm::SM_NO as usize)
823 .pinctrl() 675 .pinctrl()
824 .modify(|w| w.set_sideset_base(base_pin.pin())); 676 .modify(|w| w.set_sideset_base(base_pin.pin()));
@@ -827,10 +679,7 @@ pub trait PioStateMachine: Sized + Unpin {
827 679
828 fn get_sideset_base(&self) -> u8 { 680 fn get_sideset_base(&self) -> u8 {
829 unsafe { 681 unsafe {
830 let r = PIOS[Self::Pio::PIO_NO as usize] 682 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read();
831 .sm(Self::Sm::SM_NO as usize)
832 .pinctrl()
833 .read();
834 r.sideset_base() 683 r.sideset_base()
835 } 684 }
836 } 685 }
@@ -839,30 +688,24 @@ pub trait PioStateMachine: Sized + Unpin {
839 fn set_set_range(&mut self, base: u8, count: u8) { 688 fn set_set_range(&mut self, base: u8, count: u8) {
840 assert!(base + count < 32); 689 assert!(base + count < 32);
841 unsafe { 690 unsafe {
842 PIOS[Self::Pio::PIO_NO as usize] 691 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| {
843 .sm(Self::Sm::SM_NO as usize) 692 w.set_set_base(base);
844 .pinctrl() 693 w.set_set_count(count)
845 .modify(|w| { 694 });
846 w.set_set_base(base);
847 w.set_set_count(count)
848 });
849 } 695 }
850 } 696 }
851 697
852 /// Get the range of out pins affected by a set instruction. Returns (base, count). 698 /// Get the range of out pins affected by a set instruction. Returns (base, count).
853 fn get_set_range(&self) -> (u8, u8) { 699 fn get_set_range(&self) -> (u8, u8) {
854 unsafe { 700 unsafe {
855 let r = PIOS[Self::Pio::PIO_NO as usize] 701 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read();
856 .sm(Self::Sm::SM_NO as usize)
857 .pinctrl()
858 .read();
859 (r.set_base(), r.set_count()) 702 (r.set_base(), r.set_count())
860 } 703 }
861 } 704 }
862 705
863 fn set_in_base_pin(&mut self, base: &PioPin<Self::Pio>) { 706 fn set_in_base_pin(&mut self, base: &PioPin<Self::Pio>) {
864 unsafe { 707 unsafe {
865 PIOS[Self::Pio::PIO_NO as usize] 708 Self::Pio::PIO
866 .sm(Self::Sm::SM_NO as usize) 709 .sm(Self::Sm::SM_NO as usize)
867 .pinctrl() 710 .pinctrl()
868 .modify(|w| w.set_in_base(base.pin())); 711 .modify(|w| w.set_in_base(base.pin()));
@@ -871,10 +714,7 @@ pub trait PioStateMachine: Sized + Unpin {
871 714
872 fn get_in_base(&self) -> u8 { 715 fn get_in_base(&self) -> u8 {
873 unsafe { 716 unsafe {
874 let r = PIOS[Self::Pio::PIO_NO as usize] 717 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read();
875 .sm(Self::Sm::SM_NO as usize)
876 .pinctrl()
877 .read();
878 r.in_base() 718 r.in_base()
879 } 719 }
880 } 720 }
@@ -882,23 +722,17 @@ pub trait PioStateMachine: Sized + Unpin {
882 fn set_out_range(&mut self, base: u8, count: u8) { 722 fn set_out_range(&mut self, base: u8, count: u8) {
883 assert!(base + count < 32); 723 assert!(base + count < 32);
884 unsafe { 724 unsafe {
885 PIOS[Self::Pio::PIO_NO as usize] 725 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| {
886 .sm(Self::Sm::SM_NO as usize) 726 w.set_out_base(base);
887 .pinctrl() 727 w.set_out_count(count)
888 .modify(|w| { 728 });
889 w.set_out_base(base);
890 w.set_out_count(count)
891 });
892 } 729 }
893 } 730 }
894 731
895 /// Get the range of out pins affected by a set instruction. Returns (base, count). 732 /// Get the range of out pins affected by a set instruction. Returns (base, count).
896 fn get_out_range(&self) -> (u8, u8) { 733 fn get_out_range(&self) -> (u8, u8) {
897 unsafe { 734 unsafe {
898 let r = PIOS[Self::Pio::PIO_NO as usize] 735 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read();
899 .sm(Self::Sm::SM_NO as usize)
900 .pinctrl()
901 .read();
902 (r.out_base(), r.out_count()) 736 (r.out_base(), r.out_count())
903 } 737 }
904 } 738 }
@@ -926,50 +760,18 @@ pub trait PioStateMachine: Sized + Unpin {
926 } 760 }
927 761
928 fn get_current_instr() -> u32 { 762 fn get_current_instr() -> u32 {
929 unsafe { 763 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).instr().read().0 }
930 PIOS[Self::Pio::PIO_NO as usize]
931 .sm(Self::Sm::SM_NO as usize)
932 .instr()
933 .read()
934 .0
935 }
936 } 764 }
937 765
938 fn exec_instr(&mut self, instr: u16) { 766 fn exec_instr(&mut self, instr: u16) {
939 unsafe { 767 unsafe {
940 PIOS[Self::Pio::PIO_NO as usize] 768 Self::Pio::PIO
941 .sm(Self::Sm::SM_NO as usize) 769 .sm(Self::Sm::SM_NO as usize)
942 .instr() 770 .instr()
943 .write(|w| w.set_instr(instr)); 771 .write(|w| w.set_instr(instr));
944 } 772 }
945 } 773 }
946 774
947 fn write_instr<I>(&mut self, start: usize, instrs: I)
948 where
949 I: Iterator<Item = u16>,
950 {
951 let _ = self;
952 write_instr(
953 Self::Pio::PIO_NO,
954 start,
955 instrs,
956 MEM_USED_BY_STATEMACHINE | Self::Sm::SM_NO as u32,
957 );
958 }
959
960 fn is_irq_set(&self, irq_no: u8) -> bool {
961 assert!(irq_no < 8);
962 unsafe {
963 let irq_flags = PIOS[Self::Pio::PIO_NO as usize].irq();
964 irq_flags.read().0 & (1 << irq_no) != 0
965 }
966 }
967
968 fn clear_irq(&mut self, irq_no: usize) {
969 assert!(irq_no < 8);
970 unsafe { PIOS[Self::Pio::PIO_NO as usize].irq().write(|w| w.set_irq(1 << irq_no)) }
971 }
972
973 fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> { 775 fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> {
974 FifoOutFuture::new(self, value) 776 FifoOutFuture::new(self, value)
975 } 777 }
@@ -984,7 +786,7 @@ pub trait PioStateMachine: Sized + Unpin {
984 786
985 fn has_tx_stalled(&self) -> bool { 787 fn has_tx_stalled(&self) -> bool {
986 unsafe { 788 unsafe {
987 let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); 789 let fdebug = Self::Pio::PIO.fdebug();
988 let ret = fdebug.read().txstall() & (1 << Self::Sm::SM_NO) != 0; 790 let ret = fdebug.read().txstall() & (1 << Self::Sm::SM_NO) != 0;
989 fdebug.write(|w| w.set_txstall(1 << Self::Sm::SM_NO)); 791 fdebug.write(|w| w.set_txstall(1 << Self::Sm::SM_NO));
990 ret 792 ret
@@ -993,7 +795,7 @@ pub trait PioStateMachine: Sized + Unpin {
993 795
994 fn has_tx_overflowed(&self) -> bool { 796 fn has_tx_overflowed(&self) -> bool {
995 unsafe { 797 unsafe {
996 let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); 798 let fdebug = Self::Pio::PIO.fdebug();
997 let ret = fdebug.read().txover() & (1 << Self::Sm::SM_NO) != 0; 799 let ret = fdebug.read().txover() & (1 << Self::Sm::SM_NO) != 0;
998 fdebug.write(|w| w.set_txover(1 << Self::Sm::SM_NO)); 800 fdebug.write(|w| w.set_txover(1 << Self::Sm::SM_NO));
999 ret 801 ret
@@ -1002,7 +804,7 @@ pub trait PioStateMachine: Sized + Unpin {
1002 804
1003 fn has_rx_stalled(&self) -> bool { 805 fn has_rx_stalled(&self) -> bool {
1004 unsafe { 806 unsafe {
1005 let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); 807 let fdebug = Self::Pio::PIO.fdebug();
1006 let ret = fdebug.read().rxstall() & (1 << Self::Sm::SM_NO) != 0; 808 let ret = fdebug.read().rxstall() & (1 << Self::Sm::SM_NO) != 0;
1007 fdebug.write(|w| w.set_rxstall(1 << Self::Sm::SM_NO)); 809 fdebug.write(|w| w.set_rxstall(1 << Self::Sm::SM_NO));
1008 ret 810 ret
@@ -1011,7 +813,7 @@ pub trait PioStateMachine: Sized + Unpin {
1011 813
1012 fn has_rx_underflowed(&self) -> bool { 814 fn has_rx_underflowed(&self) -> bool {
1013 unsafe { 815 unsafe {
1014 let fdebug = PIOS[Self::Pio::PIO_NO as usize].fdebug(); 816 let fdebug = Self::Pio::PIO.fdebug();
1015 let ret = fdebug.read().rxunder() & (1 << Self::Sm::SM_NO) != 0; 817 let ret = fdebug.read().rxunder() & (1 << Self::Sm::SM_NO) != 0;
1016 fdebug.write(|w| w.set_rxunder(1 << Self::Sm::SM_NO)); 818 fdebug.write(|w| w.set_rxunder(1 << Self::Sm::SM_NO));
1017 ret 819 ret
@@ -1020,13 +822,12 @@ pub trait PioStateMachine: Sized + Unpin {
1020 822
1021 fn dma_push<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [u32]) -> Transfer<'a, C> { 823 fn dma_push<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [u32]) -> Transfer<'a, C> {
1022 unsafe { 824 unsafe {
1023 dma::init();
1024 let pio_no = Self::Pio::PIO_NO; 825 let pio_no = Self::Pio::PIO_NO;
1025 let sm_no = Self::Sm::SM_NO; 826 let sm_no = Self::Sm::SM_NO;
1026 let p = ch.regs(); 827 let p = ch.regs();
1027 p.read_addr().write_value(data.as_ptr() as u32); 828 p.read_addr().write_value(data.as_ptr() as u32);
1028 p.write_addr() 829 p.write_addr()
1029 .write_value(PIOS[pio_no as usize].txf(sm_no as usize).ptr() as u32); 830 .write_value(Self::Pio::PIO.txf(sm_no as usize).ptr() as u32);
1030 p.trans_count().write_value(data.len() as u32); 831 p.trans_count().write_value(data.len() as u32);
1031 p.ctrl_trig().write(|w| { 832 p.ctrl_trig().write(|w| {
1032 // Set TX DREQ for this statemachine 833 // Set TX DREQ for this statemachine
@@ -1044,13 +845,12 @@ pub trait PioStateMachine: Sized + Unpin {
1044 845
1045 fn dma_pull<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [u32]) -> Transfer<'a, C> { 846 fn dma_pull<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [u32]) -> Transfer<'a, C> {
1046 unsafe { 847 unsafe {
1047 dma::init();
1048 let pio_no = Self::Pio::PIO_NO; 848 let pio_no = Self::Pio::PIO_NO;
1049 let sm_no = Self::Sm::SM_NO; 849 let sm_no = Self::Sm::SM_NO;
1050 let p = ch.regs(); 850 let p = ch.regs();
1051 p.write_addr().write_value(data.as_ptr() as u32); 851 p.write_addr().write_value(data.as_ptr() as u32);
1052 p.read_addr() 852 p.read_addr()
1053 .write_value(PIOS[pio_no as usize].rxf(sm_no as usize).ptr() as u32); 853 .write_value(Self::Pio::PIO.rxf(sm_no as usize).ptr() as u32);
1054 p.trans_count().write_value(data.len() as u32); 854 p.trans_count().write_value(data.len() as u32);
1055 p.ctrl_trig().write(|w| { 855 p.ctrl_trig().write(|w| {
1056 // Set TX DREQ for this statemachine 856 // Set TX DREQ for this statemachine
@@ -1067,120 +867,127 @@ pub trait PioStateMachine: Sized + Unpin {
1067 } 867 }
1068} 868}
1069 869
1070/* 870pub struct PioCommonInstance<PIO: PioInstance> {
1071This is a bit array containing 4 bits for every word in the PIO instruction memory. 871 instructions_used: u32,
1072*/ 872 pio: PhantomData<PIO>,
1073// Bit 3-2
1074//const MEM_USE_MASK: u32 = 0b1100;
1075const MEM_NOT_USED: u32 = 0b0000;
1076const MEM_USED_BY_STATEMACHINE: u32 = 0b0100;
1077const MEM_USED_BY_COMMON: u32 = 0b1000;
1078
1079// Bit 1-0 is the number of the state machine
1080//const MEM_STATE_MASK: u32 = 0b0011;
1081
1082// Should use mutex if running on multiple cores
1083static mut INSTR_MEM_STATUS: &'static mut [[u32; 4]; 2] = &mut [[0; 4]; 2];
1084
1085fn instr_mem_get_status(pio_no: u8, addr: u8) -> u32 {
1086 ((unsafe { INSTR_MEM_STATUS[pio_no as usize][(addr >> 3) as usize] }) >> ((addr & 0x07) * 4)) & 0xf
1087}
1088
1089fn instr_mem_set_status(pio_no: u8, addr: u8, status: u32) {
1090 let w = unsafe { &mut INSTR_MEM_STATUS[pio_no as usize][(addr >> 3) as usize] };
1091 let shift = (addr & 0x07) * 4;
1092 *w = (*w & !(0xf << shift)) | (status << shift);
1093}
1094
1095fn instr_mem_is_free(pio_no: u8, addr: u8) -> bool {
1096 instr_mem_get_status(pio_no, addr) == MEM_NOT_USED
1097} 873}
1098 874
1099pub struct PioCommonInstance<PIO: PioInstance> { 875pub struct PioInstanceMemory<PIO: PioInstance> {
876 used_mask: u32,
1100 pio: PhantomData<PIO>, 877 pio: PhantomData<PIO>,
1101} 878}
1102 879
1103impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> { 880impl<PIO: PioInstance> sealed::PioCommon for PioCommonInstance<PIO> {
1104 type Pio = PIO; 881 type Pio = PIO;
1105} 882}
1106 883impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {
1107fn write_instr<I>(pio_no: u8, start: usize, instrs: I, mem_user: u32) 884 fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio>
1108where 885 where
1109 I: Iterator<Item = u16>, 886 I: Iterator<Item = u16>,
1110{ 887 {
1111 for (i, instr) in instrs.enumerate() { 888 let mut used_mask = 0;
1112 let addr = (i + start) as u8; 889 for (i, instr) in instrs.enumerate() {
1113 assert!( 890 let addr = (i + start) as u8;
1114 instr_mem_is_free(pio_no, addr), 891 let mask = 1 << (addr as usize);
1115 "Trying to write already used PIO instruction memory at {}", 892 assert!(
1116 addr 893 self.instructions_used & mask == 0,
1117 ); 894 "Trying to write already used PIO instruction memory at {}",
1118 unsafe { 895 addr
1119 PIOS[pio_no as usize].instr_mem(addr as usize).write(|w| { 896 );
1120 w.set_instr_mem(instr); 897 unsafe {
1121 }); 898 PIO::PIO.instr_mem(addr as usize).write(|w| {
1122 instr_mem_set_status(pio_no, addr, mem_user); 899 w.set_instr_mem(instr);
900 });
901 }
902 used_mask |= mask;
903 }
904 self.instructions_used |= used_mask;
905 PioInstanceMemory {
906 used_mask,
907 pio: PhantomData,
1123 } 908 }
1124 } 909 }
1125}
1126 910
1127pub trait PioCommon: Sized { 911 fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>) {
1128 type Pio: PioInstance; 912 self.instructions_used &= !instrs.used_mask;
913 }
914}
1129 915
1130 fn write_instr<I>(&mut self, start: usize, instrs: I) 916pub trait PioCommon: sealed::PioCommon + Sized {
917 fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio>
1131 where 918 where
1132 I: Iterator<Item = u16>, 919 I: Iterator<Item = u16>;
1133 { 920
1134 let _ = self; 921 // TODO make instruction memory that is currently in use unfreeable
1135 write_instr(Self::Pio::PIO_NO, start, instrs, MEM_USED_BY_COMMON); 922 fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>);
923
924 fn is_irq_set(&self, irq_no: u8) -> bool {
925 assert!(irq_no < 8);
926 unsafe {
927 let irq_flags = Self::Pio::PIO.irq();
928 irq_flags.read().0 & (1 << irq_no) != 0
929 }
1136 } 930 }
1137 931
1138 fn clear_irq(&mut self, irq_no: usize) { 932 fn clear_irq(&mut self, irq_no: usize) {
1139 assert!(irq_no < 8); 933 assert!(irq_no < 8);
1140 unsafe { PIOS[Self::Pio::PIO_NO as usize].irq().write(|w| w.set_irq(1 << irq_no)) } 934 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
1141 } 935 }
1142 936
1143 fn clear_irqs(&mut self, mask: u8) { 937 fn clear_irqs(&mut self, mask: u8) {
1144 unsafe { PIOS[Self::Pio::PIO_NO as usize].irq().write(|w| w.set_irq(mask)) } 938 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(mask)) }
1145 } 939 }
1146 940
1147 fn force_irq(&mut self, irq_no: usize) { 941 fn force_irq(&mut self, irq_no: usize) {
1148 assert!(irq_no < 8); 942 assert!(irq_no < 8);
1149 unsafe { 943 unsafe { Self::Pio::PIO.irq_force().write(|w| w.set_irq_force(1 << irq_no)) }
1150 PIOS[Self::Pio::PIO_NO as usize]
1151 .irq_force()
1152 .write(|w| w.set_irq_force(1 << irq_no))
1153 }
1154 } 944 }
1155 945
1156 fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { 946 fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) {
1157 unsafe { 947 unsafe {
1158 PIOS[Self::Pio::PIO_NO as usize] 948 Self::Pio::PIO
1159 .input_sync_bypass() 949 .input_sync_bypass()
1160 .modify(|w| *w = (*w & !mask) | (bypass & mask)); 950 .modify(|w| *w = (*w & !mask) | (bypass & mask));
1161 } 951 }
1162 } 952 }
1163 953
1164 fn get_input_sync_bypass(&self) -> u32 { 954 fn get_input_sync_bypass(&self) -> u32 {
1165 unsafe { PIOS[Self::Pio::PIO_NO as usize].input_sync_bypass().read() } 955 unsafe { Self::Pio::PIO.input_sync_bypass().read() }
956 }
957
958 fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> {
959 unsafe {
960 pin.io().ctrl().write(|w| {
961 w.set_funcsel(
962 if Self::Pio::PIO_NO == 1 {
963 pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
964 } else {
965 // PIO == 0
966 pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
967 }
968 .0,
969 );
970 });
971 }
972 PioPin {
973 pin_bank: pin.pin_bank(),
974 pio: PhantomData::default(),
975 }
1166 } 976 }
1167} 977}
1168 978
1169// Identifies a specific state machine inside a PIO device 979// Identifies a specific state machine inside a PIO device
1170pub struct SmInstanceBase<const SM_NO: u8> {} 980pub struct SmInstanceBase<const SM_NO: u8> {}
1171 981
1172pub trait SmInstance: Unpin { 982pub trait SmInstance: sealed::SmInstance + Unpin {}
1173 const SM_NO: u8;
1174}
1175 983
1176impl<const SM_NO: u8> SmInstance for SmInstanceBase<SM_NO> { 984impl<const SM_NO: u8> sealed::SmInstance for SmInstanceBase<SM_NO> {
1177 const SM_NO: u8 = SM_NO; 985 const SM_NO: u8 = SM_NO;
1178} 986}
987impl<const SM_NO: u8> SmInstance for SmInstanceBase<SM_NO> {}
1179 988
1180pub trait PioPeripheral: Sized { 989pub trait PioPeripheral: sealed::PioPeripheral + Sized {
1181 type Pio: PioInstance;
1182 fn pio(&self) -> u8 { 990 fn pio(&self) -> u8 {
1183 let _ = self;
1184 Self::Pio::PIO_NO 991 Self::Pio::PIO_NO
1185 } 992 }
1186 993
@@ -1193,9 +1000,9 @@ pub trait PioPeripheral: Sized {
1193 PioStateMachineInstance<Self::Pio, SmInstanceBase<2>>, 1000 PioStateMachineInstance<Self::Pio, SmInstanceBase<2>>,
1194 PioStateMachineInstance<Self::Pio, SmInstanceBase<3>>, 1001 PioStateMachineInstance<Self::Pio, SmInstanceBase<3>>,
1195 ) { 1002 ) {
1196 let _ = self;
1197 ( 1003 (
1198 PioCommonInstance { 1004 PioCommonInstance {
1005 instructions_used: 0,
1199 pio: PhantomData::default(), 1006 pio: PhantomData::default(),
1200 }, 1007 },
1201 PioStateMachineInstance { 1008 PioStateMachineInstance {
@@ -1218,29 +1025,46 @@ pub trait PioPeripheral: Sized {
1218 } 1025 }
1219} 1026}
1220 1027
1028mod sealed {
1029 pub trait PioInstance {
1030 const PIO_NO: u8;
1031 const PIO: &'static crate::pac::pio::Pio;
1032 }
1033
1034 pub trait PioCommon {
1035 type Pio: super::PioInstance;
1036 }
1037
1038 pub trait PioStateMachine {
1039 type Pio: super::PioInstance;
1040 type Sm: super::SmInstance;
1041 }
1042
1043 pub trait SmInstance {
1044 const SM_NO: u8;
1045 }
1046
1047 pub trait PioPeripheral {
1048 type Pio: super::PioInstance;
1049 }
1050}
1051
1221// Identifies a specific PIO device 1052// Identifies a specific PIO device
1222pub struct PioInstanceBase<const PIO_NO: u8> {} 1053pub struct PioInstanceBase<const PIO_NO: u8> {}
1223 1054
1224pub trait PioInstance: Unpin { 1055pub trait PioInstance: sealed::PioInstance + Unpin {}
1225 const PIO_NO: u8;
1226 type IrqOut: Interrupt;
1227 type IrqIn: Interrupt;
1228 type IrqSm: Interrupt;
1229}
1230 1056
1231impl PioInstance for PioInstanceBase<0> { 1057impl sealed::PioInstance for PioInstanceBase<0> {
1232 const PIO_NO: u8 = 0; 1058 const PIO_NO: u8 = 0;
1233 type IrqOut = interrupt::PIO0_IRQ_0; 1059 const PIO: &'static pac::pio::Pio = &pac::PIO0;
1234 type IrqIn = interrupt::PIO0_IRQ_1;
1235 type IrqSm = interrupt::PIO0_IRQ_1;
1236} 1060}
1061impl PioInstance for PioInstanceBase<0> {}
1237 1062
1238impl PioInstance for PioInstanceBase<1> { 1063impl sealed::PioInstance for PioInstanceBase<1> {
1239 const PIO_NO: u8 = 1; 1064 const PIO_NO: u8 = 1;
1240 type IrqOut = interrupt::PIO1_IRQ_0; 1065 const PIO: &'static pac::pio::Pio = &pac::PIO1;
1241 type IrqIn = interrupt::PIO1_IRQ_1;
1242 type IrqSm = interrupt::PIO1_IRQ_1;
1243} 1066}
1067impl PioInstance for PioInstanceBase<1> {}
1244 1068
1245pub type Pio0 = PioInstanceBase<0>; 1069pub type Pio0 = PioInstanceBase<0>;
1246pub type Pio1 = PioInstanceBase<1>; 1070pub type Pio1 = PioInstanceBase<1>;
@@ -1252,9 +1076,10 @@ pub type Sm3 = SmInstanceBase<3>;
1252 1076
1253macro_rules! impl_pio_sm { 1077macro_rules! impl_pio_sm {
1254 ($name:ident, $pio:expr) => { 1078 ($name:ident, $pio:expr) => {
1255 impl PioPeripheral for peripherals::$name { 1079 impl sealed::PioPeripheral for peripherals::$name {
1256 type Pio = PioInstanceBase<$pio>; 1080 type Pio = PioInstanceBase<$pio>;
1257 } 1081 }
1082 impl PioPeripheral for peripherals::$name {}
1258 }; 1083 };
1259} 1084}
1260 1085
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index e616d8c5a..1b075b8fd 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 pio.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;
@@ -46,16 +51,15 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
46 } 51 }
47} 52}
48 53
49#[embassy_executor::task] 54fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm1>) {
50async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
51 // Setupm sm1 55 // Setupm sm1
52 56
53 // Read 0b10101 repeatedly until ISR is full 57 // Read 0b10101 repeatedly until ISR is full
54 let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); 58 let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",);
55 59
56 let relocated = RelocatedProgram::new(&prg.program); 60 let relocated = RelocatedProgram::new(&prg.program);
57 sm.write_instr(relocated.origin() as usize, relocated.code()); 61 pio.write_instr(relocated.origin() as usize, relocated.code());
58 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 62 pio_instr_util::exec_jmp(sm, relocated.origin());
59 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); 63 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32);
60 sm.set_set_range(0, 0); 64 sm.set_set_range(0, 0);
61 let pio::Wrap { source, target } = relocated.wrap(); 65 let pio::Wrap { source, target } = relocated.wrap();
@@ -63,6 +67,10 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
63 67
64 sm.set_autopush(true); 68 sm.set_autopush(true);
65 sm.set_in_shift_dir(ShiftDirection::Right); 69 sm.set_in_shift_dir(ShiftDirection::Right);
70}
71
72#[embassy_executor::task]
73async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
66 sm.set_enable(true); 74 sm.set_enable(true);
67 loop { 75 loop {
68 let rx = sm.wait_pull().await; 76 let rx = sm.wait_pull().await;
@@ -70,8 +78,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
70 } 78 }
71} 79}
72 80
73#[embassy_executor::task] 81fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm2>) {
74async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) {
75 // Setup sm2 82 // Setup sm2
76 83
77 // Repeatedly trigger IRQ 3 84 // Repeatedly trigger IRQ 3
@@ -85,13 +92,17 @@ async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) {
85 ".wrap", 92 ".wrap",
86 ); 93 );
87 let relocated = RelocatedProgram::new(&prg.program); 94 let relocated = RelocatedProgram::new(&prg.program);
88 sm.write_instr(relocated.origin() as usize, relocated.code()); 95 pio.write_instr(relocated.origin() as usize, relocated.code());
89 96
90 let pio::Wrap { source, target } = relocated.wrap(); 97 let pio::Wrap { source, target } = relocated.wrap();
91 sm.set_wrap(source, target); 98 sm.set_wrap(source, target);
92 99
93 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 100 pio_instr_util::exec_jmp(sm, relocated.origin());
94 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); 101 sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32);
102}
103
104#[embassy_executor::task]
105async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) {
95 sm.set_enable(true); 106 sm.set_enable(true);
96 loop { 107 loop {
97 sm.wait_irq(3).await; 108 sm.wait_irq(3).await;
@@ -104,9 +115,12 @@ async fn main(spawner: Spawner) {
104 let p = embassy_rp::init(Default::default()); 115 let p = embassy_rp::init(Default::default());
105 let pio = p.PIO0; 116 let pio = p.PIO0;
106 117
107 let (_, sm0, sm1, sm2, ..) = pio.split(); 118 let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split();
108 119
109 spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap(); 120 setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade());
121 setup_pio_task_sm1(&mut pio0, &mut sm1);
122 setup_pio_task_sm2(&mut pio0, &mut sm2);
123 spawner.spawn(pio_task_sm0(sm0)).unwrap();
110 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 124 spawner.spawn(pio_task_sm1(sm1)).unwrap();
111 spawner.spawn(pio_task_sm2(sm2)).unwrap(); 125 spawner.spawn(pio_task_sm2(sm2)).unwrap();
112} 126}
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 145e4a656..7d4919f75 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -4,7 +4,7 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_rp::pio::{PioPeripheral, PioStateMachine, ShiftDirection}; 7use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection};
8use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
9use embassy_rp::{pio_instr_util, Peripheral}; 9use embassy_rp::{pio_instr_util, Peripheral};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -19,7 +19,7 @@ fn swap_nibbles(v: u32) -> u32 {
19async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
20 let p = embassy_rp::init(Default::default()); 20 let p = embassy_rp::init(Default::default());
21 let pio = p.PIO0; 21 let pio = p.PIO0;
22 let (_, mut sm, ..) = pio.split(); 22 let (mut pio0, mut sm, ..) = pio.split();
23 23
24 let prg = pio_proc::pio_asm!( 24 let prg = pio_proc::pio_asm!(
25 ".origin 0", 25 ".origin 0",
@@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) {
34 ); 34 );
35 35
36 let relocated = RelocatedProgram::new(&prg.program); 36 let relocated = RelocatedProgram::new(&prg.program);
37 sm.write_instr(relocated.origin() as usize, relocated.code()); 37 pio0.write_instr(relocated.origin() as usize, relocated.code());
38 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 38 pio_instr_util::exec_jmp(&mut sm, relocated.origin());
39 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); 39 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
40 let pio::Wrap { source, target } = relocated.wrap(); 40 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 5f8a3baee..041e8ae11 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(mut 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
@@ -49,11 +50,11 @@ impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
49 let prg = a.assemble_with_wrap(wrap_source, wrap_target); 50 let prg = a.assemble_with_wrap(wrap_source, wrap_target);
50 51
51 let relocated = RelocatedProgram::new(&prg); 52 let relocated = RelocatedProgram::new(&prg);
52 sm.write_instr(relocated.origin() as usize, relocated.code()); 53 pio.write_instr(relocated.origin() as usize, relocated.code());
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 {