From 5c4fffcea9dec327343c88d9d69abc8be8aa41b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 25 Jul 2023 19:45:24 +0200 Subject: [PATCH 1/4] Remove unnecessary Pin bounds --- esp-hal-common/src/rtc_cntl/rtc/esp32_sleep.rs | 6 +++--- esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs | 6 +++--- esp-hal-common/src/rtc_cntl/sleep.rs | 9 +++------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32_sleep.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32_sleep.rs index 0ebe8d09f84..f46b3fffbbf 100644 --- a/esp-hal-common/src/rtc_cntl/rtc/esp32_sleep.rs +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32_sleep.rs @@ -1,6 +1,6 @@ use super::{Ext0WakeupSource, Ext1WakeupSource, TimerWakeupSource, WakeSource, WakeTriggers}; use crate::{ - gpio::{Pin, RTCPin, RtcFunction}, + gpio::{RTCPin, RtcFunction}, rtc_cntl::{sleep::WakeupLevel, Clock, RtcClock}, Rtc, }; @@ -65,7 +65,7 @@ impl WakeSource for TimerWakeupSource { } } -impl WakeSource for Ext0WakeupSource<'_, P> { +impl WakeSource for Ext0WakeupSource<'_, P> { fn apply(&self, _rtc: &Rtc, triggers: &mut WakeTriggers, sleep_config: &mut RtcSleepConfig) { // don't power down RTC peripherals sleep_config.set_rtc_peri_pd_en(false); @@ -91,7 +91,7 @@ impl WakeSource for Ext0WakeupSource<'_, P> { } } -impl Drop for Ext0WakeupSource<'_, P> { +impl Drop for Ext0WakeupSource<'_, P> { fn drop(&mut self) { // should we have saved the pin configuration first? // set pin back to IO_MUX (input_enable and func have no effect when pin is sent diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs index 051b2841710..e4ecad30571 100644 --- a/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs @@ -7,7 +7,7 @@ use super::{ WakeupLevel, }; use crate::{ - gpio::{Pin, RTCPin, RtcFunction}, + gpio::{RTCPin, RtcFunction}, regi2c_write_mask, rtc_cntl::{Clock, RtcClock}, Rtc, @@ -110,7 +110,7 @@ impl WakeSource for TimerWakeupSource { } } -impl WakeSource for Ext0WakeupSource<'_, P> { +impl WakeSource for Ext0WakeupSource<'_, P> { fn apply(&self, _rtc: &Rtc, triggers: &mut WakeTriggers, sleep_config: &mut RtcSleepConfig) { // don't power down RTC peripherals sleep_config.set_rtc_peri_pd_en(false); @@ -136,7 +136,7 @@ impl WakeSource for Ext0WakeupSource<'_, P> { } } -impl Drop for Ext0WakeupSource<'_, P> { +impl Drop for Ext0WakeupSource<'_, P> { fn drop(&mut self) { // should we have saved the pin configuration first? // set pin back to IO_MUX (input_enable and func have no effect when pin is sent diff --git a/esp-hal-common/src/rtc_cntl/sleep.rs b/esp-hal-common/src/rtc_cntl/sleep.rs index 15692ce2357..a4c7989baea 100644 --- a/esp-hal-common/src/rtc_cntl/sleep.rs +++ b/esp-hal-common/src/rtc_cntl/sleep.rs @@ -21,10 +21,7 @@ use core::{cell::RefCell, time::Duration}; -use crate::{ - gpio::{Pin, RTCPin}, - Rtc, -}; +use crate::{gpio::RTCPin, Rtc}; #[cfg_attr(esp32, path = "rtc/esp32_sleep.rs")] #[cfg_attr(esp32s3, path = "rtc/esp32s3_sleep.rs")] @@ -58,12 +55,12 @@ pub enum Error { #[allow(unused)] #[derive(Debug)] -pub struct Ext0WakeupSource<'a, P: RTCPin + Pin> { +pub struct Ext0WakeupSource<'a, P: RTCPin> { pin: RefCell<&'a mut P>, level: WakeupLevel, } -impl<'a, P: RTCPin + Pin> Ext0WakeupSource<'a, P> { +impl<'a, P: RTCPin> Ext0WakeupSource<'a, P> { pub fn new(pin: &'a mut P, level: WakeupLevel) -> Self { Self { pin: RefCell::new(pin), From ca0d2186fd65c0574e5eda4584147293602745ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 25 Jul 2023 19:45:52 +0200 Subject: [PATCH 2/4] S3: Add RTC_IO wakeup source --- .../src/rtc_cntl/rtc/esp32s3_sleep.rs | 54 ++++++++++++++++++- esp-hal-common/src/rtc_cntl/sleep.rs | 18 +++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs index e4ecad30571..55fe6820984 100644 --- a/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32s3_sleep.rs @@ -9,7 +9,7 @@ use super::{ use crate::{ gpio::{RTCPin, RtcFunction}, regi2c_write_mask, - rtc_cntl::{Clock, RtcClock}, + rtc_cntl::{sleep::RtcioWakeupSource, Clock, RtcClock}, Rtc, }; @@ -191,6 +191,58 @@ impl Drop for Ext1WakeupSource<'_, '_> { } } +impl<'a, 'b> RtcioWakeupSource<'a, 'b> { + fn apply_pin(&self, pin: &mut dyn RTCPin, level: WakeupLevel) { + let rtcio = unsafe { &*crate::peripherals::RTC_IO::PTR }; + + pin.rtc_set_config(true, true, RtcFunction::Rtc); + + rtcio.pin[pin.number() as usize].modify(|_, w| { + w.wakeup_enable().set_bit().int_type().variant(match level { + WakeupLevel::Low => 4, + WakeupLevel::High => 5, + }) + }); + } +} + +impl WakeSource for RtcioWakeupSource<'_, '_> { + fn apply(&self, _rtc: &Rtc, triggers: &mut WakeTriggers, sleep_config: &mut RtcSleepConfig) { + let mut pins = self.pins.borrow_mut(); + + if pins.is_empty() { + return; + } + + // don't power down RTC peripherals + sleep_config.set_rtc_peri_pd_en(false); + triggers.set_gpio(true); + + // Since we only use RTCIO pins, we can keep deep sleep enabled. + let sens = unsafe { &*crate::peripherals::SENS::PTR }; + + // TODO: disable clock when not in use + sens.sar_peri_clk_gate_conf + .modify(|_, w| w.iomux_clk_en().set_bit()); + + for (pin, level) in pins.iter_mut() { + self.apply_pin(*pin, *level); + } + } +} + +impl Drop for RtcioWakeupSource<'_, '_> { + fn drop(&mut self) { + // should we have saved the pin configuration first? + // set pin back to IO_MUX (input_enable and func have no effect when pin is sent + // to IO_MUX) + let mut pins = self.pins.borrow_mut(); + for (pin, _level) in pins.iter_mut() { + pin.rtc_set_config(true, false, RtcFunction::Rtc); + } + } +} + bitfield::bitfield! { #[derive(Clone, Copy)] pub struct RtcSleepConfig(u64); diff --git a/esp-hal-common/src/rtc_cntl/sleep.rs b/esp-hal-common/src/rtc_cntl/sleep.rs index a4c7989baea..a70d9e40695 100644 --- a/esp-hal-common/src/rtc_cntl/sleep.rs +++ b/esp-hal-common/src/rtc_cntl/sleep.rs @@ -83,6 +83,24 @@ impl<'a, 'b> Ext1WakeupSource<'a, 'b> { } } +/// RTC_IO wakeup source +/// +/// RTC_IO wakeup allows configuring any combination of RTC_IO pins with +/// arbitrary wakeup levels to wake up the chip from sleep. This wakeup source +/// can be used to wake up from both light and deep sleep. +#[allow(unused)] +pub struct RtcioWakeupSource<'a, 'b> { + pins: RefCell<&'a mut [(&'b mut dyn RTCPin, WakeupLevel)]>, +} + +impl<'a, 'b> RtcioWakeupSource<'a, 'b> { + pub fn new(pins: &'a mut [(&'b mut dyn RTCPin, WakeupLevel)]) -> Self { + Self { + pins: RefCell::new(pins), + } + } +} + bitfield::bitfield! { #[derive(Default, Clone, Copy)] pub struct WakeTriggers(u16); From 5249ea6745fe025ca5d1a85e176603068229cbff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 25 Jul 2023 19:50:33 +0200 Subject: [PATCH 3/4] Add s3 example --- esp32s3-hal/examples/sleep_timer_rtcio.rs | 79 +++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 esp32s3-hal/examples/sleep_timer_rtcio.rs diff --git a/esp32s3-hal/examples/sleep_timer_rtcio.rs b/esp32s3-hal/examples/sleep_timer_rtcio.rs new file mode 100644 index 00000000000..e197cbf8741 --- /dev/null +++ b/esp32s3-hal/examples/sleep_timer_rtcio.rs @@ -0,0 +1,79 @@ +//! Demonstrates deep sleep with timer and ext0 (using gpio18) wakeup + +#![no_std] +#![no_main] + +use core::time::Duration; + +use esp32s3_hal as hal; +use esp_backtrace as _; +use esp_hal_common::{ + gpio::{RTCPin, RTCPinWithResistors}, + rtc_cntl::sleep::RtcioWakeupSource, +}; +use esp_println::println; +use hal::{ + clock::ClockControl, + entry, + peripherals::Peripherals, + prelude::*, + rtc_cntl::{ + get_reset_reason, + get_wakeup_cause, + sleep::{TimerWakeupSource, WakeupLevel}, + SocResetReason, + }, + timer::TimerGroup, + Delay, + Rtc, + IO, +}; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the RTC and TIMG watchdog timers + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new( + peripherals.TIMG0, + &clocks, + &mut system.peripheral_clock_control, + ); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new( + peripherals.TIMG1, + &clocks, + &mut system.peripheral_clock_control, + ); + let mut wdt1 = timer_group1.wdt; + + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let mut rtcio_pin18 = io.pins.gpio18; + + rtcio_pin18.rtcio_pad_hold(true); + rtcio_pin18.rtcio_pullup(true); + + println!("up and runnning!"); + let reason = get_reset_reason(hal::Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn); + println!("reset reason: {:?}", reason); + let wake_reason = get_wakeup_cause(); + println!("wake reason: {:?}", wake_reason); + + let mut delay = Delay::new(&clocks); + + let timer = TimerWakeupSource::new(Duration::from_secs(30)); + + let mut wakeup_pins: [(&mut dyn RTCPin, WakeupLevel); 1] = + [(&mut rtcio_pin18, WakeupLevel::Low)]; + let rtcio = RtcioWakeupSource::new(&mut wakeup_pins); + println!("sleeping!"); + delay.delay_ms(100u32); + rtc.sleep_deep(&[&timer, &rtcio], &mut delay); +} From 3b9940f0970cef95dafbe35cd2f3595f0df34575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 25 Jul 2023 19:51:05 +0200 Subject: [PATCH 4/4] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16dc67501e6..a539026ad89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add GPIO (output) and delay functionality to `esp32c6-lp-hal` (#715) - Implement RTCIO pullup, pulldown and hold control for Xtensa MCUs (#684) - Add GPIO input support and implement additional `embedded-hal` output traits for the C6's LP core [#720] +- S3: Implement RTCIO wakeup source (#690) ### Changed