diff options
| author | Mathias <[email protected]> | 2022-08-18 21:09:50 +0200 |
|---|---|---|
| committer | Mathias <[email protected]> | 2022-08-18 21:09:50 +0200 |
| commit | 1d49b3444f2bd3e049f19a72da63804192ee0402 (patch) | |
| tree | 731b8c8c67570382d32596271464c21799732553 | |
| parent | a7d6bc7ba5faef3d711b944baf6c8e3685fdb37e (diff) | |
Add DMA read + write functions
| -rw-r--r-- | embassy-rp/src/dma.rs | 48 | ||||
| -rw-r--r-- | 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}; | |||
| 5 | use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; | 5 | use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; |
| 6 | use embassy_util::waitqueue::AtomicWaker; | 6 | use embassy_util::waitqueue::AtomicWaker; |
| 7 | use futures::Future; | 7 | use futures::Future; |
| 8 | use pac::dma::vals::DataSize; | ||
| 8 | 9 | ||
| 9 | use crate::pac::dma::vals; | 10 | use crate::pac::dma::vals; |
| 10 | use crate::{pac, peripherals}; | 11 | use crate::{pac, peripherals}; |
| 11 | 12 | ||
| 12 | pub fn copy<'a, C: Channel, W: Word>(ch: impl Peripheral<P = C> + 'a, from: &[W], to: &mut [W]) -> Transfer<'a, C> { | 13 | pub(crate) fn read<'a, C: Channel, W: Word>(ch: impl Peripheral<P = C> + 'a, from: *const W, to: *mut [W]) -> Transfer<'a, C> { |
| 13 | assert!(from.len() == to.len()); | 14 | let (ptr, len) = crate::dma::slice_ptr_parts_mut(to); |
| 15 | copy(ch, from as *const u32, ptr as *mut u32, len, W::size()) | ||
| 16 | } | ||
| 17 | |||
| 18 | pub(crate) fn write<'a, C: Channel, W: Word>( | ||
| 19 | ch: impl Peripheral<P = C> + 'a, | ||
| 20 | from: *const [W], | ||
| 21 | to: *mut W, | ||
| 22 | ) -> Transfer<'a, C> { | ||
| 23 | let (from_ptr, len) = crate::dma::slice_ptr_parts(from); | ||
| 24 | copy(ch, from_ptr as *const u32, to as *mut u32, len, W::size()) | ||
| 25 | } | ||
| 14 | 26 | ||
| 27 | fn copy<'a, C: Channel>( | ||
| 28 | ch: impl Peripheral<P = C> + 'a, | ||
| 29 | from: *const u32, | ||
| 30 | to: *mut u32, | ||
| 31 | len: usize, | ||
| 32 | data_size: DataSize, | ||
| 33 | ) -> Transfer<'a, C> { | ||
| 15 | into_ref!(ch); | 34 | into_ref!(ch); |
| 16 | 35 | ||
| 17 | unsafe { | 36 | unsafe { |
| 18 | let p = ch.regs(); | 37 | let p = ch.regs(); |
| 19 | 38 | ||
| 20 | p.read_addr().write_value(from.as_ptr() as u32); | 39 | p.read_addr().write_value(from as u32); |
| 21 | p.write_addr().write_value(to.as_mut_ptr() as u32); | 40 | p.write_addr().write_value(to as u32); |
| 22 | p.trans_count().write_value(from.len() as u32); | 41 | p.trans_count().write_value(len as u32); |
| 23 | 42 | ||
| 24 | compiler_fence(Ordering::SeqCst); | 43 | compiler_fence(Ordering::SeqCst); |
| 25 | 44 | ||
| 26 | p.ctrl_trig().write(|w| { | 45 | p.ctrl_trig().write(|w| { |
| 27 | w.set_data_size(W::size()); | 46 | w.set_data_size(data_size); |
| 28 | w.set_incr_read(true); | 47 | w.set_incr_read(true); |
| 29 | w.set_incr_write(true); | 48 | w.set_incr_write(true); |
| 30 | w.set_chain_to(ch.number()); | 49 | w.set_chain_to(ch.number()); |
| @@ -60,7 +79,7 @@ impl<'a, C: Channel> Drop for Transfer<'a, C> { | |||
| 60 | impl<'a, C: Channel> Unpin for Transfer<'a, C> {} | 79 | impl<'a, C: Channel> Unpin for Transfer<'a, C> {} |
| 61 | impl<'a, C: Channel> Future for Transfer<'a, C> { | 80 | impl<'a, C: Channel> Future for Transfer<'a, C> { |
| 62 | type Output = (); | 81 | type Output = (); |
| 63 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | 82 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 64 | self.channel.set_waker(cx.waker()); | 83 | self.channel.set_waker(cx.waker()); |
| 65 | 84 | ||
| 66 | if self.channel.is_running() { | 85 | if self.channel.is_running() { |
| @@ -110,13 +129,15 @@ pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + S | |||
| 110 | } | 129 | } |
| 111 | 130 | ||
| 112 | fn is_running(&self) -> bool { | 131 | fn is_running(&self) -> bool { |
| 113 | self.regs().ctrl_trig().read().en() | 132 | unsafe { self.regs().ctrl_trig().read().en() } |
| 114 | } | 133 | } |
| 115 | 134 | ||
| 116 | fn set_waker(&self, waker: &Waker) { | 135 | fn set_waker(&self, waker: &Waker) { |
| 117 | STATE.channels[self.number() as usize].waker.register(waker); | 136 | STATE.channels[self.number() as usize].waker.register(waker); |
| 118 | } | 137 | } |
| 119 | 138 | ||
| 139 | fn on_irq() {} | ||
| 140 | |||
| 120 | fn degrade(self) -> AnyChannel { | 141 | fn degrade(self) -> AnyChannel { |
| 121 | AnyChannel { number: self.number() } | 142 | AnyChannel { number: self.number() } |
| 122 | } | 143 | } |
| @@ -177,6 +198,17 @@ macro_rules! channel { | |||
| 177 | }; | 198 | }; |
| 178 | } | 199 | } |
| 179 | 200 | ||
| 201 | // TODO: replace transmutes with core::ptr::metadata once it's stable | ||
| 202 | #[allow(unused)] | ||
| 203 | pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) { | ||
| 204 | unsafe { core::mem::transmute(slice) } | ||
| 205 | } | ||
| 206 | |||
| 207 | #[allow(unused)] | ||
| 208 | pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) { | ||
| 209 | unsafe { core::mem::transmute(slice) } | ||
| 210 | } | ||
| 211 | |||
| 180 | channel!(DMA_CH0, 0); | 212 | channel!(DMA_CH0, 0); |
| 181 | channel!(DMA_CH1, 1); | 213 | channel!(DMA_CH1, 1); |
| 182 | channel!(DMA_CH2, 2); | 214 | 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> { | |||
| 128 | } | 128 | } |
| 129 | // If we don't assign future to a variable, the data register pointer | 129 | // If we don't assign future to a variable, the data register pointer |
| 130 | // is held across an await and makes the future non-Send. | 130 | // is held across an await and makes the future non-Send. |
| 131 | let transfer = crate::dma::copy(ch, buffer, unsafe { T::regs().uartdr().ptr() }); | 131 | let transfer = crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _); |
| 132 | transfer.await; | 132 | transfer.await; |
| 133 | } | 133 | } |
| 134 | Ok(()) | 134 | Ok(()) |
| @@ -178,7 +178,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { | |||
| 178 | } | 178 | } |
| 179 | // If we don't assign future to a variable, the data register pointer | 179 | // If we don't assign future to a variable, the data register pointer |
| 180 | // is held across an await and makes the future non-Send. | 180 | // is held across an await and makes the future non-Send. |
| 181 | let transfer = crate::dma::copy(ch, unsafe { T::regs().uartdr().ptr() }, buffer); | 181 | let transfer = crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer); |
| 182 | transfer.await; | 182 | transfer.await; |
| 183 | } | 183 | } |
| 184 | Ok(()) | 184 | Ok(()) |
