rp: fix async SPI read and write
This commit is contained in:
parent
336ebe54c0
commit
ab1a6889a6
2 changed files with 79 additions and 18 deletions
|
@ -56,6 +56,25 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
|
|||
)
|
||||
}
|
||||
|
||||
pub unsafe fn read_repeated<'a, C: Channel, W: Word>(
|
||||
ch: impl Peripheral<P = C> + 'a,
|
||||
from: *const W,
|
||||
len: usize,
|
||||
dreq: u8,
|
||||
) -> Transfer<'a, C> {
|
||||
let mut dummy: u32 = 0;
|
||||
copy_inner(
|
||||
ch,
|
||||
from as *const u32,
|
||||
&mut dummy as *mut u32,
|
||||
len,
|
||||
W::size(),
|
||||
false,
|
||||
false,
|
||||
dreq,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn write<'a, C: Channel, W: Word>(
|
||||
ch: impl Peripheral<P = C> + 'a,
|
||||
from: *const [W],
|
||||
|
@ -75,6 +94,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>(
|
||||
ch: impl Peripheral<P = C> + 'a,
|
||||
from: &[W],
|
||||
|
|
|
@ -325,30 +325,53 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
|||
}
|
||||
|
||||
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
let ch = self.tx_dma.as_mut().unwrap();
|
||||
let transfer = unsafe {
|
||||
self.inner.regs().dmacr().modify(|reg| {
|
||||
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_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::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;
|
||||
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_repeated(
|
||||
rx_ch,
|
||||
self.inner.regs().dr().ptr() as *const u8,
|
||||
buffer.len(),
|
||||
T::RX_DREQ,
|
||||
)
|
||||
};
|
||||
join(tx_transfer, rx_transfer).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
let ch = self.rx_dma.as_mut().unwrap();
|
||||
let transfer = unsafe {
|
||||
self.inner.regs().dmacr().modify(|reg| {
|
||||
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_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(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(())
|
||||
}
|
||||
|
||||
|
@ -364,20 +387,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
|
|||
let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr);
|
||||
let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr);
|
||||
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_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
|
||||
// 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)
|
||||
};
|
||||
let rx_ch = self.rx_dma.as_mut().unwrap();
|
||||
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
|
||||
// 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)
|
||||
|
|
Loading…
Reference in a new issue