1use 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
50pub const FIFO_DEPTH: usize = 16;
52
53pub 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#[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 RxFifoHalfFull,
107 RxError,
109 RxTimeout,
112
113 TxFifoHalfFull,
117 TxError,
119 TxEmpty,
121 TxCts,
123}
124
125#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
126#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127pub enum BaudMode {
128 #[default]
130 _16 = 0,
131 _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 pub div: u18,
157 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 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 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#[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#[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#[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
390pub 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
440pub struct Uart {
446 tx: Tx,
447 rx: Rx,
448}
449
450impl Uart {
451 cfg_if::cfg_if! {
452 if #[cfg(feature = "vor1x")] {
453 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 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 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 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 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 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 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 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 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 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 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 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 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 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 #[inline]
808 pub fn clear_rx_fifo(&mut self) {
809 self.rx.clear_fifo();
810 }
811
812 #[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 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
930pub struct Rx {
934 id: Bank,
935 regs: regs::MmioUart<'static>,
936}
937
938impl Rx {
939 #[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 #[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 #[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
1133pub struct Tx {
1137 id: Bank,
1138 regs: regs::MmioUart<'static>,
1139}
1140
1141impl Tx {
1142 #[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 #[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 enable_tx_interrupts(tx_below_trigger, &mut self.regs);
1207 }
1208
1209 #[inline]
1213 pub fn disable_interrupts(&mut self) {
1214 disable_tx_interrupts(&mut self.regs);
1216 }
1217
1218 #[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 #[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 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
1297pub struct RxWithInterrupt(Rx);
1314
1315impl RxWithInterrupt {
1316 #[inline]
1317 pub fn new(rx: Rx) -> Self {
1318 Self(rx)
1319 }
1320
1321 pub unsafe fn steal(id: Bank) -> Self {
1330 Self(unsafe { Rx::steal(id) })
1331 }
1332
1333 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 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 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 if irq_status.rx() {
1404 let available_bytes = self.0.regs.read_rx_fifo_trigger().level().as_usize();
1405
1406 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 if irq_status.rx_timeout() {
1416 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 if rx_enabled {
1425 self.check_for_errors(&mut result.errors);
1426 }
1427
1428 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 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 if irq_status.rx() {
1468 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 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 }
1491 if irq_status.rx_timeout() {
1493 loop {
1495 if context.rx_idx == context.max_len {
1496 break;
1497 }
1498 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 if (context.rx_idx < context.max_len) && rx_enabled {
1513 self.check_for_errors(&mut result.errors);
1514 }
1515
1516 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 pub unsafe fn release(mut self) -> Rx {
1563 self.disable_interrupts();
1564 self.0
1565 }
1566}