aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src
diff options
context:
space:
mode:
authorAdrian Wowk <[email protected]>2025-07-02 20:31:45 -0500
committerDario Nieuwenhuis <[email protected]>2025-09-05 20:35:48 +0200
commit676f9da58360627699736c79a4e24ef20a2b9f87 (patch)
tree2680d97a65271dae5b4eee5613b51e8b2469a4a7 /embassy-rp/src
parent0407f7ebe8fabeb81b8a77811ec5dda0fee0b44b (diff)
rp: add new pio dma apis
This commit adds StateMachineRx::dma_pull_repeated and StateMachineTx::dma_push_repeated which allow you to discard reads or send dummy writes to the state machine using the DMA hardware
Diffstat (limited to 'embassy-rp/src')
-rw-r--r--embassy-rp/src/pio/mod.rs67
1 files changed, 59 insertions, 8 deletions
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs
index 0d8a94776..f46e664e4 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;
@@ -281,6 +281,18 @@ impl<'l, PIO: Instance> Pin<'l, PIO> {
281 }); 281 });
282 } 282 }
283 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
284 /// Set the pin's input sync bypass. 296 /// Set the pin's input sync bypass.
285 pub fn set_input_sync_bypass(&mut self, bypass: bool) { 297 pub fn set_input_sync_bypass(&mut self, bypass: bool) {
286 let mask = 1 << self.pin(); 298 let mask = 1 << self.pin();
@@ -360,6 +372,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
360 FifoInFuture::new(self) 372 FifoInFuture::new(self)
361 } 373 }
362 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
363 /// Prepare DMA transfer from RX FIFO. 379 /// Prepare DMA transfer from RX FIFO.
364 pub fn dma_pull<'a, C: Channel, W: Word>( 380 pub fn dma_pull<'a, C: Channel, W: Word>(
365 &'a mut self, 381 &'a mut self,
@@ -367,7 +383,6 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
367 data: &'a mut [W], 383 data: &'a mut [W],
368 bswap: bool, 384 bswap: bool,
369 ) -> Transfer<'a, C> { 385 ) -> Transfer<'a, C> {
370 let pio_no = PIO::PIO_NO;
371 let p = ch.regs(); 386 let p = ch.regs();
372 p.write_addr().write_value(data.as_ptr() as u32); 387 p.write_addr().write_value(data.as_ptr() as u32);
373 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);
@@ -377,8 +392,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
377 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));
378 compiler_fence(Ordering::SeqCst); 393 compiler_fence(Ordering::SeqCst);
379 p.ctrl_trig().write(|w| { 394 p.ctrl_trig().write(|w| {
380 // Set RX DREQ for this statemachine 395 w.set_treq_sel(Self::dreq());
381 w.set_treq_sel(crate::pac::dma::vals::TreqSel::from(pio_no * 8 + SM as u8 + 4));
382 w.set_data_size(W::size()); 396 w.set_data_size(W::size());
383 w.set_chain_to(ch.number()); 397 w.set_chain_to(ch.number());
384 w.set_incr_read(false); 398 w.set_incr_read(false);
@@ -389,6 +403,36 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
389 compiler_fence(Ordering::SeqCst); 403 compiler_fence(Ordering::SeqCst);
390 Transfer::new(ch) 404 Transfer::new(ch)
391 } 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 }
392} 436}
393 437
394/// Type representing a state machine TX FIFO. 438/// Type representing a state machine TX FIFO.
@@ -412,7 +456,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
412 (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f 456 (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f
413 } 457 }
414 458
415 /// Check state machine has stalled on empty TX FIFO. 459 /// Check if state machine has stalled on empty TX FIFO.
416 pub fn stalled(&self) -> bool { 460 pub fn stalled(&self) -> bool {
417 let fdebug = PIO::PIO.fdebug(); 461 let fdebug = PIO::PIO.fdebug();
418 let ret = fdebug.read().txstall() & (1 << SM) != 0; 462 let ret = fdebug.read().txstall() & (1 << SM) != 0;
@@ -451,6 +495,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
451 FifoOutFuture::new(self, value) 495 FifoOutFuture::new(self, value)
452 } 496 }
453 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
454 /// Prepare a DMA transfer to TX FIFO. 502 /// Prepare a DMA transfer to TX FIFO.
455 pub fn dma_push<'a, C: Channel, W: Word>( 503 pub fn dma_push<'a, C: Channel, W: Word>(
456 &'a mut self, 504 &'a mut self,
@@ -458,7 +506,6 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
458 data: &'a [W], 506 data: &'a [W],
459 bswap: bool, 507 bswap: bool,
460 ) -> Transfer<'a, C> { 508 ) -> Transfer<'a, C> {
461 let pio_no = PIO::PIO_NO;
462 let p = ch.regs(); 509 let p = ch.regs();
463 p.read_addr().write_value(data.as_ptr() as u32); 510 p.read_addr().write_value(data.as_ptr() as u32);
464 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);
@@ -468,8 +515,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
468 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));
469 compiler_fence(Ordering::SeqCst); 516 compiler_fence(Ordering::SeqCst);
470 p.ctrl_trig().write(|w| { 517 p.ctrl_trig().write(|w| {
471 // Set TX DREQ for this statemachine 518 w.set_treq_sel(Self::dreq());
472 w.set_treq_sel(crate::pac::dma::vals::TreqSel::from(pio_no * 8 + SM as u8));
473 w.set_data_size(W::size()); 519 w.set_data_size(W::size());
474 w.set_chain_to(ch.number()); 520 w.set_chain_to(ch.number());
475 w.set_incr_read(true); 521 w.set_incr_read(true);
@@ -480,6 +526,11 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
480 compiler_fence(Ordering::SeqCst); 526 compiler_fence(Ordering::SeqCst);
481 Transfer::new(ch) 527 Transfer::new(ch)
482 } 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 }
483} 534}
484 535
485/// A type representing a single PIO state machine. 536/// A type representing a single PIO state machine.