Skip to main content

ra_hal/
uart.rs

1//! Universal Asynchronous Receiver-Transmitter
2//!
3//! This module provides a UART driver for the `SCI` and `SCI_B` peripherals.
4
5use fugit::HertzU32;
6use micromath::F32Ext as _;
7
8use crate::interrupt::Interrupt;
9
10#[cfg_attr(not(sci_b), path = "uart/sci.rs")]
11#[cfg_attr(sci_b, path = "uart/sci_b.rs")]
12pub(crate) mod sci;
13
14/// Mode of transfer (e.g. blocking, interrupt, DMA).
15#[allow(private_bounds)]
16pub trait TransferMode: SealedTransferMode {}
17trait SealedTransferMode {}
18
19/// Asynchronous, interrupt driven, I/O.
20pub struct Async {
21    rx_int: Interrupt,
22    tx_int: Interrupt,
23}
24impl TransferMode for Async {}
25impl SealedTransferMode for Async {}
26
27/// Blocking I/O.
28pub struct Blocking {}
29impl TransferMode for Blocking {}
30impl SealedTransferMode for Blocking {}
31
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33#[derive(Debug, Copy, Clone)]
34struct BaudGenConfig {
35    small_n: u32,
36    big_n: u32,
37    err: f32,
38}
39
40/// Word length.
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42#[derive(Clone, Copy, PartialEq, Eq, Debug)]
43pub enum DataBits {
44    /// 7 bits.
45    DataBits7,
46
47    /// 8 bits.
48    DataBits8,
49
50    /// 9 bits.
51    DataBits9,
52}
53
54/// Parity bit
55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56#[derive(Clone, Copy, PartialEq, Eq, Debug)]
57pub enum Parity {
58    /// Even parity
59    Even,
60
61    /// Odd parity
62    Odd,
63
64    /// No parity bit
65    None,
66}
67
68/// Number of stop bits
69#[cfg_attr(feature = "defmt", derive(defmt::Format))]
70#[derive(Clone, Copy, PartialEq, Eq, Debug)]
71pub enum StopBits {
72    /// 1 stop bit
73    Stop1,
74
75    /// 2 stop bits
76    Stop2,
77}
78
79fn calc_baud_gen(baud: u32, clock: HertzU32) -> Option<BaudGenConfig> {
80    let semr = 64.0;
81    let mut big_n = 0_u32;
82    let mut small_n = 3_u32;
83
84    let mut best: Option<BaudGenConfig> = None;
85
86    loop {
87        let mut last_config: Option<BaudGenConfig> = None;
88
89        for _ in 0..256 {
90            let new_error = (clock.to_Hz() as f32
91                / (baud as f32
92                    * semr
93                    * (2_f32.powi(2 * small_n as i32 - 1))
94                    * (big_n as f32 + 1.0)))
95                - 1.0;
96
97            if let Some(last_config) = last_config {
98                if new_error.abs() > last_config.err.abs() {
99                    break;
100                }
101            }
102
103            last_config = Some(BaudGenConfig {
104                small_n,
105                big_n,
106                err: new_error,
107            });
108            big_n += 1;
109        }
110
111        if let Some(ref mut best) = best {
112            if last_config.unwrap().err.abs() < best.err.abs() {
113                *best = last_config.unwrap();
114            }
115        } else {
116            best = last_config;
117        }
118
119        if small_n == 0 {
120            break;
121        } else {
122            small_n -= 1;
123            big_n = 0;
124        }
125    }
126
127    best
128}
129
130pub use sci::{Config, Instance, RxInterruptHandler, TeInterruptHandler, TxInterruptHandler, Uart};