Merge #954
954: rp: fix async SPI read and write r=lulf a=newAM Closes #953 Co-authored-by: Alex Martens <alex@thinglab.org>
This commit is contained in:
		
						commit
						6663390224
					
				| @ -75,6 +75,25 @@ pub unsafe fn write<'a, C: Channel, W: Word>( | |||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub unsafe fn write_repeated<'a, C: Channel, W: Word>( | ||||||
|  |     ch: impl Peripheral<P = C> + 'a, | ||||||
|  |     to: *mut W, | ||||||
|  |     len: usize, | ||||||
|  |     dreq: u8, | ||||||
|  | ) -> Transfer<'a, C> { | ||||||
|  |     let dummy: u32 = 0; | ||||||
|  |     copy_inner( | ||||||
|  |         ch, | ||||||
|  |         &dummy as *const u32, | ||||||
|  |         to as *mut u32, | ||||||
|  |         len, | ||||||
|  |         W::size(), | ||||||
|  |         false, | ||||||
|  |         false, | ||||||
|  |         dreq, | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub unsafe fn copy<'a, C: Channel, W: Word>( | pub unsafe fn copy<'a, C: Channel, W: Word>( | ||||||
|     ch: impl Peripheral<P = C> + 'a, |     ch: impl Peripheral<P = C> + 'a, | ||||||
|     from: &[W], |     from: &[W], | ||||||
|  | |||||||
| @ -325,30 +325,52 @@ impl<'d, T: Instance> Spi<'d, T, Async> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |     pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { | ||||||
|         let ch = self.tx_dma.as_mut().unwrap(); |         let tx_ch = self.tx_dma.as_mut().unwrap(); | ||||||
|         let transfer = unsafe { |         let tx_transfer = unsafe { | ||||||
|             self.inner.regs().dmacr().modify(|reg| { |             self.inner.regs().dmacr().modify(|reg| { | ||||||
|                 reg.set_txdmae(true); |                 reg.set_txdmae(true); | ||||||
|             }); |             }); | ||||||
|             // If we don't assign future to a variable, the data register pointer
 |             // If we don't assign future to a variable, the data register pointer
 | ||||||
|             // is held across an await and makes the future non-Send.
 |             // is held across an await and makes the future non-Send.
 | ||||||
|             crate::dma::write(ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) |             crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) | ||||||
|         }; |         }; | ||||||
|         transfer.await; |         tx_transfer.await; | ||||||
|  | 
 | ||||||
|  |         let p = self.inner.regs(); | ||||||
|  |         unsafe { | ||||||
|  |             while p.sr().read().bsy() {} | ||||||
|  | 
 | ||||||
|  |             // clear RX FIFO contents to prevent stale reads
 | ||||||
|  |             while p.sr().read().rne() { | ||||||
|  |                 let _: u16 = p.dr().read().data(); | ||||||
|  |             } | ||||||
|  |             // clear RX overrun interrupt
 | ||||||
|  |             p.icr().write(|w| w.set_roric(true)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |     pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||||||
|         let ch = self.rx_dma.as_mut().unwrap(); |         unsafe { | ||||||
|         let transfer = unsafe { |             self.inner.regs().dmacr().write(|reg| { | ||||||
|             self.inner.regs().dmacr().modify(|reg| { |  | ||||||
|                 reg.set_rxdmae(true); |                 reg.set_rxdmae(true); | ||||||
|             }); |                 reg.set_txdmae(true); | ||||||
|  |             }) | ||||||
|  |         }; | ||||||
|  |         let tx_ch = self.tx_dma.as_mut().unwrap(); | ||||||
|  |         let tx_transfer = unsafe { | ||||||
|             // If we don't assign future to a variable, the data register pointer
 |             // If we don't assign future to a variable, the data register pointer
 | ||||||
|             // is held across an await and makes the future non-Send.
 |             // is held across an await and makes the future non-Send.
 | ||||||
|             crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) |             crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ) | ||||||
|         }; |         }; | ||||||
|         transfer.await; |         let rx_ch = self.rx_dma.as_mut().unwrap(); | ||||||
|  |         let rx_transfer = unsafe { | ||||||
|  |             // If we don't assign future to a variable, the data register pointer
 | ||||||
|  |             // is held across an await and makes the future non-Send.
 | ||||||
|  |             crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) | ||||||
|  |         }; | ||||||
|  |         join(tx_transfer, rx_transfer).await; | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -364,20 +386,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> { | |||||||
|         let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); |         let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); | ||||||
|         let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); |         let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); | ||||||
|         assert_eq!(from_len, to_len); |         assert_eq!(from_len, to_len); | ||||||
|  |         unsafe { | ||||||
|  |             self.inner.regs().dmacr().write(|reg| { | ||||||
|  |                 reg.set_rxdmae(true); | ||||||
|  |                 reg.set_txdmae(true); | ||||||
|  |             }) | ||||||
|  |         }; | ||||||
|         let tx_ch = self.tx_dma.as_mut().unwrap(); |         let tx_ch = self.tx_dma.as_mut().unwrap(); | ||||||
|         let tx_transfer = unsafe { |         let tx_transfer = unsafe { | ||||||
|             self.inner.regs().dmacr().modify(|reg| { |  | ||||||
|                 reg.set_txdmae(true); |  | ||||||
|             }); |  | ||||||
|             // If we don't assign future to a variable, the data register pointer
 |             // If we don't assign future to a variable, the data register pointer
 | ||||||
|             // is held across an await and makes the future non-Send.
 |             // is held across an await and makes the future non-Send.
 | ||||||
|             crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) |             crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) | ||||||
|         }; |         }; | ||||||
|         let rx_ch = self.rx_dma.as_mut().unwrap(); |         let rx_ch = self.rx_dma.as_mut().unwrap(); | ||||||
|         let rx_transfer = unsafe { |         let rx_transfer = unsafe { | ||||||
|             self.inner.regs().dmacr().modify(|reg| { |  | ||||||
|                 reg.set_rxdmae(true); |  | ||||||
|             }); |  | ||||||
|             // If we don't assign future to a variable, the data register pointer
 |             // If we don't assign future to a variable, the data register pointer
 | ||||||
|             // is held across an await and makes the future non-Send.
 |             // is held across an await and makes the future non-Send.
 | ||||||
|             crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) |             crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user