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
44#[inline(always)]
45pub(super) fn sync_regs(register_block: &RegisterBlock) {
46    version::sync_regs(register_block);
47}
48
49#[derive(Debug, EnumSetType)]
50pub(super) enum TxEvent {
51    Done,
52    FiFoEmpty,
53}
54
55#[derive(Debug, EnumSetType)]
56pub(super) enum RxEvent {
57    FifoFull,
58    CmdCharDetected,
59    FifoOvf,
60    FifoTout,
61    GlitchDetected,
62    FrameError,
63    ParityError,
64    BreakDetected,
65}
66
67pub(super) fn rx_event_check_for_error(
68    events: EnumSet<RxEvent>,
69    reported_errors: EnumSet<RxErrorKind>,
70) -> Result<(), RxError> {
71    for event in events {
72        if let Some(error) = rx_error_kind(event)
73            && reported_errors.contains(error)
74        {
75            return Err(error.into());
76        }
77    }
78
79    Ok(())
80}
81
82fn rx_error_kind(event: RxEvent) -> Option<RxErrorKind> {
83    match event {
84        RxEvent::FifoOvf => Some(RxErrorKind::FifoOverflowed),
85        RxEvent::GlitchDetected => Some(RxErrorKind::GlitchOccurred),
86        RxEvent::FrameError => Some(RxErrorKind::FrameFormatViolated),
87        RxEvent::ParityError => Some(RxErrorKind::ParityMismatch),
88        RxEvent::FifoFull
89        | RxEvent::CmdCharDetected
90        | RxEvent::FifoTout
91        | RxEvent::BreakDetected => None,
92    }
93}
94
95/// A future that resolves when the passed interrupt is triggered,
96/// or has been triggered in the meantime (flag set in INT_RAW).
97/// Upon construction the future enables the passed interrupt and when it
98/// is dropped it disables the interrupt again. The future returns the event
99/// that was initially passed, when it resolves.
100#[must_use = "futures do nothing unless you `.await` or poll them"]
101pub(super) struct UartRxFuture {
102    events: EnumSet<RxEvent>,
103    uart: &'static Info,
104    state: &'static State,
105    registered: bool,
106}
107
108impl UartRxFuture {
109    pub(super) fn new(uart: impl Instance, events: impl Into<EnumSet<RxEvent>>) -> Self {
110        Self {
111            events: events.into(),
112            uart: uart.info(),
113            state: uart.state(),
114            registered: false,
115        }
116    }
117}
118
119impl core::future::Future for UartRxFuture {
120    type Output = EnumSet<RxEvent>;
121
122    fn poll(
123        mut self: core::pin::Pin<&mut Self>,
124        cx: &mut core::task::Context<'_>,
125    ) -> core::task::Poll<Self::Output> {
126        let events = self.uart.rx_events().intersection(self.events);
127        if !events.is_empty() {
128            self.uart.clear_rx_events(events);
129            Poll::Ready(events)
130        } else {
131            self.state.rx_waker.register(cx.waker());
132            if !self.registered {
133                self.uart.enable_listen_rx(self.events, true);
134                self.registered = true;
135            }
136            Poll::Pending
137        }
138    }
139}
140
141impl Drop for UartRxFuture {
142    fn drop(&mut self) {
143        // Although the isr disables the interrupt that occurred directly, we need to
144        // disable the other interrupts (= the ones that did not occur), as
145        // soon as this future goes out of scope.
146        self.uart.enable_listen_rx(self.events, false);
147    }
148}
149
150#[must_use = "futures do nothing unless you `.await` or poll them"]
151pub(super) struct UartTxFuture {
152    events: EnumSet<TxEvent>,
153    uart: &'static Info,
154    state: &'static State,
155    registered: bool,
156}
157
158impl UartTxFuture {
159    pub(super) fn new(uart: impl Instance, events: impl Into<EnumSet<TxEvent>>) -> Self {
160        Self {
161            events: events.into(),
162            uart: uart.info(),
163            state: uart.state(),
164            registered: false,
165        }
166    }
167}
168
169impl core::future::Future for UartTxFuture {
170    type Output = ();
171
172    fn poll(
173        mut self: core::pin::Pin<&mut Self>,
174        cx: &mut core::task::Context<'_>,
175    ) -> core::task::Poll<Self::Output> {
176        let events = self.uart.tx_events().intersection(self.events);
177        if !events.is_empty() {
178            self.uart.clear_tx_events(events);
179            Poll::Ready(())
180        } else {
181            self.state.tx_waker.register(cx.waker());
182            if !self.registered {
183                self.uart.enable_listen_tx(self.events, true);
184                self.registered = true;
185            }
186            Poll::Pending
187        }
188    }
189}
190
191impl Drop for UartTxFuture {
192    fn drop(&mut self) {
193        // Although the isr disables the interrupt that occurred directly, we need to
194        // disable the other interrupts (= the ones that did not occur), as
195        // soon as this future goes out of scope.
196        self.uart.enable_listen_tx(self.events, false);
197    }
198}
199
200/// Interrupt handler for all UART instances
201/// Clears and disables interrupts that have occurred and have their enable
202/// bit set. The fact that an interrupt has been disabled is used by the
203/// futures to detect that they should indeed resolve after being woken up
204#[ram]
205pub(super) fn intr_handler(uart: &Info, state: &State) {
206    let interrupts = uart.regs().int_st().read();
207    let interrupt_bits = interrupts.bits(); // = int_raw & int_ena
208    let rx_wake = interrupts.rxfifo_full().bit_is_set()
209        | interrupts.rxfifo_ovf().bit_is_set()
210        | interrupts.rxfifo_tout().bit_is_set()
211        | interrupts.at_cmd_char_det().bit_is_set()
212        | interrupts.glitch_det().bit_is_set()
213        | interrupts.frm_err().bit_is_set()
214        | interrupts.parity_err().bit_is_set()
215        | interrupts.brk_det().bit_is_set();
216    let tx_wake = interrupts.tx_done().bit_is_set() | interrupts.txfifo_empty().bit_is_set();
217
218    uart.regs()
219        .int_ena()
220        .modify(|r, w| unsafe { w.bits(r.bits() & !interrupt_bits) });
221
222    if tx_wake {
223        state.tx_waker.wake();
224    }
225    if rx_wake {
226        state.rx_waker.wake();
227    }
228}
229
230/// A peripheral singleton compatible with the UART driver.
231pub trait Instance: crate::private::Sealed + any::Degrade {
232    #[doc(hidden)]
233    /// Returns the peripheral data and state describing this UART instance.
234    fn parts(&self) -> (&'static Info, &'static State);
235
236    /// Returns the peripheral data describing this UART instance.
237    #[inline(always)]
238    #[doc(hidden)]
239    fn info(&self) -> &'static Info {
240        self.parts().0
241    }
242
243    /// Returns the peripheral state for this UART instance.
244    #[inline(always)]
245    #[doc(hidden)]
246    fn state(&self) -> &'static State {
247        self.parts().1
248    }
249}
250
251/// Peripheral data describing a particular UART instance.
252#[doc(hidden)]
253#[non_exhaustive]
254#[allow(private_interfaces, reason = "Unstable details")]
255pub struct Info {
256    /// Pointer to the register block for this UART instance.
257    ///
258    /// Use [Self::register_block] to access the register block.
259    pub register_block: *const RegisterBlock,
260
261    /// The system peripheral marker.
262    pub peripheral: crate::system::Peripheral,
263
264    /// UART clock group instance.
265    pub clock_instance: clocks::UartInstance,
266
267    /// Interrupt handler for the asynchronous operations of this UART instance.
268    pub async_handler: InterruptHandler,
269
270    /// TX pin
271    pub tx_signal: OutputSignal,
272
273    /// RX pin
274    pub rx_signal: InputSignal,
275
276    /// CTS (Clear to Send) pin
277    pub cts_signal: InputSignal,
278
279    /// RTS (Request to Send) pin
280    pub rts_signal: OutputSignal,
281
282    /// The wakeup source of this instance, or `None` if the instance cannot wake the chip.
283    #[cfg(sleep_driver_supported)]
284    pub wakeup_source: Option<crate::rtc_cntl::WakeupSource>,
285}
286
287/// Peripheral state for a UART instance.
288#[doc(hidden)]
289#[non_exhaustive]
290pub struct State {
291    /// Waker for the asynchronous RX operations.
292    pub rx_waker: AtomicWaker,
293
294    /// Waker for the asynchronous TX operations.
295    pub tx_waker: AtomicWaker,
296
297    /// Stores whether the RX half is configured for async operation.
298    pub is_rx_async: AtomicBool,
299
300    /// Stores whether the TX half is configured for async operation.
301    pub is_tx_async: AtomicBool,
302}
303
304impl Info {
305    // Currently we don't support merging adjacent FIFO memory, so the max size is
306    // 128 bytes, the max threshold is 127 bytes.
307    pub(super) const UART_FIFO_SIZE: u16 = property!("uart.ram_size");
308    pub(super) const RX_FIFO_MAX_THRHD: u16 = Self::UART_FIFO_SIZE - 1;
309    pub(super) const TX_FIFO_MAX_THRHD: u16 = Self::RX_FIFO_MAX_THRHD;
310
311    /// Returns the register block for this UART instance.
312    pub fn regs(&self) -> &RegisterBlock {
313        unsafe { &*self.register_block }
314    }
315
316    /// Listen for the given interrupts
317    pub(super) fn enable_listen(&self, interrupts: EnumSet<UartInterrupt>, enable: bool) {
318        let reg_block = self.regs();
319
320        reg_block.int_ena().modify(|_, w| {
321            for interrupt in interrupts {
322                match interrupt {
323                    UartInterrupt::AtCmd => w.at_cmd_char_det().bit(enable),
324                    UartInterrupt::TxDone => w.tx_done().bit(enable),
325                    UartInterrupt::RxBreakDetected => w.brk_det().bit(enable),
326                    UartInterrupt::RxFifoFull => w.rxfifo_full().bit(enable),
327                    UartInterrupt::RxTimeout => w.rxfifo_tout().bit(enable),
328                };
329            }
330            w
331        });
332    }
333
334    pub(super) fn interrupts(&self) -> EnumSet<UartInterrupt> {
335        let mut res = EnumSet::new();
336        let reg_block = self.regs();
337
338        let ints = reg_block.int_raw().read();
339
340        if ints.at_cmd_char_det().bit_is_set() {
341            res.insert(UartInterrupt::AtCmd);
342        }
343        if ints.tx_done().bit_is_set() {
344            res.insert(UartInterrupt::TxDone);
345        }
346        if ints.brk_det().bit_is_set() {
347            res.insert(UartInterrupt::RxBreakDetected);
348        }
349        if ints.rxfifo_full().bit_is_set() {
350            res.insert(UartInterrupt::RxFifoFull);
351        }
352        if ints.rxfifo_tout().bit_is_set() {
353            res.insert(UartInterrupt::RxTimeout);
354        }
355
356        res
357    }
358
359    pub(super) fn clear_interrupts(&self, interrupts: EnumSet<UartInterrupt>) {
360        let reg_block = self.regs();
361
362        reg_block.int_clr().write(|w| {
363            for interrupt in interrupts {
364                match interrupt {
365                    UartInterrupt::AtCmd => w.at_cmd_char_det().clear_bit_by_one(),
366                    UartInterrupt::TxDone => w.tx_done().clear_bit_by_one(),
367                    UartInterrupt::RxBreakDetected => w.brk_det().clear_bit_by_one(),
368                    UartInterrupt::RxFifoFull => w.rxfifo_full().clear_bit_by_one(),
369                    UartInterrupt::RxTimeout => w.rxfifo_tout().clear_bit_by_one(),
370                };
371            }
372            w
373        });
374    }
375
376    pub(super) fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
377        config.validate()?;
378        self.change_baud(config)?;
379        self.change_data_bits(config.data_bits);
380        self.change_parity(config.parity);
381        self.change_stop_bits(config.stop_bits);
382        self.change_flow_control(config.sw_flow_ctrl, config.hw_flow_ctrl);
383
384        // Avoid glitch interrupts.
385        self.regs().int_clr().write(|w| unsafe { w.bits(u32::MAX) });
386
387        Ok(())
388    }
389
390    pub(super) fn enable_listen_tx(&self, events: EnumSet<TxEvent>, enable: bool) {
391        self.regs().int_ena().modify(|_, w| {
392            for event in events {
393                match event {
394                    TxEvent::Done => w.tx_done().bit(enable),
395                    TxEvent::FiFoEmpty => w.txfifo_empty().bit(enable),
396                };
397            }
398            w
399        });
400    }
401
402    fn tx_events(&self) -> EnumSet<TxEvent> {
403        let pending_interrupts = self.regs().int_raw().read();
404        let mut active_events = EnumSet::new();
405
406        if pending_interrupts.tx_done().bit_is_set() {
407            active_events |= TxEvent::Done;
408        }
409        if pending_interrupts.txfifo_empty().bit_is_set() {
410            active_events |= TxEvent::FiFoEmpty;
411        }
412
413        active_events
414    }
415
416    fn clear_tx_events(&self, events: impl Into<EnumSet<TxEvent>>) {
417        let events = events.into();
418        self.regs().int_clr().write(|w| {
419            for event in events {
420                match event {
421                    TxEvent::FiFoEmpty => w.txfifo_empty().clear_bit_by_one(),
422                    TxEvent::Done => w.tx_done().clear_bit_by_one(),
423                };
424            }
425            w
426        });
427    }
428
429    pub(super) fn enable_listen_rx(&self, events: EnumSet<RxEvent>, enable: bool) {
430        self.regs().int_ena().modify(|_, w| {
431            for event in events {
432                match event {
433                    RxEvent::FifoFull => w.rxfifo_full().bit(enable),
434                    RxEvent::BreakDetected => w.brk_det().bit(enable),
435                    RxEvent::CmdCharDetected => w.at_cmd_char_det().bit(enable),
436
437                    RxEvent::FifoOvf => w.rxfifo_ovf().bit(enable),
438                    RxEvent::FifoTout => w.rxfifo_tout().bit(enable),
439                    RxEvent::GlitchDetected => w.glitch_det().bit(enable),
440                    RxEvent::FrameError => w.frm_err().bit(enable),
441                    RxEvent::ParityError => w.parity_err().bit(enable),
442                };
443            }
444            w
445        });
446    }
447
448    fn rx_events(&self) -> EnumSet<RxEvent> {
449        let pending_interrupts = self.regs().int_raw().read();
450        let mut active_events = EnumSet::new();
451
452        if pending_interrupts.rxfifo_full().bit_is_set() {
453            active_events |= RxEvent::FifoFull;
454        }
455        if pending_interrupts.brk_det().bit_is_set() {
456            active_events |= RxEvent::BreakDetected;
457        }
458        if pending_interrupts.at_cmd_char_det().bit_is_set() {
459            active_events |= RxEvent::CmdCharDetected;
460        }
461        if pending_interrupts.rxfifo_ovf().bit_is_set() {
462            active_events |= RxEvent::FifoOvf;
463        }
464        if pending_interrupts.rxfifo_tout().bit_is_set() {
465            active_events |= RxEvent::FifoTout;
466        }
467        if pending_interrupts.glitch_det().bit_is_set() {
468            active_events |= RxEvent::GlitchDetected;
469        }
470        if pending_interrupts.frm_err().bit_is_set() {
471            active_events |= RxEvent::FrameError;
472        }
473        if pending_interrupts.parity_err().bit_is_set() {
474            active_events |= RxEvent::ParityError;
475        }
476
477        active_events
478    }
479
480    fn clear_rx_events(&self, events: impl Into<EnumSet<RxEvent>>) {
481        let events = events.into();
482        self.regs().int_clr().write(|w| {
483            for event in events {
484                match event {
485                    RxEvent::FifoFull => w.rxfifo_full().clear_bit_by_one(),
486                    RxEvent::BreakDetected => w.brk_det().clear_bit_by_one(),
487                    RxEvent::CmdCharDetected => w.at_cmd_char_det().clear_bit_by_one(),
488
489                    RxEvent::FifoOvf => w.rxfifo_ovf().clear_bit_by_one(),
490                    RxEvent::FifoTout => w.rxfifo_tout().clear_bit_by_one(),
491                    RxEvent::GlitchDetected => w.glitch_det().clear_bit_by_one(),
492                    RxEvent::FrameError => w.frm_err().clear_bit_by_one(),
493                    RxEvent::ParityError => w.parity_err().clear_bit_by_one(),
494                };
495            }
496            w
497        });
498    }
499
500    /// Configures the RX-FIFO threshold
501    ///
502    /// ## Errors
503    ///
504    /// [`ConfigError::RxFifoThresholdNotSupported`] if the provided value is zero
505    /// or exceeds [`Info::RX_FIFO_MAX_THRHD`].
506    pub(super) fn set_rx_fifo_full_threshold(&self, threshold: u16) -> Result<(), ConfigError> {
507        if threshold == 0 || threshold > Self::RX_FIFO_MAX_THRHD {
508            return Err(ConfigError::RxFifoThresholdNotSupported);
509        }
510
511        self.regs()
512            .conf1()
513            .modify(|_, w| unsafe { w.rxfifo_full_thrhd().bits(threshold as _) });
514
515        Ok(())
516    }
517
518    /// Reads the RX-FIFO threshold
519    #[allow(clippy::useless_conversion)]
520    pub(super) fn rx_fifo_full_threshold(&self) -> u16 {
521        self.regs().conf1().read().rxfifo_full_thrhd().bits().into()
522    }
523
524    /// Configures the TX-FIFO threshold
525    ///
526    /// ## Errors
527    ///
528    /// [`ConfigError::TxFifoThresholdNotSupported`] if the provided value exceeds
529    /// [`Info::TX_FIFO_MAX_THRHD`].
530    pub(super) fn set_tx_fifo_empty_threshold(&self, threshold: u16) -> Result<(), ConfigError> {
531        if threshold > Self::TX_FIFO_MAX_THRHD {
532            return Err(ConfigError::TxFifoThresholdNotSupported);
533        }
534
535        self.regs()
536            .conf1()
537            .modify(|_, w| unsafe { w.txfifo_empty_thrhd().bits(threshold as _) });
538
539        Ok(())
540    }
541
542    #[cfg(uart_has_sclk_enable)]
543    pub(super) fn set_at_cmd_clock_enabled(&self, enabled: bool) {
544        self.regs()
545            .clk_conf()
546            .modify(|_, w| w.sclk_en().bit(enabled));
547    }
548
549    #[procmacros::doc_replace(
550        "rx_timeout_limit" => {
551            cfg(esp32) => "- Symbol size is fixed to 8, do not pass a value > **0x7F**.",
552            _ => "- The value you pass times the symbol size must be <= **0x3FF**.",
553        }
554    )]
555    /// Configures the Receive Timeout detection setting
556    ///
557    /// ## Arguments
558    ///
559    /// `timeout` - the number of symbols ("bytes") to wait for before
560    /// triggering a timeout. Pass None to disable the timeout.
561    ///
562    /// ## Errors
563    ///
564    /// [`ConfigError::TimeoutTooLong`] if the provided value exceeds
565    /// the maximum value for SOC:
566    /// {rx_timeout_limit}
567    pub(super) fn set_rx_timeout(
568        &self,
569        timeout: Option<u8>,
570        symbol_len: u8,
571    ) -> Result<(), ConfigError> {
572        version::set_rx_timeout(self, timeout, symbol_len)
573    }
574
575    pub(super) fn rx_timeout_enabled(&self) -> bool {
576        version::rx_timeout_enabled(self)
577    }
578
579    pub(super) fn set_discard_erroneous_bytes(&self, discard: bool) {
580        // ERR_WR_MASK causes the hardware to discard bytes with UART errors
581        // instead of storing them in the RX FIFO.
582        self.regs()
583            .conf0()
584            .modify(|_, w| w.err_wr_mask().bit(discard));
585        self.sync_regs();
586    }
587
588    pub(super) fn is_tx_idle(&self) -> bool {
589        version::is_tx_idle(self)
590    }
591
592    fn sync_regs(&self) {
593        sync_regs(self.regs());
594    }
595
596    fn change_baud(&self, config: &Config) -> Result<(), ConfigError> {
597        ClockTree::with(|clocks| {
598            let clock = self.clock_instance;
599
600            let clk = clocks::UartInstance::function_clock_source_frequency(config.clock_source);
601
602            // The UART baud rate clock divider is, depending on the device, either a
603            // 20.4 bit, or a 12.4 bit divider.
604            const FRAC_BITS: u32 = const {
605                let largest_divider: u32 =
606                    property!("clock_tree.uart.baud_rate_generator.fractional").1;
607                ::core::assert!((largest_divider + 1).is_power_of_two());
608                largest_divider.count_ones()
609            };
610            const FRAC_MASK: u32 = (1 << FRAC_BITS) - 1;
611
612            // TODO: this block should only prepare the new clock config, and it should
613            // be applied only after validating the resulting baud rate.
614            cfg_select! {
615                any(uart_has_sclk_divider, soc_has_pcr, esp32p4, esp32s31) => {
616                    const MAX_DIV: u32 =
617                        property!("clock_tree.uart.baud_rate_generator.integral").1;
618                    let clk_div = clk.div_ceil(MAX_DIV).div_ceil(config.baudrate);
619                    debug!("SCLK: {} divider: {}", clk, clk_div);
620
621                    let conf = ClockConfig::new(config.clock_source, clk_div - 1);
622                    let divider = (clk << FRAC_BITS) / (config.baudrate * clk_div);
623                }
624                _ => {
625                    debug!("SCLK: {}", clk);
626                    let conf = ClockConfig::new(config.clock_source);
627                    let divider = (clk << FRAC_BITS) / config.baudrate;
628                }
629            }
630
631            let divider_integer = divider >> FRAC_BITS;
632            let divider_frag = divider & FRAC_MASK;
633            debug!(
634                "UART CLK divider: {} + {}/16",
635                divider_integer, divider_frag
636            );
637
638            clock.configure_function_clock(clocks, conf);
639            clock.configure_baud_rate_generator(
640                clocks,
641                BaudRateConfig::new(divider_frag, divider_integer),
642            );
643
644            self.sync_regs();
645
646            #[cfg(feature = "unstable")]
647            {
648                let deviation_limit = match config.baudrate_tolerance {
649                    BaudrateTolerance::Exact => 1, // Still allow a tiny deviation
650                    BaudrateTolerance::ErrorPercent(percent) => percent as u32,
651                    _ => return Ok(()),
652                };
653
654                let actual_baud = clock.baud_rate_generator_frequency();
655                if actual_baud == 0 {
656                    return Err(ConfigError::BaudrateNotAchievable);
657                }
658
659                let deviation = (config.baudrate.abs_diff(actual_baud) * 100) / actual_baud;
660                debug!(
661                    "Nominal baud: {}, actual: {}, deviation: {}%",
662                    config.baudrate, actual_baud, deviation
663                );
664
665                if deviation > deviation_limit {
666                    return Err(ConfigError::BaudrateNotAchievable);
667                }
668            }
669
670            Ok(())
671        })
672    }
673
674    fn change_data_bits(&self, data_bits: DataBits) {
675        self.regs()
676            .conf0()
677            .modify(|_, w| unsafe { w.bit_num().bits(data_bits as u8) });
678    }
679
680    fn change_parity(&self, parity: Parity) {
681        self.regs().conf0().modify(|_, w| match parity {
682            Parity::None => w.parity_en().clear_bit(),
683            Parity::Even => w.parity_en().set_bit().parity().clear_bit(),
684            Parity::Odd => w.parity_en().set_bit().parity().set_bit(),
685        });
686    }
687
688    fn change_stop_bits(&self, stop_bits: StopBits) {
689        version::change_stop_bits(self, stop_bits);
690    }
691
692    fn change_flow_control(&self, sw_flow_ctrl: SwFlowControl, hw_flow_ctrl: HwFlowControl) {
693        version::change_flow_control(self, sw_flow_ctrl, hw_flow_ctrl);
694    }
695
696    pub(super) fn rxfifo_reset(&self) {
697        fn rxfifo_rst(reg_block: &RegisterBlock, enable: bool) {
698            reg_block.conf0().modify(|_, w| w.rxfifo_rst().bit(enable));
699            sync_regs(reg_block);
700        }
701
702        rxfifo_rst(self.regs(), true);
703        rxfifo_rst(self.regs(), false);
704    }
705
706    pub(super) fn txfifo_reset(&self) {
707        fn txfifo_rst(reg_block: &RegisterBlock, enable: bool) {
708            reg_block.conf0().modify(|_, w| w.txfifo_rst().bit(enable));
709            sync_regs(reg_block);
710        }
711
712        txfifo_rst(self.regs(), true);
713        txfifo_rst(self.regs(), false);
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}