Change DMA write/read to use raw pointers

This commit is contained in:
Henrik Alsér 2022-08-31 19:54:38 +02:00 committed by Henrik Alsér
parent 7954cbc4e7
commit 27905f1be1
3 changed files with 39 additions and 18 deletions

View File

@ -40,14 +40,14 @@ pub(crate) unsafe fn init() {
pub unsafe fn read<'a, C: Channel, W: Word>( pub unsafe fn read<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a, ch: impl Peripheral<P = C> + 'a,
from: *const W, from: *const W,
to: &mut [W], to: *mut W,
len: usize,
dreq: u8, dreq: u8,
) -> Transfer<'a, C> { ) -> Transfer<'a, C> {
let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(to);
copy_inner( copy_inner(
ch, ch,
from as *const u32, from as *const u32,
to_ptr as *mut u32, to as *mut u32,
len, len,
W::size(), W::size(),
false, false,
@ -58,14 +58,14 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
pub unsafe fn write<'a, C: Channel, W: Word>( pub unsafe fn write<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a, ch: impl Peripheral<P = C> + 'a,
from: &[W], from: *const W,
to: *mut W, to: *mut W,
len: usize,
dreq: u8, dreq: u8,
) -> Transfer<'a, C> { ) -> Transfer<'a, C> {
let (from_ptr, len) = crate::dma::slice_ptr_parts(from);
copy_inner( copy_inner(
ch, ch,
from_ptr as *const u32, from as *const u32,
to as *mut u32, to as *mut u32,
len, len,
W::size(), W::size(),

View File

@ -285,6 +285,7 @@ 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 (from_ptr, len) = crate::dma::slice_ptr_parts(buffer);
let ch = self.tx_dma.as_mut().unwrap(); let ch = self.tx_dma.as_mut().unwrap();
let transfer = unsafe { let transfer = unsafe {
self.inner.regs().dmacr().modify(|reg| { self.inner.regs().dmacr().modify(|reg| {
@ -292,13 +293,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
}); });
// 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(ch, from_ptr as *const u32, self.inner.regs().dr().ptr() as *mut _, len, T::TX_DREQ)
}; };
transfer.await; transfer.await;
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 (to_ptr, len) = crate::dma::slice_ptr_parts_mut(buffer);
let ch = self.rx_dma.as_mut().unwrap(); let ch = self.rx_dma.as_mut().unwrap();
let transfer = unsafe { let transfer = unsafe {
self.inner.regs().dmacr().modify(|reg| { self.inner.regs().dmacr().modify(|reg| {
@ -306,13 +308,24 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
}); });
// 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::read(ch, self.inner.regs().dr().ptr() as *const _, to_ptr as *mut u32, len, T::RX_DREQ)
}; };
transfer.await; transfer.await;
Ok(()) Ok(())
} }
pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> { pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> {
self.transfer_inner(rx_buffer, tx_buffer).await
}
pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
self.transfer_inner(words, words).await
}
async fn transfer_inner(&mut self, rx_ptr: *mut [u8], tx_ptr: *const [u8]) -> Result<(), Error> {
let (from_ptr, from_len) = crate::dma::slice_ptr_parts(tx_ptr);
let (to_ptr, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr);
assert_eq!(from_len, to_len);
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| { self.inner.regs().dmacr().modify(|reg| {
@ -320,7 +333,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
}); });
// 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_buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) crate::dma::write(
tx_ch,
from_ptr as *const u32,
self.inner.regs().dr().ptr() as *mut _,
from_len,
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 {
@ -329,17 +348,17 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
}); });
// 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_buffer, T::RX_DREQ) crate::dma::read(
rx_ch,
self.inner.regs().dr().ptr() as *const _,
to_ptr as *mut u32,
to_len,
T::RX_DREQ,
)
}; };
join(tx_transfer, rx_transfer).await; join(tx_transfer, rx_transfer).await;
Ok(()) Ok(())
} }
pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
let (ptr, len) = crate::dma::slice_ptr_parts(words);
let tx_buffer = unsafe { core::slice::from_raw_parts(ptr as *const _, len) };
self.transfer(words, tx_buffer).await
}
} }
mod sealed { mod sealed {

View File

@ -120,6 +120,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
impl<'d, T: Instance> UartTx<'d, T, Async> { impl<'d, T: Instance> UartTx<'d, T, Async> {
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let (from_ptr, len) = crate::dma::slice_ptr_parts(buffer);
let ch = self.tx_dma.as_mut().unwrap(); let ch = self.tx_dma.as_mut().unwrap();
let transfer = unsafe { let transfer = unsafe {
T::regs().uartdmacr().modify(|reg| { T::regs().uartdmacr().modify(|reg| {
@ -127,7 +128,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
}); });
// 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, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ) crate::dma::write(ch, from_ptr as *const u32, T::regs().uartdr().ptr() as *mut _, len, T::TX_DREQ)
}; };
transfer.await; transfer.await;
Ok(()) Ok(())
@ -173,6 +174,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
impl<'d, T: Instance> UartRx<'d, T, Async> { impl<'d, T: Instance> UartRx<'d, T, Async> {
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(buffer);
let ch = self.rx_dma.as_mut().unwrap(); let ch = self.rx_dma.as_mut().unwrap();
let transfer = unsafe { let transfer = unsafe {
T::regs().uartdmacr().modify(|reg| { T::regs().uartdmacr().modify(|reg| {
@ -180,7 +182,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
}); });
// 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, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, to_ptr as *mut u32, len, T::RX_DREQ)
}; };
transfer.await; transfer.await;
Ok(()) Ok(())