aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-05-02 10:50:06 +0200
committerpennae <[email protected]>2023-05-02 10:56:37 +0200
commit54e695b1b2105c1b2484584d100564afc0679596 (patch)
tree2426d94bbf38d2ab3aea1f8d473a3c835ae12446
parent05c36e05f9f6b1a0a36982239b2e7c697f0d3734 (diff)
rp/pio: fix dma
fixing the dma word size to 32 makes it impossible to implement any peripheral that takes its data in smaller chunks, eg uart, spi, i2c, ws2812, the list goes on. compiler barriers were also not set correctly; we need a SeqCst barrier before starting a transfer as well to avoid reordering of accesses into a buffer after dma has started.
-rw-r--r--embassy-rp/src/pio.rs16
1 files changed, 9 insertions, 7 deletions
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 7faec10b5..cab57f765 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -8,10 +8,10 @@ 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::{Channel, Transfer}; 11use crate::dma::{Channel, Transfer, Word};
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::TreqSel;
15use crate::pio::sealed::{PioInstance as _, SmInstance as _}; 15use crate::pio::sealed::{PioInstance as _, SmInstance as _};
16use crate::{interrupt, pac, peripherals, RegExt}; 16use crate::{interrupt, pac, peripherals, RegExt};
17 17
@@ -820,7 +820,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
820 } 820 }
821 } 821 }
822 822
823 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, W: Word>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> {
824 unsafe { 824 unsafe {
825 let pio_no = Self::Pio::PIO_NO; 825 let pio_no = Self::Pio::PIO_NO;
826 let sm_no = Self::Sm::SM_NO; 826 let sm_no = Self::Sm::SM_NO;
@@ -829,10 +829,11 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
829 p.write_addr() 829 p.write_addr()
830 .write_value(Self::Pio::PIO.txf(sm_no as usize).ptr() as u32); 830 .write_value(Self::Pio::PIO.txf(sm_no as usize).ptr() as u32);
831 p.trans_count().write_value(data.len() as u32); 831 p.trans_count().write_value(data.len() as u32);
832 compiler_fence(Ordering::SeqCst);
832 p.ctrl_trig().write(|w| { 833 p.ctrl_trig().write(|w| {
833 // Set TX DREQ for this statemachine 834 // Set TX DREQ for this statemachine
834 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no)); 835 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no));
835 w.set_data_size(DataSize::SIZE_WORD); 836 w.set_data_size(W::size());
836 w.set_chain_to(ch.number()); 837 w.set_chain_to(ch.number());
837 w.set_incr_read(true); 838 w.set_incr_read(true);
838 w.set_incr_write(false); 839 w.set_incr_write(false);
@@ -843,7 +844,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
843 Transfer::new(ch) 844 Transfer::new(ch)
844 } 845 }
845 846
846 fn dma_pull<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [u32]) -> Transfer<'a, C> { 847 fn dma_pull<'a, C: Channel, W: Word>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [W]) -> Transfer<'a, C> {
847 unsafe { 848 unsafe {
848 let pio_no = Self::Pio::PIO_NO; 849 let pio_no = Self::Pio::PIO_NO;
849 let sm_no = Self::Sm::SM_NO; 850 let sm_no = Self::Sm::SM_NO;
@@ -852,10 +853,11 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
852 p.read_addr() 853 p.read_addr()
853 .write_value(Self::Pio::PIO.rxf(sm_no as usize).ptr() as u32); 854 .write_value(Self::Pio::PIO.rxf(sm_no as usize).ptr() as u32);
854 p.trans_count().write_value(data.len() as u32); 855 p.trans_count().write_value(data.len() as u32);
856 compiler_fence(Ordering::SeqCst);
855 p.ctrl_trig().write(|w| { 857 p.ctrl_trig().write(|w| {
856 // Set TX DREQ for this statemachine 858 // Set RX DREQ for this statemachine
857 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no + 4)); 859 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no + 4));
858 w.set_data_size(DataSize::SIZE_WORD); 860 w.set_data_size(W::size());
859 w.set_chain_to(ch.number()); 861 w.set_chain_to(ch.number());
860 w.set_incr_read(false); 862 w.set_incr_read(false);
861 w.set_incr_write(true); 863 w.set_incr_write(true);