From 1d49b3444f2bd3e049f19a72da63804192ee0402 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 18 Aug 2022 21:09:50 +0200 Subject: [PATCH] Add DMA read + write functions --- embassy-rp/src/dma.rs | 48 +++++++++++++++++++++++++++++++++++------- embassy-rp/src/uart.rs | 4 ++-- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 531ed8020..cfaa6dd34 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -5,26 +5,45 @@ use core::task::{Context, Poll, Waker}; use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; use embassy_util::waitqueue::AtomicWaker; use futures::Future; +use pac::dma::vals::DataSize; use crate::pac::dma::vals; use crate::{pac, peripherals}; -pub fn copy<'a, C: Channel, W: Word>(ch: impl Peripheral

+ 'a, from: &[W], to: &mut [W]) -> Transfer<'a, C> { - assert!(from.len() == to.len()); +pub(crate) fn read<'a, C: Channel, W: Word>(ch: impl Peripheral

+ 'a, from: *const W, to: *mut [W]) -> Transfer<'a, C> { + let (ptr, len) = crate::dma::slice_ptr_parts_mut(to); + copy(ch, from as *const u32, ptr as *mut u32, len, W::size()) +} +pub(crate) fn write<'a, C: Channel, W: Word>( + ch: impl Peripheral

+ 'a, + from: *const [W], + to: *mut W, +) -> Transfer<'a, C> { + let (from_ptr, len) = crate::dma::slice_ptr_parts(from); + copy(ch, from_ptr as *const u32, to as *mut u32, len, W::size()) +} + +fn copy<'a, C: Channel>( + ch: impl Peripheral

+ 'a, + from: *const u32, + to: *mut u32, + len: usize, + data_size: DataSize, +) -> Transfer<'a, C> { into_ref!(ch); unsafe { let p = ch.regs(); - p.read_addr().write_value(from.as_ptr() as u32); - p.write_addr().write_value(to.as_mut_ptr() as u32); - p.trans_count().write_value(from.len() as u32); + p.read_addr().write_value(from as u32); + p.write_addr().write_value(to as u32); + p.trans_count().write_value(len as u32); compiler_fence(Ordering::SeqCst); p.ctrl_trig().write(|w| { - w.set_data_size(W::size()); + w.set_data_size(data_size); w.set_incr_read(true); w.set_incr_write(true); w.set_chain_to(ch.number()); @@ -60,7 +79,7 @@ impl<'a, C: Channel> Drop for Transfer<'a, C> { impl<'a, C: Channel> Unpin for Transfer<'a, C> {} impl<'a, C: Channel> Future for Transfer<'a, C> { type Output = (); - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.channel.set_waker(cx.waker()); if self.channel.is_running() { @@ -110,13 +129,15 @@ pub trait Channel: Peripheral

+ sealed::Channel + Into + S } fn is_running(&self) -> bool { - self.regs().ctrl_trig().read().en() + unsafe { self.regs().ctrl_trig().read().en() } } fn set_waker(&self, waker: &Waker) { STATE.channels[self.number() as usize].waker.register(waker); } + fn on_irq() {} + fn degrade(self) -> AnyChannel { AnyChannel { number: self.number() } } @@ -177,6 +198,17 @@ macro_rules! channel { }; } +// TODO: replace transmutes with core::ptr::metadata once it's stable +#[allow(unused)] +pub(crate) fn slice_ptr_parts(slice: *const [T]) -> (usize, usize) { + unsafe { core::mem::transmute(slice) } +} + +#[allow(unused)] +pub(crate) fn slice_ptr_parts_mut(slice: *mut [T]) -> (usize, usize) { + unsafe { core::mem::transmute(slice) } +} + channel!(DMA_CH0, 0); channel!(DMA_CH1, 1); channel!(DMA_CH2, 2); diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs index c1596960f..09cadf030 100644 --- a/embassy-rp/src/uart.rs +++ b/embassy-rp/src/uart.rs @@ -128,7 +128,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> { } // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - let transfer = crate::dma::copy(ch, buffer, unsafe { T::regs().uartdr().ptr() }); + let transfer = crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _); transfer.await; } Ok(()) @@ -178,7 +178,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { } // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - let transfer = crate::dma::copy(ch, unsafe { T::regs().uartdr().ptr() }, buffer); + let transfer = crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer); transfer.await; } Ok(())