1#![expect(unsafe_code)]
4
5use ariel_os_embassy_common::{impl_async_uart_for_driver_enum, uart::ConfigError};
6use embassy_nrf::{
7 Peripheral, bind_interrupts,
8 buffered_uarte::{BufferedUarte, InterruptHandler},
9 gpio::Pin as GpioPin,
10 peripherals,
11};
12
13#[derive(Debug, Copy, Clone, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16#[non_exhaustive]
17pub struct Config {
18 pub baudrate: ariel_os_embassy_common::uart::Baudrate<Baudrate>,
20 pub data_bits: DataBits,
22 pub stop_bits: StopBits,
24 pub parity: Parity,
26}
27
28impl Default for Config {
29 fn default() -> Self {
30 Self {
31 baudrate: ariel_os_embassy_common::uart::Baudrate::_115200,
32 data_bits: DataBits::Data8,
33 stop_bits: StopBits::Stop1,
34 parity: Parity::None,
35 }
36 }
37}
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42#[non_exhaustive]
43pub enum Baudrate {
44 _1200,
46 _2400,
48 _4800,
50 _9600,
52 _14400,
54 _19200,
56 _28800,
58 _31250,
60 _38400,
62 _56000,
64 _57600,
66 _76800,
68 _115200,
70 _230400,
72 _250000,
74 _460800,
76 _921600,
78 _1000000,
80}
81
82impl From<Baudrate> for u32 {
83 fn from(baud: Baudrate) -> u32 {
84 match baud {
85 Baudrate::_1200 => 1200,
86 Baudrate::_2400 => 2400,
87 Baudrate::_4800 => 4800,
88 Baudrate::_9600 => 9600,
89 Baudrate::_14400 => 14_400,
90 Baudrate::_19200 => 19_200,
91 Baudrate::_28800 => 28_800,
92 Baudrate::_31250 => 31_250,
93 Baudrate::_38400 => 38_400,
94 Baudrate::_56000 => 56_000,
95 Baudrate::_57600 => 57_600,
96 Baudrate::_76800 => 76_800,
97 Baudrate::_115200 => 11_5200,
98 Baudrate::_230400 => 23_0400,
99 Baudrate::_250000 => 25_0000,
100 Baudrate::_460800 => 46_0800,
101 Baudrate::_921600 => 92_1600,
102 Baudrate::_1000000 => 1_000_000,
103 }
104 }
105}
106
107fn from_baudrate(baud: Baudrate) -> embassy_nrf::buffered_uarte::Baudrate {
108 match baud {
109 Baudrate::_1200 => embassy_nrf::uarte::Baudrate::BAUD1200,
110 Baudrate::_2400 => embassy_nrf::uarte::Baudrate::BAUD2400,
111 Baudrate::_4800 => embassy_nrf::uarte::Baudrate::BAUD4800,
112 Baudrate::_9600 => embassy_nrf::uarte::Baudrate::BAUD9600,
113 Baudrate::_14400 => embassy_nrf::uarte::Baudrate::BAUD14400,
114 Baudrate::_19200 => embassy_nrf::uarte::Baudrate::BAUD19200,
115 Baudrate::_28800 => embassy_nrf::uarte::Baudrate::BAUD28800,
116 Baudrate::_31250 => embassy_nrf::uarte::Baudrate::BAUD31250,
117 Baudrate::_38400 => embassy_nrf::uarte::Baudrate::BAUD38400,
118 Baudrate::_56000 => embassy_nrf::uarte::Baudrate::BAUD56000,
119 Baudrate::_57600 => embassy_nrf::uarte::Baudrate::BAUD57600,
120 Baudrate::_76800 => embassy_nrf::uarte::Baudrate::BAUD76800,
121 Baudrate::_115200 => embassy_nrf::uarte::Baudrate::BAUD115200,
122 Baudrate::_230400 => embassy_nrf::uarte::Baudrate::BAUD230400,
123 Baudrate::_250000 => embassy_nrf::uarte::Baudrate::BAUD250000,
124 Baudrate::_460800 => embassy_nrf::uarte::Baudrate::BAUD460800,
125 Baudrate::_921600 => embassy_nrf::uarte::Baudrate::BAUD921600,
126 Baudrate::_1000000 => embassy_nrf::uarte::Baudrate::BAUD1M,
127 }
128}
129
130impl From<ariel_os_embassy_common::uart::Baudrate<Self>> for Baudrate {
131 fn from(baud: ariel_os_embassy_common::uart::Baudrate<Self>) -> Baudrate {
132 match baud {
133 ariel_os_embassy_common::uart::Baudrate::Hal(baud) => baud,
134 ariel_os_embassy_common::uart::Baudrate::_2400 => Baudrate::_2400,
135 ariel_os_embassy_common::uart::Baudrate::_4800 => Baudrate::_4800,
136 ariel_os_embassy_common::uart::Baudrate::_9600 => Baudrate::_9600,
137 ariel_os_embassy_common::uart::Baudrate::_19200 => Baudrate::_19200,
138 ariel_os_embassy_common::uart::Baudrate::_38400 => Baudrate::_38400,
139 ariel_os_embassy_common::uart::Baudrate::_57600 => Baudrate::_57600,
140 ariel_os_embassy_common::uart::Baudrate::_115200 => Baudrate::_115200,
141 }
142 }
143}
144
145#[derive(Debug, Copy, Clone, PartialEq, Eq)]
147#[cfg_attr(feature = "defmt", derive(defmt::Format))]
148#[non_exhaustive]
149pub enum DataBits {
150 Data8,
152}
153
154impl From<ariel_os_embassy_common::uart::DataBits<Self>> for DataBits {
155 fn from(databits: ariel_os_embassy_common::uart::DataBits<Self>) -> DataBits {
156 match databits {
157 ariel_os_embassy_common::uart::DataBits::Hal(bits) => bits,
158 ariel_os_embassy_common::uart::DataBits::Data8 => DataBits::Data8,
159 }
160 }
161}
162#[derive(Debug, Copy, Clone, PartialEq, Eq)]
164#[cfg_attr(feature = "defmt", derive(defmt::Format))]
165#[non_exhaustive]
166pub enum StopBits {
167 Stop1,
169}
170
171impl From<ariel_os_embassy_common::uart::StopBits<Self>> for StopBits {
172 fn from(stopbits: ariel_os_embassy_common::uart::StopBits<Self>) -> Self {
173 match stopbits {
174 ariel_os_embassy_common::uart::StopBits::Hal(stopbits) => stopbits,
175 ariel_os_embassy_common::uart::StopBits::Stop1 => StopBits::Stop1,
176 }
177 }
178}
179
180#[derive(Debug, Copy, Clone, PartialEq, Eq)]
182#[cfg_attr(feature = "defmt", derive(defmt::Format))]
183#[non_exhaustive]
184pub enum Parity {
185 None,
187 Even,
189}
190
191fn from_parity(parity: Parity) -> embassy_nrf::uarte::Parity {
192 match parity {
193 Parity::None => embassy_nrf::uarte::Parity::EXCLUDED,
194 Parity::Even => embassy_nrf::uarte::Parity::INCLUDED,
195 }
196}
197
198impl From<ariel_os_embassy_common::uart::Parity<Self>> for Parity {
199 fn from(parity: ariel_os_embassy_common::uart::Parity<Self>) -> Self {
200 match parity {
201 ariel_os_embassy_common::uart::Parity::Hal(parity) => parity,
202 ariel_os_embassy_common::uart::Parity::None => Self::None,
203 ariel_os_embassy_common::uart::Parity::Even => Self::Even,
204 }
205 }
206}
207
208macro_rules! define_uart_drivers {
209 ($( $interrupt:ident => $peripheral:ident + $timer:ident + $ppi_ch1:ident + $ppi_ch2:ident + $ppi_group:ident),* $(,)?) => {
210 $(
211 pub struct $peripheral<'d> {
213 uart: BufferedUarte<'d, peripherals::$peripheral, peripherals::$timer>,
214 }
215
216 paste::paste! {
219 #[allow(dead_code)]
220 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
221 #[allow(dead_code)]
222 static [<PREVENT_MULTIPLE_ $timer>]: () = ();
223 #[allow(dead_code)]
224 static [<PREVENT_MULTIPLE_ $ppi_ch1>]: () = ();
225 #[allow(dead_code)]
226 static [<PREVENT_MULTIPLE_ $ppi_ch2>]: () = ();
227 #[allow(dead_code)]
228 static [<PREVENT_MULTIPLE_ $ppi_group>]: () = ();
229 }
230
231 impl<'d> $peripheral<'d> {
232 #[expect(clippy::new_ret_no_self)]
239 pub fn new(
240 rx_pin: impl Peripheral<P: GpioPin> + 'd,
241 tx_pin: impl Peripheral<P: GpioPin> + 'd,
242 rx_buffer: &'d mut [u8],
243 tx_buffer: &'d mut [u8],
244 config: Config,
245 ) -> Result<Uart<'d>, ConfigError> {
246 let mut uart_config = embassy_nrf::uarte::Config::default();
247 uart_config.baudrate = from_baudrate(Baudrate::from(config.baudrate));
248 uart_config.parity = from_parity(config.parity);
249 bind_interrupts!(struct Irqs {
250 $interrupt => InterruptHandler<peripherals::$peripheral>;
251 });
252
253 let uart_peripheral = unsafe { peripherals::$peripheral::steal() };
257 let timer_peripheral = unsafe { peripherals::$timer::steal() };
260 let ppi_ch1_peripheral = unsafe { peripherals::$ppi_ch1::steal() };
263 let ppi_ch2_peripheral = unsafe { peripherals::$ppi_ch2::steal() };
266 let ppi_group_peripheral = unsafe { peripherals::$ppi_group::steal() };
269
270 let uart = BufferedUarte::new(
271 uart_peripheral,
272 timer_peripheral,
273 ppi_ch1_peripheral,
274 ppi_ch2_peripheral,
275 ppi_group_peripheral,
276 Irqs,
277 rx_pin,
278 tx_pin,
279 uart_config,
280 rx_buffer,
281 tx_buffer
282 );
283
284 Ok(Uart::$peripheral(Self { uart }))
285 }
286 }
287 )*
288
289 pub enum Uart<'d> {
291 $(
292 #[doc = concat!(stringify!($peripheral), " peripheral.")]
293 $peripheral($peripheral<'d>)
294 ),*
295 }
296
297 impl embedded_io_async::ErrorType for Uart<'_> {
298 type Error = embassy_nrf::buffered_uarte::Error;
299 }
300
301 impl_async_uart_for_driver_enum!(Uart, $( $peripheral ),*);
302 }
303}
304
305#[cfg(context = "nrf52832")]
307define_uart_drivers!(
308 UARTE0 => UARTE0 + TIMER4 + PPI_CH14 + PPI_CH15 + PPI_GROUP5,
309);
310#[cfg(context = "nrf52833")]
311define_uart_drivers!(
312 UARTE0 => UARTE0 + TIMER3 + PPI_CH13 + PPI_CH14 + PPI_GROUP4,
313 UARTE1 => UARTE1 + TIMER4 + PPI_CH15 + PPI_CH16 + PPI_GROUP5,
314);
315#[cfg(context = "nrf52840")]
316define_uart_drivers!(
317 UARTE0 => UARTE0 + TIMER3 + PPI_CH13 + PPI_CH14 + PPI_GROUP4,
318 UARTE1 => UARTE1 + TIMER4 + PPI_CH15 + PPI_CH16 + PPI_GROUP5,
319);
320#[cfg(context = "nrf5340")]
321define_uart_drivers!(
322 SERIAL3 => SERIAL3 + TIMER2 + PPI_CH18 + PPI_CH19 + PPI_GROUP5,
323);
324#[cfg(any(context = "nrf9151", context = "nrf9160"))]
325define_uart_drivers!(
326 SERIAL3 => SERIAL3 + TIMER2 + PPI_CH14 + PPI_CH15 + PPI_GROUP5,
327);
328
329#[doc(hidden)]
330pub fn init(peripherals: &mut crate::OptionalPeripherals) {
331 cfg_if::cfg_if! {
333 if #[cfg(context = "nrf52832")] {
334 let _ = peripherals.UARTE0.take().unwrap();
335 let _ = peripherals.TIMER4.take().unwrap();
336 let _ = peripherals.PPI_CH14.take().unwrap();
337 let _ = peripherals.PPI_CH15.take().unwrap();
338 let _ = peripherals.PPI_GROUP5.take().unwrap();
339 } else if #[cfg(context = "nrf52833")] {
340 let _ = peripherals.UARTE0.take().unwrap();
341 let _ = peripherals.TIMER3.take().unwrap();
342 let _ = peripherals.PPI_CH13.take().unwrap();
343 let _ = peripherals.PPI_CH14.take().unwrap();
344 let _ = peripherals.PPI_GROUP4.take().unwrap();
345
346 let _ = peripherals.UARTE1.take().unwrap();
347 let _ = peripherals.TIMER4.take().unwrap();
348 let _ = peripherals.PPI_CH15.take().unwrap();
349 let _ = peripherals.PPI_CH16.take().unwrap();
350 let _ = peripherals.PPI_GROUP5.take().unwrap();
351 } else if #[cfg(context = "nrf52840")] {
352 let _ = peripherals.UARTE0.take().unwrap();
353 let _ = peripherals.TIMER3.take().unwrap();
354 let _ = peripherals.PPI_CH13.take().unwrap();
355 let _ = peripherals.PPI_CH14.take().unwrap();
356 let _ = peripherals.PPI_GROUP4.take().unwrap();
357
358 let _ = peripherals.UARTE1.take().unwrap();
359 let _ = peripherals.TIMER4.take().unwrap();
360 let _ = peripherals.PPI_CH15.take().unwrap();
361 let _ = peripherals.PPI_CH16.take().unwrap();
362 let _ = peripherals.PPI_GROUP5.take().unwrap();
363 } else if #[cfg(context = "nrf5340")] {
364 let _ = peripherals.SERIAL3.take().unwrap();
365 let _ = peripherals.TIMER2.take().unwrap();
366 let _ = peripherals.PPI_CH18.take().unwrap();
367 let _ = peripherals.PPI_CH19.take().unwrap();
368 let _ = peripherals.PPI_GROUP5.take().unwrap();
369 } else if #[cfg(any(context = "nrf9151", context = "nrf9160"))] {
370 let _ = peripherals.SERIAL3.take().unwrap();
371 let _ = peripherals.TIMER2.take().unwrap();
372 let _ = peripherals.PPI_CH14.take().unwrap();
373 let _ = peripherals.PPI_CH15.take().unwrap();
374 let _ = peripherals.PPI_GROUP5.take().unwrap();
375 } else {
376 compile_error!("this nRF chip is not supported");
377 }
378 }
379}