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#[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 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 self.uart.enable_listen_tx(self.events, false);
194 }
195}
196
197#[ram]
202pub(super) fn intr_handler(uart: &Info, state: &State) {
203 let interrupts = uart.regs().int_st().read();
204 let interrupt_bits = interrupts.bits(); 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
227pub trait Instance: crate::private::Sealed + any::Degrade {
229 #[doc(hidden)]
230 fn parts(&self) -> (&'static Info, &'static State);
232
233 #[inline(always)]
235 #[doc(hidden)]
236 fn info(&self) -> &'static Info {
237 self.parts().0
238 }
239
240 #[inline(always)]
242 #[doc(hidden)]
243 fn state(&self) -> &'static State {
244 self.parts().1
245 }
246}
247
248#[doc(hidden)]
250#[non_exhaustive]
251#[allow(private_interfaces, reason = "Unstable details")]
252pub struct Info {
253 pub register_block: *const RegisterBlock,
257
258 pub peripheral: crate::system::Peripheral,
260
261 pub clock_instance: clocks::UartInstance,
263
264 pub async_handler: InterruptHandler,
266
267 pub tx_signal: OutputSignal,
269
270 pub rx_signal: InputSignal,
272
273 pub cts_signal: InputSignal,
275
276 pub rts_signal: OutputSignal,
278
279 #[cfg(sleep_driver_supported)]
281 pub wakeup_source: Option<crate::rtc_cntl::WakeupSource>,
282}
283
284#[doc(hidden)]
286#[non_exhaustive]
287pub struct State {
288 pub rx_waker: AtomicWaker,
290
291 pub tx_waker: AtomicWaker,
293
294 pub is_rx_async: AtomicBool,
296
297 pub is_tx_async: AtomicBool,
299}
300
301impl Info {
302 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 pub fn regs(&self) -> &RegisterBlock {
310 unsafe { &*self.register_block }
311 }
312
313 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 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 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 #[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 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 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 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 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 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, 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 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 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 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 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 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 #[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 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 #[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#[cfg(sleep_driver_supported)]
878#[crate::ram]
879fn keep_peripherals_powered(config: &mut crate::rtc_cntl::sleep::WrappedSleepConfig<'_>) {
880 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
895macro_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 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}