1#![expect(unsafe_code)]
4
5use ariel_os_embassy_common::{impl_async_uart_for_driver_enum, uart::ConfigError};
6
7use embassy_rp::{
8 Peri, bind_interrupts, peripherals,
9 uart::{BufferedInterruptHandler, BufferedUart, RxPin, TxPin},
10};
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15#[non_exhaustive]
16pub struct Config {
17 pub baudrate: ariel_os_embassy_common::uart::Baudrate<Baudrate>,
19 pub data_bits: DataBits,
21 pub stop_bits: StopBits,
23 pub parity: Parity,
25}
26
27impl Default for Config {
28 fn default() -> Self {
29 Self {
30 baudrate: ariel_os_embassy_common::uart::Baudrate::_115200,
31 data_bits: DataBits::Data8,
32 stop_bits: StopBits::Stop1,
33 parity: Parity::None,
34 }
35 }
36}
37
38#[derive(Debug, Copy, Clone, PartialEq, Eq)]
40#[cfg_attr(feature = "defmt", derive(defmt::Format))]
41pub struct Baudrate {
42 baud: u32,
44}
45
46impl From<Baudrate> for u32 {
47 fn from(baud: Baudrate) -> u32 {
48 baud.baud
49 }
50}
51
52impl From<u32> for Baudrate {
53 fn from(baudrate: u32) -> Baudrate {
54 Baudrate { baud: baudrate }
55 }
56}
57
58impl From<ariel_os_embassy_common::uart::Baudrate<Self>> for Baudrate {
59 fn from(baud: ariel_os_embassy_common::uart::Baudrate<Self>) -> Baudrate {
60 match baud {
61 ariel_os_embassy_common::uart::Baudrate::Hal(baud) => baud,
62 ariel_os_embassy_common::uart::Baudrate::_2400 => Baudrate { baud: 2400 },
63 ariel_os_embassy_common::uart::Baudrate::_4800 => Baudrate { baud: 4800 },
64 ariel_os_embassy_common::uart::Baudrate::_9600 => Baudrate { baud: 9600 },
65 ariel_os_embassy_common::uart::Baudrate::_19200 => Baudrate { baud: 19_200 },
66 ariel_os_embassy_common::uart::Baudrate::_38400 => Baudrate { baud: 38_400 },
67 ariel_os_embassy_common::uart::Baudrate::_57600 => Baudrate { baud: 57_600 },
68 ariel_os_embassy_common::uart::Baudrate::_115200 => Baudrate { baud: 115_200 },
69 }
70 }
71}
72
73#[derive(Debug, Copy, Clone, PartialEq, Eq)]
75#[cfg_attr(feature = "defmt", derive(defmt::Format))]
76pub enum DataBits {
77 Data5,
79 Data6,
81 Data7,
83 Data8,
85}
86
87fn from_data_bits(databits: DataBits) -> embassy_rp::uart::DataBits {
88 match databits {
89 DataBits::Data5 => embassy_rp::uart::DataBits::DataBits5,
90 DataBits::Data6 => embassy_rp::uart::DataBits::DataBits6,
91 DataBits::Data7 => embassy_rp::uart::DataBits::DataBits7,
92 DataBits::Data8 => embassy_rp::uart::DataBits::DataBits8,
93 }
94}
95
96impl From<ariel_os_embassy_common::uart::DataBits<Self>> for DataBits {
97 fn from(databits: ariel_os_embassy_common::uart::DataBits<Self>) -> DataBits {
98 match databits {
99 ariel_os_embassy_common::uart::DataBits::Hal(bits) => bits,
100 ariel_os_embassy_common::uart::DataBits::Data8 => DataBits::Data8,
101 }
102 }
103}
104
105#[derive(Debug, Copy, Clone, PartialEq, Eq)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108pub enum Parity {
109 None,
111 Even,
113 Odd,
115}
116
117fn from_parity(parity: Parity) -> embassy_rp::uart::Parity {
118 match parity {
119 Parity::None => embassy_rp::uart::Parity::ParityNone,
120 Parity::Even => embassy_rp::uart::Parity::ParityEven,
121 Parity::Odd => embassy_rp::uart::Parity::ParityOdd,
122 }
123}
124
125impl From<ariel_os_embassy_common::uart::Parity<Self>> for Parity {
126 fn from(parity: ariel_os_embassy_common::uart::Parity<Self>) -> Self {
127 match parity {
128 ariel_os_embassy_common::uart::Parity::Hal(parity) => parity,
129 ariel_os_embassy_common::uart::Parity::None => Self::None,
130 ariel_os_embassy_common::uart::Parity::Even => Self::Even,
131 }
132 }
133}
134
135#[derive(Debug, Copy, Clone, PartialEq, Eq)]
137#[cfg_attr(feature = "defmt", derive(defmt::Format))]
138pub enum StopBits {
139 Stop1,
141 Stop2,
143}
144
145fn from_stop_bits(stop_bits: StopBits) -> embassy_rp::uart::StopBits {
146 match stop_bits {
147 StopBits::Stop1 => embassy_rp::uart::StopBits::STOP1,
148 StopBits::Stop2 => embassy_rp::uart::StopBits::STOP2,
149 }
150}
151
152impl From<ariel_os_embassy_common::uart::StopBits<Self>> for StopBits {
153 fn from(stopbits: ariel_os_embassy_common::uart::StopBits<Self>) -> Self {
154 match stopbits {
155 ariel_os_embassy_common::uart::StopBits::Hal(stopbits) => stopbits,
156 ariel_os_embassy_common::uart::StopBits::Stop1 => StopBits::Stop1,
157 }
158 }
159}
160
161macro_rules! define_uart_drivers {
162 ($( $interrupt:ident => $peripheral:ident ),* $(,)?) => {
163 $(
164 pub struct $peripheral<'d> {
166 uart: BufferedUart,
167 _phantom: core::marker::PhantomData<&'d ()>
171 }
172
173 paste::paste! {
176 #[allow(dead_code)]
177 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
178 }
179
180 impl<'d> $peripheral<'d> {
181 #[expect(clippy::new_ret_no_self)]
188 pub fn new(
189 rx_pin: Peri<'d, impl RxPin<peripherals::$peripheral>>,
190 tx_pin: Peri<'d, impl TxPin<peripherals::$peripheral>>,
191 rx_buf: &mut [u8],
192 tx_buf: &mut [u8],
193 config: Config,
194 ) -> Result<Uart<'d>, ConfigError> {
195 let mut uart_config = embassy_rp::uart::Config::default();
196 uart_config.baudrate = Baudrate::from(config.baudrate).into();
197 uart_config.data_bits = from_data_bits(config.data_bits);
198 uart_config.stop_bits = from_stop_bits(config.stop_bits);
199 uart_config.parity = from_parity(config.parity);
200 bind_interrupts!(struct Irqs {
201 $interrupt => BufferedInterruptHandler<peripherals::$peripheral>;
202 });
203
204 let uart_peripheral = unsafe { peripherals::$peripheral::steal() };
208
209 let uart = BufferedUart::new(
210 uart_peripheral,
211 tx_pin,
213 rx_pin,
214 Irqs,
215 tx_buf,
216 rx_buf,
217 uart_config,
218 );
219
220 Ok(Uart::$peripheral(Self { uart, _phantom: core::marker::PhantomData }))
221 }
222 }
223 )*
224
225 pub enum Uart<'d> {
227 $(
228 #[doc = concat!(stringify!($peripheral), " peripheral.")]
229 $peripheral($peripheral<'d>)
230 ),*
231 }
232
233 impl embedded_io_async::ErrorType for Uart<'_> {
234 type Error = embassy_rp::uart::Error;
235 }
236
237 impl_async_uart_for_driver_enum!(Uart, $( $peripheral ),*);
238 }
239}
240
241define_uart_drivers!(
242 UART0_IRQ => UART0,
243 UART1_IRQ => UART1,
244);
245
246#[doc(hidden)]
247pub fn init(peripherals: &mut crate::OptionalPeripherals) {
248 cfg_if::cfg_if! {
250 if #[cfg(any(context = "rp2040", context = "rp235xa"))] {
251 let _ = peripherals.UART0.take().unwrap();
252 let _ = peripherals.UART1.take().unwrap();
253 } else {
254 compile_error!("this RP chip is not supported");
255 }
256 }
257}