aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/uart.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp/src/uart.rs')
-rw-r--r--embassy-rp/src/uart.rs173
1 files changed, 173 insertions, 0 deletions
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs
new file mode 100644
index 000000000..3eb768a7d
--- /dev/null
+++ b/embassy-rp/src/uart.rs
@@ -0,0 +1,173 @@
1use core::marker::PhantomData;
2
3use embassy::util::PeripheralBorrow;
4use embassy_extras::unborrow;
5use gpio::Pin;
6
7use crate::{gpio, pac, peripherals};
8
9#[non_exhaustive]
10pub struct Config {
11 pub baudrate: u32,
12 pub data_bits: u8,
13 pub stop_bits: u8,
14}
15
16impl Default for Config {
17 fn default() -> Self {
18 Self {
19 baudrate: 115200,
20 data_bits: 8,
21 stop_bits: 1,
22 }
23 }
24}
25
26pub struct Uart<'d, T: Instance> {
27 inner: T,
28 phantom: PhantomData<&'d mut T>,
29}
30
31impl<'d, T: Instance> Uart<'d, T> {
32 pub fn new(
33 inner: impl PeripheralBorrow<Target = T>,
34 tx: impl PeripheralBorrow<Target = impl TxPin<T>>,
35 rx: impl PeripheralBorrow<Target = impl RxPin<T>>,
36 cts: impl PeripheralBorrow<Target = impl CtsPin<T>>,
37 rts: impl PeripheralBorrow<Target = impl RtsPin<T>>,
38 config: Config,
39 ) -> Self {
40 unborrow!(inner, tx, rx, cts, rts);
41
42 unsafe {
43 let p = inner.regs();
44
45 // todo get this from somewhere
46 let clk_base = 12_000_000;
47
48 let baud_rate_div = (8 * clk_base) / config.baudrate;
49 let mut baud_ibrd = baud_rate_div >> 7;
50 let mut baud_fbrd = ((baud_rate_div & 0x7f) + 1) / 2;
51
52 if baud_ibrd == 0 {
53 baud_ibrd = 1;
54 baud_fbrd = 0;
55 } else if baud_ibrd >= 65535 {
56 baud_ibrd = 65535;
57 baud_fbrd = 0;
58 }
59
60 // Load PL011's baud divisor registers
61 p.uartibrd()
62 .write_value(pac::uart::regs::Uartibrd(baud_ibrd));
63 p.uartfbrd()
64 .write_value(pac::uart::regs::Uartfbrd(baud_fbrd));
65
66 p.uartlcr_h().write(|w| {
67 w.set_wlen(config.data_bits - 5);
68 w.set_stp2(config.stop_bits == 2);
69 w.set_pen(false);
70 w.set_eps(false);
71 w.set_fen(true);
72 });
73
74 p.uartcr().write(|w| {
75 w.set_uarten(true);
76 w.set_rxe(true);
77 w.set_txe(true);
78 });
79
80 tx.io().ctrl().write(|w| w.set_funcsel(2));
81 rx.io().ctrl().write(|w| w.set_funcsel(2));
82 cts.io().ctrl().write(|w| w.set_funcsel(2));
83 rts.io().ctrl().write(|w| w.set_funcsel(2));
84 }
85 Self {
86 inner,
87 phantom: PhantomData,
88 }
89 }
90
91 pub fn send(&mut self, data: &[u8]) {
92 unsafe {
93 let p = self.inner.regs();
94
95 for &byte in data {
96 if !p.uartfr().read().txff() {
97 p.uartdr().write(|w| w.set_data(byte));
98 }
99 }
100 }
101 }
102}
103
104mod sealed {
105 use super::*;
106
107 pub trait Instance {
108 fn regs(&self) -> pac::uart::Uart;
109 }
110 pub trait TxPin<T: Instance> {}
111 pub trait RxPin<T: Instance> {}
112 pub trait CtsPin<T: Instance> {}
113 pub trait RtsPin<T: Instance> {}
114}
115
116pub trait Instance: sealed::Instance {}
117
118macro_rules! impl_instance {
119 ($type:ident, $irq:ident) => {
120 impl sealed::Instance for peripherals::$type {
121 fn regs(&self) -> pac::uart::Uart {
122 pac::$type
123 }
124 }
125 impl Instance for peripherals::$type {}
126 };
127}
128
129impl_instance!(UART0, UART0);
130impl_instance!(UART1, UART1);
131
132pub trait TxPin<T: Instance>: sealed::TxPin<T> + Pin {}
133pub trait RxPin<T: Instance>: sealed::RxPin<T> + Pin {}
134pub trait CtsPin<T: Instance>: sealed::CtsPin<T> + Pin {}
135pub trait RtsPin<T: Instance>: sealed::RtsPin<T> + Pin {}
136
137macro_rules! impl_pin {
138 ($pin:ident, $instance:ident, $function:ident) => {
139 impl sealed::$function<peripherals::$instance> for peripherals::$pin {}
140 impl $function<peripherals::$instance> for peripherals::$pin {}
141 };
142}
143
144impl_pin!(PIN_0, UART0, TxPin);
145impl_pin!(PIN_1, UART0, RxPin);
146impl_pin!(PIN_2, UART0, CtsPin);
147impl_pin!(PIN_3, UART0, RtsPin);
148impl_pin!(PIN_4, UART1, TxPin);
149impl_pin!(PIN_5, UART1, RxPin);
150impl_pin!(PIN_6, UART1, CtsPin);
151impl_pin!(PIN_7, UART1, RtsPin);
152impl_pin!(PIN_8, UART1, TxPin);
153impl_pin!(PIN_9, UART1, RxPin);
154impl_pin!(PIN_10, UART1, CtsPin);
155impl_pin!(PIN_11, UART1, RtsPin);
156impl_pin!(PIN_12, UART0, TxPin);
157impl_pin!(PIN_13, UART0, RxPin);
158impl_pin!(PIN_14, UART0, CtsPin);
159impl_pin!(PIN_15, UART0, RtsPin);
160impl_pin!(PIN_16, UART0, TxPin);
161impl_pin!(PIN_17, UART0, RxPin);
162impl_pin!(PIN_18, UART0, CtsPin);
163impl_pin!(PIN_19, UART0, RtsPin);
164impl_pin!(PIN_20, UART1, TxPin);
165impl_pin!(PIN_21, UART1, RxPin);
166impl_pin!(PIN_22, UART1, CtsPin);
167impl_pin!(PIN_23, UART1, RtsPin);
168impl_pin!(PIN_24, UART1, TxPin);
169impl_pin!(PIN_25, UART1, RxPin);
170impl_pin!(PIN_26, UART1, CtsPin);
171impl_pin!(PIN_27, UART1, RtsPin);
172impl_pin!(PIN_28, UART0, TxPin);
173impl_pin!(PIN_29, UART0, RxPin);