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
12macro_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 ($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
64impl_uarts!(0, 1, 2, 3, 4);
66
67#[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
185pub 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 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