Skip to main content

imxrt_hal/common/
lpuart.rs

1//! Low-power universal asynchronous receiver / transmitter.
2//!
3//! Use the LPUART peripheral to perform reads and writes with a serial
4//! device. Features include
5//!
6//! - configurable baud rates (depends on input clock frequency)
7//! - parity bits: none, even, odd
8//! - inverted TX and RX lines
9//! - TX and RX FIFOs with configurable watermarks
10//! - DMA transfers and receives
11//! - Non-blocking and blocking implementations of `embedded-hal` serial
12//!   traits.
13//!
14//! # Example
15//!
16//! Demonstrates how to create and configure an LPUART peripheral. To see an example
17//! of LPUART clock configuration, see the [`ccm::uart_clk`](crate::ccm::uart_clk) documentation.
18//! For more information on the DMA API, see the [`dma`](crate::dma) examples.
19//!
20//! ```no_run
21//! use imxrt_hal as hal;
22//! use hal::lpuart::{Baud, Direction, Lpuart, Parity, Pins, Status, Watermark};
23//! use imxrt_ral as ral;
24//! # use imxrt_iomuxc::imxrt1060 as iomuxc;
25//!
26//! # async fn opt() -> Option<()> {
27//! let (gpio_ad_b1_02, gpio_ad_b1_03) = // Handle to LPUART2 TX and RX pins...
28//!     # unsafe { (iomuxc::gpio_ad_b1::GPIO_AD_B1_02::new(), iomuxc::gpio_ad_b1::GPIO_AD_B1_03::new()) };
29//! # const UART_CLKC_HZ: u32 = 1;
30//!
31//! let registers = unsafe { ral::lpuart::LPUART2::instance() };
32//! let pins = Pins { tx: gpio_ad_b1_02, rx: gpio_ad_b1_03 };
33//! let mut lpuart2 = Lpuart::with_pins(registers, pins);
34//!
35//! const BAUD: Baud = Baud::compute(UART_CLKC_HZ, 115200);
36//! lpuart2.disable(|lpuart2| {
37//!     lpuart2.set_baud(&BAUD);
38//!     lpuart2.set_parity(Parity::ODD);
39//!     lpuart2.enable_fifo(Watermark::tx(4));
40//!     lpuart2.disable_fifo(Direction::Rx);
41//!     lpuart2.set_inversion(Direction::Rx, true);
42//! });
43//!
44//! // Fill the transmit FIFO with 0xAA...
45//! while lpuart2.status().contains(Status::TRANSMIT_EMPTY) {
46//!     lpuart2.write_byte(0xAA);
47//! }
48//!
49//! // Schedule a DMA receive...
50//! # let mut dma_channel = unsafe { hal::dma::DMA.channel(13) };
51//! let mut buffer = [0u8; 64];
52//! lpuart2.dma_read(&mut dma_channel, &mut buffer)
53//!     .await.ok()?;
54//! # Some(()) }
55//! ```
56
57use crate::iomuxc;
58use crate::ral;
59
60/// Any LPUART instance.
61type AnyInstance = crate::AnyInstance<ral::lpuart::RegisterBlock>;
62
63/// LPUART pins.
64pub struct Pins<TX, RX>
65where
66    TX: iomuxc::lpuart::Pin<Direction = iomuxc::lpuart::Tx>,
67    RX: iomuxc::lpuart::Pin<Module = TX::Module, Direction = iomuxc::lpuart::Rx>,
68{
69    /// Transfer pin.
70    pub tx: TX,
71    /// Receive pin.
72    pub rx: RX,
73}
74
75/// LPUART peripheral.
76///
77/// `Lpuart` lets you configure the LPUART peripheral, and perform I/O.
78/// See the [module-level documentation](crate::lpuart) for an example.
79///
80/// `Lpuart` implements serial traits from `embedded-hal`. It models
81/// DMA transfers as futures. The type exposes a lower-level API for
82/// coordinating DMA transfers. However, you may find it easier to use
83/// the [`dma`](crate::dma) interface.
84pub struct Lpuart {
85    pub(crate) lpuart: AnyInstance,
86}
87
88/// Serial direction.
89#[cfg_attr(feature = "defmt", derive(defmt::Format))]
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub enum Direction {
92    /// Transfer direction (leaving the peripheral).
93    Tx,
94    /// Receiver direction (entering the peripheral).
95    Rx,
96}
97
98impl Lpuart {
99    /// Create a new LPUART peripheral from its peripheral registers
100    /// and TX / RX pins.
101    ///
102    /// When this call returns, the peripheral is reset, the pins are
103    /// configured for their LPUART functions, and the TX and RX
104    /// halves are enabled.
105    ///
106    /// The pins are consumed to ensure they're properly configured, but they
107    /// are not stored in the driver.
108    pub fn with_pins<TX, RX, const N: u8>(
109        lpuart: ral::lpuart::Instance<N>,
110        mut pins: Pins<TX, RX>,
111    ) -> Self
112    where
113        TX: iomuxc::lpuart::Pin<Module = iomuxc::consts::Const<N>, Direction = iomuxc::lpuart::Tx>,
114        RX: iomuxc::lpuart::Pin<Module = iomuxc::consts::Const<N>, Direction = iomuxc::lpuart::Rx>,
115    {
116        iomuxc::lpuart::prepare(&mut pins.tx);
117        iomuxc::lpuart::prepare(&mut pins.rx);
118        Self::init(lpuart)
119    }
120
121    /// Create a new LPUART peripheral from its peripheral registers
122    /// without any pins.
123    ///
124    /// This is similar to [`with_pins()`](Self::with_pins), but it does not configure
125    /// pins to function as inputs and outputs. You're responsible
126    /// for configuring TX and RX pins and for making sure the pin state
127    /// doesn't change.
128    pub fn without_pins<const N: u8>(lpuart: ral::lpuart::Instance<N>) -> Self {
129        Self::init(lpuart)
130    }
131
132    fn init<const N: u8>(lpuart: ral::lpuart::Instance<N>) -> Self {
133        let lpuart: AnyInstance = crate::into_any(lpuart);
134        ral::write_reg!(ral::lpuart, lpuart, GLOBAL, RST: 1);
135        ral::write_reg!(ral::lpuart, lpuart, GLOBAL, RST: 0);
136        ral::modify_reg!(ral::lpuart, lpuart, CTRL, TE: TE_1, RE: RE_1);
137        Self { lpuart }
138    }
139
140    /// Indicates if the transmit / receive functions are
141    /// (`true`) or are not (`false`) enabled.
142    pub fn is_enabled(&self, direction: Direction) -> bool {
143        match direction {
144            Direction::Rx => ral::read_reg!(ral::lpuart, self.lpuart, CTRL, RE == RE_1),
145            Direction::Tx => ral::read_reg!(ral::lpuart, self.lpuart, CTRL, TE == TE_1),
146        }
147    }
148
149    /// Enable (`true`) or disable (`false`) the transmit / receive
150    /// functions.
151    pub fn set_enable(&mut self, direction: Direction, enable: bool) {
152        match direction {
153            Direction::Rx => ral::modify_reg!(ral::lpuart, self.lpuart, CTRL, RE: enable as u32),
154            Direction::Tx => ral::modify_reg!(ral::lpuart, self.lpuart, CTRL, TE: enable as u32),
155        }
156    }
157
158    /// Resets all internal logic and registers.
159    ///
160    /// Note that this may not reset all peripheral state, like the state
161    /// in the peripheral's global register.
162    pub fn reset(&mut self) {
163        ral::write_reg!(ral::lpuart, self.lpuart, GLOBAL, RST: 1);
164        ral::write_reg!(ral::lpuart, self.lpuart, GLOBAL, RST: 0);
165    }
166
167    /// Temporarily disable the LPUART peripheral.
168    ///
169    /// The handle to a [`Disabled`](crate::lpuart::Disabled) driver lets you modify
170    /// LPUART settings that require a fully disabled peripheral. This will flush
171    /// TX and RX buffers.
172    pub fn disable<R>(&mut self, func: impl FnOnce(&mut Disabled) -> R) -> R {
173        let mut disabled = Disabled::new(&mut self.lpuart);
174        func(&mut disabled)
175    }
176
177    /// Return the baud-specific timing values for this UART peripheral.
178    pub fn baud(&self) -> Baud {
179        let (osr, sbr, bothedge) =
180            ral::read_reg!(ral::lpuart, self.lpuart, BAUD, OSR, SBR, BOTHEDGE);
181        Baud {
182            osr: osr + 1,
183            sbr,
184            bothedge: bothedge != 0,
185        }
186    }
187
188    /// Return the parity seting for the UART peripheral.
189    ///
190    /// Result is `None` if there is no parity setting.
191    pub fn parity(&self) -> Option<Parity> {
192        let (pe, pt) = ral::read_reg!(ral::lpuart, self.lpuart, CTRL, PE, PT);
193        const PARITY_ODD: u32 = Parity::Odd as u32;
194        const PARITY_EVEN: u32 = Parity::Even as u32;
195        match pt {
196            PARITY_ODD if pe != 0 => Parity::ODD,
197            PARITY_EVEN if pe != 0 => Parity::EVEN,
198            _ => Parity::NONE,
199        }
200    }
201
202    /// Indicates if the bits are inverted.
203    #[inline]
204    pub fn is_inverted(&self, direction: Direction) -> bool {
205        match direction {
206            Direction::Rx => ral::read_reg!(ral::lpuart, self.lpuart, STAT, RXINV == 1),
207            Direction::Tx => ral::read_reg!(ral::lpuart, self.lpuart, CTRL, TXINV == 1),
208        }
209    }
210
211    /// Indicates if the FIFO is enabled.
212    #[inline]
213    pub fn is_fifo_enabled(&self, direction: Direction) -> bool {
214        match direction {
215            Direction::Rx => ral::read_reg!(ral::lpuart, self.lpuart, FIFO, RXFE == 1),
216            Direction::Tx => ral::read_reg!(ral::lpuart, self.lpuart, FIFO, TXFE == 1),
217        }
218    }
219
220    /// Returns the FIFO watermark value.
221    #[inline]
222    pub fn fifo_watermark(&self, direction: Direction) -> u32 {
223        match direction {
224            Direction::Rx => ral::read_reg!(ral::lpuart, self.lpuart, WATER, RXWATER),
225            Direction::Tx => ral::read_reg!(ral::lpuart, self.lpuart, WATER, TXWATER),
226        }
227    }
228
229    /// Read the data register.
230    pub fn read_data(&self) -> ReadData {
231        ReadData(ral::read_reg!(ral::lpuart, self.lpuart, DATA))
232    }
233
234    /// Write a byte.
235    ///
236    /// This does not perform any checks for space in the transmit
237    /// buffer. To check transmit buffer space, use `status`, and
238    /// check for the transmit data register empty.
239    pub fn write_byte(&self, byte: u8) {
240        ral::write_reg!(ral::lpuart, self.lpuart, DATA, byte as u32);
241    }
242
243    /// Check the peripheral status register.
244    pub fn status(&self) -> Status {
245        let stat = ral::read_reg!(ral::lpuart, self.lpuart, STAT);
246        let fifo = ral::read_reg!(ral::lpuart, self.lpuart, FIFO);
247        Status::from_registers(stat, fifo)
248    }
249
250    /// Clear the status flags.
251    ///
252    /// Bits that are read-only will be cleared by the implementation, so it's
253    /// safe to call with `Status::all()`.
254    #[inline]
255    pub fn clear_status(&mut self, status: Status) {
256        let stat_flags = status & Status::W1C & Status::stat_mask();
257        let fifo_flags = status & Status::W1C & Status::fifo_mask();
258        ral::modify_reg!(ral::lpuart, self.lpuart, STAT, |stat| {
259            let stat = stat & !Status::stat_mask().stat_bits();
260            stat | stat_flags.stat_bits()
261        });
262        ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, |fifo| {
263            let fifo = fifo & !Status::fifo_mask().fifo_bits();
264            fifo | fifo_flags.fifo_bits()
265        });
266    }
267
268    /// Flush data from the FIFO.
269    ///
270    /// This does not flush anything that's already in the transmit or receive register.
271    #[inline]
272    pub fn flush_fifo(&mut self, direction: Direction) {
273        flush_fifo(&self.lpuart, direction);
274    }
275
276    /// Return the interrupt flags.
277    ///
278    /// The interrupt flags indicate the reasons that this peripheral may generate an
279    /// interrupt.
280    pub fn interrupts(&self) -> Interrupts {
281        let ctrl = ral::read_reg!(ral::lpuart, self.lpuart, CTRL);
282        let fifo = ral::read_reg!(ral::lpuart, self.lpuart, FIFO);
283        Interrupts::from_bits_truncate(ctrl | fifo)
284    }
285
286    /// Let the peripheral act as a DMA destination.
287    ///
288    /// After this call, the peripheral will signal to the DMA engine whenever
289    /// it has free space in its transfer buffer.
290    pub fn enable_dma_transmit(&mut self) {
291        ral::modify_reg!(ral::lpuart, self.lpuart, BAUD, TDMAE: 1);
292    }
293
294    /// Stop the peripheral from acting as a DMA destination.
295    ///
296    /// See the DMA chapter in the reference manual to understand when this
297    /// should be called in the DMA transfer lifecycle.
298    pub fn disable_dma_transmit(&mut self) {
299        while ral::read_reg!(ral::lpuart, self.lpuart, BAUD, TDMAE == 1) {
300            ral::modify_reg!(ral::lpuart, self.lpuart, BAUD, TDMAE: 0);
301        }
302    }
303
304    /// Produces a pointer to the data register.
305    ///
306    /// You should use this pointer when coordinating a DMA transfer.
307    /// You're not expected to read from this pointer in software.
308    pub fn data(&self) -> *const ral::RWRegister<u32> {
309        core::ptr::addr_of!(self.lpuart.DATA)
310    }
311
312    /// Let the peripheral act as a DMA source.
313    ///
314    /// After this call, the peripheral will signal to the DMA engine whenever
315    /// it has data available to read.
316    pub fn enable_dma_receive(&mut self) {
317        self.clear_status(Status::W1C);
318        ral::modify_reg!(ral::lpuart, self.lpuart, BAUD, RDMAE: 1);
319    }
320
321    /// Stop the peripheral from acting as a DMA source.
322    ///
323    /// See the DMA chapter in the reference manual to understand when this
324    /// should be called in the DMA transfer lifecycle.
325    pub fn disable_dma_receive(&mut self) {
326        while ral::read_reg!(ral::lpuart, self.lpuart, BAUD, RDMAE == 1) {
327            ral::modify_reg!(ral::lpuart, self.lpuart, BAUD, RDMAE: 0);
328        }
329    }
330
331    /// Attempts to write a single byte to the bus.
332    ///
333    /// Returns `false` if the fifo was already full.
334    pub fn try_write(&mut self, byte: u8) -> bool {
335        ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, TXOF: TXOF_1);
336        self.write_byte(byte);
337        ral::read_reg!(ral::lpuart, self.lpuart, FIFO, TXOF == TXOF_0)
338    }
339
340    /// Attempts to read a single byte from the bus.
341    ///
342    /// Returns:
343    ///   - `Ok(Some(u8))` if data was read
344    ///   - `Ok(None)` if the fifo was empty
345    ///   - `Err(..)` if a read error happened
346    pub fn try_read(&mut self) -> Result<Option<u8>, ReadFlags> {
347        let data = self.read_data();
348        if data.flags().contains(ReadFlags::RXEMPT) {
349            Ok(None)
350        } else if data
351            .flags()
352            .intersects(ReadFlags::PARITY_ERROR | ReadFlags::FRAME_ERROR | ReadFlags::NOISY)
353        {
354            Err(data.flags())
355        } else {
356            Ok(Some(data.into()))
357        }
358    }
359}
360
361fn flush_fifo(lpuart: &AnyInstance, direction: Direction) {
362    match direction {
363        Direction::Rx => ral::modify_reg!(ral::lpuart, lpuart, FIFO, RXFLUSH: RXFLUSH_1),
364        Direction::Tx => ral::modify_reg!(ral::lpuart, lpuart, FIFO, TXFLUSH: TXFLUSH_1),
365    }
366}
367
368/// A temporarily-disabled LPUART peripheral.
369///
370/// The disabled peripheral lets you changed
371/// settings that require a disabled peripheral.
372pub struct Disabled<'a> {
373    lpuart: &'a mut AnyInstance,
374    te: bool,
375    re: bool,
376}
377
378impl Drop for Disabled<'_> {
379    fn drop(&mut self) {
380        ral::modify_reg!(ral::lpuart, self.lpuart, CTRL, TE: self.te as u32, RE: self.re as u32);
381    }
382}
383
384impl<'a> Disabled<'a> {
385    fn new(lpuart: &'a mut AnyInstance) -> Self {
386        let (te, re) = ral::read_reg!(ral::lpuart, lpuart, CTRL, TE, RE);
387        ral::modify_reg!(ral::lpuart, lpuart, CTRL, TE: TE_0, RE: RE_0);
388        for direction in [Direction::Rx, Direction::Tx] {
389            flush_fifo(lpuart, direction);
390        }
391        Self {
392            lpuart,
393            te: te != 0,
394            re: re != 0,
395        }
396    }
397
398    /// Set baud-specific timing values for this UART peripheral.
399    ///
400    /// The timing values are used to set a baud rate. To compute
401    /// a baud rate, see [`Baud::compute`](crate::lpuart::Baud::compute). Or,
402    /// you may compute your own timing values.
403    pub fn set_baud(&mut self, baud: &Baud) {
404        ral::modify_reg!(ral::lpuart, self.lpuart,
405            BAUD,
406            OSR: baud.osr.clamp(4, 32) - 1,
407            SBR: baud.sbr.min((1 << 13) - 1),
408            BOTHEDGE: baud.bothedge as u32)
409    }
410
411    /// Specify parity bit settings. If there is no parity, use `None`.
412    pub fn set_parity(&mut self, parity: Option<Parity>) {
413        ral::modify_reg!(
414            ral::lpuart,
415            self.lpuart,
416            CTRL,
417            PE: parity.is_some() as u32,
418            M: parity.is_some() as u32,
419            PT: parity.map(|p| p as u32).unwrap_or(0u32)
420        );
421    }
422
423    /// Reverse the polarity of data, affecting all data bits, start
424    /// and stop bits, and polarity bits.
425    ///
426    /// The default inversion state is `false`.
427    #[inline]
428    pub fn set_inversion(&mut self, direction: Direction, inverted: bool) {
429        match direction {
430            Direction::Rx => {
431                ral::modify_reg!(ral::lpuart, self.lpuart, STAT, RXINV: inverted as u32)
432            }
433            Direction::Tx => {
434                ral::modify_reg!(ral::lpuart, self.lpuart, CTRL, TXINV: inverted as u32)
435            }
436        }
437    }
438
439    /// Disable the FIFO for the given direction.
440    #[inline]
441    pub fn disable_fifo(&mut self, direction: Direction) {
442        match direction {
443            Direction::Rx => ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, RXFE: RXFE_0),
444            Direction::Tx => ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, TXFE: TXFE_0),
445        }
446    }
447
448    /// Enable the FIFO, and set the FIFO watermark.
449    ///
450    /// `watermark` describes the serial direction, and the point at which the hardware signals a full
451    /// or empty FIFO. Use [`Watermark::tx`](crate::lpuart::Watermark::tx)
452    /// to enable the transfer FIFO, and [`Watermark::rx`](crate::lpuart::Watermark::rx) to enable the
453    /// receive FIFO.
454    ///
455    /// The actual watermark value is limited by the hardware. `enable_fifo` returns the
456    /// actual watermark value.
457    #[inline]
458    pub fn enable_fifo(&mut self, watermark: Watermark) -> u32 {
459        let size = match watermark.direction {
460            Direction::Rx => 1 << ral::read_reg!(ral::lpuart, self.lpuart, PARAM, RXFIFO),
461            Direction::Tx => 1 << ral::read_reg!(ral::lpuart, self.lpuart, PARAM, TXFIFO),
462        };
463        let size = watermark.size.min(size - 1);
464        match watermark.direction {
465            Direction::Rx => {
466                ral::modify_reg!(ral::lpuart, self.lpuart, WATER, RXWATER: size);
467                ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, RXFE: RXFE_1);
468            }
469            Direction::Tx => {
470                ral::modify_reg!(ral::lpuart, self.lpuart, WATER, TXWATER: size);
471                ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, TXFE: TXFE_1);
472            }
473        };
474        size
475    }
476
477    /// Set the interrupt flags for this LPUART peripheral.
478    ///
479    /// Use `set_interrupts` to enable or disable interrupt generation for
480    /// this peripheral.
481    pub fn set_interrupts(&mut self, interrupts: Interrupts) {
482        let ctrl_flags = interrupts & Interrupts::ctrl_mask();
483        let fifo_flags = interrupts & Interrupts::fifo_mask();
484        ral::modify_reg!(ral::lpuart, self.lpuart, CTRL, |ctrl| {
485            let ctrl = ctrl & !Interrupts::ctrl_mask().bits();
486            ctrl | ctrl_flags.bits()
487        });
488        ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, |fifo| {
489            let fifo = fifo & !Interrupts::fifo_mask().bits();
490            fifo | fifo_flags.bits()
491        });
492    }
493}
494
495/// Values specific to the baud rate.
496///
497/// To compute the values for a given baud rate,
498/// use [`compute`](Baud::compute). To understand
499/// the actual baud rate, use [`value`](Baud::value).
500///
501/// Advanced users may choose to set the OSR, SBR, and
502/// BOTHEDGE values directly.
503///
504/// ```no_run
505/// use imxrt_hal::lpuart::Baud;
506///
507/// // Assume UART clock is driven from the crystal
508/// // oscillator...
509/// const UART_CLOCK_HZ: u32 = 24_000_000;
510/// const BAUD: Baud = Baud::compute(UART_CLOCK_HZ, 115200);
511/// ```
512#[cfg_attr(feature = "defmt", derive(defmt::Format))]
513#[derive(Debug, Clone, Copy, PartialEq, Eq)]
514pub struct Baud {
515    /// Oversampling rate.
516    ///
517    /// This should be set between 4 and 32.
518    /// The driver clamps the `osr` value within
519    /// this range.
520    pub osr: u32,
521    /// Baud rate modulo divisor.
522    ///
523    /// The driver commits this value directly.
524    /// A value of zero is allowed, but will disable
525    /// baud rate generation in hardware. The max
526    /// value is `(2^13) - 1`. The implementation
527    /// limits the max value.
528    pub sbr: u32,
529    /// Both edge sampling.
530    ///
531    /// Should be set when the oversampling
532    /// rate is between 4 and 7. Optional
533    /// for higher sampling rates. The driver
534    /// will commit this value directly.
535    pub bothedge: bool,
536}
537
538impl Baud {
539    /// Returns the baud value in bits per second.
540    ///
541    /// `source_clock_hz` is the UART clock frequency (Hz).
542    ///
543    /// # Panics
544    ///
545    /// Panics if `sbr` or `osr` is zero.
546    pub const fn value(self, source_clock_hz: u32) -> u32 {
547        source_clock_hz / (self.sbr * self.osr)
548    }
549
550    /// Computes a timings struct that represents a baud rate.
551    ///
552    /// `source_clock_hz` is the UART clock frequency (Hz). `baud`
553    /// is the intended baud rate.
554    pub const fn compute(source_clock_hz: u32, baud: u32) -> Baud {
555        const fn max(left: u32, right: u32) -> u32 {
556            if left > right { left } else { right }
557        }
558        const fn min(left: u32, right: u32) -> u32 {
559            if left < right { left } else { right }
560        }
561
562        let mut err = u32::MAX;
563        let mut best_osr = 0;
564        let mut best_sbr = 0;
565
566        let mut osr = if baud > 3_000_000 { 4 } else { 8 };
567        while osr <= 32 {
568            let mut sbr = 1;
569            while sbr < 8192 {
570                let b = source_clock_hz / (sbr * osr);
571                let e = max(baud, b) - min(baud, b);
572                if e < err {
573                    err = e;
574                    best_osr = osr;
575                    best_sbr = sbr;
576                }
577                sbr += 1;
578            }
579            osr += 1;
580        }
581        Baud {
582            osr: best_osr,
583            sbr: best_sbr,
584            bothedge: 4 <= best_osr && best_osr <= 7,
585        }
586    }
587}
588
589/// Parity bit selection.
590///
591/// See [`Disabled::set_parity`](crate::lpuart::Disabled::set_parity) and
592/// [`Lpuart::parity`](crate::lpuart::Lpuart::parity) for more information.
593/// Consider using the associated constants to quickly specify
594/// parity bits.
595#[cfg_attr(feature = "defmt", derive(defmt::Format))]
596#[derive(Debug, Clone, Copy, PartialEq, Eq)]
597#[repr(u32)]
598pub enum Parity {
599    /// Even parity.
600    Even = 0,
601    /// Odd parity.
602    Odd = 1,
603}
604
605impl Parity {
606    /// No parity.
607    pub const NONE: Option<Parity> = None;
608    /// Even parity.
609    pub const EVEN: Option<Parity> = Some(Parity::Even);
610    /// Odd parity.
611    pub const ODD: Option<Parity> = Some(Parity::Odd);
612}
613
614bitflags::bitflags! {
615    /// Errors that may occur when reading data.
616    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
617    pub struct ReadFlags : u32 {
618        /// Data was received with noise.
619        const NOISY = 1 << 15;
620        /// Parity error when receiving data.
621        const PARITY_ERROR = 1 << 14;
622        /// Framing error when receiving data.
623        const FRAME_ERROR = 1 << 13;
624        /// Receive buffer is empty.
625        ///
626        /// Asserts when there is no data in the receive buffer.
627        const RXEMPT = 1 << 12;
628        /// Idle Line.
629        ///
630        /// Indicates the receiver line was idle before receiving the character.
631        /// Overrun occured, and we lost data in the shift register.
632        const IDLINE = 1 << 11;
633    }
634}
635
636bitflags::bitflags! {
637    /// Interrupt settings.
638    ///
639    /// A set bit indicates that the interrupt is enabled.
640    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
641    pub struct Interrupts : u32 {
642        /// Overrun interrupt enable.
643        const OVERRUN = 1 << 27;
644        /// Noise error interrupt enable.
645        const NOISE_ERROR = 1 << 26;
646        /// Framing error interrupt enable.
647        const FRAMING_ERROR = 1 << 25;
648        /// Parity error interrupt enable.
649        const PARITY_ERROR = 1 << 24;
650        /// Transmit empty interrupt enable.
651        ///
652        /// Triggers when the `TRANSMIT_EMPTY` _status_ bit is high.
653        const TRANSMIT_EMPTY = 1 << 23;
654        /// Transmit complete interrupt enable.
655        ///
656        /// Triggers an interrupt when the `TRANSMIT_COMPLETE` _status_ bit is high.
657        const TRANSMIT_COMPLETE = 1 << 22;
658        /// Receiver interrupt enable.
659        ///
660        /// Triggers when the `RECEIVE_FULL` _status_ bit is high.
661        const RECEIVE_FULL = 1 << 21;
662
663        // All of the above flags pertain to the CTRL
664        // register. These flags pertain to the FIFO
665        // interrupts. They can be written directly.
666
667        /// Transmit FIFO Overflow Interrupt Enable.
668        ///
669        /// If set, a transmit FIFO overrun event generates an
670        /// interrupt.
671        const TRANSMIT_OVERFLOW = 1 << 9;
672        /// Receive FIFO Underflow Interrupt Enable.
673        ///
674        /// If set, a receive FIFO underflow event generates an
675        /// interrupt.
676        const RECEIVE_UNDERFLOW = 1 << 8;
677    }
678}
679
680impl Interrupts {
681    /// Mask for only the FIFO bits.
682    const fn fifo_mask() -> Self {
683        Self::from_bits_truncate(
684            Interrupts::TRANSMIT_OVERFLOW.bits() | Interrupts::RECEIVE_UNDERFLOW.bits(),
685        )
686    }
687    /// Mask for only the CTRL bits.
688    const fn ctrl_mask() -> Self {
689        // Safety: bits are valid for this bitflags instance.
690        Self::from_bits_truncate(Self::all().bits() & !Self::fifo_mask().bits())
691    }
692}
693
694/// The result of reading from the receiver.
695///
696/// The data contains flags, which may indicate errors
697/// in the received data. If the flags indicate value data,
698/// use `u8::from` to convert the data into its raw byte.
699#[cfg_attr(feature = "defmt", derive(defmt::Format))]
700#[derive(Clone, Copy, Debug, PartialEq, Eq)]
701#[repr(transparent)]
702pub struct ReadData(u32);
703
704impl ReadData {
705    /// Access the read flags, which indicate results of the
706    /// read operation.
707    #[inline]
708    pub fn flags(self) -> ReadFlags {
709        ReadFlags::from_bits_truncate(self.0)
710    }
711
712    /// Access the raw value.
713    #[inline]
714    pub fn raw(self) -> u32 {
715        self.0
716    }
717}
718
719impl From<ReadData> for u8 {
720    #[inline]
721    fn from(read_data: ReadData) -> u8 {
722        read_data.0 as u8
723    }
724}
725
726bitflags::bitflags! {
727    /// Status flags.
728    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
729    pub struct Status : u32 {
730        /// Receiver active flag.
731        ///
732        /// Set when the receiver detects a start bit. Cleared when
733        /// the line is idle.
734        const RECEIVE_ACTIVE = 1 << 24;
735        /// Transmit data register empty.
736        ///
737        /// This bit is set when the transmit FIFO can accept data.
738        /// - if the FIFO is enabled, this is set when the FIFO hits the watermark.
739        /// - if the FIFO is disabled, this is set when there's nothing in
740        ///   the transmit data register.
741        const TRANSMIT_EMPTY = 1 << 23;
742        /// Transmit complete.
743        ///
744        /// TC is cleared when there's a transmission in progress, or when a preamble /
745        /// break character is loaded. It's set when the transmit buffer is empty.
746        ///
747        /// To clear TC, perform a write.
748        const TRANSMIT_COMPLETE = 1 << 22;
749        /// Receiver data register full.
750        ///
751        /// This bit is set when the receive FIFO is full.
752        /// - if the FIFO is enabled, this is set when the FIFO hits the watermark.
753        /// - if the FIFO is disabled, this is set when there's something in the
754        ///   receiver register.
755        const RECEIVE_FULL = 1 << 21;
756        /// Idle line flag.
757        ///
758        /// IDLE is set when the LPUART receive line becomes idle for a full character
759        /// time after a period of activity.
760        const IDLE = 1 << 20;
761        /// Receiver overrun.
762        ///
763        /// Set when software fails to prevent the receive data register
764        /// from overflowing with data. The OR bit is set immediately after the
765        /// stop bit has been completely received for the dataword that overflows
766        /// the buffer and all the other error flags (FE, NF, and PF) are prevented
767        /// from setting.
768        const OVERRUN = 1 << 19;
769        /// Noise flag.
770        ///
771        /// This is also available in the read flags. However, setting it here
772        /// allows you to clear the noise flag in the status register.
773        const NOISY = 1 << 18;
774        /// Framing error.
775        ///
776        /// This is also available in the read flags. However, setting it here
777        /// allows you to clear the noise flag in the status register.
778        const FRAME_ERROR = 1 << 17;
779        /// Parity error.
780        ///
781        /// This is also available in the read flags. However, setting it here
782        /// allows you to clear the noise flag in the status register.
783        const PARITY_ERROR = 1 << 16;
784
785        // All flags up to and including bit 13 are marked 'reserved'
786        // in the status register. We're using these for other 'status'
787        // functions.
788
789        // These two flags relate to the FIFOs. They can only be written
790        // to the FIFO register after a left shift of FIFO_SHIFT.
791
792        /// Transmitter Buffer Overflow Flag
793        ///
794        /// Indicates that more data has been written to the transmit buffer than it can hold.
795        const TRANSMIT_OVERFLOW = 1 << 13;
796        /// Receiver Buffer Underflow Flag
797        ///
798        /// Indicates that more data has been read from the receive buffer than was present.
799        const RECEIVE_UNDERFLOW = 1 << 12;
800    }
801}
802
803impl Status {
804    /// The number of left shifts required to move the FIFO
805    /// status bits into position for the FIFO register.
806    const FIFO_SHIFT: u32 = 4;
807
808    /// The set of status bits that are W1C.
809    ///
810    /// Use this to differentiate read-only bits from bits that are
811    /// W1C.
812    pub const W1C: Status =
813        Self::from_bits_truncate(Self::all().bits() & !Self::read_only_mask().bits());
814
815    /// Status bits that are read-only.
816    ///
817    /// Includes those bits in the FIFO register.
818    const fn read_only_mask() -> Self {
819        Self::from_bits_truncate(
820            Self::RECEIVE_ACTIVE.bits()
821                | Self::TRANSMIT_EMPTY.bits()
822                | Self::TRANSMIT_COMPLETE.bits()
823                | Self::RECEIVE_FULL.bits(),
824        )
825    }
826
827    /// Return the bitflags that represent the FIFO bits.
828    const fn fifo_mask() -> Self {
829        Self::from_bits_truncate(Self::TRANSMIT_OVERFLOW.bits() | Self::RECEIVE_UNDERFLOW.bits())
830    }
831    /// Return the bitflags that represent the STAT bits.
832    const fn stat_mask() -> Self {
833        Self::from_bits_truncate(Self::all().bits() & !Self::fifo_mask().bits())
834    }
835    /// Returns the FIFO bits that may be written to the FIFO register.
836    const fn fifo_bits(self) -> u32 {
837        (self.bits() & Self::fifo_mask().bits()) << Self::FIFO_SHIFT
838    }
839    /// Returns the STAT bits that may be writeen to the STAT register.
840    const fn stat_bits(self) -> u32 {
841        self.bits() & Self::stat_mask().bits()
842    }
843    /// Compose status bitflags from raw STAT and FIFO register values.
844    ///
845    /// FIFO should only include `TXOF` and / or `RXUF` bits.
846    const fn from_registers(stat: u32, fifo: u32) -> Self {
847        Self::from_bits_truncate(stat | (fifo >> Self::FIFO_SHIFT))
848    }
849}
850
851/// Watermark levels for TX and RX FIFOs.
852///
853/// See [`Lpuart::enable_fifo`](crate::lpuart::Disabled::enable_fifo) for more
854/// information.
855#[cfg_attr(feature = "defmt", derive(defmt::Format))]
856#[derive(Debug, Clone, Copy)]
857pub struct Watermark {
858    direction: Direction,
859    size: u32,
860}
861
862impl Watermark {
863    /// Specify the transmit FIFO watermark.
864    ///
865    /// Note that the actual watermark value will be limited by the hardware.
866    #[inline]
867    pub const fn tx(size: u32) -> Self {
868        Watermark {
869            direction: Direction::Tx,
870            size,
871        }
872    }
873    /// Specify the receive FIFO watermark.
874    ///
875    /// Note that the actual watermark value with be limited by the hardware.
876    #[inline]
877    pub const fn rx(size: core::num::NonZeroU32) -> Self {
878        Watermark {
879            direction: Direction::Rx,
880            size: size.get(),
881        }
882    }
883}
884
885impl eh02::serial::Write<u8> for Lpuart {
886    type Error = core::convert::Infallible;
887
888    fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
889        self.flush()?;
890        self.write_byte(word);
891        Ok(())
892    }
893
894    fn flush(&mut self) -> nb::Result<(), Self::Error> {
895        if !self.status().contains(Status::TRANSMIT_EMPTY) {
896            Err(nb::Error::WouldBlock)
897        } else {
898            Ok(())
899        }
900    }
901}
902
903impl eh02::serial::Read<u8> for Lpuart {
904    type Error = ReadFlags;
905
906    fn read(&mut self) -> nb::Result<u8, Self::Error> {
907        let data = self.read_data();
908        self.clear_status(Status::W1C);
909        if data.flags().contains(ReadFlags::RXEMPT) {
910            Err(nb::Error::WouldBlock)
911        } else if data
912            .flags()
913            .intersects(ReadFlags::PARITY_ERROR | ReadFlags::FRAME_ERROR | ReadFlags::NOISY)
914        {
915            Err(nb::Error::Other(data.flags()))
916        } else {
917            Ok(data.into())
918        }
919    }
920}
921
922impl eh02::blocking::serial::Write<u8> for Lpuart {
923    type Error = core::convert::Infallible;
924
925    fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
926        for word in buffer {
927            nb::block!(eh02::serial::Write::write(self, *word))?;
928        }
929
930        Ok(())
931    }
932
933    fn bflush(&mut self) -> Result<(), Self::Error> {
934        nb::block!(eh02::serial::Write::flush(self))?;
935        Ok(())
936    }
937}
938
939impl core::fmt::Display for ReadFlags {
940    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
941        write!(f, "Read data error: {self:?}")
942    }
943}
944
945impl core::error::Error for ReadFlags {}
946
947impl embedded_io::Error for ReadFlags {
948    fn kind(&self) -> embedded_io::ErrorKind {
949        embedded_io::ErrorKind::Other
950    }
951}
952
953impl embedded_io::ErrorType for Lpuart {
954    type Error = ReadFlags;
955}
956
957impl embedded_io::WriteReady for Lpuart {
958    fn write_ready(&mut self) -> Result<bool, Self::Error> {
959        Ok(self.status().contains(Status::TRANSMIT_EMPTY))
960    }
961}
962
963impl embedded_io::ReadReady for Lpuart {
964    fn read_ready(&mut self) -> Result<bool, Self::Error> {
965        Ok(self.status().contains(Status::RECEIVE_FULL))
966    }
967}
968
969impl embedded_io::Write for Lpuart {
970    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
971        let mut num_written = 0;
972        for word in buf {
973            if num_written == 0 {
974                // For the first word, continue trying until we send.
975                // This function is supposed to block until at least one word is
976                // sent.
977                while !self.try_write(*word) {}
978            } else {
979                // If we already sent at least one word, return once
980                // the buffer is full
981                if !self.try_write(*word) {
982                    break;
983                }
984            }
985            num_written += 1;
986        }
987
988        Ok(num_written)
989    }
990
991    fn flush(&mut self) -> Result<(), Self::Error> {
992        while !self.status().contains(Status::TRANSMIT_COMPLETE) {}
993
994        Ok(())
995    }
996}
997
998impl embedded_io::Read for Lpuart {
999    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1000        let mut num_read = 0;
1001        for word in buf {
1002            let data = if num_read == 0 {
1003                // For the first word, continue querying until we receive something.
1004                // This function is supposed to block until at least one word is
1005                // received.
1006                loop {
1007                    if let Some(data) = self.try_read()? {
1008                        break data;
1009                    }
1010                }
1011            } else {
1012                // If we already read at least one word, return once
1013                // the buffer is empty
1014                if let Some(data) = self.try_read()? {
1015                    data
1016                } else {
1017                    break;
1018                }
1019            };
1020
1021            *word = data;
1022            num_read += 1;
1023        }
1024
1025        Ok(num_read)
1026    }
1027}
1028
1029#[cfg(test)]
1030mod tests {
1031    use super::{Baud, ReadData, ReadFlags, Status};
1032
1033    #[test]
1034    fn approximate_baud() {
1035        // Assume the 24MHz XTAL clock.
1036        const UART_CLOCK_HZ: u32 = 24_000_000;
1037        // The best baud rate we can get is
1038        const EXPECTED_BAUD: u32 = 115384;
1039        // for a target baud of
1040        const TARGET_BAUD: u32 = 115200;
1041
1042        const BAUD: Baud = Baud::compute(UART_CLOCK_HZ, TARGET_BAUD);
1043
1044        assert_eq!(BAUD.value(UART_CLOCK_HZ), EXPECTED_BAUD);
1045
1046        // These values could switch, depending on the implementation...
1047        assert!(BAUD.sbr == 8 || BAUD.sbr == 26, "SBR: {}", BAUD.sbr);
1048        if BAUD.sbr == 8 {
1049            assert_eq!(BAUD.osr, 26);
1050        } else {
1051            assert_eq!(BAUD.osr, 8);
1052        }
1053        assert!(!BAUD.bothedge);
1054    }
1055
1056    #[test]
1057    fn non_default_sbr_baud() {
1058        // Assume the 24MHz XTAL clock.
1059        const UART_CLOCK_HZ: u32 = 24_000_000;
1060        // The best baud rate we can get is
1061        const EXPECTED_BAUD: u32 = 9600;
1062        // for a target baud of
1063        const TARGET_BAUD: u32 = 9600;
1064
1065        const BAUD: Baud = Baud::compute(UART_CLOCK_HZ, TARGET_BAUD);
1066
1067        assert_eq!(BAUD.value(UART_CLOCK_HZ), EXPECTED_BAUD);
1068
1069        assert_eq!(BAUD.osr, 10, "OSR: {}", BAUD.osr);
1070        assert_eq!(BAUD.sbr, 250, "SBR: {}", BAUD.sbr);
1071        assert!(!BAUD.bothedge);
1072    }
1073
1074    #[test]
1075    fn max_baud() {
1076        // Assume the 24MHz XTAL clock.
1077        const UART_CLOCK_HZ: u32 = 24_000_000;
1078        // The best baud rate we can get is
1079        const EXPECTED_BAUD: u32 = 6_000_000;
1080        // for a target baud of
1081        const TARGET_BAUD: u32 = 6_000_000;
1082
1083        const BAUD: Baud = Baud::compute(UART_CLOCK_HZ, TARGET_BAUD);
1084
1085        assert_eq!(BAUD.value(UART_CLOCK_HZ), EXPECTED_BAUD);
1086
1087        assert_eq!(BAUD.osr, 4, "OSR: {}", BAUD.osr);
1088        assert_eq!(BAUD.sbr, 1, "SBR: {}", BAUD.sbr);
1089        assert!(BAUD.bothedge);
1090    }
1091
1092    #[test]
1093    fn read_data_flags() {
1094        let read_data = ReadData(1 << 15 | 1 << 13);
1095        let flags = read_data.flags();
1096
1097        assert!(flags.contains(ReadFlags::NOISY));
1098        assert!(!flags.contains(ReadFlags::PARITY_ERROR));
1099        assert!(flags.contains(ReadFlags::FRAME_ERROR));
1100        assert!(!flags.contains(ReadFlags::RXEMPT));
1101        assert!(!flags.contains(ReadFlags::IDLINE));
1102
1103        assert!(flags.intersects(ReadFlags::NOISY | ReadFlags::PARITY_ERROR));
1104        assert!(!flags.intersects(ReadFlags::RXEMPT | ReadFlags::PARITY_ERROR));
1105    }
1106
1107    #[test]
1108    fn status_flags() {
1109        assert_eq!(Status::fifo_mask().bits(), (1 << 13) | (1 << 12));
1110        assert_eq!(Status::fifo_mask().fifo_bits(), (1 << 17) | (1 << 16));
1111        assert_eq!(Status::stat_mask().bits(), 0x01FF_0000);
1112        assert_eq!(Status::stat_mask().stat_bits(), 0x01FF_0000);
1113        assert_eq!(Status::W1C.bits(), 0x001F_3000);
1114
1115        assert!(
1116            Status::from_registers(0, (1 << 17) | (1 << 16))
1117                .contains(Status::TRANSMIT_OVERFLOW | Status::RECEIVE_UNDERFLOW)
1118        );
1119        assert!(Status::from_registers(u32::MAX, 0).contains(Status::stat_mask()));
1120
1121        assert!(Status::all().contains(Status::TRANSMIT_EMPTY));
1122    }
1123}