Skip to main content

vorago_shared_hal/uart/
mod.rs

1//! # API for the UART peripheral
2//!
3//! The core of this API are the [Uart], [Rx] and [Tx] structures.
4//! The RX structure also has a dedicated [RxWithInterrupt] variant which allows reading the receiver
5//! using interrupts.
6//!
7//! The [rx_async] and [tx_async] modules provide an asynchronous non-blocking API for the UART
8//! peripheral.
9//!
10//! ## Examples
11//!
12//! - [UART simple example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/simple/examples/uart.rs)
13//! - [UART with IRQ and RTIC](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/rtic/src/bin/uart-echo-rtic.rs)
14//! - [Flashloader exposing a CCSDS interface via UART](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/flashloader)
15use core::convert::Infallible;
16pub mod regs;
17#[cfg(feature = "vor1x")]
18use crate::InterruptConfig;
19use crate::{
20    FunctionSelect,
21    gpio::{DynPinId, IoPeriphPin},
22    pins::AnyPin,
23    sealed::Sealed,
24};
25use arbitrary_int::{prelude::*, u6, u18};
26use regs::{ClockScale, Control, Data, Enable, FifoClear, InterruptClear, MmioUart};
27
28use crate::{PeripheralSelect, enable_nvic_interrupt, enable_peripheral_clock, time::Hertz};
29use embedded_hal_nb::serial::Read;
30pub use regs::{Bank, Stopbits, WordSize};
31
32#[cfg(feature = "vor1x")]
33mod pins_vor1x;
34#[cfg(feature = "vor4x")]
35mod pins_vor4x;
36
37#[cfg(feature = "vor4x")]
38use crate::clock::Clocks;
39#[cfg(feature = "vor1x")]
40use va108xx as pac;
41#[cfg(feature = "vor4x")]
42use va416xx as pac;
43
44pub mod tx_async;
45pub use tx_async::*;
46
47pub mod rx_async;
48pub use rx_async::*;
49
50/// FIFO depth of the UART for both the RX and TX FIFO.
51pub const FIFO_DEPTH: usize = 16;
52
53//==================================================================================================
54// Type-Level support
55//==================================================================================================
56
57pub trait TxPin0: AnyPin {
58    const BANK: Bank = Bank::Uart0;
59    const FUNC_SEL: FunctionSelect;
60}
61pub trait RxPin0: AnyPin {
62    const BANK: Bank = Bank::Uart0;
63    const FUNC_SEL: FunctionSelect;
64}
65
66pub trait TxPin1: AnyPin {
67    const BANK: Bank = Bank::Uart1;
68    const FUNC_SEL: FunctionSelect;
69}
70pub trait RxPin1: AnyPin {
71    const BANK: Bank = Bank::Uart1;
72    const FUNC_SEL: FunctionSelect;
73}
74
75#[cfg(feature = "vor4x")]
76pub trait TxPin2: AnyPin {
77    const BANK: Bank = Bank::Uart2;
78    const FUNC_SEL: FunctionSelect;
79}
80#[cfg(feature = "vor4x")]
81pub trait RxPin2: AnyPin {
82    const BANK: Bank = Bank::Uart2;
83    const FUNC_SEL: FunctionSelect;
84}
85
86//==================================================================================================
87// Regular Definitions
88//==================================================================================================
89
90#[derive(Debug, PartialEq, Eq, thiserror::Error)]
91#[cfg_attr(feature = "defmt", derive(defmt::Format))]
92#[error("no interrupt ID was set")]
93pub struct NoInterruptIdWasSet;
94
95#[derive(Debug, PartialEq, Eq, thiserror::Error)]
96#[cfg_attr(feature = "defmt", derive(defmt::Format))]
97#[error("transer is pending")]
98pub struct TransferPendingError;
99
100#[derive(Debug, PartialEq, Eq, Copy, Clone)]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102pub enum Event {
103    // Receiver FIFO interrupt enable. Generates interrupt
104    // when FIFO is at least half full. Half full is defined as FIFO
105    // count >= RXFIFOIRQTRG
106    RxFifoHalfFull,
107    // Framing error, Overrun error, Parity Error and Break error
108    RxError,
109    // Event for timeout condition: Data in the FIFO and no receiver
110    // FIFO activity for 4 character times
111    RxTimeout,
112
113    // Transmitter FIFO interrupt enable. Generates interrupt
114    // when FIFO is at least half full. Half full is defined as FIFO
115    // count >= TXFIFOIRQTRG
116    TxFifoHalfFull,
117    // FIFO overflow error
118    TxError,
119    // Generate interrupt when transmit FIFO is empty and TXBUSY is 0
120    TxEmpty,
121    // Interrupt when CTSn changes value
122    TxCts,
123}
124
125#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
126#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127pub enum BaudMode {
128    /// Default 16x baud clock.
129    #[default]
130    _16 = 0,
131    /// Slower 8x baud clock.
132    _8 = 1,
133}
134
135impl BaudMode {
136    pub const fn multiplier(&self) -> u32 {
137        match self {
138            BaudMode::_16 => 16,
139            BaudMode::_8 => 8,
140        }
141    }
142}
143
144#[derive(Debug, Copy, Clone, PartialEq, Eq)]
145#[cfg_attr(feature = "defmt", derive(defmt::Format))]
146pub enum Parity {
147    None,
148    Odd,
149    Even,
150}
151
152#[derive(Debug, Copy, Clone, PartialEq, Eq)]
153#[cfg_attr(feature = "defmt", derive(defmt::Format))]
154pub struct ClockConfig {
155    /// Integer divisor.
156    pub div: u18,
157    /// Fractional divide value in 1/64 units.
158    pub frac: u6,
159    pub baud_mode: BaudMode,
160}
161
162impl ClockConfig {
163    pub const fn calculate(ref_clk: Hertz, baudrate: Hertz, baud_mode: BaudMode) -> Self {
164        // This is the calculation: (64.0 * (x - integer_part as f32) + 0.5) as u32 without floating
165        // point calculations.
166        let multiplier = baud_mode.multiplier();
167        let frac = ((ref_clk.to_raw() % (baudrate.to_raw() * multiplier)) * 64
168            + (baudrate.to_raw() * (multiplier / 2)))
169            / (baudrate.to_raw() * multiplier);
170        // Calculations here are derived from chapter 4.8.5 (p.79) of the datasheet.
171        let integer_div = ref_clk.to_raw() / (baudrate.to_raw() * multiplier);
172        Self {
173            frac: u6::new(frac as u8),
174            div: u18::new(integer_div),
175            baud_mode,
176        }
177    }
178
179    #[cfg(feature = "vor4x")]
180    pub fn calculate_with_clocks(
181        uart_id: Bank,
182        clks: &Clocks,
183        baudrate: Hertz,
184        baud_mode: BaudMode,
185    ) -> Self {
186        let clk = if uart_id == Bank::Uart2 {
187            clks.apb1()
188        } else {
189            clks.apb2()
190        };
191        Self::calculate(clk, baudrate, baud_mode)
192    }
193}
194
195#[derive(Debug, Copy, Clone, PartialEq, Eq)]
196#[cfg_attr(feature = "defmt", derive(defmt::Format))]
197pub struct Config {
198    pub clock_config: ClockConfig,
199    pub parity: Parity,
200    pub stopbits: Stopbits,
201    pub wordsize: WordSize,
202    pub enable_tx: bool,
203    pub enable_rx: bool,
204}
205
206impl Config {
207    pub fn new_with_clock_config(clock_config: ClockConfig) -> Self {
208        Config {
209            clock_config,
210            parity: Parity::None,
211            stopbits: Stopbits::One,
212            wordsize: WordSize::Eight,
213            enable_tx: true,
214            enable_rx: true,
215        }
216    }
217
218    pub fn with_clock_config(mut self, clock_config: ClockConfig) -> Self {
219        self.clock_config = clock_config;
220        self
221    }
222
223    pub fn with_parity_none(mut self) -> Self {
224        self.parity = Parity::None;
225        self
226    }
227
228    pub fn with_parity_even(mut self) -> Self {
229        self.parity = Parity::Even;
230        self
231    }
232
233    pub fn with_parity_odd(mut self) -> Self {
234        self.parity = Parity::Odd;
235        self
236    }
237
238    pub fn with_stopbits(mut self, stopbits: Stopbits) -> Self {
239        self.stopbits = stopbits;
240        self
241    }
242
243    pub fn with_wordsize(mut self, wordsize: WordSize) -> Self {
244        self.wordsize = wordsize;
245        self
246    }
247}
248
249//==================================================================================================
250// IRQ Definitions
251//==================================================================================================
252
253#[derive(Debug, Copy, Clone)]
254#[cfg_attr(feature = "defmt", derive(defmt::Format))]
255pub struct InterruptContextTimeoutOrMaxSize {
256    rx_idx: usize,
257    mode: InterruptReceptionMode,
258    pub max_len: usize,
259}
260
261impl InterruptContextTimeoutOrMaxSize {
262    pub fn new(max_len: usize) -> Self {
263        InterruptContextTimeoutOrMaxSize {
264            rx_idx: 0,
265            max_len,
266            mode: InterruptReceptionMode::Idle,
267        }
268    }
269}
270
271impl InterruptContextTimeoutOrMaxSize {
272    pub fn reset(&mut self) {
273        self.rx_idx = 0;
274        self.mode = InterruptReceptionMode::Idle;
275    }
276}
277
278/// This struct is used to return the default IRQ handler result to the user
279#[derive(Debug, Default)]
280#[cfg_attr(feature = "defmt", derive(defmt::Format))]
281pub struct InterruptResult {
282    pub bytes_read: usize,
283    pub errors: Option<UartErrors>,
284}
285
286/// This struct is used to return the default IRQ handler result to the user
287#[derive(Debug, Default)]
288#[cfg_attr(feature = "defmt", derive(defmt::Format))]
289pub struct InterruptResultMaxSizeOrTimeout {
290    complete: bool,
291    timeout: bool,
292    pub errors: Option<UartErrors>,
293    pub bytes_read: usize,
294}
295
296impl InterruptResultMaxSizeOrTimeout {
297    pub fn new() -> Self {
298        InterruptResultMaxSizeOrTimeout {
299            complete: false,
300            timeout: false,
301            errors: None,
302            bytes_read: 0,
303        }
304    }
305}
306impl InterruptResultMaxSizeOrTimeout {
307    #[inline]
308    pub fn has_errors(&self) -> bool {
309        self.errors.is_some()
310    }
311
312    #[inline]
313    pub fn overflow_error(&self) -> bool {
314        self.errors.is_some_and(|e| e.overflow)
315    }
316
317    #[inline]
318    pub fn framing_error(&self) -> bool {
319        self.errors.is_some_and(|e| e.framing)
320    }
321
322    #[inline]
323    pub fn parity_error(&self) -> bool {
324        self.errors.is_some_and(|e| e.parity)
325    }
326
327    #[inline]
328    pub fn timeout(&self) -> bool {
329        self.timeout
330    }
331
332    #[inline]
333    pub fn complete(&self) -> bool {
334        self.complete
335    }
336}
337
338#[derive(Debug, PartialEq, Copy, Clone)]
339#[cfg_attr(feature = "defmt", derive(defmt::Format))]
340enum InterruptReceptionMode {
341    Idle,
342    Pending,
343}
344
345#[derive(Default, Debug, Copy, Clone)]
346#[cfg_attr(feature = "defmt", derive(defmt::Format))]
347pub struct UartErrors {
348    overflow: bool,
349    framing: bool,
350    parity: bool,
351    other: bool,
352}
353
354impl UartErrors {
355    #[inline(always)]
356    pub fn overflow(&self) -> bool {
357        self.overflow
358    }
359
360    #[inline(always)]
361    pub fn framing(&self) -> bool {
362        self.framing
363    }
364
365    #[inline(always)]
366    pub fn parity(&self) -> bool {
367        self.parity
368    }
369
370    #[inline(always)]
371    pub fn other(&self) -> bool {
372        self.other
373    }
374}
375
376impl UartErrors {
377    #[inline(always)]
378    pub fn error(&self) -> bool {
379        self.overflow || self.framing || self.parity || self.other
380    }
381}
382
383#[derive(Debug, PartialEq, Eq)]
384#[cfg_attr(feature = "defmt", derive(defmt::Format))]
385pub struct BufferTooShortError {
386    found: usize,
387    expected: usize,
388}
389
390//==================================================================================================
391// UART peripheral wrapper
392//==================================================================================================
393
394pub trait Uart0Instance: Sealed {
395    const ID: Bank = Bank::Uart0;
396    const PERIPH_SEL: PeripheralSelect;
397}
398
399pub trait Uart1Instance: Sealed {
400    const ID: Bank = Bank::Uart1;
401    const PERIPH_SEL: PeripheralSelect;
402}
403
404#[cfg(feature = "vor4x")]
405pub trait Uart2Instance: Sealed {
406    const ID: Bank = Bank::Uart2;
407    const PERIPH_SEL: PeripheralSelect;
408}
409
410#[cfg(feature = "vor1x")]
411pub type Uart0 = pac::Uarta;
412#[cfg(feature = "vor4x")]
413pub type Uart0 = pac::Uart0;
414
415impl Uart0Instance for Uart0 {
416    const ID: Bank = Bank::Uart0;
417    const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Uart0;
418}
419impl Sealed for Uart0 {}
420
421#[cfg(feature = "vor1x")]
422pub type Uart1 = pac::Uartb;
423#[cfg(feature = "vor4x")]
424pub type Uart1 = pac::Uart1;
425
426impl Uart1Instance for Uart1 {
427    const ID: Bank = Bank::Uart1;
428    const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Uart1;
429}
430impl Sealed for Uart1 {}
431
432#[cfg(feature = "vor4x")]
433impl Uart2Instance for pac::Uart2 {
434    const ID: Bank = Bank::Uart2;
435    const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Uart2;
436}
437#[cfg(feature = "vor4x")]
438impl Sealed for pac::Uart2 {}
439
440//==================================================================================================
441// UART implementation
442//==================================================================================================
443
444/// UART driver structure.
445pub struct Uart {
446    tx: Tx,
447    rx: Rx,
448}
449
450impl Uart {
451    cfg_if::cfg_if! {
452        if #[cfg(feature = "vor1x")] {
453            /// Calls [Self::new_for_uart0] with the interrupt configuration to some valid value.
454            pub fn new_with_interrupt_uart0<Uart: Uart0Instance, Tx: TxPin0, Rx: RxPin0>(
455                uart: Uart,
456                tx_pin: Tx,
457                rx_pin: Rx,
458                config: Config,
459                irq_cfg: InterruptConfig,
460            ) -> Self {
461                Self::new_for_uart0(uart, tx_pin, rx_pin, config, Some(irq_cfg))
462            }
463
464            /// Calls [Self::new_for_uart1] with the interrupt configuration to some valid value.
465            pub fn new_with_interrupt_uart1<Uart: Uart1Instance, Tx: TxPin1, Rx: RxPin1>(
466                uart: Uart,
467                tx_pin: Tx,
468                rx_pin: Rx,
469                config: Config,
470                irq_cfg: InterruptConfig,
471            ) -> Self {
472                Self::new_for_uart1(uart, tx_pin, rx_pin, config, Some(irq_cfg))
473            }
474
475            /// Calls [Self::new_for_uart0] with the interrupt configuration to [None].
476            pub fn new_without_interrupt_uart0<Uart: Uart0Instance, Tx: TxPin0, Rx: RxPin0>(
477                uart: Uart,
478                tx_pin: Tx,
479                rx_pin: Rx,
480                config: Config,
481            ) -> Self {
482                Self::new_for_uart0(uart, tx_pin, rx_pin, config, None)
483            }
484
485            /// Calls [Self::new_for_uart1] with the interrupt configuration to [None].
486            pub fn new_without_interrupt_uart1<Uart: Uart1Instance, Tx: TxPin1, Rx: RxPin1>(
487                uart: Uart,
488                tx_pin: Tx,
489                rx_pin: Rx,
490                config: Config,
491            ) -> Self {
492                Self::new_for_uart1(uart, tx_pin, rx_pin, config, None)
493            }
494
495            /// Create a new UART peripheral driver with an interrupt configuration.
496            ///
497            /// # Arguments
498            ///
499            /// - `syscfg`: The system configuration register block
500            /// - `sys_clk`: The system clock frequency
501            /// - `uart`: The concrete UART peripheral instance.
502            /// - `pins`: UART TX and RX pin tuple.
503            /// - `config`: UART specific configuration parameters like baudrate.
504            /// - `irq_cfg`: Optional interrupt configuration. This should be a valid value if the plan
505            ///   is to use TX or RX functionality relying on interrupts. If only the blocking API without
506            ///   any interrupt support is used, this can be [None].
507            pub fn new_for_uart0<Uart: Uart0Instance, Tx: TxPin0, Rx: RxPin0>(
508                _uart: Uart,
509                _tx_pin: Tx,
510                _rx_pin: Rx,
511                config: Config,
512                opt_irq_cfg: Option<InterruptConfig>,
513            ) -> Self {
514                Self::new_internal(
515                    Uart::PERIPH_SEL,
516                    Uart::ID,
517                    Tx::ID,
518                    Tx::FUNC_SEL,
519                    Rx::ID,
520                    Rx::FUNC_SEL,
521                    config,
522                    opt_irq_cfg
523                )
524            }
525
526            /// Create a new UART peripheral driver with an interrupt configuration.
527            ///
528            /// # Arguments
529            ///
530            /// - `syscfg`: The system configuration register block
531            /// - `sys_clk`: The system clock frequency
532            /// - `uart`: The concrete UART peripheral instance.
533            /// - `pins`: UART TX and RX pin tuple.
534            /// - `config`: UART specific configuration parameters like baudrate.
535            /// - `irq_cfg`: Optional interrupt configuration. This should be a valid value if the plan
536            ///   is to use TX or RX functionality relying on interrupts. If only the blocking API without
537            ///   any interrupt support is used, this can be [None].
538            pub fn new_for_uart1<Uart: Uart1Instance, Tx: TxPin1, Rx: RxPin1>(
539                _uart: Uart,
540                _tx_pin: Tx,
541                _rx_pin: Rx,
542                config: Config,
543                opt_irq_cfg: Option<InterruptConfig>,
544            ) -> Self {
545                Self::new_internal(
546                    Uart::PERIPH_SEL,
547                    Uart::ID,
548                    Tx::ID,
549                    Tx::FUNC_SEL,
550                    Rx::ID,
551                    Rx::FUNC_SEL,
552                    config,
553                    opt_irq_cfg
554                )
555            }
556        } else if #[cfg(feature = "vor4x")] {
557            /// Create a new UART peripheral driver for UART 0.
558            ///
559            /// # Arguments
560            ///
561            /// - `clks`: Frozen system clock configuration.
562            /// - `uart`: The concrete UART peripheral instance.
563            /// - `pins`: UART TX and RX pin tuple.
564            /// - `config`: UART specific configuration parameters like baudrate.
565            pub fn new_for_uart0<Uart: Uart0Instance, Tx: TxPin0, Rx: RxPin0>(
566                _uart: Uart,
567                _tx_pin: Tx,
568                _rx_pin: Rx,
569                config: Config,
570            ) -> Self {
571                Self::new_internal(
572                    Uart::PERIPH_SEL,
573                    Uart::ID,
574                    Tx::ID,
575                    Tx::FUNC_SEL,
576                    Rx::ID,
577                    Rx::FUNC_SEL,
578                    config
579                )
580            }
581
582            /// Create a new UART peripheral driver for UART 1.
583            ///
584            /// # Arguments
585            ///
586            /// - `clks`: Frozen system clock configuration.
587            /// - `uart`: The concrete UART peripheral instance.
588            /// - `pins`: UART TX and RX pin tuple.
589            /// - `config`: UART specific configuration parameters like baudrate.
590            pub fn new_for_uart1<Uart: Uart1Instance, Tx: TxPin1, Rx: RxPin1>(
591                _uart: Uart,
592                _tx_pin: Tx,
593                _rx_pin: Rx,
594                config: Config,
595            ) -> Self {
596                Self::new_internal(
597                    Uart::PERIPH_SEL,
598                    Uart::ID,
599                    Tx::ID,
600                    Tx::FUNC_SEL,
601                    Rx::ID,
602                    Rx::FUNC_SEL,
603                    config
604                )
605            }
606
607            /// Create a new UART peripheral driver for UART 2.
608            ///
609            /// # Arguments
610            ///
611            /// - `clks`: Frozen system clock configuration.
612            /// - `uart`: The concrete UART peripheral instance.
613            /// - `pins`: UART TX and RX pin tuple.
614            /// - `config`: UART specific configuration parameters like baudrate.
615            pub fn new_for_uart2<Uart: Uart2Instance, Tx: TxPin2, Rx: RxPin2>(
616                _uart: Uart,
617                _tx_pin: Tx,
618                _rx_pin: Rx,
619                config: Config,
620            ) -> Self {
621                Self::new_internal(
622                    Uart::PERIPH_SEL,
623                    Uart::ID,
624                    Tx::ID,
625                    Tx::FUNC_SEL,
626                    Rx::ID,
627                    Rx::FUNC_SEL,
628                    config
629                )
630            }
631
632            /// Create a new UART peripheral driver given a reference clock with UART 0.
633            ///
634            /// # Arguments
635            ///
636            /// - `ref_clk`: APB1 clock for UART2, APB2 clock otherwise.
637            /// - `uart`: The concrete UART peripheral instance.
638            /// - `pins`: UART TX and RX pin tuple.
639            /// - `config`: UART specific configuration parameters like baudrate.
640            pub fn new_with_ref_clk_uart0<Uart: Uart0Instance, Tx: TxPin0, Rx: RxPin0>(
641                _uart: Uart,
642                _tx_pin: Tx,
643                _rx_pin: Rx,
644                config: Config,
645            ) -> Self {
646                Self::new_internal(
647                    Uart::PERIPH_SEL,
648                    Uart::ID,
649                    Tx::ID,
650                    Tx::FUNC_SEL,
651                    Rx::ID,
652                    Rx::FUNC_SEL,
653                    config
654                )
655            }
656
657            /// Create a new UART peripheral driver given a reference clock with UART 1.
658            ///
659            /// # Arguments
660            ///
661            /// - `ref_clk`: APB1 clock for UART2, APB2 clock otherwise.
662            /// - `uart`: The concrete UART peripheral instance.
663            /// - `pins`: UART TX and RX pin tuple.
664            /// - `config`: UART specific configuration parameters like baudrate.
665            pub fn new_with_ref_clk_uart1<Uart: Uart1Instance, Tx: TxPin1, Rx: RxPin1>(
666                _uart: Uart,
667                _tx_pin: Tx,
668                _rx_pin: Rx,
669                config: Config,
670            ) -> Self {
671                Self::new_internal(
672                    Uart::PERIPH_SEL,
673                    Uart::ID,
674                    Tx::ID,
675                    Tx::FUNC_SEL,
676                    Rx::ID,
677                    Rx::FUNC_SEL,
678                    config
679                )
680            }
681
682            /// Create a new UART peripheral driver given a reference clock with UART 2.
683            ///
684            /// # Arguments
685            ///
686            /// - `ref_clk`: APB1 clock for UART2, APB2 clock otherwise.
687            /// - `uart`: The concrete UART peripheral instance.
688            /// - `pins`: UART TX and RX pin tuple.
689            /// - `config`: UART specific configuration parameters like baudrate.
690            pub fn new_with_ref_clk_uart2<Uart: Uart2Instance, Tx: TxPin2, Rx: RxPin2>(
691                _uart: Uart,
692                _tx_pin: Tx,
693                _rx_pin: Rx,
694                config: Config,
695            ) -> Self {
696                Self::new_internal(
697                    Uart::PERIPH_SEL,
698                    Uart::ID,
699                    Tx::ID,
700                    Tx::FUNC_SEL,
701                    Rx::ID,
702                    Rx::FUNC_SEL,
703                    config
704                )
705            }
706        }
707    }
708
709    #[allow(clippy::too_many_arguments)]
710    fn new_internal(
711        periph_sel: PeripheralSelect,
712        uart_bank: Bank,
713        tx_pin_id: DynPinId,
714        tx_func_sel: FunctionSelect,
715        rx_pin_id: DynPinId,
716        rx_func_sel: FunctionSelect,
717        config: Config,
718        #[cfg(feature = "vor1x")] opt_irq_cfg: Option<InterruptConfig>,
719    ) -> Self {
720        IoPeriphPin::new(tx_pin_id, tx_func_sel, None);
721        IoPeriphPin::new(rx_pin_id, rx_func_sel, None);
722        enable_peripheral_clock(periph_sel);
723
724        let mut reg_block = regs::Uart::new_mmio(uart_bank);
725        reg_block.write_clkscale(
726            ClockScale::builder()
727                .with_int(config.clock_config.div)
728                .with_frac(config.clock_config.frac)
729                .build(),
730        );
731
732        let (paren, pareven) = match config.parity {
733            Parity::None => (false, false),
734            Parity::Odd => (true, false),
735            Parity::Even => (true, true),
736        };
737        reg_block.write_control(
738            Control::builder()
739                .with_baud8(config.clock_config.baud_mode == BaudMode::_8)
740                .with_auto_rts(false)
741                .with_def_rts(false)
742                .with_auto_cts(false)
743                .with_loopback_block(false)
744                .with_loopback(false)
745                .with_wordsize(config.wordsize)
746                .with_stopbits(config.stopbits)
747                .with_parity_manual(false)
748                .with_parity_even(pareven)
749                .with_parity_enable(paren)
750                .build(),
751        );
752        // Clear the FIFO
753        reg_block.write_fifo_clr(FifoClear::builder().with_tx(true).with_rx(true).build());
754        reg_block.write_enable(
755            Enable::builder()
756                .with_tx(config.enable_tx)
757                .with_rx(config.enable_rx)
758                .build(),
759        );
760
761        #[cfg(feature = "vor1x")]
762        if let Some(irq_cfg) = opt_irq_cfg {
763            if irq_cfg.route {
764                enable_peripheral_clock(PeripheralSelect::Irqsel);
765                unsafe { va108xx::Irqsel::steal() }
766                    .uart(uart_bank as usize)
767                    .write(|w| unsafe { w.bits(irq_cfg.id as u32) });
768            }
769            if irq_cfg.enable_in_nvic {
770                // Safety: User has specifically configured this.
771                unsafe { enable_nvic_interrupt(irq_cfg.id) };
772            }
773        }
774
775        Uart {
776            tx: Tx::new(uart_bank),
777            rx: Rx::new(uart_bank),
778        }
779    }
780
781    #[inline]
782    pub fn peripheral_id(&self) -> u32 {
783        self.tx.perid()
784    }
785
786    #[inline]
787    pub fn enable_rx(&mut self) {
788        self.rx.enable();
789    }
790
791    #[inline]
792    pub fn disable_rx(&mut self) {
793        self.rx.disable();
794    }
795
796    #[inline]
797    pub fn enable_tx(&mut self) {
798        self.tx.enable();
799    }
800
801    #[inline]
802    pub fn disable_tx(&mut self) {
803        self.tx.disable();
804    }
805
806    /// This also clears status conditons for the RX FIFO.
807    #[inline]
808    pub fn clear_rx_fifo(&mut self) {
809        self.rx.clear_fifo();
810    }
811
812    /// This also clears status conditons for the TX FIFO.
813    #[inline]
814    pub fn clear_tx_fifo(&mut self) {
815        self.tx.clear_fifo();
816    }
817
818    pub fn listen(&mut self, event: Event) {
819        self.tx.regs.modify_interrupt_enable(|mut value| {
820            match event {
821                Event::RxError => value.set_rx_status(true),
822                Event::RxFifoHalfFull => value.set_rx(true),
823                Event::RxTimeout => value.set_rx_timeout(true),
824                Event::TxEmpty => value.set_tx_empty(true),
825                Event::TxError => value.set_tx_status(true),
826                Event::TxFifoHalfFull => value.set_tx_below_trigger(true),
827                Event::TxCts => value.set_tx_cts(true),
828            }
829            value
830        });
831    }
832
833    pub fn unlisten(&mut self, event: Event) {
834        self.tx.regs.modify_interrupt_enable(|mut value| {
835            match event {
836                Event::RxError => value.set_rx_status(false),
837                Event::RxFifoHalfFull => value.set_rx(false),
838                Event::RxTimeout => value.set_rx_timeout(false),
839                Event::TxEmpty => value.set_tx_empty(false),
840                Event::TxError => value.set_tx_status(false),
841                Event::TxFifoHalfFull => value.set_tx_below_trigger(false),
842                Event::TxCts => value.set_tx_cts(false),
843            }
844            value
845        });
846    }
847
848    /// Poll receiver errors.
849    pub fn poll_rx_errors(&self) -> Option<UartErrors> {
850        self.rx.poll_errors()
851    }
852
853    pub fn split(self) -> (Tx, Rx) {
854        (self.tx, self.rx)
855    }
856}
857
858impl embedded_io::ErrorType for Uart {
859    type Error = Infallible;
860}
861
862impl embedded_hal_nb::serial::ErrorType for Uart {
863    type Error = Infallible;
864}
865
866impl embedded_hal_nb::serial::Read<u8> for Uart {
867    fn read(&mut self) -> nb::Result<u8, Self::Error> {
868        self.rx.read()
869    }
870}
871
872impl embedded_hal_nb::serial::Write<u8> for Uart {
873    fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
874        self.tx.write(word).map_err(|e| {
875            if let nb::Error::Other(_) = e {
876                unreachable!()
877            }
878            nb::Error::WouldBlock
879        })
880    }
881
882    fn flush(&mut self) -> nb::Result<(), Self::Error> {
883        self.tx.flush().map_err(|e| {
884            if let nb::Error::Other(_) = e {
885                unreachable!()
886            }
887            nb::Error::WouldBlock
888        })
889    }
890}
891
892#[inline(always)]
893pub fn enable_rx(uart: &mut MmioUart<'static>) {
894    uart.modify_enable(|mut value| {
895        value.set_rx(true);
896        value
897    });
898}
899
900#[inline(always)]
901pub fn disable_rx(uart: &mut MmioUart<'static>) {
902    uart.modify_enable(|mut value| {
903        value.set_rx(false);
904        value
905    });
906}
907
908#[inline(always)]
909pub fn enable_rx_interrupts(uart: &mut MmioUart<'static>, timeout: bool) {
910    uart.modify_interrupt_enable(|mut value| {
911        value.set_rx_status(true);
912        value.set_rx(true);
913        if timeout {
914            value.set_rx_timeout(true);
915        }
916        value
917    });
918}
919
920#[inline(always)]
921pub fn disable_rx_interrupts(uart: &mut MmioUart<'static>) {
922    uart.modify_interrupt_enable(|mut value| {
923        value.set_rx_status(false);
924        value.set_rx(false);
925        value.set_rx_timeout(false);
926        value
927    });
928}
929
930/// Serial receiver.
931///
932/// Can be created by using the [Uart::split] API.
933pub struct Rx {
934    id: Bank,
935    regs: regs::MmioUart<'static>,
936}
937
938impl Rx {
939    /// Retrieve a TX pin without expecting an explicit UART structure
940    ///
941    /// # Safety
942    ///
943    /// Circumvents the HAL safety guarantees.
944    #[inline(always)]
945    pub unsafe fn steal(id: Bank) -> Self {
946        Self::new(id)
947    }
948
949    #[inline(always)]
950    fn new(id: Bank) -> Self {
951        Self {
952            id,
953            regs: regs::Uart::new_mmio(id),
954        }
955    }
956
957    pub fn poll_errors(&self) -> Option<UartErrors> {
958        let mut errors = UartErrors::default();
959
960        let status = self.regs.read_rx_status();
961        if status.overrun_error() {
962            errors.overflow = true;
963        } else if status.framing_error() {
964            errors.framing = true;
965        } else if status.parity_error() {
966            errors.parity = true;
967        } else {
968            return None;
969        };
970        Some(errors)
971    }
972
973    #[inline]
974    pub fn perid(&self) -> u32 {
975        self.regs.read_perid()
976    }
977
978    #[inline]
979    pub fn clear_fifo(&mut self) {
980        self.regs
981            .write_fifo_clr(FifoClear::builder().with_tx(false).with_rx(true).build());
982    }
983
984    #[inline]
985    pub fn disable_interrupts(&mut self) {
986        disable_rx_interrupts(&mut self.regs);
987    }
988
989    #[inline]
990    pub fn enable_interrupts(
991        &mut self,
992        #[cfg(feature = "vor4x")] enable_in_nvic: bool,
993        timeout: bool,
994    ) {
995        #[cfg(feature = "vor4x")]
996        if enable_in_nvic {
997            unsafe {
998                enable_nvic_interrupt(self.id.interrupt_id_rx());
999            }
1000        }
1001        enable_rx_interrupts(&mut self.regs, timeout);
1002    }
1003
1004    #[inline]
1005    pub fn enable(&mut self) {
1006        enable_rx(&mut self.regs);
1007    }
1008
1009    #[inline]
1010    pub fn disable(&mut self) {
1011        disable_rx(&mut self.regs);
1012    }
1013
1014    /// Low level function to read a word from the UART FIFO.
1015    ///
1016    /// Uses the [nb] API to allow usage in blocking and non-blocking contexts.
1017    ///
1018    /// Please note that you might have to mask the returned value with 0xff to retrieve the actual
1019    /// value if you use the manual parity mode. See chapter 4.6.2 for more information.
1020    #[inline(always)]
1021    pub fn read_fifo(&mut self) -> nb::Result<u32, Infallible> {
1022        if !self.regs.read_rx_status().data_available() {
1023            return Err(nb::Error::WouldBlock);
1024        }
1025        Ok(self.read_fifo_unchecked())
1026    }
1027
1028    /// Low level function to read a word from from the UART FIFO.
1029    ///
1030    /// This does not necesarily mean there is a word in the FIFO available.
1031    /// Use the [Self::read_fifo] function to read a word from the FIFO reliably using the [nb]
1032    /// API.
1033    ///
1034    /// Please note that you might have to mask the returned value with 0xff to retrieve the actual
1035    /// value if you use the manual parity mode. See chapter 4.6.2 for more information.
1036    #[inline(always)]
1037    pub fn read_fifo_unchecked(&mut self) -> u32 {
1038        self.regs.read_data().raw_value()
1039    }
1040
1041    #[inline]
1042    pub fn into_rx_with_interrupt(self) -> RxWithInterrupt {
1043        RxWithInterrupt::new(self)
1044    }
1045
1046    #[deprecated(since = "0.3.0", note = "Use into_rx_with_interrupt instead")]
1047    #[inline]
1048    pub fn into_rx_with_irq(self) -> RxWithInterrupt {
1049        RxWithInterrupt::new(self)
1050    }
1051}
1052
1053impl embedded_io::ErrorType for Rx {
1054    type Error = Infallible;
1055}
1056
1057impl embedded_hal_nb::serial::ErrorType for Rx {
1058    type Error = Infallible;
1059}
1060
1061impl embedded_hal_nb::serial::Read<u8> for Rx {
1062    fn read(&mut self) -> nb::Result<u8, Self::Error> {
1063        self.read_fifo().map(|val| (val & 0xff) as u8).map_err(|e| {
1064            if let nb::Error::Other(_) = e {
1065                unreachable!()
1066            }
1067            nb::Error::WouldBlock
1068        })
1069    }
1070}
1071
1072impl embedded_io::Read for Rx {
1073    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1074        if buf.is_empty() {
1075            return Ok(0);
1076        }
1077        let mut read = 0;
1078        loop {
1079            if self.regs.read_rx_status().data_available() {
1080                break;
1081            }
1082        }
1083        for byte in buf.iter_mut() {
1084            match <Self as embedded_hal_nb::serial::Read<u8>>::read(self) {
1085                Ok(w) => {
1086                    *byte = w;
1087                    read += 1;
1088                }
1089                Err(nb::Error::WouldBlock) => break,
1090            }
1091        }
1092
1093        Ok(read)
1094    }
1095}
1096
1097#[inline(always)]
1098pub fn enable_tx(uart: &mut MmioUart<'static>) {
1099    uart.modify_enable(|mut value| {
1100        value.set_tx(true);
1101        value
1102    });
1103}
1104
1105#[inline(always)]
1106pub fn disable_tx(uart: &mut MmioUart<'static>) {
1107    uart.modify_enable(|mut value| {
1108        value.set_tx(false);
1109        value
1110    });
1111}
1112
1113#[inline(always)]
1114pub fn enable_tx_interrupts(tx_below_trigger: bool, uart: &mut MmioUart<'static>) {
1115    uart.modify_interrupt_enable(|mut value| {
1116        value.set_tx_below_trigger(tx_below_trigger);
1117        value.set_tx_empty(true);
1118        value.set_tx_status(true);
1119        value
1120    });
1121}
1122
1123#[inline(always)]
1124pub fn disable_tx_interrupts(uart: &mut MmioUart<'static>) {
1125    uart.modify_interrupt_enable(|mut value| {
1126        value.set_tx_below_trigger(false);
1127        value.set_tx_empty(false);
1128        value.set_tx_status(false);
1129        value
1130    });
1131}
1132
1133/// Serial transmitter
1134///
1135/// Can be created by using the [Uart::split] API.
1136pub struct Tx {
1137    id: Bank,
1138    regs: regs::MmioUart<'static>,
1139}
1140
1141impl Tx {
1142    /// Retrieve a TX pin without expecting an explicit UART structure
1143    ///
1144    /// # Safety
1145    ///
1146    /// Circumvents the HAL safety guarantees.
1147    #[inline(always)]
1148    pub unsafe fn steal(id: Bank) -> Self {
1149        Self::new(id)
1150    }
1151
1152    #[inline(always)]
1153    fn new(id: Bank) -> Self {
1154        Self {
1155            id,
1156            regs: regs::Uart::new_mmio(id),
1157        }
1158    }
1159
1160    #[inline]
1161    pub fn perid(&self) -> u32 {
1162        self.regs.read_perid()
1163    }
1164
1165    #[inline]
1166    pub fn clear_fifo(&mut self) {
1167        self.regs
1168            .write_fifo_clr(FifoClear::builder().with_tx(true).with_rx(false).build());
1169    }
1170
1171    #[inline]
1172    pub fn enable(&mut self) {
1173        self.regs.modify_enable(|mut value| {
1174            value.set_tx(true);
1175            value
1176        });
1177    }
1178
1179    #[inline]
1180    pub fn disable(&mut self) {
1181        self.regs.modify_enable(|mut value| {
1182            value.set_tx(false);
1183            value
1184        });
1185    }
1186
1187    /// Enables the IRQ_TX, IRQ_TX_STATUS and IRQ_TX_EMPTY interrupts.
1188    ///
1189    /// - The IRQ_TX interrupt is generated when the TX FIFO is at least half empty and the
1190    ///   `tx_below_trigger` parameter is set to `true`. This should be set to true if the total
1191    ///   amount of data to be transmitted is larger than the FIFO size.
1192    /// - The IRQ_TX_STATUS interrupt is generated when write data is lost due to a FIFO overflow
1193    /// - The IRQ_TX_EMPTY interrupt is generated when the TX FIFO is empty and the TXBUSY signal
1194    ///   is 0
1195    #[inline]
1196    pub fn enable_interrupts(
1197        &mut self,
1198        tx_below_trigger: bool,
1199        #[cfg(feature = "vor4x")] enable_in_nvic: bool,
1200    ) {
1201        #[cfg(feature = "vor4x")]
1202        if enable_in_nvic {
1203            unsafe { enable_nvic_interrupt(self.id.interrupt_id_tx()) };
1204        }
1205        // Safety: We own the UART structure
1206        enable_tx_interrupts(tx_below_trigger, &mut self.regs);
1207    }
1208
1209    /// Disables the IRQ_TX, IRQ_TX_STATUS and IRQ_TX_EMPTY interrupts.
1210    ///
1211    /// [Self::enable_interrupts] documents the interrupts.
1212    #[inline]
1213    pub fn disable_interrupts(&mut self) {
1214        // Safety: We own the UART structure
1215        disable_tx_interrupts(&mut self.regs);
1216    }
1217
1218    /// Low level function to write a word to the UART FIFO.
1219    ///
1220    /// Uses the [nb] API to allow usage in blocking and non-blocking contexts.
1221    ///
1222    /// Please note that you might have to mask the returned value with 0xff to retrieve the actual
1223    /// value if you use the manual parity mode. See chapter 11.4.1 for more information.
1224    #[inline(always)]
1225    pub fn write_fifo(&mut self, data: u32) -> nb::Result<(), Infallible> {
1226        if !self.regs.read_tx_status().ready() {
1227            return Err(nb::Error::WouldBlock);
1228        }
1229        self.write_fifo_unchecked(data);
1230        Ok(())
1231    }
1232
1233    /// Low level function to write a word to the UART FIFO.
1234    ///
1235    /// This does not necesarily mean that the FIFO can process another word because it might be
1236    /// full.
1237    /// Use the [Self::write_fifo] function to write a word to the FIFO reliably using the [nb]
1238    /// API.
1239    #[inline(always)]
1240    pub fn write_fifo_unchecked(&mut self, data: u32) {
1241        self.regs.write_data(Data::new_with_raw_value(data));
1242    }
1243
1244    pub fn into_async(self) -> TxAsync {
1245        TxAsync::new(self)
1246    }
1247}
1248
1249impl embedded_io::ErrorType for Tx {
1250    type Error = Infallible;
1251}
1252
1253impl embedded_hal_nb::serial::ErrorType for Tx {
1254    type Error = Infallible;
1255}
1256
1257impl embedded_hal_nb::serial::Write<u8> for Tx {
1258    fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
1259        self.write_fifo(word as u32)
1260    }
1261
1262    fn flush(&mut self) -> nb::Result<(), Self::Error> {
1263        // SAFETY: Only TX related registers are used.
1264        if self.regs.read_tx_status().write_busy() {
1265            return Err(nb::Error::WouldBlock);
1266        }
1267        Ok(())
1268    }
1269}
1270
1271impl embedded_io::Write for Tx {
1272    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1273        if buf.is_empty() {
1274            return Ok(0);
1275        }
1276        loop {
1277            if self.regs.read_tx_status().ready() {
1278                break;
1279            }
1280        }
1281        let mut written = 0;
1282        for byte in buf.iter() {
1283            match <Self as embedded_hal_nb::serial::Write<u8>>::write(self, *byte) {
1284                Ok(_) => written += 1,
1285                Err(nb::Error::WouldBlock) => return Ok(written),
1286            }
1287        }
1288
1289        Ok(written)
1290    }
1291
1292    fn flush(&mut self) -> Result<(), Self::Error> {
1293        nb::block!(<Self as embedded_hal_nb::serial::Write<u8>>::flush(self))
1294    }
1295}
1296
1297/// Serial receiver, using interrupts to offload reading to the hardware.
1298///
1299/// You can use [Rx::into_rx_with_irq] to convert a normal [Rx] structure into this structure.
1300/// This structure provides two distinct ways to read the UART RX using interrupts. It should
1301/// be noted that the interrupt service routine (ISR) still has to be provided by the user. However,
1302/// this structure provides API calls which can be used inside the ISRs to simplify the reading
1303/// of the UART.
1304///
1305///  1. The first way simply empties the FIFO on an interrupt into a user provided buffer. You
1306///     can simply use [Self::start] to prepare the peripheral and then call the
1307///     [Self::on_interrupt] in the interrupt service routine.
1308///  2. The second way reads packets bounded by a maximum size or a baudtick based timeout. You
1309///     can use [Self::read_fixed_len_or_timeout_based_using_irq] to prepare the peripheral and
1310///     then call the [Self::on_interrupt_max_size_or_timeout_based] in the interrupt service
1311///     routine. You have to call [Self::read_fixed_len_or_timeout_based_using_irq] in the ISR to
1312///     start reading the next packet.
1313pub struct RxWithInterrupt(Rx);
1314
1315impl RxWithInterrupt {
1316    #[inline]
1317    pub fn new(rx: Rx) -> Self {
1318        Self(rx)
1319    }
1320
1321    /// Steal the RX peripheral with interrupt support for the given UART bank.
1322    ///
1323    /// Can be useful to retrieve an instance in an interrupt if this instance is not used in the
1324    /// main thread after initialization time.
1325    ///
1326    /// # Safety
1327    ///
1328    /// Circumvents the HAL ownership and safety guarantees.
1329    pub unsafe fn steal(id: Bank) -> Self {
1330        Self(unsafe { Rx::steal(id) })
1331    }
1332
1333    /// This function should be called once at initialization time if the regular
1334    /// [Self::on_interrupt] is used to read the UART receiver to enable and start the receiver.
1335    pub fn start(&mut self) {
1336        #[cfg(feature = "vor4x")]
1337        self.enable_interrupts(true, true);
1338        #[cfg(feature = "vor1x")]
1339        self.enable_interrupts(true);
1340        self.0.enable();
1341    }
1342
1343    #[inline(always)]
1344    pub fn rx(&self) -> &Rx {
1345        &self.0
1346    }
1347
1348    /// This function is used together with the [Self::on_interrupt_max_size_or_timeout_based]
1349    /// function to read packets with a maximum size or variable sized packets by using the
1350    /// receive timeout of the hardware.
1351    ///
1352    /// This function should be called once at initialization to initiate the context state
1353    /// and to [Self::start] the receiver. After that, it should be called after each
1354    /// completed [Self::on_interrupt_max_size_or_timeout_based] call to restart the reception
1355    /// of a packet.
1356    pub fn read_fixed_len_or_timeout_based_using_irq(
1357        &mut self,
1358        context: &mut InterruptContextTimeoutOrMaxSize,
1359    ) -> Result<(), TransferPendingError> {
1360        if context.mode != InterruptReceptionMode::Idle {
1361            return Err(TransferPendingError);
1362        }
1363        context.mode = InterruptReceptionMode::Pending;
1364        context.rx_idx = 0;
1365        self.start();
1366        Ok(())
1367    }
1368
1369    #[inline]
1370    fn enable_interrupts(&mut self, #[cfg(feature = "vor4x")] enable_in_nvic: bool, timeout: bool) {
1371        #[cfg(feature = "vor4x")]
1372        self.0.enable_interrupts(enable_in_nvic, timeout);
1373        #[cfg(feature = "vor1x")]
1374        self.0.enable_interrupts(timeout);
1375    }
1376
1377    #[inline]
1378    fn disable_interrupts(&mut self) {
1379        self.0.disable_interrupts();
1380    }
1381
1382    pub fn cancel_transfer(&mut self) {
1383        self.disable_interrupts();
1384        self.0.clear_fifo();
1385    }
1386
1387    /// This function should be called in the user provided UART interrupt handler.
1388    ///
1389    /// It simply empties any bytes in the FIFO into the user provided buffer and returns the
1390    /// result of the operation.
1391    ///
1392    /// This function will not disable the RX interrupts, so you don't need to call any other
1393    /// API after calling this function to continue emptying the FIFO. RX errors are handled
1394    /// as partial errors and are returned as part of the [InterruptResult].
1395    pub fn on_interrupt(&mut self, buf: &mut [u8; 16]) -> InterruptResult {
1396        let mut result = InterruptResult::default();
1397
1398        let irq_status = self.0.regs.read_interrupt_status();
1399        let irq_enabled = self.0.regs.read_interrupt_enable();
1400        let rx_enabled = irq_enabled.rx();
1401
1402        // Half-Full interrupt. We have a guaranteed amount of data we can read.
1403        if irq_status.rx() {
1404            let available_bytes = self.0.regs.read_rx_fifo_trigger().level().as_usize();
1405
1406            // If this interrupt bit is set, the trigger level is available at the very least.
1407            // Read everything as fast as possible
1408            for _ in 0..available_bytes {
1409                buf[result.bytes_read] = (self.0.read_fifo_unchecked() & 0xff) as u8;
1410                result.bytes_read += 1;
1411            }
1412        }
1413
1414        // Timeout, empty the FIFO completely.
1415        if irq_status.rx_timeout() {
1416            // While there is data in the FIFO, write it into the reception buffer
1417            while let Ok(byte) = self.0.read_fifo() {
1418                buf[result.bytes_read] = byte as u8;
1419                result.bytes_read += 1;
1420            }
1421        }
1422
1423        // RX transfer not complete, check for RX errors
1424        if rx_enabled {
1425            self.check_for_errors(&mut result.errors);
1426        }
1427
1428        // Clear the interrupt status bits
1429        self.0.regs.write_irq_clr(
1430            InterruptClear::builder()
1431                .with_rx_overrun(true)
1432                .with_tx_overrun(false)
1433                .build(),
1434        );
1435        result
1436    }
1437
1438    /// This function should be called in the user provided UART interrupt handler.
1439    ///
1440    /// This function is used to read packets which either have a maximum size or variable sized
1441    /// packet which are bounded by sufficient delays between them, triggering a hardware timeout.
1442    ///
1443    /// If either the maximum number of packets have been read or a timeout occured, the transfer
1444    /// will be deemed completed. The state information of the transfer is tracked in the
1445    /// [InterruptContextTimeoutOrMaxSize] structure.
1446    ///
1447    /// If passed buffer is equal to or larger than the specified maximum length, an
1448    /// [BufferTooShortError] will be returned. Other RX errors are treated as partial errors
1449    /// and returned inside the [InterruptResultMaxSizeOrTimeout] structure.
1450    pub fn on_interrupt_max_size_or_timeout_based(
1451        &mut self,
1452        context: &mut InterruptContextTimeoutOrMaxSize,
1453        buf: &mut [u8],
1454    ) -> Result<InterruptResultMaxSizeOrTimeout, BufferTooShortError> {
1455        if buf.len() < context.max_len {
1456            return Err(BufferTooShortError {
1457                found: buf.len(),
1458                expected: context.max_len,
1459            });
1460        }
1461        let mut result = InterruptResultMaxSizeOrTimeout::default();
1462
1463        let irq_status = self.0.regs.read_interrupt_status();
1464        let rx_enabled = self.0.regs.read_enable().rx();
1465
1466        // Half-Full interrupt. We have a guaranteed amount of data we can read.
1467        if irq_status.rx() {
1468            // Determine the number of bytes to read, ensuring we leave 1 byte in the FIFO.
1469            // We use this trick/hack because the timeout feature of the peripheral relies on data
1470            // being in the RX FIFO. If data continues arriving, another half-full IRQ will fire.
1471            // If not, the last byte(s) is/are emptied by the timeout interrupt.
1472            let available_bytes = self.0.regs.read_rx_fifo_trigger().level().as_usize();
1473
1474            let bytes_to_read = core::cmp::min(
1475                available_bytes.saturating_sub(1),
1476                context.max_len - context.rx_idx,
1477            );
1478
1479            // If this interrupt bit is set, the trigger level is available at the very least.
1480            // Read everything as fast as possible
1481            for _ in 0..bytes_to_read {
1482                buf[context.rx_idx] = (self.0.read_fifo_unchecked() & 0xff) as u8;
1483                context.rx_idx += 1;
1484            }
1485
1486            // On high-baudrates, data might be available immediately, and we possible have to
1487            // read continuosly? Then again, the CPU should always be faster than that. I'd rather
1488            // rely on the hardware firing another IRQ. I have not tried baudrates higher than
1489            // 115200 so far.
1490        }
1491        // Timeout, empty the FIFO completely.
1492        if irq_status.rx_timeout() {
1493            // While there is data in the FIFO, write it into the reception buffer
1494            loop {
1495                if context.rx_idx == context.max_len {
1496                    break;
1497                }
1498                // While there is data in the FIFO, write it into the reception buffer
1499                match self.0.read() {
1500                    Ok(byte) => {
1501                        buf[context.rx_idx] = byte;
1502                        context.rx_idx += 1;
1503                    }
1504                    Err(_) => break,
1505                }
1506            }
1507            self.irq_completion_handler_max_size_timeout(&mut result, context);
1508            return Ok(result);
1509        }
1510
1511        // RX transfer not complete, check for RX errors
1512        if (context.rx_idx < context.max_len) && rx_enabled {
1513            self.check_for_errors(&mut result.errors);
1514        }
1515
1516        // Clear the interrupt status bits
1517        self.0.regs.write_irq_clr(
1518            InterruptClear::builder()
1519                .with_rx_overrun(true)
1520                .with_tx_overrun(false)
1521                .build(),
1522        );
1523        Ok(result)
1524    }
1525
1526    fn check_for_errors(&self, errors: &mut Option<UartErrors>) {
1527        let rx_status = self.0.regs.read_rx_status();
1528
1529        if rx_status.overrun_error() || rx_status.framing_error() || rx_status.parity_error() {
1530            let err = errors.get_or_insert(UartErrors::default());
1531
1532            if rx_status.overrun_error() {
1533                err.overflow = true;
1534            }
1535            if rx_status.framing_error() {
1536                err.framing = true;
1537            }
1538            if rx_status.parity_error() {
1539                err.parity = true;
1540            }
1541        }
1542    }
1543
1544    fn irq_completion_handler_max_size_timeout(
1545        &mut self,
1546        res: &mut InterruptResultMaxSizeOrTimeout,
1547        context: &mut InterruptContextTimeoutOrMaxSize,
1548    ) {
1549        self.disable_interrupts();
1550        self.0.disable();
1551        res.bytes_read = context.rx_idx;
1552        res.complete = true;
1553        context.mode = InterruptReceptionMode::Idle;
1554        context.rx_idx = 0;
1555    }
1556
1557    /// # Safety
1558    ///
1559    /// This API allows creating multiple UART instances when releasing the TX structure as well.
1560    /// The user must ensure that these instances are not used to create multiple overlapping
1561    /// UART drivers.
1562    pub unsafe fn release(mut self) -> Rx {
1563        self.disable_interrupts();
1564        self.0
1565    }
1566}