aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLachezar Lechev <[email protected]>2023-03-20 16:34:30 +0200
committerLachezar Lechev <[email protected]>2023-03-20 16:34:30 +0200
commit7a4db1da2641c785f5fd9d2365df2a213f3aaade (patch)
tree2b65b047a5aa6c151b5ce886245c3295506ada7e
parentb6663a013f8632cefbc6d6ab9a9aa7afbcd1314b (diff)
fix(rp): spi transfer
Signed-off-by: Lachezar Lechev <[email protected]>
-rw-r--r--embassy-rp/src/dma.rs1
-rw-r--r--embassy-rp/src/spi.rs46
2 files changed, 41 insertions, 6 deletions
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 05adcecdd..ba07a88df 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -1,3 +1,4 @@
1//! Direct Memory Access (DMA)
1use core::future::Future; 2use core::future::Future;
2use core::pin::Pin; 3use core::pin::Pin;
3use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 584370d56..c48e33fce 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -1,3 +1,4 @@
1//! Serial Peripheral Interface
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2 3
3use embassy_embedded_hal::SetConfig; 4use embassy_embedded_hal::SetConfig;
@@ -385,19 +386,36 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
385 async fn transfer_inner(&mut self, rx_ptr: *mut [u8], tx_ptr: *const [u8]) -> Result<(), Error> { 386 async fn transfer_inner(&mut self, rx_ptr: *mut [u8], tx_ptr: *const [u8]) -> Result<(), Error> {
386 let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); 387 let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr);
387 let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); 388 let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr);
388 assert_eq!(from_len, to_len); 389
389 unsafe { 390 unsafe {
390 self.inner.regs().dmacr().write(|reg| { 391 self.inner.regs().dmacr().write(|reg| {
391 reg.set_rxdmae(true); 392 reg.set_rxdmae(true);
392 reg.set_txdmae(true); 393 reg.set_txdmae(true);
393 }) 394 })
394 }; 395 };
395 let tx_ch = self.tx_dma.as_mut().unwrap(); 396
396 let tx_transfer = unsafe { 397 let mut tx_ch = self.tx_dma.as_mut().unwrap();
397 // If we don't assign future to a variable, the data register pointer 398 // If we don't assign future to a variable, the data register pointer
398 // is held across an await and makes the future non-Send. 399 // is held across an await and makes the future non-Send.
399 crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) 400 let tx_transfer = async {
401 let p = self.inner.regs();
402 unsafe {
403 crate::dma::write(&mut tx_ch, tx_ptr, p.dr().ptr() as *mut _, T::TX_DREQ).await;
404
405 if from_len > to_len {
406 let write_bytes_len = from_len - to_len;
407 // disable incrementation of buffer
408 tx_ch.regs().ctrl_trig().modify(|ctrl_trig| {
409 ctrl_trig.set_incr_write(false);
410 ctrl_trig.set_incr_read(false);
411 });
412
413 // write dummy data
414 crate::dma::write_repeated(tx_ch, p.dr().ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await
415 }
416 }
400 }; 417 };
418
401 let rx_ch = self.rx_dma.as_mut().unwrap(); 419 let rx_ch = self.rx_dma.as_mut().unwrap();
402 let rx_transfer = unsafe { 420 let rx_transfer = unsafe {
403 // If we don't assign future to a variable, the data register pointer 421 // If we don't assign future to a variable, the data register pointer
@@ -405,6 +423,22 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
405 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) 423 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ)
406 }; 424 };
407 join(tx_transfer, rx_transfer).await; 425 join(tx_transfer, rx_transfer).await;
426
427 // if tx > rx we should clear any overflow of the FIFO SPI buffer
428 if from_len > to_len {
429 let p = self.inner.regs();
430 unsafe {
431 while p.sr().read().bsy() {}
432
433 // clear RX FIFO contents to prevent stale reads
434 while p.sr().read().rne() {
435 let _: u16 = p.dr().read().data();
436 }
437 // clear RX overrun interrupt
438 p.icr().write(|w| w.set_roric(true));
439 }
440 }
441
408 Ok(()) 442 Ok(())
409 } 443 }
410} 444}