aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/pio/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp/src/pio/mod.rs')
-rw-r--r--embassy-rp/src/pio/mod.rs90
1 files changed, 80 insertions, 10 deletions
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs
index ec698d99c..5f554dfe3 100644
--- a/embassy-rp/src/pio/mod.rs
+++ b/embassy-rp/src/pio/mod.rs
@@ -12,7 +12,7 @@ use fixed::types::extra::U8;
12use fixed::FixedU32; 12use fixed::FixedU32;
13use pio::{Program, SideSet, Wrap}; 13use pio::{Program, SideSet, Wrap};
14 14
15use crate::dma::{Channel, Transfer, Word}; 15use crate::dma::{self, Channel, Transfer, Word};
16use crate::gpio::{self, AnyPin, Drive, Level, Pull, SealedPin, SlewRate}; 16use crate::gpio::{self, AnyPin, Drive, Level, Pull, SealedPin, SlewRate};
17use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; 17use crate::interrupt::typelevel::{Binding, Handler, Interrupt};
18use crate::relocate::RelocatedProgram; 18use crate::relocate::RelocatedProgram;
@@ -98,6 +98,9 @@ pub enum StatusSource {
98 TxFifoLevel = 0, 98 TxFifoLevel = 0,
99 /// All-ones if RX FIFO level < N, otherwise all-zeroes. 99 /// All-ones if RX FIFO level < N, otherwise all-zeroes.
100 RxFifoLevel = 1, 100 RxFifoLevel = 1,
101 /// All-ones if the indexed IRQ flag is raised, otherwise all-zeroes
102 #[cfg(feature = "_rp235x")]
103 Irq = 2,
101} 104}
102 105
103const RXNEMPTY_MASK: u32 = 1 << 0; 106const RXNEMPTY_MASK: u32 = 1 << 0;
@@ -278,6 +281,18 @@ impl<'l, PIO: Instance> Pin<'l, PIO> {
278 }); 281 });
279 } 282 }
280 283
284 /// Configure the output logic inversion of this pin.
285 #[inline]
286 pub fn set_output_inversion(&mut self, invert: bool) {
287 self.pin.gpio().ctrl().modify(|w| {
288 w.set_outover(if invert {
289 pac::io::vals::Outover::INVERT
290 } else {
291 pac::io::vals::Outover::NORMAL
292 })
293 });
294 }
295
281 /// Set the pin's input sync bypass. 296 /// Set the pin's input sync bypass.
282 pub fn set_input_sync_bypass(&mut self, bypass: bool) { 297 pub fn set_input_sync_bypass(&mut self, bypass: bool) {
283 let mask = 1 << self.pin(); 298 let mask = 1 << self.pin();
@@ -357,6 +372,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
357 FifoInFuture::new(self) 372 FifoInFuture::new(self)
358 } 373 }
359 374
375 fn dreq() -> crate::pac::dma::vals::TreqSel {
376 crate::pac::dma::vals::TreqSel::from(PIO::PIO_NO * 8 + SM as u8 + 4)
377 }
378
360 /// Prepare DMA transfer from RX FIFO. 379 /// Prepare DMA transfer from RX FIFO.
361 pub fn dma_pull<'a, C: Channel, W: Word>( 380 pub fn dma_pull<'a, C: Channel, W: Word>(
362 &'a mut self, 381 &'a mut self,
@@ -364,7 +383,6 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
364 data: &'a mut [W], 383 data: &'a mut [W],
365 bswap: bool, 384 bswap: bool,
366 ) -> Transfer<'a, C> { 385 ) -> Transfer<'a, C> {
367 let pio_no = PIO::PIO_NO;
368 let p = ch.regs(); 386 let p = ch.regs();
369 p.write_addr().write_value(data.as_ptr() as u32); 387 p.write_addr().write_value(data.as_ptr() as u32);
370 p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32); 388 p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32);
@@ -374,8 +392,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
374 p.trans_count().write(|w| w.set_count(data.len() as u32)); 392 p.trans_count().write(|w| w.set_count(data.len() as u32));
375 compiler_fence(Ordering::SeqCst); 393 compiler_fence(Ordering::SeqCst);
376 p.ctrl_trig().write(|w| { 394 p.ctrl_trig().write(|w| {
377 // Set RX DREQ for this statemachine 395 w.set_treq_sel(Self::dreq());
378 w.set_treq_sel(crate::pac::dma::vals::TreqSel::from(pio_no * 8 + SM as u8 + 4));
379 w.set_data_size(W::size()); 396 w.set_data_size(W::size());
380 w.set_chain_to(ch.number()); 397 w.set_chain_to(ch.number());
381 w.set_incr_read(false); 398 w.set_incr_read(false);
@@ -386,6 +403,36 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
386 compiler_fence(Ordering::SeqCst); 403 compiler_fence(Ordering::SeqCst);
387 Transfer::new(ch) 404 Transfer::new(ch)
388 } 405 }
406
407 /// Prepare a repeated DMA transfer from RX FIFO.
408 pub fn dma_pull_repeated<'a, C: Channel, W: Word>(&'a mut self, ch: Peri<'a, C>, len: usize) -> Transfer<'a, C> {
409 // This is the read version of dma::write_repeated. This allows us to
410 // discard reads from the RX FIFO through DMA.
411
412 // static mut so it gets allocated in RAM
413 static mut DUMMY: u32 = 0;
414
415 let p = ch.regs();
416 p.write_addr().write_value(core::ptr::addr_of_mut!(DUMMY) as u32);
417 p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32);
418
419 #[cfg(feature = "rp2040")]
420 p.trans_count().write(|w| *w = len as u32);
421 #[cfg(feature = "_rp235x")]
422 p.trans_count().write(|w| w.set_count(len as u32));
423
424 compiler_fence(Ordering::SeqCst);
425 p.ctrl_trig().write(|w| {
426 w.set_treq_sel(Self::dreq());
427 w.set_data_size(W::size());
428 w.set_chain_to(ch.number());
429 w.set_incr_read(false);
430 w.set_incr_write(false);
431 w.set_en(true);
432 });
433 compiler_fence(Ordering::SeqCst);
434 Transfer::new(ch)
435 }
389} 436}
390 437
391/// Type representing a state machine TX FIFO. 438/// Type representing a state machine TX FIFO.
@@ -409,7 +456,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
409 (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f 456 (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f
410 } 457 }
411 458
412 /// Check state machine has stalled on empty TX FIFO. 459 /// Check if state machine has stalled on empty TX FIFO.
413 pub fn stalled(&self) -> bool { 460 pub fn stalled(&self) -> bool {
414 let fdebug = PIO::PIO.fdebug(); 461 let fdebug = PIO::PIO.fdebug();
415 let ret = fdebug.read().txstall() & (1 << SM) != 0; 462 let ret = fdebug.read().txstall() & (1 << SM) != 0;
@@ -448,6 +495,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
448 FifoOutFuture::new(self, value) 495 FifoOutFuture::new(self, value)
449 } 496 }
450 497
498 fn dreq() -> crate::pac::dma::vals::TreqSel {
499 crate::pac::dma::vals::TreqSel::from(PIO::PIO_NO * 8 + SM as u8)
500 }
501
451 /// Prepare a DMA transfer to TX FIFO. 502 /// Prepare a DMA transfer to TX FIFO.
452 pub fn dma_push<'a, C: Channel, W: Word>( 503 pub fn dma_push<'a, C: Channel, W: Word>(
453 &'a mut self, 504 &'a mut self,
@@ -455,7 +506,6 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
455 data: &'a [W], 506 data: &'a [W],
456 bswap: bool, 507 bswap: bool,
457 ) -> Transfer<'a, C> { 508 ) -> Transfer<'a, C> {
458 let pio_no = PIO::PIO_NO;
459 let p = ch.regs(); 509 let p = ch.regs();
460 p.read_addr().write_value(data.as_ptr() as u32); 510 p.read_addr().write_value(data.as_ptr() as u32);
461 p.write_addr().write_value(PIO::PIO.txf(SM).as_ptr() as u32); 511 p.write_addr().write_value(PIO::PIO.txf(SM).as_ptr() as u32);
@@ -465,8 +515,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
465 p.trans_count().write(|w| w.set_count(data.len() as u32)); 515 p.trans_count().write(|w| w.set_count(data.len() as u32));
466 compiler_fence(Ordering::SeqCst); 516 compiler_fence(Ordering::SeqCst);
467 p.ctrl_trig().write(|w| { 517 p.ctrl_trig().write(|w| {
468 // Set TX DREQ for this statemachine 518 w.set_treq_sel(Self::dreq());
469 w.set_treq_sel(crate::pac::dma::vals::TreqSel::from(pio_no * 8 + SM as u8));
470 w.set_data_size(W::size()); 519 w.set_data_size(W::size());
471 w.set_chain_to(ch.number()); 520 w.set_chain_to(ch.number());
472 w.set_incr_read(true); 521 w.set_incr_read(true);
@@ -477,6 +526,11 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
477 compiler_fence(Ordering::SeqCst); 526 compiler_fence(Ordering::SeqCst);
478 Transfer::new(ch) 527 Transfer::new(ch)
479 } 528 }
529
530 /// Prepare a repeated DMA transfer to TX FIFO.
531 pub fn dma_push_repeated<'a, C: Channel, W: Word>(&'a mut self, ch: Peri<'a, C>, len: usize) -> Transfer<'a, C> {
532 unsafe { dma::write_repeated(ch, PIO::PIO.txf(SM).as_ptr(), len, Self::dreq()) }
533 }
480} 534}
481 535
482/// A type representing a single PIO state machine. 536/// A type representing a single PIO state machine.
@@ -736,6 +790,7 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
736 w.set_status_sel(match config.status_sel { 790 w.set_status_sel(match config.status_sel {
737 StatusSource::TxFifoLevel => pac::pio::vals::ExecctrlStatusSel::TXLEVEL, 791 StatusSource::TxFifoLevel => pac::pio::vals::ExecctrlStatusSel::TXLEVEL,
738 StatusSource::RxFifoLevel => pac::pio::vals::ExecctrlStatusSel::RXLEVEL, 792 StatusSource::RxFifoLevel => pac::pio::vals::ExecctrlStatusSel::RXLEVEL,
793 StatusSource::Irq => pac::pio::vals::ExecctrlStatusSel::IRQ,
739 }); 794 });
740 #[cfg(feature = "rp2040")] 795 #[cfg(feature = "rp2040")]
741 w.set_status_sel(match config.status_sel { 796 w.set_status_sel(match config.status_sel {
@@ -922,13 +977,27 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
922 self.set_enable(enabled); 977 self.set_enable(enabled);
923 } 978 }
924 979
980 #[cfg(feature = "rp2040")]
981 fn pin_base() -> u8 {
982 0
983 }
984
985 #[cfg(feature = "_rp235x")]
986 fn pin_base() -> u8 {
987 if PIO::PIO.gpiobase().read().gpiobase() {
988 16
989 } else {
990 0
991 }
992 }
993
925 /// Sets pin directions. This pauses the current state machine to run `SET` commands 994 /// Sets pin directions. This pauses the current state machine to run `SET` commands
926 /// and temporarily unsets the `OUT_STICKY` bit. 995 /// and temporarily unsets the `OUT_STICKY` bit.
927 pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) { 996 pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) {
928 self.with_paused(|sm| { 997 self.with_paused(|sm| {
929 for pin in pins { 998 for pin in pins {
930 Self::this_sm().pinctrl().write(|w| { 999 Self::this_sm().pinctrl().write(|w| {
931 w.set_set_base(pin.pin()); 1000 w.set_set_base(pin.pin() - Self::pin_base());
932 w.set_set_count(1); 1001 w.set_set_count(1);
933 }); 1002 });
934 // SET PINDIRS, (dir) 1003 // SET PINDIRS, (dir)
@@ -943,7 +1012,7 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
943 self.with_paused(|sm| { 1012 self.with_paused(|sm| {
944 for pin in pins { 1013 for pin in pins {
945 Self::this_sm().pinctrl().write(|w| { 1014 Self::this_sm().pinctrl().write(|w| {
946 w.set_set_base(pin.pin()); 1015 w.set_set_base(pin.pin() - Self::pin_base());
947 w.set_set_count(1); 1016 w.set_set_count(1);
948 }); 1017 });
949 // SET PINS, (dir) 1018 // SET PINS, (dir)
@@ -1306,6 +1375,7 @@ impl<'d, PIO: Instance> Pio<'d, PIO> {
1306 PIO::state().users.store(5, Ordering::Release); 1375 PIO::state().users.store(5, Ordering::Release);
1307 PIO::state().used_pins.store(0, Ordering::Release); 1376 PIO::state().used_pins.store(0, Ordering::Release);
1308 PIO::Interrupt::unpend(); 1377 PIO::Interrupt::unpend();
1378
1309 unsafe { PIO::Interrupt::enable() }; 1379 unsafe { PIO::Interrupt::enable() };
1310 Self { 1380 Self {
1311 common: Common { 1381 common: Common {