aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-08-18 19:39:13 +0200
committerMathias <[email protected]>2022-08-18 19:39:13 +0200
commitd35a1c9790e32477aac2fd6abe38a8c76263fcc8 (patch)
tree8889211d1d33bf75083e7863fc48b4d7bd1b6982
parent0f74f870b00942a3020a32d44470edf80870676c (diff)
Preliminary DMA support for RP2040
-rw-r--r--embassy-rp/src/dma.rs139
-rw-r--r--embassy-rp/src/uart.rs195
2 files changed, 257 insertions, 77 deletions
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 42c4fd13e..dfa047a2f 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -1,39 +1,71 @@
1use core::pin::Pin;
1use core::sync::atomic::{compiler_fence, Ordering}; 2use core::sync::atomic::{compiler_fence, Ordering};
3use core::task::{Context, Poll};
2 4
3use embassy_hal_common::impl_peripheral; 5use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
6use futures::Future;
4 7
5use crate::pac::dma::vals; 8use crate::pac::dma::vals;
6use crate::{pac, peripherals}; 9use crate::{pac, peripherals};
7 10
8pub struct Dma<T: Channel> { 11pub fn copy<'a, C: Channel, W: Word>(ch: impl Peripheral<P = C> + 'a, from: &[W], to: &mut [W]) -> Transfer<'a, C> {
9 _inner: T, 12 assert!(from.len() == to.len());
10}
11 13
12impl<T: Channel> Dma<T> { 14 into_ref!(ch);
13 pub fn copy(inner: T, from: &[u32], to: &mut [u32]) {
14 assert!(from.len() == to.len());
15 15
16 unsafe { 16 unsafe {
17 let p = inner.regs(); 17 let p = ch.regs();
18 18
19 p.read_addr().write_value(from.as_ptr() as u32); 19 p.read_addr().write_value(from.as_ptr() as u32);
20 p.write_addr().write_value(to.as_mut_ptr() as u32); 20 p.write_addr().write_value(to.as_mut_ptr() as u32);
21 p.trans_count().write_value(from.len() as u32); 21 p.trans_count().write_value(from.len() as u32);
22 22
23 compiler_fence(Ordering::SeqCst); 23 compiler_fence(Ordering::SeqCst);
24 24
25 p.ctrl_trig().write(|w| { 25 p.ctrl_trig().write(|w| {
26 w.set_data_size(vals::DataSize::SIZE_WORD); 26 w.set_data_size(W::size());
27 w.set_incr_read(true); 27 w.set_incr_read(true);
28 w.set_incr_write(true); 28 w.set_incr_write(true);
29 w.set_chain_to(inner.number()); 29 w.set_chain_to(ch.number());
30 w.set_en(true); 30 w.set_en(true);
31 }); 31 });
32 32
33 while p.ctrl_trig().read().busy() {} 33 // FIXME:
34 while p.ctrl_trig().read().busy() {}
34 35
35 compiler_fence(Ordering::SeqCst); 36 compiler_fence(Ordering::SeqCst);
36 } 37 }
38 Transfer::new(ch)
39}
40
41pub(crate) struct Transfer<'a, C: Channel> {
42 channel: PeripheralRef<'a, C>,
43}
44
45impl<'a, C: Channel> Transfer<'a, C> {
46 pub(crate) fn new(channel: impl Peripheral<P = C> + 'a) -> Self {
47 into_ref!(channel);
48 Self { channel }
49 }
50}
51
52impl<'a, C: Channel> Drop for Transfer<'a, C> {
53 fn drop(&mut self) {
54 // self.channel.request_stop();
55 // while self.channel.is_running() {}
56 }
57}
58
59impl<'a, C: Channel> Unpin for Transfer<'a, C> {}
60impl<'a, C: Channel> Future for Transfer<'a, C> {
61 type Output = ();
62 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
63 // self.channel.set_waker(cx.waker());
64 // if self.channel.is_running() {
65 // Poll::Pending
66 // } else {
67 Poll::Ready(())
68 // }
37 } 69 }
38} 70}
39 71
@@ -42,38 +74,77 @@ pub struct NoDma;
42impl_peripheral!(NoDma); 74impl_peripheral!(NoDma);
43 75
44mod sealed { 76mod sealed {
45 use super::*; 77 pub trait Channel {}
78
79 pub trait Word {}
80}
46 81
47 pub trait Channel { 82pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static {
48 fn number(&self) -> u8; 83 fn number(&self) -> u8;
49 84
50 fn regs(&self) -> pac::dma::Channel { 85 fn regs(&self) -> pac::dma::Channel {
51 pac::DMA.ch(self.number() as _) 86 pac::DMA.ch(self.number() as _)
87 }
88
89 fn degrade(self) -> AnyChannel {
90 AnyChannel {
91 number: self.number(),
52 } 92 }
53 } 93 }
54} 94}
55 95
56pub trait Channel: sealed::Channel {} 96pub trait Word: sealed::Word {
97 fn size() -> vals::DataSize;
98}
99
100impl sealed::Word for u8 {}
101impl Word for u8 {
102 fn size() -> vals::DataSize {
103 vals::DataSize::SIZE_BYTE
104 }
105}
106
107impl sealed::Word for u16 {}
108impl Word for u16 {
109 fn size() -> vals::DataSize {
110 vals::DataSize::SIZE_HALFWORD
111 }
112}
113
114impl sealed::Word for u32 {}
115impl Word for u32 {
116 fn size() -> vals::DataSize {
117 vals::DataSize::SIZE_WORD
118 }
119}
57 120
58pub struct AnyChannel { 121pub struct AnyChannel {
59 number: u8, 122 number: u8,
60} 123}
61 124
62impl Channel for AnyChannel {} 125impl_peripheral!(AnyChannel);
63impl sealed::Channel for AnyChannel { 126
127impl sealed::Channel for AnyChannel {}
128impl Channel for AnyChannel {
64 fn number(&self) -> u8 { 129 fn number(&self) -> u8 {
65 self.number 130 self.number
66 } 131 }
67} 132}
68 133
69macro_rules! channel { 134macro_rules! channel {
70 ($type:ident, $num:expr) => { 135 ($name:ident, $num:expr) => {
71 impl Channel for peripherals::$type {} 136 impl sealed::Channel for peripherals::$name {}
72 impl sealed::Channel for peripherals::$type { 137 impl Channel for peripherals::$name {
73 fn number(&self) -> u8 { 138 fn number(&self) -> u8 {
74 $num 139 $num
75 } 140 }
76 } 141 }
142
143 impl From<peripherals::$name> for crate::dma::AnyChannel {
144 fn from(val: peripherals::$name) -> Self {
145 crate::dma::Channel::degrade(val)
146 }
147 }
77 }; 148 };
78} 149}
79 150
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs
index 6c5ab3515..c1596960f 100644
--- a/embassy-rp/src/uart.rs
+++ b/embassy-rp/src/uart.rs
@@ -2,6 +2,7 @@ use core::marker::PhantomData;
2 2
3use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_common::{into_ref, PeripheralRef};
4 4
5use crate::dma::{AnyChannel, Channel};
5use crate::gpio::sealed::Pin; 6use crate::gpio::sealed::Pin;
6use crate::gpio::AnyPin; 7use crate::gpio::AnyPin;
7use crate::{pac, peripherals, Peripheral}; 8use crate::{pac, peripherals, Peripheral};
@@ -76,26 +77,27 @@ pub enum Error {
76 Framing, 77 Framing,
77} 78}
78 79
79pub struct Uart<'d, T: Instance> { 80pub struct Uart<'d, T: Instance, M: Mode> {
80 tx: UartTx<'d, T>, 81 tx: UartTx<'d, T, M>,
81 rx: UartRx<'d, T>, 82 rx: UartRx<'d, T, M>,
82} 83}
83 84
84pub struct UartTx<'d, T: Instance> { 85pub struct UartTx<'d, T: Instance, M: Mode> {
85 phantom: PhantomData<&'d mut T>, 86 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
87 phantom: PhantomData<(&'d mut T, M)>,
86} 88}
87 89
88pub struct UartRx<'d, T: Instance> { 90pub struct UartRx<'d, T: Instance, M: Mode> {
89 phantom: PhantomData<&'d mut T>, 91 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
92 phantom: PhantomData<(&'d mut T, M)>,
90} 93}
91 94
92impl<'d, T: Instance> UartTx<'d, T> { 95impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
93 fn new() -> Self { 96 fn new(tx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
94 Self { phantom: PhantomData } 97 Self {
95 } 98 tx_dma,
96 99 phantom: PhantomData,
97 pub async fn write(&mut self, _buffer: &[u8]) -> Result<(), Error> { 100 }
98 todo!()
99 } 101 }
100 102
101 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 103 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
@@ -116,13 +118,29 @@ impl<'d, T: Instance> UartTx<'d, T> {
116 } 118 }
117} 119}
118 120
119impl<'d, T: Instance> UartRx<'d, T> { 121impl<'d, T: Instance> UartTx<'d, T, Async> {
120 fn new() -> Self { 122 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
121 Self { phantom: PhantomData } 123 if let Some(ch) = &mut self.tx_dma {
124 unsafe {
125 T::regs().uartdmacr().modify(|reg| {
126 reg.set_txdmae(true);
127 });
128 }
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.
131 let transfer = crate::dma::copy(ch, buffer, unsafe { T::regs().uartdr().ptr() });
132 transfer.await;
133 }
134 Ok(())
122 } 135 }
136}
123 137
124 pub async fn read(&mut self, _buffer: &mut [u8]) -> Result<(), Error> { 138impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
125 todo!(); 139 fn new(rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
140 Self {
141 rx_dma,
142 phantom: PhantomData,
143 }
126 } 144 }
127 145
128 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 146 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
@@ -150,25 +168,42 @@ impl<'d, T: Instance> UartRx<'d, T> {
150 } 168 }
151} 169}
152 170
153impl<'d, T: Instance> Uart<'d, T> { 171impl<'d, T: Instance> UartRx<'d, T, Async> {
172 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
173 if let Some(ch) = &mut self.rx_dma {
174 unsafe {
175 T::regs().uartdmacr().modify(|reg| {
176 reg.set_rxdmae(true);
177 });
178 }
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.
181 let transfer = crate::dma::copy(ch, unsafe { T::regs().uartdr().ptr() }, buffer);
182 transfer.await;
183 }
184 Ok(())
185 }
186}
187
188impl<'d, T: Instance> Uart<'d, T, Blocking> {
154 /// Create a new UART without hardware flow control 189 /// Create a new UART without hardware flow control
155 pub fn new( 190 pub fn new_blocking(
156 uart: impl Peripheral<P = T> + 'd, 191 uart: impl Peripheral<P = T> + 'd,
157 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 192 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
158 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 193 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
159 config: Config, 194 config: Config,
160 ) -> Self { 195 ) -> Self {
161 into_ref!(tx, rx); 196 into_ref!(tx, rx);
162 Self::new_inner(uart, rx.map_into(), tx.map_into(), None, None, config) 197 Self::new_inner(uart, rx.map_into(), tx.map_into(), None, None, None, None, config)
163 } 198 }
164 199
165 /// Create a new UART with hardware flow control (RTS/CTS) 200 /// Create a new UART with hardware flow control (RTS/CTS)
166 pub fn new_with_rtscts( 201 pub fn new_with_rtscts_blocking(
167 uart: impl Peripheral<P = T> + 'd, 202 uart: impl Peripheral<P = T> + 'd,
168 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 203 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
169 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 204 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
170 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
171 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 205 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
206 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
172 config: Config, 207 config: Config,
173 ) -> Self { 208 ) -> Self {
174 into_ref!(tx, rx, cts, rts); 209 into_ref!(tx, rx, cts, rts);
@@ -176,18 +211,72 @@ impl<'d, T: Instance> Uart<'d, T> {
176 uart, 211 uart,
177 rx.map_into(), 212 rx.map_into(),
178 tx.map_into(), 213 tx.map_into(),
214 Some(rts.map_into()),
179 Some(cts.map_into()), 215 Some(cts.map_into()),
216 None,
217 None,
218 config,
219 )
220 }
221}
222
223impl<'d, T: Instance> Uart<'d, T, Async> {
224 /// Create a new DMA enabled UART without hardware flow control
225 pub fn new(
226 uart: impl Peripheral<P = T> + 'd,
227 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
228 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
229 tx_dma: impl Peripheral<P = impl Channel> + 'd,
230 rx_dma: impl Peripheral<P = impl Channel> + 'd,
231 config: Config,
232 ) -> Self {
233 into_ref!(tx, rx, tx_dma, rx_dma);
234 Self::new_inner(
235 uart,
236 rx.map_into(),
237 tx.map_into(),
238 None,
239 None,
240 Some(tx_dma.map_into()),
241 Some(rx_dma.map_into()),
242 config,
243 )
244 }
245
246 /// Create a new DMA enabled UART with hardware flow control (RTS/CTS)
247 pub fn new_with_rtscts(
248 uart: impl Peripheral<P = T> + 'd,
249 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
250 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
251 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
252 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
253 tx_dma: impl Peripheral<P = impl Channel> + 'd,
254 rx_dma: impl Peripheral<P = impl Channel> + 'd,
255 config: Config,
256 ) -> Self {
257 into_ref!(tx, rx, cts, rts, tx_dma, rx_dma);
258 Self::new_inner(
259 uart,
260 rx.map_into(),
261 tx.map_into(),
180 Some(rts.map_into()), 262 Some(rts.map_into()),
263 Some(cts.map_into()),
264 Some(tx_dma.map_into()),
265 Some(rx_dma.map_into()),
181 config, 266 config,
182 ) 267 )
183 } 268 }
269}
184 270
271impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
185 fn new_inner( 272 fn new_inner(
186 _uart: impl Peripheral<P = T> + 'd, 273 _uart: impl Peripheral<P = T> + 'd,
187 tx: PeripheralRef<'d, AnyPin>, 274 tx: PeripheralRef<'d, AnyPin>,
188 rx: PeripheralRef<'d, AnyPin>, 275 rx: PeripheralRef<'d, AnyPin>,
189 cts: Option<PeripheralRef<'d, AnyPin>>,
190 rts: Option<PeripheralRef<'d, AnyPin>>, 276 rts: Option<PeripheralRef<'d, AnyPin>>,
277 cts: Option<PeripheralRef<'d, AnyPin>>,
278 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
279 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
191 config: Config, 280 config: Config,
192 ) -> Self { 281 ) -> Self {
193 into_ref!(_uart); 282 into_ref!(_uart);
@@ -246,15 +335,13 @@ impl<'d, T: Instance> Uart<'d, T> {
246 } 335 }
247 336
248 Self { 337 Self {
249 tx: UartTx::new(), 338 tx: UartTx::new(tx_dma),
250 rx: UartRx::new(), 339 rx: UartRx::new(rx_dma),
251 } 340 }
252 } 341 }
342}
253 343
254 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 344impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
255 self.tx.write(buffer).await
256 }
257
258 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 345 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
259 self.tx.blocking_write(buffer) 346 self.tx.blocking_write(buffer)
260 } 347 }
@@ -263,26 +350,31 @@ impl<'d, T: Instance> Uart<'d, T> {
263 self.tx.blocking_flush() 350 self.tx.blocking_flush()
264 } 351 }
265 352
266 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
267 self.rx.read(buffer).await
268 }
269
270 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 353 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
271 self.rx.blocking_read(buffer) 354 self.rx.blocking_read(buffer)
272 } 355 }
273 356
274 /// Split the Uart into a transmitter and receiver, which is 357 /// Split the Uart into a transmitter and receiver, which is particuarly
275 /// particuarly useful when having two tasks correlating to 358 /// useful when having two tasks correlating to transmitting and receiving.
276 /// transmitting and receiving. 359 pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) {
277 pub fn split(self) -> (UartTx<'d, T>, UartRx<'d, T>) {
278 (self.tx, self.rx) 360 (self.tx, self.rx)
279 } 361 }
280} 362}
281 363
364impl<'d, T: Instance> Uart<'d, T, Async> {
365 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
366 self.tx.write(buffer).await
367 }
368
369 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
370 self.rx.read(buffer).await
371 }
372}
373
282mod eh02 { 374mod eh02 {
283 use super::*; 375 use super::*;
284 376
285 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for UartRx<'d, T> { 377 impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, M> {
286 type Error = Error; 378 type Error = Error;
287 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 379 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
288 let r = T::regs(); 380 let r = T::regs();
@@ -306,7 +398,7 @@ mod eh02 {
306 } 398 }
307 } 399 }
308 400
309 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T> { 401 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> {
310 type Error = Error; 402 type Error = Error;
311 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { 403 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
312 self.blocking_write(buffer) 404 self.blocking_write(buffer)
@@ -316,14 +408,14 @@ mod eh02 {
316 } 408 }
317 } 409 }
318 410
319 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for Uart<'d, T> { 411 impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> {
320 type Error = Error; 412 type Error = Error;
321 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 413 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
322 embedded_hal_02::serial::Read::read(&mut self.rx) 414 embedded_hal_02::serial::Read::read(&mut self.rx)
323 } 415 }
324 } 416 }
325 417
326 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T> { 418 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> {
327 type Error = Error; 419 type Error = Error;
328 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { 420 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
329 self.blocking_write(buffer) 421 self.blocking_write(buffer)
@@ -419,6 +511,8 @@ cfg_if::cfg_if! {
419mod sealed { 511mod sealed {
420 use super::*; 512 use super::*;
421 513
514 pub trait Mode {}
515
422 pub trait Instance { 516 pub trait Instance {
423 fn regs() -> pac::uart::Uart; 517 fn regs() -> pac::uart::Uart;
424 } 518 }
@@ -428,6 +522,21 @@ mod sealed {
428 pub trait RtsPin<T: Instance> {} 522 pub trait RtsPin<T: Instance> {}
429} 523}
430 524
525pub trait Mode: sealed::Mode {}
526
527macro_rules! impl_mode {
528 ($name:ident) => {
529 impl sealed::Mode for $name {}
530 impl Mode for $name {}
531 };
532}
533
534pub struct Blocking;
535pub struct Async;
536
537impl_mode!(Blocking);
538impl_mode!(Async);
539
431pub trait Instance: sealed::Instance {} 540pub trait Instance: sealed::Instance {}
432 541
433macro_rules! impl_instance { 542macro_rules! impl_instance {