max7800x_hal/
uart.rs

1//! # Universal Asynchronous Receiver/Transmitter (UART)
2use core::marker::PhantomData;
3use core::ops::Deref;
4
5use crate::gcr::{
6    clocks::{Clock, InternalBaudRateOscillator, PeripheralClock},
7    ClockForPeripheral,
8};
9use crate::gpio::{Af1, Pin};
10use embedded_hal_nb::{nb, serial};
11use paste::paste;
12
13enum UartClockSource {
14    Pclk,
15    Ibro,
16}
17
18/// Number of data bits in a UART frame.
19pub enum DataBits {
20    /// 5 data bits.
21    Five,
22    /// 6 data bits.
23    Six,
24    /// 7 data bits.
25    Seven,
26    /// 8 data bits.
27    Eight,
28}
29
30/// Number of stop bits in a UART frame.
31pub enum StopBits {
32    /// 1 stop bit.
33    One,
34    /// 1.5 stop bits when using 5 data bits.
35    /// 2 stop bits when using 6-8 data bits.
36    More,
37}
38
39/// Parity bit configuration for a UART frame.
40pub enum ParityBit {
41    /// Parity bit is not used.
42    None,
43    /// The total count of 1 bits in the data frame, including the parity bit,
44    /// is even.
45    ///
46    /// Examples:
47    /// - `01101` would have a parity bit of `1` since there is an odd number
48    /// of 1s and an extra 1 is needed to make it even.
49    /// - `01100` would have a parity bit of `0` since there is already an even
50    /// number of 1s.
51    Even,
52    /// The total count of 1 bits in the data frame, including the parity bit,
53    /// is odd.
54    ///
55    /// Examples:
56    /// - `01101` would have a parity bit of `0` since there is already an odd
57    /// number of 1s.
58    /// - `01100` would have a parity bit of `1` since there is an even number
59    /// of 1s and an extra 1 is needed to make it odd.
60    Odd,
61    /// The parity bit is always `0`.
62    SpaceZero,
63    /// The parity bit is always `1`.
64    MarkOne,
65}
66
67#[doc(hidden)]
68pub mod marker {
69    /// Marker traits for the build state of the UART peripheral.
70    pub trait UartState: crate::Sealed {}
71    #[doc(hidden)]
72    pub struct NotBuilt;
73    #[doc(hidden)]
74    pub struct Built;
75
76    impl crate::Sealed for NotBuilt {}
77    impl crate::Sealed for Built {}
78    impl UartState for NotBuilt {}
79    impl UartState for Built {}
80
81    /// Marker traits for the clock state of the UART peripheral.
82    pub trait UartClockState: crate::Sealed {}
83    #[doc(hidden)]
84    pub struct NotClockSet;
85    #[doc(hidden)]
86    pub struct ClockSet;
87    impl crate::Sealed for NotClockSet {}
88    impl crate::Sealed for ClockSet {}
89    impl UartClockState for NotClockSet {}
90    impl UartClockState for ClockSet {}
91}
92
93/// # Universal Asynchronous Receiver/Transmitter (UART) Peripheral
94///
95/// This struct makes use of [typestates](https://docs.rust-embedded.org/book/static-guarantees/typestate-programming.html)
96/// to ensure any UART peripheral cannot be configured with an invalid set
97/// of pins or clocks.
98///
99/// Traits from [`embedded_hal_nb::serial`] are also implemented for the UART
100/// peripherals.
101///
102/// ## Example
103/// ```
104/// let pins = hal::gpio::Gpio0::new(p.gpio0, &mut gcr.reg).split();
105/// let uart = hal::uart::UartPeripheral::uart0(
106///     p.uart0,                // UART peripheral from the PAC
107///     &mut gcr.reg,           // GCR instance
108///     pins.p0_0.into_af1(),   // RX pin
109///     pins.p0_1.into_af1()    // TX pin
110/// )
111///     .clock_pclk(&clks.pclk) // or clocks_ibro(&ibro)
112///     .baud(115200)
113///     .data_bits(hal::uart::DataBits::Eight)
114///     .stop_bits(hal::uart::StopBits::One)
115///     .parity(hal::uart::Parity::None)
116///     .build();
117///
118/// uart.write_bytes(b"Hello, world!\r\n");
119
120/// ```
121pub struct UartPeripheral<STATE: marker::UartState, CLOCK, UART, RX, TX, CTS, RTS> {
122    _state: PhantomData<STATE>,
123    _clock: PhantomData<CLOCK>,
124    uart: UART,
125    _rx_pin: RX,
126    _tx_pin: TX,
127    _cts_pin: CTS,
128    _rts_pin: RTS,
129    clk_src: Option<UartClockSource>,
130    clk_src_freq: Option<u32>,
131    baud: u32,
132    data_bits: DataBits,
133    stop_bits: StopBits,
134    parity: ParityBit,
135}
136
137pub struct BuiltUartPeripheral<UART, RX, TX, CTS, RTS> {
138    uart: UART,
139    _rx_pin: RX,
140    _tx_pin: TX,
141    _cts_pin: CTS,
142    _rts_pin: RTS,
143}
144
145// TODO
146// pub struct UartReceiver<UART, RX, CTS> {
147//     _uart: UART,
148//     _rx_pin: RX,
149//     _cts_pin: CTS,
150// }
151
152// TODO
153// pub struct UartTransmitter<UART, TX, RTS> {
154//     _uart: UART,
155//     _tx_pin: TX,
156//     _rts_pin: RTS,
157// }
158
159/// Pins that can be used for receiving data on a UART peripheral.
160pub trait RxPin<UART>: crate::Sealed {}
161/// Pins that can be used for transmitting data on a UART peripheral.
162pub trait TxPin<UART>: crate::Sealed {}
163
164// TODO: Implement CTS and RTS pins for hardware flow control
165// pub trait CtsPin<UART>: crate::Sealed {}
166// pub trait RtsPin<UART>: crate::Sealed {}
167
168// All UART peripherals are derived from the same register block
169type UartRegisterBlock = crate::pac::uart0::RegisterBlock;
170
171macro_rules! uart {
172    (
173        $uart:ident,
174        rx: $rx_pin:ty,
175        tx: $tx_pin:ty,
176        cts: $cts_pin:ty,
177        rts: $rts_pin:ty,
178    ) => {
179        paste! {
180            use crate::pac::$uart;
181
182            impl crate::Sealed for $rx_pin {}
183            impl RxPin<$uart> for $rx_pin {}
184
185            impl crate::Sealed for $tx_pin {}
186            impl TxPin<$uart> for $tx_pin {}
187
188            impl UartPeripheral<
189                marker::NotBuilt,
190                marker::NotClockSet,
191                $uart,
192                $rx_pin,
193                $tx_pin,
194                // $cts_pin,
195                // $rts_pin
196                (),
197                (),
198            >
199            {
200                #[doc = "Construct a new "]
201                #[doc = stringify!([<$uart:upper>])]
202                #[doc = " peripheral."]
203                pub fn [<$uart:lower>](
204                    uart: $uart,
205                    reg: &mut crate::gcr::GcrRegisters,
206                    rx_pin: $rx_pin,
207                    tx_pin: $tx_pin
208                ) -> UartPeripheral<marker::NotBuilt, marker::NotClockSet, $uart, $rx_pin, $tx_pin, (), ()> {
209                    // Enable the UART peripheral clock
210                    unsafe { uart.enable_clock(&mut reg.gcr); }
211                    UartPeripheral {
212                        _state: PhantomData,
213                        _clock: PhantomData,
214                        uart,
215                        _rx_pin: rx_pin,
216                        _tx_pin: tx_pin,
217                        _cts_pin: (),
218                        _rts_pin: (),
219                        clk_src: None,
220                        clk_src_freq: None,
221                        baud: 115200,
222                        data_bits: DataBits::Eight,
223                        stop_bits: StopBits::One,
224                        parity: ParityBit::None,
225                    }
226                }
227            }
228        }
229    };
230}
231
232uart! {Uart0,
233    rx: Pin<0, 0, Af1>,
234    tx: Pin<0, 1, Af1>,
235    cts: (),
236    rts: (),
237}
238
239uart! {Uart1,
240    rx: Pin<0, 12, Af1>,
241    tx: Pin<0, 13, Af1>,
242    cts: (),
243    rts: (),
244}
245
246uart! {Uart2,
247    rx: Pin<1, 0, Af1>,
248    tx: Pin<1, 1, Af1>,
249    cts: (),
250    rts: (),
251}
252
253/// # Clock Methods
254/// You must set the clock source for the UART peripheral after using a
255/// constructor and before building the peripheral.
256impl<UART, RX, TX, CTS, RTS>
257    UartPeripheral<marker::NotBuilt, marker::NotClockSet, UART, RX, TX, CTS, RTS>
258{
259    /// Set the clock source for the UART peripheral to the PCLK.
260    pub fn clock_pclk(
261        self,
262        clock: &Clock<PeripheralClock>,
263    ) -> UartPeripheral<marker::NotBuilt, marker::ClockSet, UART, RX, TX, CTS, RTS> {
264        UartPeripheral {
265            _state: PhantomData,
266            _clock: PhantomData,
267            uart: self.uart,
268            _rx_pin: self._rx_pin,
269            _tx_pin: self._tx_pin,
270            _cts_pin: self._cts_pin,
271            _rts_pin: self._rts_pin,
272            clk_src: Some(UartClockSource::Pclk),
273            clk_src_freq: Some(clock.frequency),
274            baud: self.baud,
275            data_bits: self.data_bits,
276            stop_bits: self.stop_bits,
277            parity: self.parity,
278        }
279    }
280
281    /// Set the clock source for the UART peripheral to the IBRO.
282    pub fn clock_ibro(
283        self,
284        clock: &Clock<InternalBaudRateOscillator>,
285    ) -> UartPeripheral<marker::NotBuilt, marker::ClockSet, UART, RX, TX, CTS, RTS> {
286        UartPeripheral {
287            _state: PhantomData,
288            _clock: PhantomData,
289            uart: self.uart,
290            _rx_pin: self._rx_pin,
291            _tx_pin: self._tx_pin,
292            _cts_pin: self._cts_pin,
293            _rts_pin: self._rts_pin,
294            clk_src: Some(UartClockSource::Ibro),
295            clk_src_freq: Some(clock.frequency),
296            baud: self.baud,
297            data_bits: self.data_bits,
298            stop_bits: self.stop_bits,
299            parity: self.parity,
300        }
301    }
302}
303
304/// # Builder Methods
305/// These methods are used to configure the UART peripheral before it is built
306/// to be used. Configure the peripheral by chaining these methods together,
307/// with the [`UartPeripheral::build()`] method called at the end.
308impl<CLOCK, UART, RX, TX, CTS, RTS> UartPeripheral<marker::NotBuilt, CLOCK, UART, RX, TX, CTS, RTS>
309where
310    UART: Deref<Target = UartRegisterBlock>,
311{
312    /// Set the baud rate (bits per second) for the UART peripheral.
313    ///
314    /// Default: `115200`
315    pub fn baud(mut self, baud: u32) -> Self {
316        self.baud = baud;
317        self
318    }
319
320    /// Set the number of data bits for the UART peripheral.
321    ///
322    /// Default: [`DataBits::Eight`]
323    pub fn data_bits(mut self, data_bits: DataBits) -> Self {
324        self.data_bits = data_bits;
325        self
326    }
327
328    /// Set the number of stop bits for the UART peripheral.
329    ///
330    /// Default: [`StopBits::One`]
331    pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
332        self.stop_bits = stop_bits;
333        self
334    }
335
336    /// Set the parity for the UART peripheral.
337    ///
338    /// Default: [`ParityBit::None`]
339    pub fn parity(mut self, parity: ParityBit) -> Self {
340        self.parity = parity;
341        self
342    }
343
344    // TODO: Implement hardware flow control
345    // pub fn enable_hfc(
346    //     self,
347    //     cts_pin: $cts_pin,
348    //     rts_pin: $rts_pin
349    // ) -> UartPeripheral<NotBuilt, CLOCK, $uart, RX, TX, $cts_pin, $rts_pin> {
350    //     // Enable CTS and RTS pins
351    //     // cts_pin.enable();
352    //     // rts_pin.enable();
353    //     UartPeripheral {
354    //         _state: PhantomData,
355    //         _clock: PhantomData,
356    //         uart: self.uart,
357    //         _rx_pin: self._rx_pin,
358    //         _tx_pin: self._tx_pin,
359    //         _cts_pin: cts_pin,
360    //         _rts_pin: rts_pin,
361    //         clk_src: self.clk_src,
362    //         clk_src_freq: self.clk_src_freq,
363    //         baud: self.baud,
364    //         data_bits: self.data_bits,
365    //         stop_bits: self.stop_bits,
366    //         parity: self.parity,
367    //     }
368    // }
369}
370
371impl<UART, RX, TX, CTS, RTS>
372    UartPeripheral<marker::NotBuilt, marker::ClockSet, UART, RX, TX, CTS, RTS>
373where
374    UART: Deref<Target = UartRegisterBlock>,
375{
376    /// Apply all settings and configure the UART peripheral.
377    /// This must be called before the UART peripheral can be used.
378    pub fn build(self) -> BuiltUartPeripheral<UART, RX, TX, CTS, RTS> {
379        // Configure the UART peripheral
380        let clk_src_freq = self.clk_src_freq.unwrap();
381        self.uart.ctrl().write(|w| {
382            w.ucagm().set_bit();
383            match self.clk_src {
384                Some(UartClockSource::Pclk) => w.bclksrc().peripheral_clock(),
385                Some(UartClockSource::Ibro) => w.bclksrc().clk2(),
386                None => unreachable!("UART clock source not set"),
387            };
388            w.bclken().set_bit();
389            match self.data_bits {
390                DataBits::Five => w.char_size()._5bits(),
391                DataBits::Six => w.char_size()._6bits(),
392                DataBits::Seven => w.char_size()._7bits(),
393                DataBits::Eight => w.char_size()._8bits(),
394            };
395            match self.stop_bits {
396                StopBits::One => w.stopbits().clear_bit(),
397                StopBits::More => w.stopbits().set_bit(),
398            };
399            match self.parity {
400                ParityBit::None => w.par_en().clear_bit(),
401                ParityBit::Even => w.par_en().set_bit().par_eo().clear_bit(),
402                ParityBit::Odd => w.par_en().set_bit().par_eo().set_bit(),
403                ParityBit::SpaceZero => w.par_en().set_bit().par_md().clear_bit(),
404                ParityBit::MarkOne => w.par_en().set_bit().par_md().set_bit(),
405            };
406            return w;
407        });
408        // Set the baud rate
409        let clkdiv = clk_src_freq / self.baud;
410        self.uart
411            .clkdiv()
412            .write(|w| unsafe { w.clkdiv().bits(clkdiv) });
413        // Wait until baud clock is ready
414        while self.uart.ctrl().read().bclkrdy().bit_is_clear() {}
415        BuiltUartPeripheral {
416            uart: self.uart,
417            _rx_pin: self._rx_pin,
418            _tx_pin: self._tx_pin,
419            _cts_pin: self._cts_pin,
420            _rts_pin: self._rts_pin,
421        }
422    }
423}
424
425/// # UART Methods
426/// These methods are used to interact with the UART peripheral after it has
427/// been built.
428impl<UART, RX, TX, CTS, RTS> BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
429where
430    UART: Deref<Target = UartRegisterBlock>,
431{
432    #[doc(hidden)]
433    #[inline(always)]
434    fn _is_tx_full(&self) -> bool {
435        self.uart.status().read().tx_full().bit_is_set()
436    }
437
438    #[doc(hidden)]
439    #[inline(always)]
440    fn _is_tx_empty(&self) -> bool {
441        self.uart.status().read().tx_em().bit_is_set()
442    }
443
444    #[doc(hidden)]
445    #[inline(always)]
446    fn _is_rx_empty(&self) -> bool {
447        self.uart.status().read().rx_em().bit_is_set()
448    }
449
450    #[doc(hidden)]
451    #[inline(always)]
452    fn _read_byte(&self) -> nb::Result<u8, serial::ErrorKind> {
453        if self._is_rx_empty() {
454            return Err(nb::Error::WouldBlock);
455        }
456        Ok(self.uart.fifo().read().data().bits())
457    }
458
459    #[doc(hidden)]
460    #[inline(always)]
461    fn _write_byte(&self, byte: u8) -> nb::Result<(), serial::ErrorKind> {
462        if self._is_tx_full() {
463            return Err(nb::Error::WouldBlock);
464        }
465        self.uart.fifo().write(|w| unsafe { w.data().bits(byte) });
466        Ok(())
467    }
468
469    /// Flush the transmit buffer, ensuring that all bytes have been sent.
470    /// This is a blocking operation.
471    #[inline(always)]
472    fn flush_tx(&self) {
473        while !self._is_tx_empty() {}
474    }
475
476    /// Reads a single byte. This is a blocking operation.
477    pub fn read_byte(&self) -> u8 {
478        nb::block!(self._read_byte()).unwrap()
479    }
480
481    /// Writes a single byte. This is a blocking operation.
482    pub fn write_byte(&self, byte: u8) {
483        nb::block!(self._write_byte(byte)).unwrap()
484    }
485
486    /// Reads bytes to a buffer. The entire length of the buffer will be
487    /// filled with bytes from the UART peripheral. This is a blocking
488    /// operation.
489    pub fn read_bytes(&self, buffer: &mut [u8]) {
490        for byte in buffer {
491            *byte = self.read_byte();
492        }
493    }
494
495    /// Write bytes from a buffer (blocking). The entire buffer will be written
496    /// to the UART peripheral. This is a blocking operation.
497    pub fn write_bytes(&self, buffer: &[u8]) {
498        for byte in buffer {
499            self.write_byte(*byte);
500        }
501    }
502}
503
504// Embedded HAL non-blocking serial traits
505impl<UART, RX, TX, CTS, RTS> serial::ErrorType for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
506where
507    UART: Deref<Target = UartRegisterBlock>,
508{
509    type Error = serial::ErrorKind;
510}
511
512impl<UART, RX, TX, CTS, RTS> serial::Read<u8> for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
513where
514    UART: Deref<Target = UartRegisterBlock>,
515{
516    fn read(&mut self) -> nb::Result<u8, Self::Error> {
517        self._read_byte()
518    }
519}
520
521impl<UART, RX, TX, CTS, RTS> serial::Write<u8> for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
522where
523    UART: Deref<Target = UartRegisterBlock>,
524{
525    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
526        self._write_byte(byte)
527    }
528
529    fn flush(&mut self) -> nb::Result<(), Self::Error> {
530        self.flush_tx();
531        Ok(())
532    }
533}
534
535// Embedded IO traits
536impl<UART, RX, TX, CTS, RTS> embedded_io::ErrorType for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
537where
538    UART: Deref<Target = UartRegisterBlock>,
539{
540    type Error = core::convert::Infallible;
541}
542
543impl<UART, RX, TX, CTS, RTS> embedded_io::Read for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
544where
545    UART: Deref<Target = UartRegisterBlock>,
546{
547    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
548        let mut count = 0;
549        if buf.len() == 0 {
550            return Ok(0);
551        }
552        // If no bytes are currently available to read, this function blocks
553        // until at least one byte is available.
554        if self._is_rx_empty() {
555            let byte = self.read_byte();
556            buf[count] = byte;
557            count += 1;
558        // If bytes are available, a non-zero amount of bytes is read.
559        } else {
560            while count < buf.len() && !self._is_rx_empty() {
561                let byte = self.read_byte();
562                buf[count] = byte;
563                count += 1;
564            }
565        }
566        Ok(count)
567    }
568}
569
570impl<UART, RX, TX, CTS, RTS> embedded_io::ReadReady for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
571where
572    UART: Deref<Target = UartRegisterBlock>,
573{
574    fn read_ready(&mut self) -> Result<bool, Self::Error> {
575        Ok(!self._is_rx_empty())
576    }
577}
578
579impl<UART, RX, TX, CTS, RTS> embedded_io::Write for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
580where
581    UART: Deref<Target = UartRegisterBlock>,
582{
583    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
584        for byte in buf {
585            self.write_byte(*byte);
586        }
587        Ok(buf.len())
588    }
589
590    fn flush(&mut self) -> Result<(), Self::Error> {
591        self.flush_tx();
592        Ok(())
593    }
594}
595
596impl<UART, RX, TX, CTS, RTS> embedded_io::WriteReady for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
597where
598    UART: Deref<Target = UartRegisterBlock>,
599{
600    fn write_ready(&mut self) -> Result<bool, Self::Error> {
601        Ok(!self._is_tx_full())
602    }
603}