1#![expect(unsafe_code)]
4
5use portable_atomic::{AtomicBool, Ordering};
6
7use ariel_os_embassy_common::{impl_async_uart_for_driver_enum, uart::ConfigError};
8use embassy_stm32::{
9 bind_interrupts, peripherals,
10 usart::{BufferedInterruptHandler, BufferedUart, RxPin, TxPin},
11};
12
13#[derive(Debug, 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))]
42pub struct Baudrate {
43 baudrate: u32,
45}
46
47impl From<Baudrate> for u32 {
48 fn from(baudrate: Baudrate) -> u32 {
49 baudrate.baudrate
50 }
51}
52
53impl From<u32> for Baudrate {
54 fn from(baudrate: u32) -> Baudrate {
55 Baudrate { baudrate }
56 }
57}
58
59impl From<ariel_os_embassy_common::uart::Baudrate<Self>> for Baudrate {
60 fn from(baud: ariel_os_embassy_common::uart::Baudrate<Self>) -> Baudrate {
61 match baud {
62 ariel_os_embassy_common::uart::Baudrate::Hal(baudrate) => baudrate,
63 ariel_os_embassy_common::uart::Baudrate::_2400 => Baudrate { baudrate: 2400 },
64 ariel_os_embassy_common::uart::Baudrate::_4800 => Baudrate { baudrate: 4800 },
65 ariel_os_embassy_common::uart::Baudrate::_9600 => Baudrate { baudrate: 9600 },
66 ariel_os_embassy_common::uart::Baudrate::_19200 => Baudrate { baudrate: 19_200 },
67 ariel_os_embassy_common::uart::Baudrate::_38400 => Baudrate { baudrate: 38_400 },
68 ariel_os_embassy_common::uart::Baudrate::_57600 => Baudrate { baudrate: 57_600 },
69 ariel_os_embassy_common::uart::Baudrate::_115200 => Baudrate { baudrate: 115_200 },
70 }
71 }
72}
73
74#[derive(Debug, Copy, Clone, PartialEq, Eq)]
76#[cfg_attr(feature = "defmt", derive(defmt::Format))]
77pub enum DataBits {
78 Data7,
80 Data8,
82 Data9,
84}
85
86fn from_databits(databits: DataBits) -> embassy_stm32::usart::DataBits {
87 match databits {
88 DataBits::Data7 => embassy_stm32::usart::DataBits::DataBits7,
89 DataBits::Data8 => embassy_stm32::usart::DataBits::DataBits8,
90 DataBits::Data9 => embassy_stm32::usart::DataBits::DataBits9,
91 }
92}
93
94impl From<ariel_os_embassy_common::uart::DataBits<Self>> for DataBits {
95 fn from(databits: ariel_os_embassy_common::uart::DataBits<Self>) -> DataBits {
96 match databits {
97 ariel_os_embassy_common::uart::DataBits::Hal(bits) => bits,
98 ariel_os_embassy_common::uart::DataBits::Data8 => DataBits::Data8,
99 }
100 }
101}
102
103#[derive(Debug, Copy, Clone, PartialEq, Eq)]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106pub enum Parity {
107 None,
109 Even,
111 Odd,
113}
114
115fn from_parity(parity: Parity) -> embassy_stm32::usart::Parity {
116 match parity {
117 Parity::None => embassy_stm32::usart::Parity::ParityNone,
118 Parity::Even => embassy_stm32::usart::Parity::ParityEven,
119 Parity::Odd => embassy_stm32::usart::Parity::ParityOdd,
120 }
121}
122
123impl From<ariel_os_embassy_common::uart::Parity<Self>> for Parity {
124 fn from(parity: ariel_os_embassy_common::uart::Parity<Self>) -> Self {
125 match parity {
126 ariel_os_embassy_common::uart::Parity::Hal(parity) => parity,
127 ariel_os_embassy_common::uart::Parity::None => Self::None,
128 ariel_os_embassy_common::uart::Parity::Even => Self::Even,
129 }
130 }
131}
132
133#[derive(Debug, Copy, Clone, PartialEq, Eq)]
135#[cfg_attr(feature = "defmt", derive(defmt::Format))]
136pub enum StopBits {
137 Stop1,
139 Stop0P5,
141 Stop2,
143 Stop1P5,
145}
146
147fn from_stopbits(stop_bits: StopBits) -> embassy_stm32::usart::StopBits {
148 match stop_bits {
149 StopBits::Stop1 => embassy_stm32::usart::StopBits::STOP1,
150 StopBits::Stop0P5 => embassy_stm32::usart::StopBits::STOP0P5,
151 StopBits::Stop2 => embassy_stm32::usart::StopBits::STOP2,
152 StopBits::Stop1P5 => embassy_stm32::usart::StopBits::STOP1P5,
153 }
154}
155
156impl From<ariel_os_embassy_common::uart::StopBits<Self>> for StopBits {
157 fn from(stopbits: ariel_os_embassy_common::uart::StopBits<Self>) -> Self {
158 match stopbits {
159 ariel_os_embassy_common::uart::StopBits::Hal(stopbits) => stopbits,
160 ariel_os_embassy_common::uart::StopBits::Stop1 => StopBits::Stop1,
161 }
162 }
163}
164
165fn convert_error(err: embassy_stm32::usart::ConfigError) -> ConfigError {
166 match err {
167 embassy_stm32::usart::ConfigError::BaudrateTooLow
168 | embassy_stm32::usart::ConfigError::BaudrateTooHigh => ConfigError::BaudrateNotSupported,
169 embassy_stm32::usart::ConfigError::DataParityNotSupported => {
170 ConfigError::DataParityNotSupported
171 }
172 _ => ConfigError::ConfigurationNotSupported,
173 }
174}
175
176macro_rules! define_uart_drivers {
177 ($( $interrupt:ident => $peripheral:ident ),* $(,)?) => {
178 $(
179 pub struct $peripheral<'d> {
181 uart: BufferedUart<'d>,
182 }
183
184 paste::paste! {
187 #[allow(dead_code)]
188 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
189 }
190
191 paste::paste! {
193 static [< ACTIVE_ $peripheral >]: AtomicBool = AtomicBool::new(false);
194 }
195
196 impl<'d> $peripheral<'d> {
197 #[expect(clippy::new_ret_no_self)]
209 pub fn new<RX: RxPin<peripherals::$peripheral>, TX: TxPin<peripherals::$peripheral>>(
210 rx_pin: impl $crate::IntoPeripheral<'d, RX>,
211 tx_pin: impl $crate::IntoPeripheral<'d, TX>,
212 rx_buf: &'d mut [u8],
213 tx_buf: &'d mut [u8],
214 config: Config,
215 ) -> Result<Uart<'d>, ConfigError> {
216
217 let mut uart_config = embassy_stm32::usart::Config::default();
218 uart_config.baudrate = Baudrate::from(config.baudrate).into();
219 uart_config.data_bits = from_databits(config.data_bits).into();
220 uart_config.stop_bits = from_stopbits(config.stop_bits).into();
221 uart_config.parity = from_parity(config.parity).into();
222 bind_interrupts!(struct Irqs {
223 $interrupt => BufferedInterruptHandler<peripherals::$peripheral>;
224 });
225
226 let uart_peripheral = unsafe { peripherals::$peripheral::steal() };
230
231 paste::paste! {
233 if [< ACTIVE_ $peripheral >].swap(true, Ordering::AcqRel) {
234 panic!("UART peripheral already initialized")
235 }
236 }
237
238 let uart = BufferedUart::new(
239 uart_peripheral,
240 rx_pin.into_hal_peripheral(),
241 tx_pin.into_hal_peripheral(),
242 tx_buf,
243 rx_buf,
244 Irqs,
245 uart_config,
246 ).map_err(|e| {
247 paste::paste! {
249 [< ACTIVE_ $peripheral >].store(false, Ordering::Release);
250 }
251 convert_error(e)
252 })?;
253
254 Ok(Uart::$peripheral(Self { uart }))
255 }
256 }
257
258 impl<'d> Drop for $peripheral<'d> {
259 fn drop(&mut self) {
260 paste::paste! {
261 [< ACTIVE_ $peripheral >].store(false, Ordering::Release);
262 }
263 }
264 }
265 )*
266
267 pub enum Uart<'d> {
269 $(
270 #[doc = concat!(stringify!($peripheral), " peripheral.")]
271 $peripheral($peripheral<'d>)
272 ),*
273 }
274
275 impl embedded_io_async::ErrorType for Uart<'_> {
276 type Error = embassy_stm32::usart::Error;
277 }
278
279 impl_async_uart_for_driver_enum!(Uart, $( $peripheral ),*);
280 }
281}
282
283#[cfg(context = "stm32c031c6")]
284define_uart_drivers!(
285 USART1 => USART1,
286 USART2 => USART2,
287);
288#[cfg(context = "stm32f042k6")]
289define_uart_drivers!(
290 USART1 => USART1,
291 USART2 => USART2,
292);
293#[cfg(context = "stm32f303cb")]
294define_uart_drivers!(
295 USART1 => USART1,
296 USART2 => USART2,
297 USART3 => USART3,
298);
299#[cfg(context = "stm32f303re")]
300define_uart_drivers!(
301 USART1 => USART1,
302 USART2 => USART2,
303 USART3 => USART3,
304 UART4 => UART4,
305 UART5 => UART5,
306);
307#[cfg(context = "stm32f401re")]
308define_uart_drivers!(
309 USART1 => USART1,
310 USART2 => USART2,
311 USART6 => USART6,
312);
313#[cfg(context = "stm32f411re")]
314define_uart_drivers!(
315 USART1 => USART1,
316 USART2 => USART2,
317 USART6 => USART6,
318);
319#[cfg(context = "stm32g431rb")]
320define_uart_drivers!(
321 LPUART1 => LPUART1,
322 USART1 => USART1,
323 USART2 => USART2,
324 USART3 => USART3,
325 UART4 => UART4,
326);
327#[cfg(context = "stm32f767zi")]
328define_uart_drivers!(
329 USART1 => USART1,
330 USART2 => USART2,
331 USART3 => USART3,
332 UART4 => UART4,
333 UART5 => UART5,
334 USART6 => USART6,
335 UART7 => UART7,
336 UART8 => UART8,
337);
338#[cfg(any(context = "stm32h755zi", context = "stm32h753zi"))]
339define_uart_drivers!(
340 LPUART1 => LPUART1,
341 USART1 => USART1,
342 USART2 => USART2,
343 USART3 => USART3,
344 UART4 => UART4,
345 UART5 => UART5,
346 USART6 => USART6,
347 UART7 => UART7,
348 UART8 => UART8,
349);
350#[cfg(context = "stm32l072cz")]
351define_uart_drivers!(
352 USART1 => USART1,
353 USART2 => USART2,
354 USART4_5 => USART4,
355 );
358#[cfg(context = "stm32l475vg")]
359define_uart_drivers!(
360 LPUART1 => LPUART1,
361 USART1 => USART1,
362 USART2 => USART2,
363 USART3 => USART3,
364 UART4 => UART4,
365 UART5 => UART5,
366);
367#[cfg(any(context = "stm32u073kc", context = "stm32u083mc"))]
368define_uart_drivers!(
369 USART1 => USART1,
370 USART2_LPUART2 => USART2,
371 USART3_LPUART1 => USART3,
372 );
374#[cfg(context = "stm32u585ai")]
375define_uart_drivers!(
376 LPUART1 => LPUART1,
377 USART1 => USART1,
378 USART2 => USART2,
379 USART3 => USART3,
380 UART4 => UART4,
381 UART5 => UART5,
382);
383#[cfg(context = "stm32wb55rg")]
384define_uart_drivers!(
385 LPUART1 => LPUART1,
386 USART1 => USART1,
387);
388#[cfg(context = "stm32wba55cg")]
389define_uart_drivers!(
390 LPUART1 => LPUART1,
391 USART1 => USART1,
392 USART2 => USART2,
393);
394#[cfg(context = "stm32wba65ri")]
395define_uart_drivers!(
396 LPUART1 => LPUART1,
397 USART1 => USART1,
398 USART2 => USART2,
399 USART3 => USART3,
400);
401#[cfg(context = "stm32wle5jc")]
402define_uart_drivers!(
403 LPUART1 => LPUART1,
404 USART1 => USART1,
405 USART2 => USART2,
406);
407
408#[doc(hidden)]
409pub fn init(peripherals: &mut crate::OptionalPeripherals) {
410 cfg_select! {
412 context = "stm32c031c6" => {
413 let _ = peripherals.USART1.take().unwrap();
414 let _ = peripherals.USART2.take().unwrap();
415 }
416 context = "stm32f042k6" => {
417 let _ = peripherals.USART1.take().unwrap();
418 let _ = peripherals.USART2.take().unwrap();
419 }
420 context = "stm32f303cb" => {
421 let _ = peripherals.USART1.take().unwrap();
422 let _ = peripherals.USART2.take().unwrap();
423 let _ = peripherals.USART3.take().unwrap();
424 }
425 context = "stm32f303re" => {
426 let _ = peripherals.USART1.take().unwrap();
427 let _ = peripherals.USART2.take().unwrap();
428 let _ = peripherals.USART3.take().unwrap();
429 let _ = peripherals.UART4.take().unwrap();
430 let _ = peripherals.UART5.take().unwrap();
431 }
432 context = "stm32f401re" => {
433 let _ = peripherals.USART1.take().unwrap();
434 let _ = peripherals.USART2.take().unwrap();
435 let _ = peripherals.USART6.take().unwrap();
436 }
437 context = "stm32f411re" => {
438 let _ = peripherals.USART1.take().unwrap();
439 let _ = peripherals.USART2.take().unwrap();
440 let _ = peripherals.USART6.take().unwrap();
441 }
442 context = "stm32g431rb" => {
443 let _ = peripherals.LPUART1.take().unwrap();
444 let _ = peripherals.USART1.take().unwrap();
445 let _ = peripherals.USART2.take().unwrap();
446 let _ = peripherals.USART3.take().unwrap();
447 let _ = peripherals.UART4.take().unwrap();
448 }
449 context = "stm32f767zi" => {
450 let _ = peripherals.USART1.take().unwrap();
451 let _ = peripherals.USART2.take().unwrap();
452 let _ = peripherals.USART3.take().unwrap();
453 let _ = peripherals.UART4.take().unwrap();
454 let _ = peripherals.UART5.take().unwrap();
455 let _ = peripherals.USART6.take().unwrap();
456 let _ = peripherals.UART7.take().unwrap();
457 let _ = peripherals.UART8.take().unwrap();
458 }
459 context = "stm32h755zi" => {
460 let _ = peripherals.LPUART1.take().unwrap();
461 let _ = peripherals.USART1.take().unwrap();
462 let _ = peripherals.USART2.take().unwrap();
463 let _ = peripherals.USART3.take().unwrap();
464 let _ = peripherals.UART4.take().unwrap();
465 let _ = peripherals.UART5.take().unwrap();
466 let _ = peripherals.USART6.take().unwrap();
467 let _ = peripherals.UART7.take().unwrap();
468 let _ = peripherals.UART8.take().unwrap();
469 }
470 context = "stm32h753zi" => {
471 let _ = peripherals.LPUART1.take().unwrap();
472 let _ = peripherals.USART1.take().unwrap();
473 let _ = peripherals.USART2.take().unwrap();
474 let _ = peripherals.USART3.take().unwrap();
475 let _ = peripherals.UART4.take().unwrap();
476 let _ = peripherals.UART5.take().unwrap();
477 let _ = peripherals.USART6.take().unwrap();
478 let _ = peripherals.UART7.take().unwrap();
479 let _ = peripherals.UART8.take().unwrap();
480 }
481 context = "stm32l072cz" => {
482 let _ = peripherals.LPUART1.take().unwrap();
483 let _ = peripherals.USART1.take().unwrap();
484 let _ = peripherals.USART2.take().unwrap();
485 let _ = peripherals.USART4.take().unwrap();
486 let _ = peripherals.USART5.take().unwrap();
487 }
488 context = "stm32l475vg" => {
489 let _ = peripherals.LPUART1.take().unwrap();
490 let _ = peripherals.USART1.take().unwrap();
491 let _ = peripherals.USART2.take().unwrap();
492 let _ = peripherals.USART3.take().unwrap();
493 let _ = peripherals.UART4.take().unwrap();
494 let _ = peripherals.UART5.take().unwrap();
495 }
496 any(context = "stm32u073kc", context = "stm32u083mc") => {
497 let _ = peripherals.LPUART1.take().unwrap();
498 let _ = peripherals.LPUART2.take().unwrap();
499 let _ = peripherals.LPUART3.take().unwrap();
500 let _ = peripherals.USART1.take().unwrap();
501 let _ = peripherals.USART2.take().unwrap();
502 let _ = peripherals.USART3.take().unwrap();
503 let _ = peripherals.USART4.take().unwrap();
504 }
505 context = "stm32u585ai" => {
506 let _ = peripherals.LPUART1.take().unwrap();
507 let _ = peripherals.USART1.take().unwrap();
508 let _ = peripherals.USART2.take().unwrap();
509 let _ = peripherals.USART3.take().unwrap();
510 let _ = peripherals.UART4.take().unwrap();
511 let _ = peripherals.UART5.take().unwrap();
512 }
513 context = "stm32wb55rg" => {
514 let _ = peripherals.LPUART1.take().unwrap();
515 let _ = peripherals.USART1.take().unwrap();
516 }
517 context = "stm32wba55cg" => {
518 let _ = peripherals.LPUART1.take().unwrap();
519 let _ = peripherals.USART1.take().unwrap();
520 let _ = peripherals.USART2.take().unwrap();
521 }
522 context = "stm32wba65ri" => {
523 let _ = peripherals.LPUART1.take().unwrap();
524 let _ = peripherals.USART1.take().unwrap();
525 let _ = peripherals.USART2.take().unwrap();
526 let _ = peripherals.USART3.take().unwrap();
527 }
528 context = "stm32wle5jc" => {
529 let _ = peripherals.LPUART1.take().unwrap();
530 let _ = peripherals.USART1.take().unwrap();
531 let _ = peripherals.USART2.take().unwrap();
532 }
533 _ => {
534 compile_error!("this STM32 chip is not supported");
535 }
536 }
537}