aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/dma.rs19
-rw-r--r--embassy-rp/src/spi.rs54
2 files changed, 57 insertions, 16 deletions
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index acf338225..7ad1a6bfe 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -75,6 +75,25 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
75 ) 75 )
76} 76}
77 77
78pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
79 ch: impl Peripheral<P = C> + 'a,
80 to: *mut W,
81 len: usize,
82 dreq: u8,
83) -> Transfer<'a, C> {
84 let dummy: u32 = 0;
85 copy_inner(
86 ch,
87 &dummy as *const u32,
88 to as *mut u32,
89 len,
90 W::size(),
91 false,
92 false,
93 dreq,
94 )
95}
96
78pub unsafe fn copy<'a, C: Channel, W: Word>( 97pub unsafe fn copy<'a, C: Channel, W: Word>(
79 ch: impl Peripheral<P = C> + 'a, 98 ch: impl Peripheral<P = C> + 'a,
80 from: &[W], 99 from: &[W],
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 74f0b04de..3cf823573 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -325,30 +325,52 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
325 } 325 }
326 326
327 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 327 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
328 let ch = self.tx_dma.as_mut().unwrap(); 328 let tx_ch = self.tx_dma.as_mut().unwrap();
329 let transfer = unsafe { 329 let tx_transfer = unsafe {
330 self.inner.regs().dmacr().modify(|reg| { 330 self.inner.regs().dmacr().modify(|reg| {
331 reg.set_txdmae(true); 331 reg.set_txdmae(true);
332 }); 332 });
333 // If we don't assign future to a variable, the data register pointer 333 // If we don't assign future to a variable, the data register pointer
334 // is held across an await and makes the future non-Send. 334 // is held across an await and makes the future non-Send.
335 crate::dma::write(ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) 335 crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ)
336 }; 336 };
337 transfer.await; 337 tx_transfer.await;
338
339 let p = self.inner.regs();
340 unsafe {
341 while p.sr().read().bsy() {}
342
343 // clear RX FIFO contents to prevent stale reads
344 while p.sr().read().rne() {
345 let _: u16 = p.dr().read().data();
346 }
347 // clear RX overrun interrupt
348 p.icr().write(|w| w.set_roric(true));
349 }
350
338 Ok(()) 351 Ok(())
339 } 352 }
340 353
341 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 354 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
342 let ch = self.rx_dma.as_mut().unwrap(); 355 unsafe {
343 let transfer = unsafe { 356 self.inner.regs().dmacr().write(|reg| {
344 self.inner.regs().dmacr().modify(|reg| {
345 reg.set_rxdmae(true); 357 reg.set_rxdmae(true);
346 }); 358 reg.set_txdmae(true);
359 })
360 };
361 let tx_ch = self.tx_dma.as_mut().unwrap();
362 let tx_transfer = unsafe {
347 // If we don't assign future to a variable, the data register pointer 363 // If we don't assign future to a variable, the data register pointer
348 // is held across an await and makes the future non-Send. 364 // is held across an await and makes the future non-Send.
349 crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) 365 crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ)
350 }; 366 };
351 transfer.await; 367 let rx_ch = self.rx_dma.as_mut().unwrap();
368 let rx_transfer = unsafe {
369 // If we don't assign future to a variable, the data register pointer
370 // is held across an await and makes the future non-Send.
371 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ)
372 };
373 join(tx_transfer, rx_transfer).await;
352 Ok(()) 374 Ok(())
353 } 375 }
354 376
@@ -364,20 +386,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
364 let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); 386 let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr);
365 let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); 387 let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr);
366 assert_eq!(from_len, to_len); 388 assert_eq!(from_len, to_len);
389 unsafe {
390 self.inner.regs().dmacr().write(|reg| {
391 reg.set_rxdmae(true);
392 reg.set_txdmae(true);
393 })
394 };
367 let tx_ch = self.tx_dma.as_mut().unwrap(); 395 let tx_ch = self.tx_dma.as_mut().unwrap();
368 let tx_transfer = unsafe { 396 let tx_transfer = unsafe {
369 self.inner.regs().dmacr().modify(|reg| {
370 reg.set_txdmae(true);
371 });
372 // If we don't assign future to a variable, the data register pointer 397 // If we don't assign future to a variable, the data register pointer
373 // is held across an await and makes the future non-Send. 398 // is held across an await and makes the future non-Send.
374 crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) 399 crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ)
375 }; 400 };
376 let rx_ch = self.rx_dma.as_mut().unwrap(); 401 let rx_ch = self.rx_dma.as_mut().unwrap();
377 let rx_transfer = unsafe { 402 let rx_transfer = unsafe {
378 self.inner.regs().dmacr().modify(|reg| {
379 reg.set_rxdmae(true);
380 });
381 // If we don't assign future to a variable, the data register pointer 403 // If we don't assign future to a variable, the data register pointer
382 // is held across an await and makes the future non-Send. 404 // is held across an await and makes the future non-Send.
383 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) 405 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ)