mpfs_hal/
uart.rs

1use crate::pac;
2use embassy_embedded_hal::SetConfig;
3use paste::paste;
4
5pub trait UartPeripheral {
6    #[doc(hidden)]
7    fn address(&self) -> *mut pac::mss_uart_instance_t;
8    #[doc(hidden)]
9    fn number(&self) -> u8;
10}
11
12//-------------------------------------------------------------------
13// Create the UART peripherals
14
15macro_rules! impl_uart {
16    ($n:expr) => {
17        paste! {
18            impl_uart!([<UART $n>], [<UART $n _TAKEN>], $n, [<g_mss_uart $n _lo>]);
19        }
20    };
21
22    // E.g. impl_uart!(UART0, UART0_TAKEN, 0, g_mss_uart_0_lo);
23    ($UART:ident, $UART_TAKEN:ident, $num:expr, $instance:ident) => {
24        pub struct $UART {
25            _private: (),
26        }
27        static mut $UART_TAKEN: bool = false;
28
29        impl crate::Peripheral for $UART {
30            fn take() -> Option<Self> {
31                critical_section::with(|_| unsafe {
32                    if $UART_TAKEN {
33                        None
34                    } else {
35                        $UART_TAKEN = true;
36                        Some(Self { _private: () })
37                    }
38                })
39            }
40
41            unsafe fn steal() -> Self {
42                Self { _private: () }
43            }
44        }
45
46        impl UartPeripheral for $UART {
47            fn address(&self) -> *mut pac::mss_uart_instance_t {
48                core::ptr::addr_of_mut!(pac::$instance)
49            }
50
51            fn number(&self) -> u8 {
52                $num
53            }
54        }
55    };
56}
57
58macro_rules! impl_uarts {
59    ($($n:expr),*) => {
60        $(impl_uart!($n);)*
61    };
62}
63
64// Generates UART0, UART1, UART2, UART3, UART4
65impl_uarts!(0, 1, 2, 3, 4);
66
67//-------------------------------------------------------------------
68// Configs
69
70#[derive(Debug, Clone, Copy, PartialEq)]
71pub struct UartConfig {
72    pub baud_rate: BaudRate,
73    pub data_bits: DataBits,
74    pub stop_bits: StopBits,
75    pub parity: Parity,
76}
77
78impl Default for UartConfig {
79    fn default() -> Self {
80        Self {
81            baud_rate: BaudRate::Baud115200,
82            data_bits: DataBits::Data8,
83            stop_bits: StopBits::One,
84            parity: Parity::NoParity,
85        }
86    }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq)]
90pub enum BaudRate {
91    Baud110,
92    Baud300,
93    Baud600,
94    Baud1200,
95    Baud2400,
96    Baud4800,
97    Baud9600,
98    Baud19200,
99    Baud38400,
100    Baud57600,
101    Baud115200,
102    Baud230400,
103    Baud460800,
104    Baud921600,
105}
106
107impl BaudRate {
108    pub fn value(&self) -> u32 {
109        match self {
110            BaudRate::Baud110 => pac::MSS_UART_110_BAUD,
111            BaudRate::Baud300 => pac::MSS_UART_300_BAUD,
112            BaudRate::Baud600 => pac::MSS_UART_600_BAUD,
113            BaudRate::Baud1200 => pac::MSS_UART_1200_BAUD,
114            BaudRate::Baud2400 => pac::MSS_UART_2400_BAUD,
115            BaudRate::Baud4800 => pac::MSS_UART_4800_BAUD,
116            BaudRate::Baud9600 => pac::MSS_UART_9600_BAUD,
117            BaudRate::Baud19200 => pac::MSS_UART_19200_BAUD,
118            BaudRate::Baud38400 => pac::MSS_UART_38400_BAUD,
119            BaudRate::Baud57600 => pac::MSS_UART_57600_BAUD,
120            BaudRate::Baud115200 => pac::MSS_UART_115200_BAUD,
121            BaudRate::Baud230400 => pac::MSS_UART_230400_BAUD,
122            BaudRate::Baud460800 => pac::MSS_UART_460800_BAUD,
123            BaudRate::Baud921600 => pac::MSS_UART_921600_BAUD,
124        }
125    }
126}
127
128#[derive(Debug, Clone, Copy, PartialEq)]
129pub enum DataBits {
130    Data5,
131    Data6,
132    Data7,
133    Data8,
134}
135
136impl DataBits {
137    pub fn value(&self) -> u8 {
138        match self {
139            DataBits::Data5 => pac::MSS_UART_DATA_5_BITS,
140            DataBits::Data6 => pac::MSS_UART_DATA_6_BITS,
141            DataBits::Data7 => pac::MSS_UART_DATA_7_BITS,
142            DataBits::Data8 => pac::MSS_UART_DATA_8_BITS,
143        }
144    }
145}
146
147#[derive(Debug, Clone, Copy, PartialEq)]
148pub enum StopBits {
149    One,
150    OneHalf,
151    Two,
152}
153
154impl StopBits {
155    pub fn value(&self) -> u8 {
156        match self {
157            StopBits::One => pac::MSS_UART_ONE_STOP_BIT,
158            StopBits::OneHalf => pac::MSS_UART_ONEHALF_STOP_BIT,
159            StopBits::Two => pac::MSS_UART_TWO_STOP_BITS,
160        }
161    }
162}
163
164#[derive(Debug, Clone, Copy, PartialEq)]
165pub enum Parity {
166    NoParity,
167    OddParity,
168    EvenParity,
169    StickParity0,
170    StickParity1,
171}
172
173impl Parity {
174    pub fn value(&self) -> u8 {
175        match self {
176            Parity::NoParity => pac::MSS_UART_NO_PARITY,
177            Parity::OddParity => pac::MSS_UART_ODD_PARITY,
178            Parity::EvenParity => pac::MSS_UART_EVEN_PARITY,
179            Parity::StickParity0 => pac::MSS_UART_STICK_PARITY_0,
180            Parity::StickParity1 => pac::MSS_UART_STICK_PARITY_1,
181        }
182    }
183}
184
185//-------------------------------------------------------------------
186pub struct Uart<T: UartPeripheral> {
187    peripheral: T,
188}
189
190impl<T: UartPeripheral> Uart<T> {
191    pub fn new(peripheral: T, config: UartConfig) -> Self {
192        critical_section::with(|_| unsafe {
193            pac::mss_config_clk_rst(
194                peripheral.number() as u32,
195                pac::MPFS_HAL_FIRST_HART as u8,
196                pac::PERIPH_RESET_STATE__PERIPHERAL_ON,
197            );
198            let mut uart = Uart { peripheral };
199            uart.set_config(&config).unwrap();
200            uart
201        })
202    }
203}
204
205impl<T: UartPeripheral> SetConfig for Uart<T> {
206    type Config = UartConfig;
207    type ConfigError = ();
208    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
209        unsafe {
210            pac::MSS_UART_init(
211                self.peripheral.address(),
212                config.baud_rate.value(),
213                config.data_bits.value() | config.parity.value() | config.stop_bits.value(),
214            );
215        }
216        Ok(())
217    }
218}
219
220#[derive(Debug)]
221pub enum Error {}
222
223impl embedded_io::Error for Error {
224    fn kind(&self) -> embedded_io::ErrorKind {
225        embedded_io::ErrorKind::Other
226    }
227}
228
229impl<T: UartPeripheral> embedded_io::ErrorType for Uart<T> {
230    type Error = Error;
231}
232
233impl<T: UartPeripheral> embedded_io::Write for Uart<T> {
234    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
235        // TODO buffered writing
236        unsafe {
237            pac::MSS_UART_polled_tx(self.peripheral.address(), buf.as_ptr(), buf.len() as u32);
238        }
239        Ok(buf.len())
240    }
241
242    fn flush(&mut self) -> Result<(), Error> {
243        Ok(())
244    }
245}
246
247// TODO: Implement Read