Skip to main content

esp_hal/uart/low_level/
mod.rs

1use core::task::Poll;
2
3use enumset::{EnumSet, EnumSetType};
4use portable_atomic::AtomicBool;
5
6#[cfg(feature = "unstable")]
7use super::BaudrateTolerance;
8use super::{
9    AnyUart,
10    Config,
11    ConfigError,
12    DataBits,
13    HwFlowControl,
14    Parity,
15    RxError,
16    RxErrorKind,
17    StopBits,
18    SwFlowControl,
19    TxError,
20    UartInterrupt,
21    any,
22};
23#[cfg(sleep_driver_supported)]
24use super::{WakeConfigError, WakeupConfig};
25use crate::{
26    asynch::AtomicWaker,
27    gpio::{InputSignal, OutputSignal},
28    handler,
29    interrupt::InterruptHandler,
30    pac::uart0::RegisterBlock,
31    ram,
32    soc::clocks::{
33        self,
34        ClockTree,
35        UartBaudRateGeneratorConfig as BaudRateConfig,
36        UartFunctionClockConfig as ClockConfig,
37    },
38};
39
40#[cfg_attr(uart_version = "1", path = "v1.rs")]
41#[cfg_attr(uart_version = "2", path = "v2.rs")]
42mod version;
43
44pub(super) use version::{enable_register_sync, sync_regs};
45
46#[derive(Debug, EnumSetType)]
47pub(super) enum TxEvent {
48    Done,
49    FiFoEmpty,
50}
51
52#[derive(Debug, EnumSetType)]
53pub(super) enum RxEvent {
54    FifoFull,
55    CmdCharDetected,
56    FifoOvf,
57    FifoTout,
58    GlitchDetected,
59    FrameError,
60    ParityError,
61    BreakDetected,
62}
63
64pub(super) fn rx_event_check_for_error(
65    events: EnumSet<RxEvent>,
66    reported_errors: EnumSet<RxErrorKind>,
67) -> Result<(), RxError> {
68    for event in events {
69        if let Some(error) = rx_error_kind(event)
70            && reported_errors.contains(error)
71        {
72            return Err(error.into());
73        }
74    }
75
76    Ok(())
77}
78
79fn rx_error_kind(event: RxEvent) -> Option<RxErrorKind> {
80    match event {
81        RxEvent::FifoOvf => Some(RxErrorKind::FifoOverflowed),
82        RxEvent::GlitchDetected => Some(RxErrorKind::GlitchOccurred),
83        RxEvent::FrameError => Some(RxErrorKind::FrameFormatViolated),
84        RxEvent::ParityError => Some(RxErrorKind::ParityMismatch),
85        RxEvent::FifoFull
86        | RxEvent::CmdCharDetected
87        | RxEvent::FifoTout
88        | RxEvent::BreakDetected => None,
89    }
90}
91
92/// A future that resolves when the passed interrupt is triggered,
93/// or has been triggered in the meantime (flag set in INT_RAW).
94/// Upon construction the future enables the passed interrupt and when it
95/// is dropped it disables the interrupt again. The future returns the event
96/// that was initially passed, when it resolves.
97#[must_use = "futures do nothing unless you `.await` or poll them"]
98pub(super) struct UartRxFuture {
99    events: EnumSet<RxEvent>,
100    uart: &'static Info,
101    state: &'static State,
102    registered: bool,
103}
104
105impl UartRxFuture {
106    pub(super) fn new(uart: impl Instance, events: impl Into<EnumSet<RxEvent>>) -> Self {
107        Self {
108            events: events.into(),
109            uart: uart.info(),
110            state: uart.state(),
111            registered: false,
112        }
113    }
114}
115
116impl core::future::Future for UartRxFuture {
117    type Output = EnumSet<RxEvent>;
118
119    fn poll(
120        mut self: core::pin::Pin<&mut Self>,
121        cx: &mut core::task::Context<'_>,
122    ) -> core::task::Poll<Self::Output> {
123        let events = self.uart.rx_events().intersection(self.events);
124        if !events.is_empty() {
125            self.uart.clear_rx_events(events);
126            Poll::Ready(events)
127        } else {
128            self.state.rx_waker.register(cx.waker());
129            if !self.registered {
130                self.uart.enable_listen_rx(self.events, true);
131                self.registered = true;
132            }
133            Poll::Pending
134        }
135    }
136}
137
138impl Drop for UartRxFuture {
139    fn drop(&mut self) {
140        // Although the isr disables the interrupt that occurred directly, we need to
141        // disable the other interrupts (= the ones that did not occur), as
142        // soon as this future goes out of scope.
143        self.uart.enable_listen_rx(self.events, false);
144    }
145}
146
147#[must_use = "futures do nothing unless you `.await` or poll them"]
148pub(super) struct UartTxFuture {
149    events: EnumSet<TxEvent>,
150    uart: &'static Info,
151    state: &'static State,
152    registered: bool,
153}
154
155impl UartTxFuture {
156    pub(super) fn new(uart: impl Instance, events: impl Into<EnumSet<TxEvent>>) -> Self {
157        Self {
158            events: events.into(),
159            uart: uart.info(),
160            state: uart.state(),
161            registered: false,
162        }
163    }
164}
165
166impl core::future::Future for UartTxFuture {
167    type Output = ();
168
169    fn poll(
170        mut self: core::pin::Pin<&mut Self>,
171        cx: &mut core::task::Context<'_>,
172    ) -> core::task::Poll<Self::Output> {
173        let events = self.uart.tx_events().intersection(self.events);
174        if !events.is_empty() {
175            self.uart.clear_tx_events(events);
176            Poll::Ready(())
177        } else {
178            self.state.tx_waker.register(cx.waker());
179            if !self.registered {
180                self.uart.enable_listen_tx(self.events, true);
181                self.registered = true;
182            }
183            Poll::Pending
184        }
185    }
186}
187
188impl Drop for UartTxFuture {
189    fn drop(&mut self) {
190        // Although the isr disables the interrupt that occurred directly, we need to
191        // disable the other interrupts (= the ones that did not occur), as
192        // soon as this future goes out of scope.
193        self.uart.enable_listen_tx(self.events, false);
194    }
195}
196
197/// Interrupt handler for all UART instances
198/// Clears and disables interrupts that have occurred and have their enable
199/// bit set. The fact that an interrupt has been disabled is used by the
200/// futures to detect that they should indeed resolve after being woken up
201#[ram]
202pub(super) fn intr_handler(uart: &Info, state: &State) {
203    let interrupts = uart.regs().int_st().read();
204    let interrupt_bits = interrupts.bits(); // = int_raw & int_ena
205    let rx_wake = interrupts.rxfifo_full().bit_is_set()
206        | interrupts.rxfifo_ovf().bit_is_set()
207        | interrupts.rxfifo_tout().bit_is_set()
208        | interrupts.at_cmd_char_det().bit_is_set()
209        | interrupts.glitch_det().bit_is_set()
210        | interrupts.frm_err().bit_is_set()
211        | interrupts.parity_err().bit_is_set()
212        | interrupts.brk_det().bit_is_set();
213    let tx_wake = interrupts.tx_done().bit_is_set() | interrupts.txfifo_empty().bit_is_set();
214
215    uart.regs()
216        .int_ena()
217        .modify(|r, w| unsafe { w.bits(r.bits() & !interrupt_bits) });
218
219    if tx_wake {
220        state.tx_waker.wake();
221    }
222    if rx_wake {
223        state.rx_waker.wake();
224    }
225}
226
227/// A peripheral singleton compatible with the UART driver.
228pub trait Instance: crate::private::Sealed + any::Degrade {
229    #[doc(hidden)]
230    /// Returns the peripheral data and state describing this UART instance.
231    fn parts(&self) -> (&'static Info, &'static State);
232
233    /// Returns the peripheral data describing this UART instance.
234    #[inline(always)]
235    #[doc(hidden)]
236    fn info(&self) -> &'static Info {
237        self.parts().0
238    }
239
240    /// Returns the peripheral state for this UART instance.
241    #[inline(always)]
242    #[doc(hidden)]
243    fn state(&self) -> &'static State {
244        self.parts().1
245    }
246}
247
248/// Peripheral data describing a particular UART instance.
249#[doc(hidden)]
250#[non_exhaustive]
251#[allow(private_interfaces, reason = "Unstable details")]
252pub struct Info {
253    /// Pointer to the register block for this UART instance.
254    ///
255    /// Used with [`Self::register_block`] to access the register block.
256    pub register_block: *const RegisterBlock,
257
258    /// The system peripheral marker.
259    pub peripheral: crate::system::Peripheral,
260
261    /// UART clock group instance.
262    pub clock_instance: clocks::UartInstance,
263
264    /// Interrupt handler for the asynchronous operations of this UART instance.
265    pub async_handler: InterruptHandler,
266
267    /// TX pin
268    pub tx_signal: OutputSignal,
269
270    /// RX pin
271    pub rx_signal: InputSignal,
272
273    /// CTS (Clear to Send) pin
274    pub cts_signal: InputSignal,
275
276    /// RTS (Request to Send) pin
277    pub rts_signal: OutputSignal,
278
279    /// The wakeup source of this instance, or `None` if the instance cannot wake the chip.
280    #[cfg(sleep_driver_supported)]
281    pub wakeup_source: Option<crate::rtc_cntl::WakeupSource>,
282}
283
284/// Peripheral state for a UART instance.
285#[doc(hidden)]
286#[non_exhaustive]
287pub struct State {
288    /// Waker for the asynchronous RX operations.
289    pub rx_waker: AtomicWaker,
290
291    /// Waker for the asynchronous TX operations.
292    pub tx_waker: AtomicWaker,
293
294    /// Stores whether the RX half is configured for async operation.
295    pub is_rx_async: AtomicBool,
296
297    /// Stores whether the TX half is configured for async operation.
298    pub is_tx_async: AtomicBool,
299}
300
301impl Info {
302    // Currently we don't support merging adjacent FIFO memory, so the max size is
303    // 128 bytes, the max threshold is 127 bytes.
304    pub(super) const UART_FIFO_SIZE: u16 = property!("uart.ram_size");
305    pub(super) const RX_FIFO_MAX_THRHD: u16 = Self::UART_FIFO_SIZE - 1;
306    pub(super) const TX_FIFO_MAX_THRHD: u16 = Self::RX_FIFO_MAX_THRHD;
307
308    /// Returns the register block for this UART instance.
309    pub fn regs(&self) -> &RegisterBlock {
310        unsafe { &*self.register_block }
311    }
312
313    /// Listens for the given interrupts.
314    pub(super) fn enable_listen(&self, interrupts: EnumSet<UartInterrupt>, enable: bool) {
315        let reg_block = self.regs();
316
317        reg_block.int_ena().modify(|_, w| {
318            for interrupt in interrupts {
319                match interrupt {
320                    UartInterrupt::AtCmd => w.at_cmd_char_det().bit(enable),
321                    UartInterrupt::TxDone => w.tx_done().bit(enable),
322                    UartInterrupt::RxBreakDetected => w.brk_det().bit(enable),
323                    UartInterrupt::RxFifoFull => w.rxfifo_full().bit(enable),
324                    UartInterrupt::RxTimeout => w.rxfifo_tout().bit(enable),
325                };
326            }
327            w
328        });
329    }
330
331    pub(super) fn interrupts(&self) -> EnumSet<UartInterrupt> {
332        let mut res = EnumSet::new();
333        let reg_block = self.regs();
334
335        let ints = reg_block.int_raw().read();
336
337        if ints.at_cmd_char_det().bit_is_set() {
338            res.insert(UartInterrupt::AtCmd);
339        }
340        if ints.tx_done().bit_is_set() {
341            res.insert(UartInterrupt::TxDone);
342        }
343        if ints.brk_det().bit_is_set() {
344            res.insert(UartInterrupt::RxBreakDetected);
345        }
346        if ints.rxfifo_full().bit_is_set() {
347            res.insert(UartInterrupt::RxFifoFull);
348        }
349        if ints.rxfifo_tout().bit_is_set() {
350            res.insert(UartInterrupt::RxTimeout);
351        }
352
353        res
354    }
355
356    pub(super) fn clear_interrupts(&self, interrupts: EnumSet<UartInterrupt>) {
357        let reg_block = self.regs();
358
359        reg_block.int_clr().write(|w| {
360            for interrupt in interrupts {
361                match interrupt {
362                    UartInterrupt::AtCmd => w.at_cmd_char_det().clear_bit_by_one(),
363                    UartInterrupt::TxDone => w.tx_done().clear_bit_by_one(),
364                    UartInterrupt::RxBreakDetected => w.brk_det().clear_bit_by_one(),
365                    UartInterrupt::RxFifoFull => w.rxfifo_full().clear_bit_by_one(),
366                    UartInterrupt::RxTimeout => w.rxfifo_tout().clear_bit_by_one(),
367                };
368            }
369            w
370        });
371    }
372
373    pub(super) fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
374        config.validate()?;
375        self.change_baud(config)?;
376        self.change_data_bits(config.data_bits);
377        self.change_parity(config.parity);
378        self.change_stop_bits(config.stop_bits);
379        self.change_flow_control(config.sw_flow_ctrl, config.hw_flow_ctrl);
380
381        // Avoid glitch interrupts.
382        self.regs().int_clr().write(|w| unsafe { w.bits(u32::MAX) });
383
384        Ok(())
385    }
386
387    pub(super) fn enable_listen_tx(&self, events: EnumSet<TxEvent>, enable: bool) {
388        self.regs().int_ena().modify(|_, w| {
389            for event in events {
390                match event {
391                    TxEvent::Done => w.tx_done().bit(enable),
392                    TxEvent::FiFoEmpty => w.txfifo_empty().bit(enable),
393                };
394            }
395            w
396        });
397    }
398
399    fn tx_events(&self) -> EnumSet<TxEvent> {
400        let pending_interrupts = self.regs().int_raw().read();
401        let mut active_events = EnumSet::new();
402
403        if pending_interrupts.tx_done().bit_is_set() {
404            active_events |= TxEvent::Done;
405        }
406        if pending_interrupts.txfifo_empty().bit_is_set() {
407            active_events |= TxEvent::FiFoEmpty;
408        }
409
410        active_events
411    }
412
413    fn clear_tx_events(&self, events: impl Into<EnumSet<TxEvent>>) {
414        let events = events.into();
415        self.regs().int_clr().write(|w| {
416            for event in events {
417                match event {
418                    TxEvent::FiFoEmpty => w.txfifo_empty().clear_bit_by_one(),
419                    TxEvent::Done => w.tx_done().clear_bit_by_one(),
420                };
421            }
422            w
423        });
424    }
425
426    pub(super) fn enable_listen_rx(&self, events: EnumSet<RxEvent>, enable: bool) {
427        self.regs().int_ena().modify(|_, w| {
428            for event in events {
429                match event {
430                    RxEvent::FifoFull => w.rxfifo_full().bit(enable),
431                    RxEvent::BreakDetected => w.brk_det().bit(enable),
432                    RxEvent::CmdCharDetected => w.at_cmd_char_det().bit(enable),
433
434                    RxEvent::FifoOvf => w.rxfifo_ovf().bit(enable),
435                    RxEvent::FifoTout => w.rxfifo_tout().bit(enable),
436                    RxEvent::GlitchDetected => w.glitch_det().bit(enable),
437                    RxEvent::FrameError => w.frm_err().bit(enable),
438                    RxEvent::ParityError => w.parity_err().bit(enable),
439                };
440            }
441            w
442        });
443    }
444
445    fn rx_events(&self) -> EnumSet<RxEvent> {
446        let pending_interrupts = self.regs().int_raw().read();
447        let mut active_events = EnumSet::new();
448
449        if pending_interrupts.rxfifo_full().bit_is_set() {
450            active_events |= RxEvent::FifoFull;
451        }
452        if pending_interrupts.brk_det().bit_is_set() {
453            active_events |= RxEvent::BreakDetected;
454        }
455        if pending_interrupts.at_cmd_char_det().bit_is_set() {
456            active_events |= RxEvent::CmdCharDetected;
457        }
458        if pending_interrupts.rxfifo_ovf().bit_is_set() {
459            active_events |= RxEvent::FifoOvf;
460        }
461        if pending_interrupts.rxfifo_tout().bit_is_set() {
462            active_events |= RxEvent::FifoTout;
463        }
464        if pending_interrupts.glitch_det().bit_is_set() {
465            active_events |= RxEvent::GlitchDetected;
466        }
467        if pending_interrupts.frm_err().bit_is_set() {
468            active_events |= RxEvent::FrameError;
469        }
470        if pending_interrupts.parity_err().bit_is_set() {
471            active_events |= RxEvent::ParityError;
472        }
473
474        active_events
475    }
476
477    fn clear_rx_events(&self, events: impl Into<EnumSet<RxEvent>>) {
478        let events = events.into();
479        self.regs().int_clr().write(|w| {
480            for event in events {
481                match event {
482                    RxEvent::FifoFull => w.rxfifo_full().clear_bit_by_one(),
483                    RxEvent::BreakDetected => w.brk_det().clear_bit_by_one(),
484                    RxEvent::CmdCharDetected => w.at_cmd_char_det().clear_bit_by_one(),
485
486                    RxEvent::FifoOvf => w.rxfifo_ovf().clear_bit_by_one(),
487                    RxEvent::FifoTout => w.rxfifo_tout().clear_bit_by_one(),
488                    RxEvent::GlitchDetected => w.glitch_det().clear_bit_by_one(),
489                    RxEvent::FrameError => w.frm_err().clear_bit_by_one(),
490                    RxEvent::ParityError => w.parity_err().clear_bit_by_one(),
491                };
492            }
493            w
494        });
495    }
496
497    /// Configures the RX-FIFO threshold.
498    ///
499    /// # Errors
500    ///
501    /// [`ConfigError::RxFifoThresholdNotSupported`] if the provided value is zero
502    /// or exceeds [`Info::RX_FIFO_MAX_THRHD`].
503    pub(super) fn set_rx_fifo_full_threshold(&self, threshold: u16) -> Result<(), ConfigError> {
504        if threshold == 0 || threshold > Self::RX_FIFO_MAX_THRHD {
505            return Err(ConfigError::RxFifoThresholdNotSupported);
506        }
507
508        self.regs()
509            .conf1()
510            .modify(|_, w| unsafe { w.rxfifo_full_thrhd().bits(threshold as _) });
511
512        Ok(())
513    }
514
515    /// Reads the RX-FIFO threshold.
516    #[allow(clippy::useless_conversion)]
517    pub(super) fn rx_fifo_full_threshold(&self) -> u16 {
518        self.regs().conf1().read().rxfifo_full_thrhd().bits().into()
519    }
520
521    /// Configures the TX-FIFO threshold.
522    ///
523    /// # Errors
524    ///
525    /// [`ConfigError::TxFifoThresholdNotSupported`] if the provided value exceeds
526    /// [`Info::TX_FIFO_MAX_THRHD`].
527    pub(super) fn set_tx_fifo_empty_threshold(&self, threshold: u16) -> Result<(), ConfigError> {
528        if threshold > Self::TX_FIFO_MAX_THRHD {
529            return Err(ConfigError::TxFifoThresholdNotSupported);
530        }
531
532        self.regs()
533            .conf1()
534            .modify(|_, w| unsafe { w.txfifo_empty_thrhd().bits(threshold as _) });
535
536        Ok(())
537    }
538
539    #[cfg(uart_has_sclk_enable)]
540    pub(super) fn set_at_cmd_clock_enabled(&self, enabled: bool) {
541        self.regs()
542            .clk_conf()
543            .modify(|_, w| w.sclk_en().bit(enabled));
544    }
545
546    #[procmacros::doc_replace(
547        "rx_timeout_limit" => {
548            cfg(esp32) => "- Symbol size is fixed to 8, do not pass a value > **0x7F**.",
549            _ => "- The value you pass times the symbol size must be <= **0x3FF**.",
550        }
551    )]
552    /// Configures the Receive Timeout detection setting.
553    ///
554    /// ## Arguments
555    ///
556    /// `timeout` - the number of symbols ("bytes") to wait for before
557    /// triggering a timeout. Pass None to disable the timeout.
558    ///
559    /// # Errors
560    ///
561    /// [`ConfigError::TimeoutTooLong`] if the provided value exceeds
562    /// the maximum value for SOC:
563    /// {rx_timeout_limit}
564    pub(super) fn set_rx_timeout(
565        &self,
566        timeout: Option<u8>,
567        symbol_len: u8,
568    ) -> Result<(), ConfigError> {
569        version::set_rx_timeout(self, timeout, symbol_len)
570    }
571
572    pub(super) fn rx_timeout_enabled(&self) -> bool {
573        version::rx_timeout_enabled(self)
574    }
575
576    pub(super) fn set_discard_erroneous_bytes(&self, discard: bool) {
577        // ERR_WR_MASK causes the hardware to discard bytes with UART errors
578        // instead of storing them in the RX FIFO.
579        self.regs()
580            .conf0()
581            .modify(|_, w| w.err_wr_mask().bit(discard));
582        self.sync_regs();
583    }
584
585    pub(super) fn is_tx_idle(&self) -> bool {
586        version::is_tx_idle(self)
587    }
588
589    fn sync_regs(&self) {
590        sync_regs(self.regs());
591    }
592
593    fn change_baud(&self, config: &Config) -> Result<(), ConfigError> {
594        ClockTree::with(|clocks| {
595            let clock = self.clock_instance;
596
597            let clk = clocks::UartInstance::function_clock_source_frequency(config.clock_source);
598
599            // The UART baud rate clock divider is, depending on the device, either a
600            // 20.4 bit, or a 12.4 bit divider.
601            const FRAC_BITS: u32 = const {
602                let largest_divider: u32 =
603                    property!("clock_tree.uart.baud_rate_generator.fractional").1;
604                ::core::assert!((largest_divider + 1).is_power_of_two());
605                largest_divider.count_ones()
606            };
607            const FRAC_MASK: u32 = (1 << FRAC_BITS) - 1;
608
609            // TODO: this block should only prepare the new clock config, and it should
610            // be applied only after validating the resulting baud rate.
611            cfg_select! {
612                any(uart_has_sclk_divider, soc_has_pcr, esp32p4, esp32s31) => {
613                    const MAX_DIV: u32 =
614                        property!("clock_tree.uart.baud_rate_generator.integral").1;
615                    let clk_div = clk.div_ceil(MAX_DIV).div_ceil(config.baudrate);
616                    debug!("SCLK: {} divider: {}", clk, clk_div);
617
618                    let conf = ClockConfig::new(config.clock_source, clk_div - 1);
619                    let divider = (clk << FRAC_BITS) / (config.baudrate * clk_div);
620                }
621                _ => {
622                    debug!("SCLK: {}", clk);
623                    let conf = ClockConfig::new(config.clock_source);
624                    let divider = (clk << FRAC_BITS) / config.baudrate;
625                }
626            }
627
628            let divider_integer = divider >> FRAC_BITS;
629            let divider_frag = divider & FRAC_MASK;
630            debug!(
631                "UART CLK divider: {} + {}/16",
632                divider_integer, divider_frag
633            );
634
635            clock.configure_function_clock(clocks, conf);
636            clock.configure_baud_rate_generator(
637                clocks,
638                BaudRateConfig::new(divider_frag, divider_integer),
639            );
640
641            self.sync_regs();
642
643            #[cfg(feature = "unstable")]
644            {
645                let deviation_limit = match config.baudrate_tolerance {
646                    BaudrateTolerance::Exact => 1, // Still allow a tiny deviation
647                    BaudrateTolerance::ErrorPercent(percent) => percent as u32,
648                    _ => return Ok(()),
649                };
650
651                let actual_baud = clock.baud_rate_generator_frequency();
652                if actual_baud == 0 {
653                    return Err(ConfigError::BaudrateNotAchievable);
654                }
655
656                let deviation = (config.baudrate.abs_diff(actual_baud) * 100) / actual_baud;
657                debug!(
658                    "Nominal baud: {}, actual: {}, deviation: {}%",
659                    config.baudrate, actual_baud, deviation
660                );
661
662                if deviation > deviation_limit {
663                    return Err(ConfigError::BaudrateNotAchievable);
664                }
665            }
666
667            Ok(())
668        })
669    }
670
671    fn change_data_bits(&self, data_bits: DataBits) {
672        self.regs()
673            .conf0()
674            .modify(|_, w| unsafe { w.bit_num().bits(data_bits as u8) });
675    }
676
677    fn change_parity(&self, parity: Parity) {
678        self.regs().conf0().modify(|_, w| match parity {
679            Parity::None => w.parity_en().clear_bit(),
680            Parity::Even => w.parity_en().set_bit().parity().clear_bit(),
681            Parity::Odd => w.parity_en().set_bit().parity().set_bit(),
682        });
683    }
684
685    fn change_stop_bits(&self, stop_bits: StopBits) {
686        version::change_stop_bits(self, stop_bits);
687    }
688
689    fn change_flow_control(&self, sw_flow_ctrl: SwFlowControl, hw_flow_ctrl: HwFlowControl) {
690        version::change_flow_control(self, sw_flow_ctrl, hw_flow_ctrl);
691    }
692
693    pub(super) fn rxfifo_reset(&self) {
694        fn rxfifo_rst(reg_block: &RegisterBlock, enable: bool) {
695            reg_block.conf0().modify(|_, w| w.rxfifo_rst().bit(enable));
696            sync_regs(reg_block);
697        }
698
699        rxfifo_rst(self.regs(), true);
700        rxfifo_rst(self.regs(), false);
701    }
702
703    pub(super) fn txfifo_reset(&self) {
704        fn txfifo_rst(reg_block: &RegisterBlock, enable: bool) {
705            reg_block.conf0().modify(|_, w| w.txfifo_rst().bit(enable));
706            sync_regs(reg_block);
707        }
708
709        txfifo_rst(self.regs(), true);
710        txfifo_rst(self.regs(), false);
711
712        // The reset can drive the state machine. Wait for it to settle.
713        while !self.is_tx_idle() {}
714    }
715
716    pub(super) fn current_symbol_length(&self) -> u8 {
717        version::current_symbol_length(self)
718    }
719
720    /// Reads one byte from the RX FIFO.
721    ///
722    /// If the FIFO is empty, the value of the returned byte is not specified.
723    pub(super) fn read_next_from_fifo(&self) -> u8 {
724        version::read_next_from_fifo(self)
725    }
726
727    #[allow(clippy::useless_conversion)]
728    pub(super) fn tx_fifo_count(&self) -> u16 {
729        u16::from(self.regs().status().read().txfifo_cnt().bits())
730    }
731
732    pub(super) fn write_byte(&self, byte: u8) {
733        self.regs()
734            .fifo()
735            .write(|w| unsafe { w.rxfifo_rd_byte().bits(byte) });
736    }
737
738    fn check_for_errors_and_reset_fifo(
739        &self,
740        reported_errors: EnumSet<RxErrorKind>,
741    ) -> Result<bool, RxError> {
742        let errors =
743            RxEvent::FifoOvf | RxEvent::GlitchDetected | RxEvent::FrameError | RxEvent::ParityError;
744        let events = self.rx_events().intersection(errors);
745        let result = rx_event_check_for_error(events, reported_errors);
746        let fifo_overflowed = events.contains(RxEvent::FifoOvf);
747        if !events.is_empty() {
748            self.clear_rx_events(events);
749            if fifo_overflowed {
750                self.rxfifo_reset();
751            }
752        }
753        result.map(|()| fifo_overflowed)
754    }
755
756    pub(super) fn check_for_errors(
757        &self,
758        reported_errors: EnumSet<RxErrorKind>,
759    ) -> Result<(), RxError> {
760        self.check_for_errors_and_reset_fifo(reported_errors)
761            .map(|_| ())
762    }
763
764    pub(super) fn check_rx_break_detected(&self) -> bool {
765        self.rx_events().contains(RxEvent::BreakDetected)
766    }
767
768    pub(super) fn clear_rx_break_detected(&self) {
769        self.clear_rx_events(RxEvent::BreakDetected);
770    }
771
772    pub(super) fn rx_fifo_count(&self) -> u16 {
773        version::rx_fifo_count(self)
774    }
775
776    pub(super) fn write(&self, data: &[u8]) -> Result<usize, TxError> {
777        if data.is_empty() {
778            return Ok(0);
779        }
780
781        while self.tx_fifo_count() >= Info::UART_FIFO_SIZE {}
782
783        let space = (Info::UART_FIFO_SIZE - self.tx_fifo_count()) as usize;
784        let to_write = space.min(data.len());
785        for &byte in &data[..to_write] {
786            self.write_byte(byte);
787        }
788
789        Ok(to_write)
790    }
791
792    pub(super) fn read(
793        &self,
794        buf: &mut [u8],
795        reported_errors: EnumSet<RxErrorKind>,
796    ) -> Result<usize, RxError> {
797        if buf.is_empty() {
798            return Ok(0);
799        }
800
801        loop {
802            while self.rx_fifo_count() == 0 {
803                // Block until we received at least one byte
804                self.check_for_errors(reported_errors)?;
805            }
806
807            let read = self.read_buffered(buf, reported_errors)?;
808            if read > 0 {
809                break Ok(read);
810            }
811        }
812    }
813
814    pub(super) fn read_buffered(
815        &self,
816        buf: &mut [u8],
817        reported_errors: EnumSet<RxErrorKind>,
818    ) -> Result<usize, RxError> {
819        // Get the count first, to avoid accidentally reading a corrupted byte received
820        // after the error check.
821        let to_read = (self.rx_fifo_count() as usize).min(buf.len());
822        if self.check_for_errors_and_reset_fifo(reported_errors)? {
823            return Ok(0);
824        }
825
826        for byte_into in buf[..to_read].iter_mut() {
827            *byte_into = self.read_next_from_fifo();
828        }
829
830        // This bit is not cleared until the FIFO actually drops below the threshold.
831        self.clear_rx_events(RxEvent::FifoFull);
832
833        Ok(to_read)
834    }
835
836    #[cfg(sleep_driver_supported)]
837    pub(crate) fn suspend_for_sleep(&self) {
838        version::suspend(self, true);
839        version::wait_for_suspended(self);
840    }
841
842    #[cfg(sleep_driver_supported)]
843    pub(crate) fn resume_from_sleep(&self) {
844        version::suspend(self, false);
845    }
846
847    /// Lets this instance wake the chip from light sleep.
848    #[cfg(sleep_driver_supported)]
849    pub(crate) fn enable_wakeup(&self, config: &WakeupConfig) -> Result<(), WakeConfigError> {
850        let source = self
851            .wakeup_source
852            .ok_or(WakeConfigError::NotAWakeupSource)?;
853
854        let edges = config.rising_edges();
855        if !(super::MIN_WAKEUP_EDGES..=super::MAX_WAKEUP_EDGES).contains(&edges) {
856            return Err(WakeConfigError::EdgeCountUnsupported);
857        }
858
859        // The register holds the number of edges above a fixed offset.
860        version::set_wakeup_edge_threshold(self, edges - super::WAKEUP_EDGE_OFFSET);
861
862        source.enable_with_hooks(Some(keep_peripherals_powered), None);
863
864        Ok(())
865    }
866
867    /// Stops this instance from waking the chip.
868    #[cfg(sleep_driver_supported)]
869    pub(crate) fn disable_wakeup(&self) {
870        if let Some(source) = self.wakeup_source {
871            source.disable();
872        }
873    }
874}
875
876/// The UART peripheral monitors the RX line itself, so the peripheral must stay powered.
877#[cfg(sleep_driver_supported)]
878#[crate::ram]
879fn keep_peripherals_powered(config: &mut crate::rtc_cntl::sleep::WrappedSleepConfig<'_>) {
880    // A deep sleep powers the peripheral down in all cases, so this request gives no wake there. It
881    // only increases the current.
882    if !config.is_deep_sleep() {
883        config.keep_alive(crate::rtc_cntl::sleep::SleepResource::HpPeripherals);
884    }
885}
886
887impl PartialEq for Info {
888    fn eq(&self, other: &Self) -> bool {
889        core::ptr::eq(self.register_block, other.register_block)
890    }
891}
892
893unsafe impl Sync for Info {}
894
895// Each instance names its wakeup source, and no code calculates the source from the metadata flag.
896// An instance that cannot wake the chip has no `WakeupSource` variant to name.
897macro_rules! impl_instance {
898    ($inst:ident, $peri:ident, $rxd:ident, $txd:ident, $cts:ident, $rts:ident, $wakeup_source:expr) => {
899        impl Instance for crate::peripherals::$inst<'_> {
900            fn parts(&self) -> (&'static Info, &'static State) {
901                #[handler]
902                #[ram]
903                pub(super) fn irq_handler() {
904                    intr_handler(&PERIPHERAL, &STATE);
905                }
906
907                static STATE: State = State {
908                    tx_waker: AtomicWaker::new(),
909                    rx_waker: AtomicWaker::new(),
910                    is_rx_async: AtomicBool::new(false),
911                    is_tx_async: AtomicBool::new(false),
912                };
913
914                static PERIPHERAL: Info = Info {
915                    register_block: crate::peripherals::$inst::ptr(),
916                    peripheral: crate::system::Peripheral::$peri,
917                    clock_instance: clocks::UartInstance::$peri,
918                    async_handler: irq_handler,
919                    tx_signal: OutputSignal::$txd,
920                    rx_signal: InputSignal::$rxd,
921                    cts_signal: InputSignal::$cts,
922                    rts_signal: OutputSignal::$rts,
923                    #[cfg(sleep_driver_supported)]
924                    wakeup_source: $wakeup_source,
925                };
926                (&PERIPHERAL, &STATE)
927            }
928        }
929    };
930}
931
932for_each_uart! {
933    ($id:literal, $inst:ident, $peri:ident, $rxd:ident, $txd:ident, $cts:ident, $rts:ident, wakeup_source = true) => {
934        impl_instance!($inst, $peri, $rxd, $txd, $cts, $rts, Some(crate::rtc_cntl::WakeupSource::$peri));
935    };
936    ($id:literal, $inst:ident, $peri:ident, $rxd:ident, $txd:ident, $cts:ident, $rts:ident, wakeup_source = false) => {
937        impl_instance!($inst, $peri, $rxd, $txd, $cts, $rts, None);
938    };
939}
940
941pub(super) struct UartClockGuard<'t> {
942    uart: AnyUart<'t>,
943}
944
945impl<'t> UartClockGuard<'t> {
946    pub(super) fn new(uart: AnyUart<'t>) -> Self {
947        let this = Self::new_inner(uart, false);
948        crate::rom::ets_delay_us(100);
949        this
950    }
951
952    pub(super) fn new_inner(uart: AnyUart<'t>, clone: bool) -> Self {
953        ClockTree::with(|clocks| {
954            let clock = uart.info().clock_instance;
955
956            // Apply default SCLK configuration when first instance is created.
957            if !clone {
958                let sclk_config = ClockConfig::new(
959                    Default::default(),
960                    #[cfg(any(uart_has_sclk_divider, soc_has_pcr, esp32p4, esp32s31))]
961                    0,
962                );
963                clock.configure_function_clock(clocks, sclk_config);
964            }
965            clock.request_function_clock(clocks);
966            clock.request_baud_rate_generator(clocks);
967            #[cfg(soc_has_clock_node_uart_mem_clock)]
968            clock.request_mem_clock(clocks);
969        });
970
971        Self { uart }
972    }
973}
974
975impl Clone for UartClockGuard<'_> {
976    fn clone(&self) -> Self {
977        Self::new_inner(unsafe { self.uart.clone_unchecked() }, true)
978    }
979}
980
981impl Drop for UartClockGuard<'_> {
982    fn drop(&mut self) {
983        ClockTree::with(|clocks| {
984            let clock = self.uart.info().clock_instance;
985
986            #[cfg(soc_has_clock_node_uart_mem_clock)]
987            clock.release_mem_clock(clocks);
988            clock.release_baud_rate_generator(clocks);
989            clock.release_function_clock(clocks);
990        });
991    }
992}