diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-09-19 07:26:10 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-09-19 07:26:10 +0000 |
| commit | 66633902240a70eaf7b2bc6db285884ccdd8182f (patch) | |
| tree | 994ec6a95fb6ae0f50b2c307454bf362721a7d54 | |
| parent | ac13675f3a6f30e09baeb9ec604d300b84b0db49 (diff) | |
| parent | 295cc997ae8b1468617dd9f430be4e502901f4f2 (diff) | |
Merge #954
954: rp: fix async SPI read and write r=lulf a=newAM
Closes #953
Co-authored-by: Alex Martens <[email protected]>
| -rw-r--r-- | embassy-rp/src/dma.rs | 19 | ||||
| -rw-r--r-- | embassy-rp/src/spi.rs | 54 |
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 | ||
| 78 | pub 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 | |||
| 78 | pub unsafe fn copy<'a, C: Channel, W: Word>( | 97 | pub 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) |
