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 );
288#[cfg(context = "stm32f042k6")]
289define_uart_drivers!(
290 USART1 => USART1,
291 );
293#[cfg(context = "stm32f303cb")]
294define_uart_drivers!(
295 USART1 => USART1,
296 USART3 => USART3,
298);
299#[cfg(context = "stm32f303re")]
300define_uart_drivers!(
301 USART1 => USART1,
302 USART3 => USART3,
304 UART4 => UART4,
305 UART5 => UART5,
306);
307#[cfg(context = "stm32f401re")]
308define_uart_drivers!(
309 USART1 => USART1,
310 USART6 => USART6,
312);
313#[cfg(context = "stm32f411re")]
314define_uart_drivers!(
315 USART1 => USART1,
316 USART6 => USART6,
318);
319#[cfg(context = "stm32g431rb")]
320define_uart_drivers!(
321 LPUART1 => LPUART1,
322 USART1 => USART1,
323 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 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 USART6 => USART6,
347 UART7 => UART7,
348 UART8 => UART8,
349);
350#[cfg(context = "stm32l475vg")]
351define_uart_drivers!(
352 LPUART1 => LPUART1,
353 USART1 => USART1,
354 USART2 => USART2,
355 USART3 => USART3,
356 UART4 => UART4,
357 );
359#[cfg(any(context = "stm32u073kc", context = "stm32u083mc"))]
360define_uart_drivers!(
361 USART1 => USART1,
362 USART2_LPUART2 => USART2,
363 USART3_LPUART1 => USART3,
364 );
366#[cfg(context = "stm32u585ai")]
367define_uart_drivers!(
368 LPUART1 => LPUART1,
369 USART1 => USART1,
370 USART3 => USART3,
372 UART4 => UART4,
373 UART5 => UART5,
374);
375#[cfg(context = "stm32wb55rg")]
376define_uart_drivers!(
377 LPUART1 => LPUART1,
378 );
380#[cfg(context = "stm32wba55cg")]
381define_uart_drivers!(
382 LPUART1 => LPUART1,
383 USART1 => USART1,
384 );
386#[cfg(context = "stm32wle5jc")]
387define_uart_drivers!(
388 LPUART1 => LPUART1,
389 USART1 => USART1,
390 );
392
393#[doc(hidden)]
394pub fn init(peripherals: &mut crate::OptionalPeripherals) {
395 cfg_select! {
397 context = "stm32c031c6" => {
398 let _ = peripherals.USART1.take().unwrap();
399 }
400 context = "stm32f042k6" => {
401 let _ = peripherals.USART1.take().unwrap();
402 let _ = peripherals.USART2.take().unwrap();
403 }
404 context = "stm32f303cb" => {
405 let _ = peripherals.USART1.take().unwrap();
406 let _ = peripherals.USART2.take().unwrap();
407 let _ = peripherals.USART3.take().unwrap();
408 }
409 context = "stm32f303re" => {
410 let _ = peripherals.USART1.take().unwrap();
411 let _ = peripherals.USART2.take().unwrap();
412 let _ = peripherals.USART3.take().unwrap();
413 let _ = peripherals.UART4.take().unwrap();
414 let _ = peripherals.UART5.take().unwrap();
415 }
416 context = "stm32f401re" => {
417 let _ = peripherals.USART1.take().unwrap();
418 let _ = peripherals.USART2.take().unwrap();
419 let _ = peripherals.USART6.take().unwrap();
420 }
421 context = "stm32f411re" => {
422 let _ = peripherals.USART1.take().unwrap();
423 let _ = peripherals.USART2.take().unwrap();
424 let _ = peripherals.USART6.take().unwrap();
425 }
426 context = "stm32g431rb" => {
427 let _ = peripherals.LPUART1.take().unwrap();
428 let _ = peripherals.USART1.take().unwrap();
429 let _ = peripherals.USART2.take().unwrap();
430 let _ = peripherals.USART3.take().unwrap();
431 let _ = peripherals.UART4.take().unwrap();
432 }
433 context = "stm32f767zi" => {
434 let _ = peripherals.USART1.take().unwrap();
435 let _ = peripherals.USART2.take().unwrap();
436 let _ = peripherals.USART3.take().unwrap();
437 let _ = peripherals.UART4.take().unwrap();
438 let _ = peripherals.UART5.take().unwrap();
439 let _ = peripherals.USART6.take().unwrap();
440 let _ = peripherals.UART7.take().unwrap();
441 let _ = peripherals.UART8.take().unwrap();
442 }
443 context = "stm32h755zi" => {
444 let _ = peripherals.LPUART1.take().unwrap();
445 let _ = peripherals.USART1.take().unwrap();
446 let _ = peripherals.USART2.take().unwrap();
447 let _ = peripherals.USART3.take().unwrap();
448 let _ = peripherals.UART4.take().unwrap();
449 let _ = peripherals.UART5.take().unwrap();
450 let _ = peripherals.USART6.take().unwrap();
451 let _ = peripherals.UART7.take().unwrap();
452 let _ = peripherals.UART8.take().unwrap();
453 }
454 context = "stm32h753zi" => {
455 let _ = peripherals.LPUART1.take().unwrap();
456 let _ = peripherals.USART1.take().unwrap();
457 let _ = peripherals.USART2.take().unwrap();
458 let _ = peripherals.USART3.take().unwrap();
459 let _ = peripherals.UART4.take().unwrap();
460 let _ = peripherals.UART5.take().unwrap();
461 let _ = peripherals.USART6.take().unwrap();
462 let _ = peripherals.UART7.take().unwrap();
463 let _ = peripherals.UART8.take().unwrap();
464 }
465 context = "stm32l475vg" => {
466 let _ = peripherals.LPUART1.take().unwrap();
467 let _ = peripherals.USART1.take().unwrap();
468 let _ = peripherals.USART2.take().unwrap();
469 let _ = peripherals.USART3.take().unwrap();
470 let _ = peripherals.UART4.take().unwrap();
471 let _ = peripherals.UART5.take().unwrap();
472 }
473 any(context = "stm32u073kc", context = "stm32u083mc") => {
474 let _ = peripherals.LPUART1.take().unwrap();
475 let _ = peripherals.LPUART2.take().unwrap();
476 let _ = peripherals.LPUART3.take().unwrap();
477 let _ = peripherals.USART1.take().unwrap();
478 let _ = peripherals.USART2.take().unwrap();
479 let _ = peripherals.USART3.take().unwrap();
480 let _ = peripherals.USART4.take().unwrap();
481 }
482 context = "stm32u585ai" => {
483 let _ = peripherals.LPUART1.take().unwrap();
484 let _ = peripherals.USART1.take().unwrap();
485 let _ = peripherals.USART2.take().unwrap();
486 let _ = peripherals.USART3.take().unwrap();
487 let _ = peripherals.UART4.take().unwrap();
488 let _ = peripherals.UART5.take().unwrap();
489 }
490 context = "stm32wb55rg" => {
491 let _ = peripherals.LPUART1.take().unwrap();
492 let _ = peripherals.USART1.take().unwrap();
493 }
494 context = "stm32wba55cg" => {
495 let _ = peripherals.LPUART1.take().unwrap();
496 let _ = peripherals.USART1.take().unwrap();
497 let _ = peripherals.USART2.take().unwrap();
498 }
499 context = "stm32wle5jc" => {
500 let _ = peripherals.LPUART1.take().unwrap();
501 let _ = peripherals.USART1.take().unwrap();
502 let _ = peripherals.USART2.take().unwrap();
503 }
504 _ => {
505 compile_error!("this STM32 chip is not supported");
506 }
507 }
508}