1#![expect(unsafe_code)]
4
5use ariel_os_embassy_common::{impl_async_uart_for_driver_enum, uart::ConfigError};
6
7use embassy_rp::{
8 Peripheral, 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<'d, peripherals::$peripheral>,
167 }
168
169 paste::paste! {
172 #[allow(dead_code)]
173 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
174 }
175
176 impl<'d> $peripheral<'d> {
177 #[expect(clippy::new_ret_no_self)]
184 pub fn new(
185 rx_pin: impl Peripheral<P: RxPin<peripherals::$peripheral>> + 'd,
186 tx_pin: impl Peripheral<P: TxPin<peripherals::$peripheral>> + 'd,
187 rx_buf: &'d mut [u8],
188 tx_buf: &'d mut [u8],
189 config: Config,
190 ) -> Result<Uart<'d>, ConfigError> {
191 let mut uart_config = embassy_rp::uart::Config::default();
192 uart_config.baudrate = Baudrate::from(config.baudrate).into();
193 uart_config.data_bits = from_data_bits(config.data_bits);
194 uart_config.stop_bits = from_stop_bits(config.stop_bits);
195 uart_config.parity = from_parity(config.parity);
196 bind_interrupts!(struct Irqs {
197 $interrupt => BufferedInterruptHandler<peripherals::$peripheral>;
198 });
199
200 let uart_peripheral = unsafe { peripherals::$peripheral::steal() };
204
205 let uart = BufferedUart::new(
206 uart_peripheral,
207 Irqs,
208 tx_pin,
210 rx_pin,
211 tx_buf,
212 rx_buf,
213 uart_config,
214 );
215
216 Ok(Uart::$peripheral(Self { uart }))
217 }
218 }
219 )*
220
221 pub enum Uart<'d> {
223 $(
224 #[doc = concat!(stringify!($peripheral), " peripheral.")]
225 $peripheral($peripheral<'d>)
226 ),*
227 }
228
229 impl embedded_io_async::ErrorType for Uart<'_> {
230 type Error = embassy_rp::uart::Error;
231 }
232
233 impl_async_uart_for_driver_enum!(Uart, $( $peripheral ),*);
234 }
235}
236
237define_uart_drivers!(
238 UART0_IRQ => UART0,
239 UART1_IRQ => UART1,
240);
241
242#[doc(hidden)]
243pub fn init(peripherals: &mut crate::OptionalPeripherals) {
244 cfg_if::cfg_if! {
246 if #[cfg(any(context = "rp2040", context = "rp235xa"))] {
247 let _ = peripherals.UART0.take().unwrap();
248 let _ = peripherals.UART1.take().unwrap();
249 } else {
250 compile_error!("this RP chip is not supported");
251 }
252 }
253}