aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-08-26 10:57:10 +0000
committerGitHub <[email protected]>2022-08-26 10:57:10 +0000
commit24ab21a7ddcf8dafd6f464e6d66c9011cc08047b (patch)
tree3f0aaf9178281349767f977df3d69f521ed6d0d7
parent1125d578428dd0af3274142edbac46ae90042a0e (diff)
parentbd27b9080fd9019e69e84fd30894a71db9fd61b5 (diff)
Merge #913
913: (embassy-rp): Add DMA implementation r=Dirbaio a=MathiasKoch This PR adds everything necessary to do peripheral to memory DMA & memory to memory DMA operations. It also adds async UART read & write, powered by DMA Co-authored-by: Mathias <[email protected]>
-rw-r--r--embassy-rp/src/dma.rs255
-rw-r--r--embassy-rp/src/lib.rs1
-rw-r--r--embassy-rp/src/uart.rs274
-rw-r--r--examples/rp/src/bin/uart.rs2
-rw-r--r--tests/rp/src/bin/dma_copy_async.rs41
-rw-r--r--tests/rp/src/bin/uart.rs32
-rw-r--r--tests/rp/src/bin/uart_dma.rs32
7 files changed, 532 insertions, 105 deletions
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 42c4fd13e..75d7492e0 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -1,82 +1,265 @@
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_cortex_m::interrupt::{Interrupt, InterruptExt};
6use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker;
8use futures::Future;
9use pac::dma::vals::DataSize;
4 10
5use crate::pac::dma::vals; 11use crate::pac::dma::vals;
6use crate::{pac, peripherals}; 12use crate::{interrupt, pac, peripherals};
7 13
8pub struct Dma<T: Channel> { 14#[interrupt]
9 _inner: T, 15unsafe fn DMA_IRQ_0() {
16 let ints0 = pac::DMA.ints0().read().ints0();
17 for channel in 0..CHANNEL_COUNT {
18 let ctrl_trig = pac::DMA.ch(channel).ctrl_trig().read();
19 if ctrl_trig.ahb_error() {
20 panic!("DMA: error on DMA_0 channel {}", channel);
21 }
22
23 if ints0 & (1 << channel) == (1 << channel) {
24 CHANNEL_WAKERS[channel].wake();
25 }
26 }
27 pac::DMA.ints0().write(|w| w.set_ints0(ints0));
10} 28}
11 29
12impl<T: Channel> Dma<T> { 30pub(crate) unsafe fn init() {
13 pub fn copy(inner: T, from: &[u32], to: &mut [u32]) { 31 let irq = interrupt::DMA_IRQ_0::steal();
14 assert!(from.len() == to.len()); 32 irq.disable();
33 irq.set_priority(interrupt::Priority::P3);
15 34
16 unsafe { 35 pac::DMA.inte0().write(|w| w.set_inte0(0xFFFF));
17 let p = inner.regs(); 36
37 irq.enable();
38}
18 39
19 p.read_addr().write_value(from.as_ptr() as u32); 40pub unsafe fn read<'a, C: Channel, W: Word>(
20 p.write_addr().write_value(to.as_mut_ptr() as u32); 41 ch: impl Peripheral<P = C> + 'a,
21 p.trans_count().write_value(from.len() as u32); 42 from: *const W,
43 to: &mut [W],
44 dreq: u8,
45) -> Transfer<'a, C> {
46 let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(to);
47 copy_inner(
48 ch,
49 from as *const u32,
50 to_ptr as *mut u32,
51 len,
52 W::size(),
53 false,
54 true,
55 dreq,
56 )
57}
22 58
23 compiler_fence(Ordering::SeqCst); 59pub unsafe fn write<'a, C: Channel, W: Word>(
60 ch: impl Peripheral<P = C> + 'a,
61 from: &[W],
62 to: *mut W,
63 dreq: u8,
64) -> Transfer<'a, C> {
65 let (from_ptr, len) = crate::dma::slice_ptr_parts(from);
66 copy_inner(
67 ch,
68 from_ptr as *const u32,
69 to as *mut u32,
70 len,
71 W::size(),
72 true,
73 false,
74 dreq,
75 )
76}
24 77
25 p.ctrl_trig().write(|w| { 78pub unsafe fn copy<'a, C: Channel, W: Word>(
26 w.set_data_size(vals::DataSize::SIZE_WORD); 79 ch: impl Peripheral<P = C> + 'a,
27 w.set_incr_read(true); 80 from: &[W],
28 w.set_incr_write(true); 81 to: &mut [W],
29 w.set_chain_to(inner.number()); 82) -> Transfer<'a, C> {
30 w.set_en(true); 83 let (from_ptr, from_len) = crate::dma::slice_ptr_parts(from);
31 }); 84 let (to_ptr, to_len) = crate::dma::slice_ptr_parts_mut(to);
85 assert_eq!(from_len, to_len);
86 copy_inner(
87 ch,
88 from_ptr as *const u32,
89 to_ptr as *mut u32,
90 from_len,
91 W::size(),
92 true,
93 true,
94 vals::TreqSel::PERMANENT.0,
95 )
96}
32 97
33 while p.ctrl_trig().read().busy() {} 98fn copy_inner<'a, C: Channel>(
99 ch: impl Peripheral<P = C> + 'a,
100 from: *const u32,
101 to: *mut u32,
102 len: usize,
103 data_size: DataSize,
104 incr_read: bool,
105 incr_write: bool,
106 dreq: u8,
107) -> Transfer<'a, C> {
108 into_ref!(ch);
109
110 unsafe {
111 let p = ch.regs();
112
113 p.read_addr().write_value(from as u32);
114 p.write_addr().write_value(to as u32);
115 p.trans_count().write_value(len as u32);
116
117 compiler_fence(Ordering::SeqCst);
34 118
35 compiler_fence(Ordering::SeqCst); 119 p.ctrl_trig().write(|w| {
120 // TODO: Add all DREQ options to pac vals::TreqSel, and use
121 // `set_treq:sel`
122 w.0 = ((dreq as u32) & 0x3f) << 15usize;
123 w.set_data_size(data_size);
124 w.set_incr_read(incr_read);
125 w.set_incr_write(incr_write);
126 w.set_chain_to(ch.number());
127 w.set_en(true);
128 });
129
130 compiler_fence(Ordering::SeqCst);
131 }
132 Transfer::new(ch)
133}
134
135pub struct Transfer<'a, C: Channel> {
136 channel: PeripheralRef<'a, C>,
137}
138
139impl<'a, C: Channel> Transfer<'a, C> {
140 pub(crate) fn new(channel: impl Peripheral<P = C> + 'a) -> Self {
141 into_ref!(channel);
142
143 Self { channel }
144 }
145}
146
147impl<'a, C: Channel> Drop for Transfer<'a, C> {
148 fn drop(&mut self) {
149 let p = self.channel.regs();
150 unsafe {
151 pac::DMA
152 .chan_abort()
153 .modify(|m| m.set_chan_abort(1 << self.channel.number()));
154 while p.ctrl_trig().read().busy() {}
36 } 155 }
37 } 156 }
38} 157}
39 158
40pub struct NoDma; 159impl<'a, C: Channel> Unpin for Transfer<'a, C> {}
160impl<'a, C: Channel> Future for Transfer<'a, C> {
161 type Output = ();
162 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
163 // We need to register/re-register the waker for each poll because any
164 // calls to wake will deregister the waker.
165 CHANNEL_WAKERS[self.channel.number() as usize].register(cx.waker());
41 166
42impl_peripheral!(NoDma); 167 if unsafe { self.channel.regs().ctrl_trig().read().busy() } {
168 Poll::Pending
169 } else {
170 Poll::Ready(())
171 }
172 }
173}
174
175const CHANNEL_COUNT: usize = 12;
176const NEW_AW: AtomicWaker = AtomicWaker::new();
177static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AW; CHANNEL_COUNT];
43 178
44mod sealed { 179mod sealed {
45 use super::*; 180 pub trait Channel {}
46 181
47 pub trait Channel { 182 pub trait Word {}
48 fn number(&self) -> u8; 183}
49 184
50 fn regs(&self) -> pac::dma::Channel { 185pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static {
51 pac::DMA.ch(self.number() as _) 186 fn number(&self) -> u8;
52 } 187
188 fn regs(&self) -> pac::dma::Channel {
189 pac::DMA.ch(self.number() as _)
190 }
191
192 fn degrade(self) -> AnyChannel {
193 AnyChannel { number: self.number() }
194 }
195}
196
197pub trait Word: sealed::Word {
198 fn size() -> vals::DataSize;
199}
200
201impl sealed::Word for u8 {}
202impl Word for u8 {
203 fn size() -> vals::DataSize {
204 vals::DataSize::SIZE_BYTE
53 } 205 }
54} 206}
55 207
56pub trait Channel: sealed::Channel {} 208impl sealed::Word for u16 {}
209impl Word for u16 {
210 fn size() -> vals::DataSize {
211 vals::DataSize::SIZE_HALFWORD
212 }
213}
214
215impl sealed::Word for u32 {}
216impl Word for u32 {
217 fn size() -> vals::DataSize {
218 vals::DataSize::SIZE_WORD
219 }
220}
57 221
58pub struct AnyChannel { 222pub struct AnyChannel {
59 number: u8, 223 number: u8,
60} 224}
61 225
62impl Channel for AnyChannel {} 226impl_peripheral!(AnyChannel);
63impl sealed::Channel for AnyChannel { 227
228impl sealed::Channel for AnyChannel {}
229impl Channel for AnyChannel {
64 fn number(&self) -> u8 { 230 fn number(&self) -> u8 {
65 self.number 231 self.number
66 } 232 }
67} 233}
68 234
69macro_rules! channel { 235macro_rules! channel {
70 ($type:ident, $num:expr) => { 236 ($name:ident, $num:expr) => {
71 impl Channel for peripherals::$type {} 237 impl sealed::Channel for peripherals::$name {}
72 impl sealed::Channel for peripherals::$type { 238 impl Channel for peripherals::$name {
73 fn number(&self) -> u8 { 239 fn number(&self) -> u8 {
74 $num 240 $num
75 } 241 }
76 } 242 }
243
244 impl From<peripherals::$name> for crate::dma::AnyChannel {
245 fn from(val: peripherals::$name) -> Self {
246 crate::dma::Channel::degrade(val)
247 }
248 }
77 }; 249 };
78} 250}
79 251
252// TODO: replace transmutes with core::ptr::metadata once it's stable
253#[allow(unused)]
254pub(crate) fn slice_ptr_parts<T>(slice: *const [T]) -> (usize, usize) {
255 unsafe { core::mem::transmute(slice) }
256}
257
258#[allow(unused)]
259pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
260 unsafe { core::mem::transmute(slice) }
261}
262
80channel!(DMA_CH0, 0); 263channel!(DMA_CH0, 0);
81channel!(DMA_CH1, 1); 264channel!(DMA_CH1, 1);
82channel!(DMA_CH2, 2); 265channel!(DMA_CH2, 2);
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 8c053a4f7..6db77b8cd 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -105,6 +105,7 @@ pub fn init(_config: config::Config) -> Peripherals {
105 unsafe { 105 unsafe {
106 clocks::init(); 106 clocks::init();
107 timer::init(); 107 timer::init();
108 dma::init();
108 } 109 }
109 110
110 peripherals 111 peripherals
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs
index 6c5ab3515..4a3c7a0ce 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> {
@@ -111,18 +113,33 @@ impl<'d, T: Instance> UartTx<'d, T> {
111 113
112 pub fn blocking_flush(&mut self) -> Result<(), Error> { 114 pub fn blocking_flush(&mut self) -> Result<(), Error> {
113 let r = T::regs(); 115 let r = T::regs();
114 unsafe { while r.uartfr().read().txff() {} } 116 unsafe { while !r.uartfr().read().txfe() {} }
115 Ok(()) 117 Ok(())
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 let ch = self.tx_dma.as_mut().unwrap();
124 let transfer = unsafe {
125 T::regs().uartdmacr().modify(|reg| {
126 reg.set_txdmae(true);
127 });
128 // If we don't assign future to a variable, the data register pointer
129 // is held across an await and makes the future non-Send.
130 crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ)
131 };
132 transfer.await;
133 Ok(())
122 } 134 }
135}
123 136
124 pub async fn read(&mut self, _buffer: &mut [u8]) -> Result<(), Error> { 137impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
125 todo!(); 138 fn new(rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
139 Self {
140 rx_dma,
141 phantom: PhantomData,
142 }
126 } 143 }
127 144
128 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 145 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
@@ -130,6 +147,10 @@ impl<'d, T: Instance> UartRx<'d, T> {
130 unsafe { 147 unsafe {
131 for b in buffer { 148 for b in buffer {
132 *b = loop { 149 *b = loop {
150 if r.uartfr().read().rxfe() {
151 continue;
152 }
153
133 let dr = r.uartdr().read(); 154 let dr = r.uartdr().read();
134 155
135 if dr.oe() { 156 if dr.oe() {
@@ -140,7 +161,7 @@ impl<'d, T: Instance> UartRx<'d, T> {
140 return Err(Error::Parity); 161 return Err(Error::Parity);
141 } else if dr.fe() { 162 } else if dr.fe() {
142 return Err(Error::Framing); 163 return Err(Error::Framing);
143 } else if dr.fe() { 164 } else {
144 break dr.data(); 165 break dr.data();
145 } 166 }
146 }; 167 };
@@ -150,25 +171,41 @@ impl<'d, T: Instance> UartRx<'d, T> {
150 } 171 }
151} 172}
152 173
153impl<'d, T: Instance> Uart<'d, T> { 174impl<'d, T: Instance> UartRx<'d, T, Async> {
175 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
176 let ch = self.rx_dma.as_mut().unwrap();
177 let transfer = unsafe {
178 T::regs().uartdmacr().modify(|reg| {
179 reg.set_rxdmae(true);
180 });
181 // If we don't assign future to a variable, the data register pointer
182 // is held across an await and makes the future non-Send.
183 crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ)
184 };
185 transfer.await;
186 Ok(())
187 }
188}
189
190impl<'d, T: Instance> Uart<'d, T, Blocking> {
154 /// Create a new UART without hardware flow control 191 /// Create a new UART without hardware flow control
155 pub fn new( 192 pub fn new_blocking(
156 uart: impl Peripheral<P = T> + 'd, 193 uart: impl Peripheral<P = T> + 'd,
157 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 194 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
158 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 195 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
159 config: Config, 196 config: Config,
160 ) -> Self { 197 ) -> Self {
161 into_ref!(tx, rx); 198 into_ref!(tx, rx);
162 Self::new_inner(uart, rx.map_into(), tx.map_into(), None, None, config) 199 Self::new_inner(uart, rx.map_into(), tx.map_into(), None, None, None, None, config)
163 } 200 }
164 201
165 /// Create a new UART with hardware flow control (RTS/CTS) 202 /// Create a new UART with hardware flow control (RTS/CTS)
166 pub fn new_with_rtscts( 203 pub fn new_with_rtscts_blocking(
167 uart: impl Peripheral<P = T> + 'd, 204 uart: impl Peripheral<P = T> + 'd,
168 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 205 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
169 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 206 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, 207 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
208 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
172 config: Config, 209 config: Config,
173 ) -> Self { 210 ) -> Self {
174 into_ref!(tx, rx, cts, rts); 211 into_ref!(tx, rx, cts, rts);
@@ -176,18 +213,72 @@ impl<'d, T: Instance> Uart<'d, T> {
176 uart, 213 uart,
177 rx.map_into(), 214 rx.map_into(),
178 tx.map_into(), 215 tx.map_into(),
216 Some(rts.map_into()),
179 Some(cts.map_into()), 217 Some(cts.map_into()),
218 None,
219 None,
220 config,
221 )
222 }
223}
224
225impl<'d, T: Instance> Uart<'d, T, Async> {
226 /// Create a new DMA enabled UART without hardware flow control
227 pub fn new(
228 uart: impl Peripheral<P = T> + 'd,
229 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
230 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
231 tx_dma: impl Peripheral<P = impl Channel> + 'd,
232 rx_dma: impl Peripheral<P = impl Channel> + 'd,
233 config: Config,
234 ) -> Self {
235 into_ref!(tx, rx, tx_dma, rx_dma);
236 Self::new_inner(
237 uart,
238 rx.map_into(),
239 tx.map_into(),
240 None,
241 None,
242 Some(tx_dma.map_into()),
243 Some(rx_dma.map_into()),
244 config,
245 )
246 }
247
248 /// Create a new DMA enabled UART with hardware flow control (RTS/CTS)
249 pub fn new_with_rtscts(
250 uart: impl Peripheral<P = T> + 'd,
251 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
252 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
253 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
254 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
255 tx_dma: impl Peripheral<P = impl Channel> + 'd,
256 rx_dma: impl Peripheral<P = impl Channel> + 'd,
257 config: Config,
258 ) -> Self {
259 into_ref!(tx, rx, cts, rts, tx_dma, rx_dma);
260 Self::new_inner(
261 uart,
262 rx.map_into(),
263 tx.map_into(),
180 Some(rts.map_into()), 264 Some(rts.map_into()),
265 Some(cts.map_into()),
266 Some(tx_dma.map_into()),
267 Some(rx_dma.map_into()),
181 config, 268 config,
182 ) 269 )
183 } 270 }
271}
184 272
273impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
185 fn new_inner( 274 fn new_inner(
186 _uart: impl Peripheral<P = T> + 'd, 275 _uart: impl Peripheral<P = T> + 'd,
187 tx: PeripheralRef<'d, AnyPin>, 276 tx: PeripheralRef<'d, AnyPin>,
188 rx: PeripheralRef<'d, AnyPin>, 277 rx: PeripheralRef<'d, AnyPin>,
189 cts: Option<PeripheralRef<'d, AnyPin>>,
190 rts: Option<PeripheralRef<'d, AnyPin>>, 278 rts: Option<PeripheralRef<'d, AnyPin>>,
279 cts: Option<PeripheralRef<'d, AnyPin>>,
280 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
281 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
191 config: Config, 282 config: Config,
192 ) -> Self { 283 ) -> Self {
193 into_ref!(_uart); 284 into_ref!(_uart);
@@ -195,6 +286,30 @@ impl<'d, T: Instance> Uart<'d, T> {
195 unsafe { 286 unsafe {
196 let r = T::regs(); 287 let r = T::regs();
197 288
289 tx.io().ctrl().write(|w| w.set_funcsel(2));
290 rx.io().ctrl().write(|w| w.set_funcsel(2));
291
292 tx.pad_ctrl().write(|w| {
293 w.set_ie(true);
294 });
295
296 rx.pad_ctrl().write(|w| {
297 w.set_ie(true);
298 });
299
300 if let Some(pin) = &cts {
301 pin.io().ctrl().write(|w| w.set_funcsel(2));
302 pin.pad_ctrl().write(|w| {
303 w.set_ie(true);
304 });
305 }
306 if let Some(pin) = &rts {
307 pin.io().ctrl().write(|w| w.set_funcsel(2));
308 pin.pad_ctrl().write(|w| {
309 w.set_ie(true);
310 });
311 }
312
198 let clk_base = crate::clocks::clk_peri_freq(); 313 let clk_base = crate::clocks::clk_peri_freq();
199 314
200 let baud_rate_div = (8 * clk_base) / config.baudrate; 315 let baud_rate_div = (8 * clk_base) / config.baudrate;
@@ -215,10 +330,14 @@ impl<'d, T: Instance> Uart<'d, T> {
215 330
216 let (pen, eps) = match config.parity { 331 let (pen, eps) = match config.parity {
217 Parity::ParityNone => (false, false), 332 Parity::ParityNone => (false, false),
218 Parity::ParityEven => (true, true),
219 Parity::ParityOdd => (true, false), 333 Parity::ParityOdd => (true, false),
334 Parity::ParityEven => (true, true),
220 }; 335 };
221 336
337 // PL011 needs a (dummy) line control register write to latch in the
338 // divisors. We don't want to actually change LCR contents here.
339 r.uartlcr_h().modify(|_| {});
340
222 r.uartlcr_h().write(|w| { 341 r.uartlcr_h().write(|w| {
223 w.set_wlen(config.data_bits.bits()); 342 w.set_wlen(config.data_bits.bits());
224 w.set_stp2(config.stop_bits == StopBits::STOP2); 343 w.set_stp2(config.stop_bits == StopBits::STOP2);
@@ -234,27 +353,16 @@ impl<'d, T: Instance> Uart<'d, T> {
234 w.set_ctsen(cts.is_some()); 353 w.set_ctsen(cts.is_some());
235 w.set_rtsen(rts.is_some()); 354 w.set_rtsen(rts.is_some());
236 }); 355 });
237
238 tx.io().ctrl().write(|w| w.set_funcsel(2));
239 rx.io().ctrl().write(|w| w.set_funcsel(2));
240 if let Some(pin) = &cts {
241 pin.io().ctrl().write(|w| w.set_funcsel(2));
242 }
243 if let Some(pin) = &rts {
244 pin.io().ctrl().write(|w| w.set_funcsel(2));
245 }
246 } 356 }
247 357
248 Self { 358 Self {
249 tx: UartTx::new(), 359 tx: UartTx::new(tx_dma),
250 rx: UartRx::new(), 360 rx: UartRx::new(rx_dma),
251 } 361 }
252 } 362 }
363}
253 364
254 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 365impl<'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> { 366 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
259 self.tx.blocking_write(buffer) 367 self.tx.blocking_write(buffer)
260 } 368 }
@@ -263,30 +371,39 @@ impl<'d, T: Instance> Uart<'d, T> {
263 self.tx.blocking_flush() 371 self.tx.blocking_flush()
264 } 372 }
265 373
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> { 374 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
271 self.rx.blocking_read(buffer) 375 self.rx.blocking_read(buffer)
272 } 376 }
273 377
274 /// Split the Uart into a transmitter and receiver, which is 378 /// Split the Uart into a transmitter and receiver, which is particuarly
275 /// particuarly useful when having two tasks correlating to 379 /// useful when having two tasks correlating to transmitting and receiving.
276 /// transmitting and receiving. 380 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) 381 (self.tx, self.rx)
279 } 382 }
280} 383}
281 384
385impl<'d, T: Instance> Uart<'d, T, Async> {
386 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
387 self.tx.write(buffer).await
388 }
389
390 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
391 self.rx.read(buffer).await
392 }
393}
394
282mod eh02 { 395mod eh02 {
283 use super::*; 396 use super::*;
284 397
285 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for UartRx<'d, T> { 398 impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, M> {
286 type Error = Error; 399 type Error = Error;
287 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 400 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
288 let r = T::regs(); 401 let r = T::regs();
289 unsafe { 402 unsafe {
403 if r.uartfr().read().rxfe() {
404 return Err(nb::Error::WouldBlock);
405 }
406
290 let dr = r.uartdr().read(); 407 let dr = r.uartdr().read();
291 408
292 if dr.oe() { 409 if dr.oe() {
@@ -297,16 +414,14 @@ mod eh02 {
297 Err(nb::Error::Other(Error::Parity)) 414 Err(nb::Error::Other(Error::Parity))
298 } else if dr.fe() { 415 } else if dr.fe() {
299 Err(nb::Error::Other(Error::Framing)) 416 Err(nb::Error::Other(Error::Framing))
300 } else if dr.fe() {
301 Ok(dr.data())
302 } else { 417 } else {
303 Err(nb::Error::WouldBlock) 418 Ok(dr.data())
304 } 419 }
305 } 420 }
306 } 421 }
307 } 422 }
308 423
309 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T> { 424 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> {
310 type Error = Error; 425 type Error = Error;
311 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { 426 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
312 self.blocking_write(buffer) 427 self.blocking_write(buffer)
@@ -316,14 +431,14 @@ mod eh02 {
316 } 431 }
317 } 432 }
318 433
319 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for Uart<'d, T> { 434 impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> {
320 type Error = Error; 435 type Error = Error;
321 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 436 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
322 embedded_hal_02::serial::Read::read(&mut self.rx) 437 embedded_hal_02::serial::Read::read(&mut self.rx)
323 } 438 }
324 } 439 }
325 440
326 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T> { 441 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> {
327 type Error = Error; 442 type Error = Error;
328 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { 443 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
329 self.blocking_write(buffer) 444 self.blocking_write(buffer)
@@ -349,15 +464,15 @@ mod eh1 {
349 } 464 }
350 } 465 }
351 466
352 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for Uart<'d, T> { 467 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for Uart<'d, T, M> {
353 type Error = Error; 468 type Error = Error;
354 } 469 }
355 470
356 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UartTx<'d, T> { 471 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartTx<'d, T, M> {
357 type Error = Error; 472 type Error = Error;
358 } 473 }
359 474
360 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UartRx<'d, T> { 475 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> {
361 type Error = Error; 476 type Error = Error;
362 } 477 }
363} 478}
@@ -366,7 +481,7 @@ cfg_if::cfg_if! {
366 if #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "_todo_embedded_hal_serial"))] { 481 if #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "_todo_embedded_hal_serial"))] {
367 use core::future::Future; 482 use core::future::Future;
368 483
369 impl<'d, T: Instance> embedded_hal_async::serial::Write for UartTx<'d, T> 484 impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Write for UartTx<'d, T, M>
370 { 485 {
371 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 486 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
372 487
@@ -381,7 +496,7 @@ cfg_if::cfg_if! {
381 } 496 }
382 } 497 }
383 498
384 impl<'d, T: Instance> embedded_hal_async::serial::Read for UartRx<'d, T> 499 impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Read for UartRx<'d, T, M>
385 { 500 {
386 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 501 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
387 502
@@ -390,7 +505,7 @@ cfg_if::cfg_if! {
390 } 505 }
391 } 506 }
392 507
393 impl<'d, T: Instance> embedded_hal_async::serial::Write for Uart<'d, T> 508 impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Write for Uart<'d, T, M>
394 { 509 {
395 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 510 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
396 511
@@ -405,7 +520,7 @@ cfg_if::cfg_if! {
405 } 520 }
406 } 521 }
407 522
408 impl<'d, T: Instance> embedded_hal_async::serial::Read for Uart<'d, T> 523 impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Read for Uart<'d, T, M>
409 { 524 {
410 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; 525 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
411 526
@@ -419,7 +534,12 @@ cfg_if::cfg_if! {
419mod sealed { 534mod sealed {
420 use super::*; 535 use super::*;
421 536
537 pub trait Mode {}
538
422 pub trait Instance { 539 pub trait Instance {
540 const TX_DREQ: u8;
541 const RX_DREQ: u8;
542
423 fn regs() -> pac::uart::Uart; 543 fn regs() -> pac::uart::Uart;
424 } 544 }
425 pub trait TxPin<T: Instance> {} 545 pub trait TxPin<T: Instance> {}
@@ -428,11 +548,29 @@ mod sealed {
428 pub trait RtsPin<T: Instance> {} 548 pub trait RtsPin<T: Instance> {}
429} 549}
430 550
551pub trait Mode: sealed::Mode {}
552
553macro_rules! impl_mode {
554 ($name:ident) => {
555 impl sealed::Mode for $name {}
556 impl Mode for $name {}
557 };
558}
559
560pub struct Blocking;
561pub struct Async;
562
563impl_mode!(Blocking);
564impl_mode!(Async);
565
431pub trait Instance: sealed::Instance {} 566pub trait Instance: sealed::Instance {}
432 567
433macro_rules! impl_instance { 568macro_rules! impl_instance {
434 ($inst:ident, $irq:ident) => { 569 ($inst:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => {
435 impl sealed::Instance for peripherals::$inst { 570 impl sealed::Instance for peripherals::$inst {
571 const TX_DREQ: u8 = $tx_dreq;
572 const RX_DREQ: u8 = $rx_dreq;
573
436 fn regs() -> pac::uart::Uart { 574 fn regs() -> pac::uart::Uart {
437 pac::$inst 575 pac::$inst
438 } 576 }
@@ -441,8 +579,8 @@ macro_rules! impl_instance {
441 }; 579 };
442} 580}
443 581
444impl_instance!(UART0, UART0); 582impl_instance!(UART0, UART0, 20, 21);
445impl_instance!(UART1, UART1); 583impl_instance!(UART1, UART1, 22, 23);
446 584
447pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 585pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
448pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 586pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}
diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs
index c63b31cae..05177a6b4 100644
--- a/examples/rp/src/bin/uart.rs
+++ b/examples/rp/src/bin/uart.rs
@@ -10,7 +10,7 @@ use {defmt_rtt as _, panic_probe as _};
10async fn main(_spawner: Spawner) { 10async fn main(_spawner: Spawner) {
11 let p = embassy_rp::init(Default::default()); 11 let p = embassy_rp::init(Default::default());
12 let config = uart::Config::default(); 12 let config = uart::Config::default();
13 let mut uart = uart::Uart::new_with_rtscts(p.UART0, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, config); 13 let mut uart = uart::Uart::new_with_rtscts_blocking(p.UART0, p.PIN_0, p.PIN_1, p.PIN_3, p.PIN_2, config);
14 uart.blocking_write("Hello World!\r\n".as_bytes()).unwrap(); 14 uart.blocking_write("Hello World!\r\n".as_bytes()).unwrap();
15 15
16 loop { 16 loop {
diff --git a/tests/rp/src/bin/dma_copy_async.rs b/tests/rp/src/bin/dma_copy_async.rs
new file mode 100644
index 000000000..c53f644bd
--- /dev/null
+++ b/tests/rp/src/bin/dma_copy_async.rs
@@ -0,0 +1,41 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert_eq, *};
6use embassy_executor::Spawner;
7use embassy_rp::dma::copy;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default());
13 info!("Hello World!");
14
15 // Check `u8` copy
16 {
17 let data: [u8; 2] = [0xC0, 0xDE];
18 let mut buf = [0; 2];
19 unsafe { copy(p.DMA_CH0, &data, &mut buf).await };
20 assert_eq!(buf, data);
21 }
22
23 // Check `u16` copy
24 {
25 let data: [u16; 2] = [0xC0BE, 0xDEAD];
26 let mut buf = [0; 2];
27 unsafe { copy(p.DMA_CH1, &data, &mut buf).await };
28 assert_eq!(buf, data);
29 }
30
31 // Check `u32` copy
32 {
33 let data: [u32; 2] = [0xC0BEDEAD, 0xDEADAAFF];
34 let mut buf = [0; 2];
35 unsafe { copy(p.DMA_CH2, &data, &mut buf).await };
36 assert_eq!(buf, data);
37 }
38
39 info!("Test OK");
40 cortex_m::asm::bkpt();
41}
diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs
new file mode 100644
index 000000000..92f61464e
--- /dev/null
+++ b/tests/rp/src/bin/uart.rs
@@ -0,0 +1,32 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert_eq, *};
6use embassy_executor::Spawner;
7use embassy_rp::uart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default());
13 info!("Hello World!");
14
15 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0);
16
17 let config = Config::default();
18 let mut uart = Uart::new_blocking(uart, tx, rx, config);
19
20 // We can't send too many bytes, they have to fit in the FIFO.
21 // This is because we aren't sending+receiving at the same time.
22
23 let data = [0xC0, 0xDE];
24 uart.blocking_write(&data).unwrap();
25
26 let mut buf = [0; 2];
27 uart.blocking_read(&mut buf).unwrap();
28 assert_eq!(buf, data);
29
30 info!("Test OK");
31 cortex_m::asm::bkpt();
32}
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs
new file mode 100644
index 000000000..963c22707
--- /dev/null
+++ b/tests/rp/src/bin/uart_dma.rs
@@ -0,0 +1,32 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert_eq, *};
6use embassy_executor::Spawner;
7use embassy_rp::uart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default());
13 info!("Hello World!");
14
15 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0);
16
17 let config = Config::default();
18 let mut uart = Uart::new(uart, tx, rx, p.DMA_CH0, p.DMA_CH1, config);
19
20 // We can't send too many bytes, they have to fit in the FIFO.
21 // This is because we aren't sending+receiving at the same time.
22
23 let data = [0xC0, 0xDE];
24 uart.write(&data).await.unwrap();
25
26 let mut buf = [0; 2];
27 uart.read(&mut buf).await.unwrap();
28 assert_eq!(buf, data);
29
30 info!("Test OK");
31 cortex_m::asm::bkpt();
32}