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