aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/Cargo.toml2
-rw-r--r--embassy-rp/src/dma.rs6
-rw-r--r--embassy-rp/src/uart.rs401
-rw-r--r--examples/rp/src/bin/uart.rs6
4 files changed, 374 insertions, 41 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index aaf4ede13..af7c8ee6e 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -36,6 +36,8 @@ embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
36atomic-polyfill = "1.0.1" 36atomic-polyfill = "1.0.1"
37defmt = { version = "0.3", optional = true } 37defmt = { version = "0.3", optional = true }
38log = { version = "0.4.14", optional = true } 38log = { version = "0.4.14", optional = true }
39nb = "1.0.0"
40cfg-if = "1.0.0"
39cortex-m-rt = ">=0.6.15,<0.8" 41cortex-m-rt = ">=0.6.15,<0.8"
40cortex-m = "0.7.6" 42cortex-m = "0.7.6"
41critical-section = "1.1" 43critical-section = "1.1"
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 235e92d7c..42c4fd13e 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -1,5 +1,7 @@
1use core::sync::atomic::{compiler_fence, Ordering}; 1use core::sync::atomic::{compiler_fence, Ordering};
2 2
3use embassy_hal_common::impl_peripheral;
4
3use crate::pac::dma::vals; 5use crate::pac::dma::vals;
4use crate::{pac, peripherals}; 6use crate::{pac, peripherals};
5 7
@@ -35,6 +37,10 @@ impl<T: Channel> Dma<T> {
35 } 37 }
36} 38}
37 39
40pub struct NoDma;
41
42impl_peripheral!(NoDma);
43
38mod sealed { 44mod sealed {
39 use super::*; 45 use super::*;
40 46
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs
index b19f043f8..6c5ab3515 100644
--- a/embassy-rp/src/uart.rs
+++ b/embassy-rp/src/uart.rs
@@ -1,42 +1,199 @@
1use core::marker::PhantomData;
2
1use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_common::{into_ref, PeripheralRef};
2use gpio::Pin;
3 4
4use crate::{gpio, pac, peripherals, Peripheral}; 5use crate::gpio::sealed::Pin;
6use crate::gpio::AnyPin;
7use crate::{pac, peripherals, Peripheral};
8
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10pub enum DataBits {
11 DataBits5,
12 DataBits6,
13 DataBits7,
14 DataBits8,
15}
16
17impl DataBits {
18 fn bits(&self) -> u8 {
19 match self {
20 Self::DataBits5 => 0b00,
21 Self::DataBits6 => 0b01,
22 Self::DataBits7 => 0b10,
23 Self::DataBits8 => 0b11,
24 }
25 }
26}
27
28#[derive(Clone, Copy, PartialEq, Eq, Debug)]
29pub enum Parity {
30 ParityNone,
31 ParityEven,
32 ParityOdd,
33}
34
35#[derive(Clone, Copy, PartialEq, Eq, Debug)]
36pub enum StopBits {
37 #[doc = "1 stop bit"]
38 STOP1,
39 #[doc = "2 stop bits"]
40 STOP2,
41}
5 42
6#[non_exhaustive] 43#[non_exhaustive]
44#[derive(Clone, Copy, PartialEq, Eq, Debug)]
7pub struct Config { 45pub struct Config {
8 pub baudrate: u32, 46 pub baudrate: u32,
9 pub data_bits: u8, 47 pub data_bits: DataBits,
10 pub stop_bits: u8, 48 pub stop_bits: StopBits,
49 pub parity: Parity,
11} 50}
12 51
13impl Default for Config { 52impl Default for Config {
14 fn default() -> Self { 53 fn default() -> Self {
15 Self { 54 Self {
16 baudrate: 115200, 55 baudrate: 115200,
17 data_bits: 8, 56 data_bits: DataBits::DataBits8,
18 stop_bits: 1, 57 stop_bits: StopBits::STOP1,
58 parity: Parity::ParityNone,
19 } 59 }
20 } 60 }
21} 61}
22 62
63/// Serial error
64#[derive(Debug, Eq, PartialEq, Copy, Clone)]
65#[cfg_attr(feature = "defmt", derive(defmt::Format))]
66#[non_exhaustive]
67pub enum Error {
68 /// Triggered when the FIFO (or shift-register) is overflowed.
69 Overrun,
70 /// Triggered when a break is received
71 Break,
72 /// Triggered when there is a parity mismatch between what's received and
73 /// our settings.
74 Parity,
75 /// Triggered when the received character didn't have a valid stop bit.
76 Framing,
77}
78
23pub struct Uart<'d, T: Instance> { 79pub struct Uart<'d, T: Instance> {
24 inner: PeripheralRef<'d, T>, 80 tx: UartTx<'d, T>,
81 rx: UartRx<'d, T>,
82}
83
84pub struct UartTx<'d, T: Instance> {
85 phantom: PhantomData<&'d mut T>,
86}
87
88pub struct UartRx<'d, T: Instance> {
89 phantom: PhantomData<&'d mut T>,
90}
91
92impl<'d, T: Instance> UartTx<'d, T> {
93 fn new() -> Self {
94 Self { phantom: PhantomData }
95 }
96
97 pub async fn write(&mut self, _buffer: &[u8]) -> Result<(), Error> {
98 todo!()
99 }
100
101 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
102 let r = T::regs();
103 unsafe {
104 for &b in buffer {
105 while r.uartfr().read().txff() {}
106 r.uartdr().write(|w| w.set_data(b));
107 }
108 }
109 Ok(())
110 }
111
112 pub fn blocking_flush(&mut self) -> Result<(), Error> {
113 let r = T::regs();
114 unsafe { while r.uartfr().read().txff() {} }
115 Ok(())
116 }
117}
118
119impl<'d, T: Instance> UartRx<'d, T> {
120 fn new() -> Self {
121 Self { phantom: PhantomData }
122 }
123
124 pub async fn read(&mut self, _buffer: &mut [u8]) -> Result<(), Error> {
125 todo!();
126 }
127
128 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
129 let r = T::regs();
130 unsafe {
131 for b in buffer {
132 *b = loop {
133 let dr = r.uartdr().read();
134
135 if dr.oe() {
136 return Err(Error::Overrun);
137 } else if dr.be() {
138 return Err(Error::Break);
139 } else if dr.pe() {
140 return Err(Error::Parity);
141 } else if dr.fe() {
142 return Err(Error::Framing);
143 } else if dr.fe() {
144 break dr.data();
145 }
146 };
147 }
148 }
149 Ok(())
150 }
25} 151}
26 152
27impl<'d, T: Instance> Uart<'d, T> { 153impl<'d, T: Instance> Uart<'d, T> {
154 /// Create a new UART without hardware flow control
28 pub fn new( 155 pub fn new(
29 inner: impl Peripheral<P = T> + 'd, 156 uart: impl Peripheral<P = T> + 'd,
157 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
158 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
159 config: Config,
160 ) -> Self {
161 into_ref!(tx, rx);
162 Self::new_inner(uart, rx.map_into(), tx.map_into(), None, None, config)
163 }
164
165 /// Create a new UART with hardware flow control (RTS/CTS)
166 pub fn new_with_rtscts(
167 uart: impl Peripheral<P = T> + 'd,
30 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 168 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
31 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 169 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
32 cts: impl Peripheral<P = impl CtsPin<T>> + 'd, 170 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
33 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 171 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
34 config: Config, 172 config: Config,
35 ) -> Self { 173 ) -> Self {
36 into_ref!(inner, tx, rx, cts, rts); 174 into_ref!(tx, rx, cts, rts);
175 Self::new_inner(
176 uart,
177 rx.map_into(),
178 tx.map_into(),
179 Some(cts.map_into()),
180 Some(rts.map_into()),
181 config,
182 )
183 }
184
185 fn new_inner(
186 _uart: impl Peripheral<P = T> + 'd,
187 tx: PeripheralRef<'d, AnyPin>,
188 rx: PeripheralRef<'d, AnyPin>,
189 cts: Option<PeripheralRef<'d, AnyPin>>,
190 rts: Option<PeripheralRef<'d, AnyPin>>,
191 config: Config,
192 ) -> Self {
193 into_ref!(_uart);
37 194
38 unsafe { 195 unsafe {
39 let p = inner.regs(); 196 let r = T::regs();
40 197
41 let clk_base = crate::clocks::clk_peri_freq(); 198 let clk_base = crate::clocks::clk_peri_freq();
42 199
@@ -53,49 +210,217 @@ impl<'d, T: Instance> Uart<'d, T> {
53 } 210 }
54 211
55 // Load PL011's baud divisor registers 212 // Load PL011's baud divisor registers
56 p.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); 213 r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd));
57 p.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd)); 214 r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd));
58 215
59 p.uartlcr_h().write(|w| { 216 let (pen, eps) = match config.parity {
60 w.set_wlen(config.data_bits - 5); 217 Parity::ParityNone => (false, false),
61 w.set_stp2(config.stop_bits == 2); 218 Parity::ParityEven => (true, true),
62 w.set_pen(false); 219 Parity::ParityOdd => (true, false),
63 w.set_eps(false); 220 };
221
222 r.uartlcr_h().write(|w| {
223 w.set_wlen(config.data_bits.bits());
224 w.set_stp2(config.stop_bits == StopBits::STOP2);
225 w.set_pen(pen);
226 w.set_eps(eps);
64 w.set_fen(true); 227 w.set_fen(true);
65 }); 228 });
66 229
67 p.uartcr().write(|w| { 230 r.uartcr().write(|w| {
68 w.set_uarten(true); 231 w.set_uarten(true);
69 w.set_rxe(true); 232 w.set_rxe(true);
70 w.set_txe(true); 233 w.set_txe(true);
234 w.set_ctsen(cts.is_some());
235 w.set_rtsen(rts.is_some());
71 }); 236 });
72 237
73 tx.io().ctrl().write(|w| w.set_funcsel(2)); 238 tx.io().ctrl().write(|w| w.set_funcsel(2));
74 rx.io().ctrl().write(|w| w.set_funcsel(2)); 239 rx.io().ctrl().write(|w| w.set_funcsel(2));
75 cts.io().ctrl().write(|w| w.set_funcsel(2)); 240 if let Some(pin) = &cts {
76 rts.io().ctrl().write(|w| w.set_funcsel(2)); 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 }
247
248 Self {
249 tx: UartTx::new(),
250 rx: UartRx::new(),
77 } 251 }
78 Self { inner }
79 } 252 }
80 253
81 pub fn send(&mut self, data: &[u8]) { 254 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
82 unsafe { 255 self.tx.write(buffer).await
83 let p = self.inner.regs(); 256 }
257
258 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
259 self.tx.blocking_write(buffer)
260 }
84 261
85 for &byte in data { 262 pub fn blocking_flush(&mut self) -> Result<(), Error> {
86 if !p.uartfr().read().txff() { 263 self.tx.blocking_flush()
87 p.uartdr().write(|w| w.set_data(byte)); 264 }
265
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> {
271 self.rx.blocking_read(buffer)
272 }
273
274 /// Split the Uart into a transmitter and receiver, which is
275 /// particuarly useful when having two tasks correlating to
276 /// transmitting and receiving.
277 pub fn split(self) -> (UartTx<'d, T>, UartRx<'d, T>) {
278 (self.tx, self.rx)
279 }
280}
281
282mod eh02 {
283 use super::*;
284
285 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for UartRx<'d, T> {
286 type Error = Error;
287 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
288 let r = T::regs();
289 unsafe {
290 let dr = r.uartdr().read();
291
292 if dr.oe() {
293 Err(nb::Error::Other(Error::Overrun))
294 } else if dr.be() {
295 Err(nb::Error::Other(Error::Break))
296 } else if dr.pe() {
297 Err(nb::Error::Other(Error::Parity))
298 } else if dr.fe() {
299 Err(nb::Error::Other(Error::Framing))
300 } else if dr.fe() {
301 Ok(dr.data())
302 } else {
303 Err(nb::Error::WouldBlock)
88 } 304 }
89 } 305 }
90 } 306 }
91 } 307 }
308
309 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T> {
310 type Error = Error;
311 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
312 self.blocking_write(buffer)
313 }
314 fn bflush(&mut self) -> Result<(), Self::Error> {
315 self.blocking_flush()
316 }
317 }
318
319 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for Uart<'d, T> {
320 type Error = Error;
321 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
322 embedded_hal_02::serial::Read::read(&mut self.rx)
323 }
324 }
325
326 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T> {
327 type Error = Error;
328 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
329 self.blocking_write(buffer)
330 }
331 fn bflush(&mut self) -> Result<(), Self::Error> {
332 self.blocking_flush()
333 }
334 }
335}
336
337#[cfg(feature = "unstable-traits")]
338mod eh1 {
339 use super::*;
340
341 impl embedded_hal_1::serial::Error for Error {
342 fn kind(&self) -> embedded_hal_1::serial::ErrorKind {
343 match *self {
344 Self::Framing => embedded_hal_1::serial::ErrorKind::FrameFormat,
345 Self::Break => embedded_hal_1::serial::ErrorKind::Other,
346 Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun,
347 Self::Parity => embedded_hal_1::serial::ErrorKind::Parity,
348 }
349 }
350 }
351
352 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for Uart<'d, T> {
353 type Error = Error;
354 }
355
356 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UartTx<'d, T> {
357 type Error = Error;
358 }
359
360 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UartRx<'d, T> {
361 type Error = Error;
362 }
363}
364
365cfg_if::cfg_if! {
366 if #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "_todo_embedded_hal_serial"))] {
367 use core::future::Future;
368
369 impl<'d, T: Instance> embedded_hal_async::serial::Write for UartTx<'d, T>
370 {
371 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
372
373 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
374 self.write(buf)
375 }
376
377 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
378
379 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
380 async move { Ok(()) }
381 }
382 }
383
384 impl<'d, T: Instance> embedded_hal_async::serial::Read for UartRx<'d, T>
385 {
386 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
387
388 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
389 self.read(buf)
390 }
391 }
392
393 impl<'d, T: Instance> embedded_hal_async::serial::Write for Uart<'d, T>
394 {
395 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
396
397 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
398 self.write(buf)
399 }
400
401 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
402
403 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
404 async move { Ok(()) }
405 }
406 }
407
408 impl<'d, T: Instance> embedded_hal_async::serial::Read for Uart<'d, T>
409 {
410 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
411
412 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
413 self.read(buf)
414 }
415 }
416 }
92} 417}
93 418
94mod sealed { 419mod sealed {
95 use super::*; 420 use super::*;
96 421
97 pub trait Instance { 422 pub trait Instance {
98 fn regs(&self) -> pac::uart::Uart; 423 fn regs() -> pac::uart::Uart;
99 } 424 }
100 pub trait TxPin<T: Instance> {} 425 pub trait TxPin<T: Instance> {}
101 pub trait RxPin<T: Instance> {} 426 pub trait RxPin<T: Instance> {}
@@ -106,23 +431,23 @@ mod sealed {
106pub trait Instance: sealed::Instance {} 431pub trait Instance: sealed::Instance {}
107 432
108macro_rules! impl_instance { 433macro_rules! impl_instance {
109 ($type:ident, $irq:ident) => { 434 ($inst:ident, $irq:ident) => {
110 impl sealed::Instance for peripherals::$type { 435 impl sealed::Instance for peripherals::$inst {
111 fn regs(&self) -> pac::uart::Uart { 436 fn regs() -> pac::uart::Uart {
112 pac::$type 437 pac::$inst
113 } 438 }
114 } 439 }
115 impl Instance for peripherals::$type {} 440 impl Instance for peripherals::$inst {}
116 }; 441 };
117} 442}
118 443
119impl_instance!(UART0, UART0); 444impl_instance!(UART0, UART0);
120impl_instance!(UART1, UART1); 445impl_instance!(UART1, UART1);
121 446
122pub trait TxPin<T: Instance>: sealed::TxPin<T> + Pin {} 447pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
123pub trait RxPin<T: Instance>: sealed::RxPin<T> + Pin {} 448pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}
124pub trait CtsPin<T: Instance>: sealed::CtsPin<T> + Pin {} 449pub trait CtsPin<T: Instance>: sealed::CtsPin<T> + crate::gpio::Pin {}
125pub trait RtsPin<T: Instance>: sealed::RtsPin<T> + Pin {} 450pub trait RtsPin<T: Instance>: sealed::RtsPin<T> + crate::gpio::Pin {}
126 451
127macro_rules! impl_pin { 452macro_rules! impl_pin {
128 ($pin:ident, $instance:ident, $function:ident) => { 453 ($pin:ident, $instance:ident, $function:ident) => {
diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs
index 5fdc3ff77..c63b31cae 100644
--- a/examples/rp/src/bin/uart.rs
+++ b/examples/rp/src/bin/uart.rs
@@ -10,11 +10,11 @@ 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(p.UART0, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, config); 13 let mut uart = uart::Uart::new_with_rtscts(p.UART0, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, config);
14 uart.send("Hello World!\r\n".as_bytes()); 14 uart.blocking_write("Hello World!\r\n".as_bytes()).unwrap();
15 15
16 loop { 16 loop {
17 uart.send("hello there!\r\n".as_bytes()); 17 uart.blocking_write("hello there!\r\n".as_bytes()).unwrap();
18 cortex_m::asm::delay(1_000_000); 18 cortex_m::asm::delay(1_000_000);
19 } 19 }
20} 20}