Skip to main content

mpfs_hal/
uart.rs

1use crate::pac;
2use core::task::Poll;
3use embassy_embedded_hal::SetConfig;
4use paste::paste;
5
6pub trait UartPeripheral: crate::Peripheral {
7    #[doc(hidden)]
8    fn address(&self) -> *mut pac::mss_uart_instance_t;
9    #[doc(hidden)]
10    fn number(&self) -> u8;
11}
12
13pub trait UartRxPeripheral: crate::Peripheral + UartPeripheral {}
14
15pub trait UartTxPeripheral: crate::Peripheral + UartPeripheral {}
16
17//-------------------------------------------------------------------
18// Create the UART peripherals
19
20macro_rules! impl_uart {
21    ($n:expr) => {
22        paste! {
23            impl_uart!([<Uart $n>], [<UartRx $n>], [<UartTx $n>], [<UART_RX_TAKEN $n>], [<UART_TX_TAKEN $n>], $n, [<g_mss_uart $n _lo>]);
24        }
25    };
26
27    // E.g. impl_uart!(UART0, UART0_RX, UART0_TX, UART0_RX_TAKEN, UART0_TX_TAKEN, 0, g_mss_uart_0_lo);
28    ($UART:ident, $UART_RX:ident, $UART_TX:ident, $UART_RX_TAKEN:ident, $UART_TX_TAKEN:ident, $num:expr, $instance:ident) => {
29        pub struct $UART {
30            _private: (),
31        }
32
33        pub struct $UART_RX {
34            _private: (),
35        }
36
37        pub struct $UART_TX {
38            _private: (),
39        }
40
41        static mut $UART_RX_TAKEN: bool = false;
42        static mut $UART_TX_TAKEN: bool = false;
43
44        impl crate::Peripheral for $UART {
45            fn take() -> Option<Self> {
46                critical_section::with(|_| unsafe {
47                    if $UART_RX_TAKEN || $UART_TX_TAKEN {
48                        None
49                    } else {
50                        $UART_RX_TAKEN = true;
51                        $UART_TX_TAKEN = true;
52                        Some(Self { _private: () })
53                    }
54                })
55            }
56
57            unsafe fn steal() -> Self {
58                Self { _private: () }
59            }
60        }
61
62        impl crate::Peripheral for $UART_RX {
63            fn take() -> Option<Self> {
64                critical_section::with(|_| unsafe {
65                    if $UART_RX_TAKEN {
66                        None
67                    } else {
68                        $UART_RX_TAKEN = true;
69                        Some(Self { _private: () })
70                    }
71                })
72            }
73
74            unsafe fn steal() -> Self {
75                Self { _private: () }
76            }
77        }
78
79        impl crate::Peripheral for $UART_TX {
80            fn take() -> Option<Self> {
81                critical_section::with(|_| unsafe {
82                    if $UART_TX_TAKEN {
83                        None
84                    } else {
85                        $UART_TX_TAKEN = true;
86                        Some(Self { _private: () })
87                    }
88                })
89            }
90
91            unsafe fn steal() -> Self {
92                Self { _private: () }
93            }
94        }
95
96        impl UartPeripheral for $UART {
97            fn address(&self) -> *mut pac::mss_uart_instance_t {
98                &raw mut pac::$instance
99            }
100
101            fn number(&self) -> u8 {
102                $num
103            }
104        }
105
106        impl UartPeripheral for $UART_RX {
107            fn address(&self) -> *mut pac::mss_uart_instance_t {
108                &raw mut pac::$instance
109            }
110
111            fn number(&self) -> u8 {
112                $num
113            }
114        }
115
116        impl UartRxPeripheral for $UART_RX {}
117
118        impl UartPeripheral for $UART_TX {
119            fn address(&self) -> *mut pac::mss_uart_instance_t {
120                &raw mut pac::$instance
121            }
122
123            fn number(&self) -> u8 {
124                $num
125            }
126        }
127
128        impl UartTxPeripheral for $UART_TX {}
129    };
130}
131
132macro_rules! impl_uarts {
133    ($($n:expr),*) => {
134        $(impl_uart!($n);)*
135    };
136}
137
138// Generates UART0, UART1, UART2, UART3, UART4
139impl_uarts!(0, 1, 2, 3, 4);
140
141//-------------------------------------------------------------------
142// Configs
143
144#[derive(Debug, Clone, Copy, PartialEq)]
145pub struct UartConfig {
146    pub baud_rate: BaudRate,
147    pub data_bits: DataBits,
148    pub stop_bits: StopBits,
149    pub parity: Parity,
150}
151
152impl Default for UartConfig {
153    fn default() -> Self {
154        Self {
155            baud_rate: BaudRate::Baud115200,
156            data_bits: DataBits::Data8,
157            stop_bits: StopBits::One,
158            parity: Parity::NoParity,
159        }
160    }
161}
162
163#[derive(Debug, Clone, Copy, PartialEq)]
164pub enum BaudRate {
165    Baud110,
166    Baud300,
167    Baud600,
168    Baud1200,
169    Baud2400,
170    Baud4800,
171    Baud9600,
172    Baud19200,
173    Baud38400,
174    Baud57600,
175    Baud115200,
176    Baud230400,
177    Baud460800,
178    Baud921600,
179    Custom(u32),
180}
181
182impl BaudRate {
183    pub fn value(&self) -> u32 {
184        match self {
185            BaudRate::Baud110 => pac::MSS_UART_110_BAUD,
186            BaudRate::Baud300 => pac::MSS_UART_300_BAUD,
187            BaudRate::Baud600 => pac::MSS_UART_600_BAUD,
188            BaudRate::Baud1200 => pac::MSS_UART_1200_BAUD,
189            BaudRate::Baud2400 => pac::MSS_UART_2400_BAUD,
190            BaudRate::Baud4800 => pac::MSS_UART_4800_BAUD,
191            BaudRate::Baud9600 => pac::MSS_UART_9600_BAUD,
192            BaudRate::Baud19200 => pac::MSS_UART_19200_BAUD,
193            BaudRate::Baud38400 => pac::MSS_UART_38400_BAUD,
194            BaudRate::Baud57600 => pac::MSS_UART_57600_BAUD,
195            BaudRate::Baud115200 => pac::MSS_UART_115200_BAUD,
196            BaudRate::Baud230400 => pac::MSS_UART_230400_BAUD,
197            BaudRate::Baud460800 => pac::MSS_UART_460800_BAUD,
198            BaudRate::Baud921600 => pac::MSS_UART_921600_BAUD,
199            BaudRate::Custom(value) => *value,
200        }
201    }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq)]
205pub enum DataBits {
206    Data5,
207    Data6,
208    Data7,
209    Data8,
210}
211
212impl DataBits {
213    pub fn value(&self) -> u8 {
214        match self {
215            DataBits::Data5 => pac::MSS_UART_DATA_5_BITS,
216            DataBits::Data6 => pac::MSS_UART_DATA_6_BITS,
217            DataBits::Data7 => pac::MSS_UART_DATA_7_BITS,
218            DataBits::Data8 => pac::MSS_UART_DATA_8_BITS,
219        }
220    }
221}
222
223#[derive(Debug, Clone, Copy, PartialEq)]
224pub enum StopBits {
225    One,
226    OneHalf,
227    Two,
228}
229
230impl StopBits {
231    pub fn value(&self) -> u8 {
232        match self {
233            StopBits::One => pac::MSS_UART_ONE_STOP_BIT,
234            StopBits::OneHalf => pac::MSS_UART_ONEHALF_STOP_BIT,
235            StopBits::Two => pac::MSS_UART_TWO_STOP_BITS,
236        }
237    }
238}
239
240#[derive(Debug, Clone, Copy, PartialEq)]
241pub enum Parity {
242    NoParity,
243    OddParity,
244    EvenParity,
245    StickParity0,
246    StickParity1,
247}
248
249impl Parity {
250    pub fn value(&self) -> u8 {
251        match self {
252            Parity::NoParity => pac::MSS_UART_NO_PARITY,
253            Parity::OddParity => pac::MSS_UART_ODD_PARITY,
254            Parity::EvenParity => pac::MSS_UART_EVEN_PARITY,
255            Parity::StickParity0 => pac::MSS_UART_STICK_PARITY_0,
256            Parity::StickParity1 => pac::MSS_UART_STICK_PARITY_1,
257        }
258    }
259}
260
261//-------------------------------------------------------------------
262
263pub(crate) fn init_uart() {
264    unsafe {
265        // It just so happens that the UARTs are the first peripherals on the MPFS
266        for i in 0..NUM_UARTS {
267            pac::mss_config_clk_rst(
268                i as u32,
269                pac::MPFS_HAL_FIRST_HART as u8,
270                pac::PERIPH_RESET_STATE__PERIPHERAL_ON,
271            );
272        }
273    }
274}
275
276unsafe fn init_uart_interrupt(num: usize) {
277    unsafe {
278        // It just so happens that the UARTs are the first peripherals on the MPFS
279        pac::PLIC_SetPriority(pac::PLIC_IRQn_Type_PLIC_MMUART0_INT_OFFSET + num as u32, 2);
280
281        let uart = match num {
282            0 => &raw mut pac::g_mss_uart0_lo,
283            1 => &raw mut pac::g_mss_uart1_lo,
284            2 => &raw mut pac::g_mss_uart2_lo,
285            3 => &raw mut pac::g_mss_uart3_lo,
286            4 => &raw mut pac::g_mss_uart4_lo,
287            _ => panic!("Invalid UART number"),
288        };
289        pac::MSS_UART_set_rx_handler(
290            uart,
291            Some(uart_rx_handler),
292            pac::mss_uart_rx_trig_level_t_MSS_UART_FIFO_SINGLE_BYTE,
293        );
294        pac::MSS_UART_enable_irq(uart, (pac::MSS_UART_RBF_IRQ | pac::MSS_UART_TBE_IRQ) as u16);
295    }
296}
297
298//-------------------------------------------------------------------
299pub struct Uart<T: UartPeripheral> {
300    rx: UartRx<T>,
301    tx: UartTx<T>,
302}
303
304impl<T: UartPeripheral> Uart<T> {
305    pub fn new(peripheral: T, config: UartConfig) -> Self {
306        unsafe {
307            let mut uart = Uart {
308                rx: UartRx { peripheral },
309                tx: UartTx {
310                    peripheral: T::steal(),
311                },
312            };
313            uart.set_config(&config).unwrap();
314            init_uart_interrupt(uart.rx.peripheral.number() as usize);
315            uart
316        }
317    }
318
319    pub fn split(self) -> (UartRx<T>, UartTx<T>) {
320        (self.rx, self.tx)
321    }
322}
323
324impl<T: UartPeripheral> SetConfig for Uart<T> {
325    type Config = UartConfig;
326    type ConfigError = ();
327    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
328        unsafe {
329            pac::MSS_UART_init(
330                self.tx.peripheral.address(),
331                config.baud_rate.value(),
332                config.data_bits.value() | config.parity.value() | config.stop_bits.value(),
333            );
334        }
335        Ok(())
336    }
337}
338
339#[derive(Debug)]
340pub enum Error {
341    EmptyBuffer,
342}
343
344impl embedded_io::Error for Error {
345    fn kind(&self) -> embedded_io::ErrorKind {
346        embedded_io::ErrorKind::Other
347    }
348}
349
350impl<T: UartPeripheral> embedded_io::ErrorType for Uart<T> {
351    type Error = Error;
352}
353
354impl<T: UartPeripheral> embedded_io::Write for Uart<T> {
355    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
356        self.tx.write(buf)
357    }
358
359    fn flush(&mut self) -> Result<(), Error> {
360        Ok(())
361    }
362}
363
364impl<T: UartPeripheral> embedded_io::Read for Uart<T> {
365    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
366        self.rx.read(buf)
367    }
368}
369
370impl<T: UartPeripheral> embedded_io_async::Read for Uart<T> {
371    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
372        self.rx.read(buf).await
373    }
374}
375
376//-----------------------------------------------------------------
377// Tx
378
379pub struct UartTx<T: UartPeripheral> {
380    peripheral: T,
381}
382
383impl<TX: UartTxPeripheral> UartTx<TX> {
384    pub fn new(peripheral: TX, config: UartConfig) -> Self {
385        let mut uart = Self { peripheral };
386        uart.set_config(&config).unwrap();
387        uart
388    }
389}
390
391impl<T: UartPeripheral> embedded_io::ErrorType for UartTx<T> {
392    type Error = Error;
393}
394
395impl<T: UartPeripheral> embedded_io::Write for UartTx<T> {
396    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
397        // TODO buffered writing
398        unsafe {
399            pac::MSS_UART_polled_tx(self.peripheral.address(), buf.as_ptr(), buf.len() as u32);
400        }
401        Ok(buf.len())
402    }
403
404    fn flush(&mut self) -> Result<(), Error> {
405        Ok(())
406    }
407}
408
409impl<T: UartPeripheral> SetConfig for UartTx<T> {
410    type Config = UartConfig;
411    type ConfigError = ();
412    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
413        unsafe {
414            pac::MSS_UART_init(
415                self.peripheral.address(),
416                config.baud_rate.value(),
417                config.data_bits.value() | config.parity.value() | config.stop_bits.value(),
418            );
419        }
420        Ok(())
421    }
422}
423
424//-----------------------------------------------------------------
425// Rx
426const NUM_UARTS: usize = 5;
427const RX_BUF_SIZE: usize = 128;
428
429static mut RX_BUF: [[u8; RX_BUF_SIZE]; NUM_UARTS] = [[0; RX_BUF_SIZE]; NUM_UARTS];
430// (write_idx, read_idx)
431static mut RX_BUFFER_USED: [(usize, usize); NUM_UARTS] = [(0, 0); NUM_UARTS];
432static mut RX_WAKERS: [Option<core::task::Waker>; NUM_UARTS] = [const { None }; NUM_UARTS];
433
434pub struct UartRx<T: UartPeripheral> {
435    peripheral: T,
436}
437
438impl<RX: UartRxPeripheral> UartRx<RX> {
439    pub fn new(peripheral: RX, config: UartConfig) -> Self {
440        let mut uart = Self { peripheral };
441        uart.set_config(&config).unwrap();
442        unsafe { init_uart_interrupt(uart.peripheral.number() as usize) };
443        uart
444    }
445}
446
447impl<T: UartPeripheral> SetConfig for UartRx<T> {
448    type Config = UartConfig;
449    type ConfigError = ();
450    fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
451        unsafe {
452            pac::MSS_UART_init(
453                self.peripheral.address(),
454                config.baud_rate.value(),
455                config.data_bits.value() | config.parity.value() | config.stop_bits.value(),
456            );
457        }
458        Ok(())
459    }
460}
461
462impl<T: UartPeripheral> UartRx<T> {
463    fn _read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
464        let uart_idx = self.peripheral.number() as usize;
465        let mut read = 0;
466
467        while read < buf.len() {
468            let (write_idx, read_idx) = critical_section::with(|_| unsafe {
469                let indices = RX_BUFFER_USED[uart_idx];
470                if indices.1 != indices.0 {
471                    // Update read index
472                    RX_BUFFER_USED[uart_idx].1 = (indices.1 + 1) % RX_BUF_SIZE;
473                    // Copy data
474                    buf[read] = RX_BUF[uart_idx][indices.1];
475                }
476                indices
477            });
478
479            if read_idx == write_idx {
480                break;
481            }
482            read += 1;
483        }
484
485        Ok(read)
486    }
487}
488
489impl<T: UartPeripheral> embedded_io::ErrorType for UartRx<T> {
490    type Error = Error;
491}
492
493impl<T: UartPeripheral> embedded_io::Read for UartRx<T> {
494    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
495        if buf.len() == 0 {
496            return Err(Error::EmptyBuffer);
497        }
498        unsafe {
499            loop {
500                let (write_idx, read_idx) = RX_BUFFER_USED[self.peripheral.number() as usize];
501                if write_idx != read_idx {
502                    break;
503                }
504            }
505        }
506        self._read(buf)
507    }
508}
509
510impl<T: UartPeripheral> embedded_io_async::Read for UartRx<T> {
511    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
512        if buf.len() == 0 {
513            return Err(Error::EmptyBuffer);
514        }
515        let uart_idx = self.peripheral.number() as usize;
516        trace!("UART{}: read", uart_idx);
517
518        // Wait for data if buffer is empty
519        core::future::poll_fn(|cx| {
520            critical_section::with(|_| unsafe {
521                let (write_idx, read_idx) = RX_BUFFER_USED[uart_idx];
522                if write_idx != read_idx {
523                    Poll::Ready(())
524                } else {
525                    RX_WAKERS[uart_idx] = Some(cx.waker().clone());
526                    Poll::Pending
527                }
528            })
529        })
530        .await;
531
532        self._read(buf)
533    }
534}
535
536fn uart_idx(uart: *mut pac::mss_uart_instance_t) -> usize {
537    if uart == &raw mut pac::g_mss_uart0_lo {
538        0
539    } else if uart == &raw mut pac::g_mss_uart1_lo {
540        1
541    } else if uart == &raw mut pac::g_mss_uart2_lo {
542        2
543    } else if uart == &raw mut pac::g_mss_uart3_lo {
544        3
545    } else if uart == &raw mut pac::g_mss_uart4_lo {
546        4
547    } else {
548        panic!("Invalid UART instance")
549    }
550}
551
552extern "C" fn uart_rx_handler(uart: *mut pac::mss_uart_instance_t) {
553    let uart_idx = uart_idx(uart);
554    trace!("UART{}: rx handler", uart_idx);
555    unsafe {
556        let (mut write_idx, mut read_idx) = RX_BUFFER_USED[uart_idx];
557
558        // Read one byte into the circular buffer
559        let size = pac::MSS_UART_get_rx(uart, &mut RX_BUF[uart_idx][write_idx] as *mut u8, 1);
560
561        if size > 0 {
562            // Update write index
563            write_idx = (write_idx + 1) % RX_BUF_SIZE;
564
565            // If buffer would overflow, advance read index
566            if write_idx == read_idx {
567                read_idx = (read_idx + 1) % RX_BUF_SIZE;
568                RX_BUFFER_USED[uart_idx].1 = read_idx;
569            }
570
571            RX_BUFFER_USED[uart_idx].0 = write_idx;
572
573            // Wake any waiting readers
574            if let Some(waker) = RX_WAKERS[uart_idx].take() {
575                waker.wake();
576            }
577        }
578
579        trace!("UART{}: got {} bytes", uart_idx, size);
580    }
581}