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#[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 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 self.uart.enable_listen_tx(self.events, false);
197 }
198}
199
200#[ram]
205pub(super) fn intr_handler(uart: &Info, state: &State) {
206 let interrupts = uart.regs().int_st().read();
207 let interrupt_bits = interrupts.bits(); 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
230pub trait Instance: crate::private::Sealed + any::Degrade {
232 #[doc(hidden)]
233 fn parts(&self) -> (&'static Info, &'static State);
235
236 #[inline(always)]
238 #[doc(hidden)]
239 fn info(&self) -> &'static Info {
240 self.parts().0
241 }
242
243 #[inline(always)]
245 #[doc(hidden)]
246 fn state(&self) -> &'static State {
247 self.parts().1
248 }
249}
250
251#[doc(hidden)]
253#[non_exhaustive]
254#[allow(private_interfaces, reason = "Unstable details")]
255pub struct Info {
256 pub register_block: *const RegisterBlock,
260
261 pub peripheral: crate::system::Peripheral,
263
264 pub clock_instance: clocks::UartInstance,
266
267 pub async_handler: InterruptHandler,
269
270 pub tx_signal: OutputSignal,
272
273 pub rx_signal: InputSignal,
275
276 pub cts_signal: InputSignal,
278
279 pub rts_signal: OutputSignal,
281
282 #[cfg(sleep_driver_supported)]
284 pub wakeup_source: Option<crate::rtc_cntl::WakeupSource>,
285}
286
287#[doc(hidden)]
289#[non_exhaustive]
290pub struct State {
291 pub rx_waker: AtomicWaker,
293
294 pub tx_waker: AtomicWaker,
296
297 pub is_rx_async: AtomicBool,
299
300 pub is_tx_async: AtomicBool,
302}
303
304impl Info {
305 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 pub fn regs(&self) -> &RegisterBlock {
313 unsafe { &*self.register_block }
314 }
315
316 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 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 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 #[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 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 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 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 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 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, 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 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}