aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Martens <[email protected]>2022-09-18 12:02:05 -0700
committerAlex Martens <[email protected]>2022-09-18 12:02:05 -0700
commitab1a6889a62e86a80af6fc572ffa992cfb9ef960 (patch)
tree4486533bbb111191b91fce46915d094e6df06755
parent336ebe54c0f32fd729d50889850032222c6c6ca4 (diff)
rp: fix async SPI read and write
-rw-r--r--embassy-rp/src/dma.rs38
-rw-r--r--embassy-rp/src/spi.rs59
2 files changed, 79 insertions, 18 deletions
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index acf338225..b256cc2f0 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -56,6 +56,25 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
56 ) 56 )
57} 57}
58 58
59pub unsafe fn read_repeated<'a, C: Channel, W: Word>(
60 ch: impl Peripheral<P = C> + 'a,
61 from: *const W,
62 len: usize,
63 dreq: u8,
64) -> Transfer<'a, C> {
65 let mut dummy: u32 = 0;
66 copy_inner(
67 ch,
68 from as *const u32,
69 &mut dummy as *mut u32,
70 len,
71 W::size(),
72 false,
73 false,
74 dreq,
75 )
76}
77
59pub unsafe fn write<'a, C: Channel, W: Word>( 78pub unsafe fn write<'a, C: Channel, W: Word>(
60 ch: impl Peripheral<P = C> + 'a, 79 ch: impl Peripheral<P = C> + 'a,
61 from: *const [W], 80 from: *const [W],
@@ -75,6 +94,25 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
75 ) 94 )
76} 95}
77 96
97pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
98 ch: impl Peripheral<P = C> + 'a,
99 to: *mut W,
100 len: usize,
101 dreq: u8,
102) -> Transfer<'a, C> {
103 let dummy: u32 = 0;
104 copy_inner(
105 ch,
106 &dummy as *const u32,
107 to as *mut u32,
108 len,
109 W::size(),
110 false,
111 false,
112 dreq,
113 )
114}
115
78pub unsafe fn copy<'a, C: Channel, W: Word>( 116pub unsafe fn copy<'a, C: Channel, W: Word>(
79 ch: impl Peripheral<P = C> + 'a, 117 ch: impl Peripheral<P = C> + 'a,
80 from: &[W], 118 from: &[W],
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 74f0b04de..e7cd99929 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -325,30 +325,53 @@ 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 unsafe {
329 let transfer = unsafe { 329 self.inner.regs().dmacr().write(|reg| {
330 self.inner.regs().dmacr().modify(|reg| { 330 reg.set_rxdmae(true);
331 reg.set_txdmae(true); 331 reg.set_txdmae(true);
332 }); 332 })
333 };
334 let tx_ch = self.tx_dma.as_mut().unwrap();
335 let tx_transfer = unsafe {
336 // If we don't assign future to a variable, the data register pointer
337 // is held across an await and makes the future non-Send.
338 crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ)
339 };
340 let rx_ch = self.rx_dma.as_mut().unwrap();
341 let rx_transfer = unsafe {
333 // If we don't assign future to a variable, the data register pointer 342 // 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. 343 // 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) 344 crate::dma::read_repeated(
345 rx_ch,
346 self.inner.regs().dr().ptr() as *const u8,
347 buffer.len(),
348 T::RX_DREQ,
349 )
336 }; 350 };
337 transfer.await; 351 join(tx_transfer, rx_transfer).await;
338 Ok(()) 352 Ok(())
339 } 353 }
340 354
341 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 355 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
342 let ch = self.rx_dma.as_mut().unwrap(); 356 unsafe {
343 let transfer = unsafe { 357 self.inner.regs().dmacr().write(|reg| {
344 self.inner.regs().dmacr().modify(|reg| {
345 reg.set_rxdmae(true); 358 reg.set_rxdmae(true);
346 }); 359 reg.set_txdmae(true);
360 })
361 };
362 let tx_ch = self.tx_dma.as_mut().unwrap();
363 let tx_transfer = unsafe {
364 // If we don't assign future to a variable, the data register pointer
365 // is held across an await and makes the future non-Send.
366 crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ)
367 };
368 let rx_ch = self.rx_dma.as_mut().unwrap();
369 let rx_transfer = unsafe {
347 // If we don't assign future to a variable, the data register pointer 370 // 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. 371 // 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) 372 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ)
350 }; 373 };
351 transfer.await; 374 join(tx_transfer, rx_transfer).await;
352 Ok(()) 375 Ok(())
353 } 376 }
354 377
@@ -364,20 +387,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
364 let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); 387 let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr);
365 let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); 388 let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr);
366 assert_eq!(from_len, to_len); 389 assert_eq!(from_len, to_len);
390 unsafe {
391 self.inner.regs().dmacr().write(|reg| {
392 reg.set_rxdmae(true);
393 reg.set_txdmae(true);
394 })
395 };
367 let tx_ch = self.tx_dma.as_mut().unwrap(); 396 let tx_ch = self.tx_dma.as_mut().unwrap();
368 let tx_transfer = unsafe { 397 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 398 // 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. 399 // 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) 400 crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ)
375 }; 401 };
376 let rx_ch = self.rx_dma.as_mut().unwrap(); 402 let rx_ch = self.rx_dma.as_mut().unwrap();
377 let rx_transfer = unsafe { 403 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 404 // 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. 405 // 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) 406 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ)