Skip to content

Commit

Permalink
Add GPIO as wake-up source (#1724)
Browse files Browse the repository at this point in the history
* Add GPIO as wake-up source

* CHANGELOG.md

* Clippy

* Doc fix
  • Loading branch information
bjoernQ authored Jun 28, 2024
1 parent 347ef51 commit 8cb921f
Show file tree
Hide file tree
Showing 4 changed files with 71 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 @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add DmaTransactionTxOwned, DmaTransactionRxOwned, DmaTransactionTxRxOwned, functions to do owning transfers added to SPI half-duplex (#1672)
- 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)

### Fixed

Expand Down
2 changes: 2 additions & 0 deletions esp-hal/src/gpio/any_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ impl<'d> Pin for AnyPin<'d> {
fn unlisten(&mut self, _internal: private::Internal);
fn is_interrupt_set(&self, _internal: private::Internal) -> bool;
fn clear_interrupt(&mut self, _internal: private::Internal);
fn wakeup_enable(&mut self, enable: bool, event: WakeEvent, _internal: private::Internal);
}
}
}
Expand Down Expand Up @@ -260,6 +261,7 @@ impl<'d> Pin for AnyInputOnlyPin<'d> {
fn unlisten(&mut self, _internal: private::Internal);
fn is_interrupt_set(&self, _internal: private::Internal) -> bool;
fn clear_interrupt(&mut self, _internal: private::Internal);
fn wakeup_enable(&mut self, enable: bool, event: WakeEvent, _internal: private::Internal);
}
}
}
Expand Down
40 changes: 40 additions & 0 deletions esp-hal/src/gpio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,25 @@ pub enum Event {
HighLevel = 5,
}

impl From<WakeEvent> for Event {
fn from(value: WakeEvent) -> Self {
match value {
WakeEvent::LowLevel => Event::LowLevel,
WakeEvent::HighLevel => Event::HighLevel,
}
}
}

/// Event used to wake up from light sleep.
#[derive(Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum WakeEvent {
/// Wake on low level
LowLevel = 4,
/// Wake on high level
HighLevel = 5,
}

/// Digital input or output level.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
Expand Down Expand Up @@ -227,6 +246,9 @@ pub trait Pin: private::Sealed {

/// Clear the interrupt status bit for this Pin
fn clear_interrupt(&mut self, _: private::Internal);

/// Enable this pin as a wake up source
fn wakeup_enable(&mut self, enable: bool, event: WakeEvent, _: private::Internal);
}

/// Trait implemented by pins which can be used as inputs
Expand Down Expand Up @@ -862,6 +884,10 @@ where
fn clear_interrupt(&mut self, _: private::Internal) {
<Self as GpioProperties>::Bank::write_interrupt_status_clear(1 << (GPIONUM % 32));
}

fn wakeup_enable(&mut self, enable: bool, event: WakeEvent, _: private::Internal) {
self.listen_with_options(event.into(), false, false, enable, private::Internal);
}
}

impl<const GPIONUM: u8> GpioPin<GPIONUM>
Expand Down Expand Up @@ -1672,6 +1698,14 @@ where
pub fn clear_interrupt(&mut self) {
self.pin.clear_interrupt(private::Internal);
}

/// Enable as a wake-up source.
///
/// This will unlisten for interrupts
#[inline]
pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) {
self.pin.wakeup_enable(enable, event, private::Internal);
}
}

/// GPIO open-drain output driver.
Expand Down Expand Up @@ -2302,6 +2336,12 @@ pub(crate) mod internal {
Pin::clear_interrupt(target, private::Internal)
})
}

fn wakeup_enable(&mut self, enable: bool, event: WakeEvent, _: private::Internal) {
handle_gpio_input!(self, target, {
Pin::wakeup_enable(target, enable, event, private::Internal)
})
}
}

impl InputPin for ErasedPin {
Expand Down
28 changes: 28 additions & 0 deletions esp-hal/src/rtc_cntl/sleep/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,34 @@ impl Default for WakeFromLpCoreWakeupSource {
}
}

/// GPIO wakeup source
///
/// Wake up from GPIO high or low level. Any pin can be used with this wake up
/// source. Configure the pin for wake up via
/// [crate::gpio::Input::wakeup_enable].
///
/// This wakeup source can be used to wake up from light sleep only.
pub struct GpioWakeupSource {}

impl GpioWakeupSource {
/// Create a new instance of [GpioWakeupSource]
pub fn new() -> Self {
Self {}
}
}

impl Default for GpioWakeupSource {
fn default() -> Self {
Self::new()
}
}

impl WakeSource for GpioWakeupSource {
fn apply(&self, _rtc: &Rtc, triggers: &mut WakeTriggers, _sleep_config: &mut RtcSleepConfig) {
triggers.set_gpio(true);
}
}

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

0 comments on commit 8cb921f

Please sign in to comment.