Skip to content

Commit

Permalink
Add UART wakeup source (esp-rs#1727)
Browse files Browse the repository at this point in the history
* Add UART wakeup source

* CHANGELOG.md
  • Loading branch information
bjoernQ authored Jul 1, 2024
1 parent 3af45a2 commit 40810a5
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
1 change: 1 addition & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- uart: Implement `embedded_io::ReadReady` for `Uart` and `UartRx` (#1702)
- ESP32-C6: Support lp-core as wake-up source (#1723)
- Add support for GPIO wake-up source (#1724)
- Add `uart` wake source (#1727)

### Fixed

Expand Down
65 changes: 65 additions & 0 deletions esp-hal/src/rtc_cntl/sleep/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,71 @@ impl WakeSource for GpioWakeupSource {
}
}

macro_rules! uart_wakeup_impl {
($num:literal) => {
paste::paste! {
#[doc = concat!("UART", $num, " wakeup source")]
///
/// The chip can be woken up by reverting RXD for multiple cycles until the
/// number of rising edges is equal to or greater than the given value.
///
/// Note that the character which triggers wakeup (and any characters before
/// it) will not be received by the UART after wakeup. This means that the
/// external device typically needs to send an extra character to trigger
/// wakeup before sending the data.
///
/// After waking-up from UART, you should send some extra data through the UART
/// port in Active mode, so that the internal wakeup indication signal can be
/// cleared. Otherwise, the next UART wake-up would trigger with two less
/// rising edges than the configured threshold value.
///
/// Wakeup from light sleep takes some time, so not every character sent to the
/// UART can be received by the application.
///
/// This wakeup source can be used to wake up from light sleep only.
pub struct [< Uart $num WakeupSource >] {
threshold: u16,
}

impl [< Uart $num WakeupSource >] {
#[doc = concat!("Create a new instance of UART", $num, " wakeup source>") ]
///
/// # Panics
///
/// Panics if `threshold` is out of bounds.
pub fn new(threshold: u16) -> Self {
if threshold > 1023 {
panic!("Invalid threshold");
}
Self { threshold }
}
}

impl WakeSource for [< Uart $num WakeupSource >] {
fn apply(&self, _rtc: &Rtc, triggers: &mut WakeTriggers, _sleep_config: &mut RtcSleepConfig) {
triggers.[< set_uart $num >](true);
let uart = unsafe { crate::peripherals::[< UART $num >]::steal() };

#[cfg(any(esp32, esp32s2, esp32s3, esp32c2, esp32c3))]
uart.sleep_conf()
.modify(|_, w| unsafe { w.active_threshold().bits(self.threshold) });

#[cfg(not(any(esp32, esp32s2, esp32s3, esp32c2, esp32c3)))]
uart.sleep_conf2().modify(|_, w| unsafe {
w.wk_mode_sel()
.bits(0)
.active_threshold()
.bits(self.threshold)
});
}
}
}
};
}

uart_wakeup_impl!(0);
uart_wakeup_impl!(1);

#[cfg(not(pmu))]
bitfield::bitfield! {
#[derive(Default, Clone, Copy)]
Expand Down

0 comments on commit 40810a5

Please sign in to comment.