aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-08-18 21:09:50 +0200
committerMathias <[email protected]>2022-08-18 21:09:50 +0200
commit1d49b3444f2bd3e049f19a72da63804192ee0402 (patch)
tree731b8c8c67570382d32596271464c21799732553
parenta7d6bc7ba5faef3d711b944baf6c8e3685fdb37e (diff)
Add DMA read + write functions
-rw-r--r--embassy-rp/src/dma.rs48
-rw-r--r--embassy-rp/src/uart.rs4
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};
5use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; 5use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
6use embassy_util::waitqueue::AtomicWaker; 6use embassy_util::waitqueue::AtomicWaker;
7use futures::Future; 7use futures::Future;
8use pac::dma::vals::DataSize;
8 9
9use crate::pac::dma::vals; 10use crate::pac::dma::vals;
10use crate::{pac, peripherals}; 11use crate::{pac, peripherals};
11 12
12pub fn copy<'a, C: Channel, W: Word>(ch: impl Peripheral<P = C> + 'a, from: &[W], to: &mut [W]) -> Transfer<'a, C> { 13pub(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
18pub(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
27fn 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> {
60impl<'a, C: Channel> Unpin for Transfer<'a, C> {} 79impl<'a, C: Channel> Unpin for Transfer<'a, C> {}
61impl<'a, C: Channel> Future for Transfer<'a, C> { 80impl<'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)]
203pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) {
204 unsafe { core::mem::transmute(slice) }
205}
206
207#[allow(unused)]
208pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
209 unsafe { core::mem::transmute(slice) }
210}
211
180channel!(DMA_CH0, 0); 212channel!(DMA_CH0, 0);
181channel!(DMA_CH1, 1); 213channel!(DMA_CH1, 1);
182channel!(DMA_CH2, 2); 214channel!(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(())