diff options
| author | Lachezar Lechev <[email protected]> | 2023-03-20 16:34:30 +0200 |
|---|---|---|
| committer | Lachezar Lechev <[email protected]> | 2023-03-20 16:34:30 +0200 |
| commit | 7a4db1da2641c785f5fd9d2365df2a213f3aaade (patch) | |
| tree | 2b65b047a5aa6c151b5ce886245c3295506ada7e /embassy-rp/src | |
| parent | b6663a013f8632cefbc6d6ab9a9aa7afbcd1314b (diff) | |
fix(rp): spi transfer
Signed-off-by: Lachezar Lechev <[email protected]>
Diffstat (limited to 'embassy-rp/src')
| -rw-r--r-- | embassy-rp/src/dma.rs | 1 | ||||
| -rw-r--r-- | embassy-rp/src/spi.rs | 46 |
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) | ||
| 1 | use core::future::Future; | 2 | use core::future::Future; |
| 2 | use core::pin::Pin; | 3 | use core::pin::Pin; |
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use 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 | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | 3 | ||
| 3 | use embassy_embedded_hal::SetConfig; | 4 | use 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 | } |
