Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
API change: move sleep into RTC as sleep, sleep_deep, sleep_light
  • Loading branch information
liebman committed Jul 14, 2023
commit c81f9d09ae257d31093a52c3460c017c69624cc0
52 changes: 52 additions & 0 deletions esp-hal-common/src/rtc_cntl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use fugit::HertzU32;
use fugit::MicrosDurationU64;

pub use self::rtc::SocResetReason;
use self::sleep::{RtcSleepConfig, WakeSource};
#[cfg(not(any(esp32c6, esp32h2)))]
use crate::clock::XtalClock;
#[cfg(not(esp32))]
Expand All @@ -18,6 +19,7 @@ use crate::{
clock::Clock,
peripheral::{Peripheral, PeripheralRef},
reset::{SleepSource, WakeupReason},
rtc_cntl::sleep::WakeTriggers,
Cpu,
};

Expand Down Expand Up @@ -195,6 +197,56 @@ impl<'d> Rtc<'d> {
pub fn get_time_ms(&self) -> u64 {
self.get_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64
}

/// enter deep sleep and wake with the provided `wake_sources`
pub fn sleep_deep<'a>(
&mut self,
wake_sources: &[&'a dyn WakeSource],
delay: &mut crate::Delay,
) -> ! {
let config = RtcSleepConfig::deep();
self.sleep(&config, wake_sources, delay);
unreachable!();
}
pub fn sleep_light<'a>(
&mut self,
wake_sources: &[&'a dyn WakeSource],
delay: &mut crate::Delay,
) {
let config = RtcSleepConfig::default();
self.sleep(&config, wake_sources, delay)
}
pub fn sleep<'a>(
&mut self,
config: &RtcSleepConfig,
wake_sources: &[&'a dyn WakeSource],
delay: &mut crate::Delay,
) {
let mut config = config.clone();
let mut wakeup_triggers = WakeTriggers::default();
for wake_source in wake_sources {
wake_source.apply(self, &mut wakeup_triggers, &mut config)
}
config.apply(self);
use embedded_hal::blocking::delay::DelayMs;
delay.delay_ms(100u32);
unsafe {
let rtc_cntl = &*RTC_CNTL::ptr();

rtc_cntl
.reset_state
.modify(|_, w| w.procpu_stat_vector_sel().set_bit());

// set bits for what can wake us up
rtc_cntl
.wakeup_state
.modify(|_, w| w.wakeup_ena().bits(wakeup_triggers.0.into()));

rtc_cntl
.state0
.write(|w| w.sleep_en().set_bit().slp_wakeup().set_bit());
}
}
}

#[cfg(not(any(esp32c6, esp32h2)))]
Expand Down
11 changes: 5 additions & 6 deletions esp-hal-common/src/rtc_cntl/rtc/esp32_sleep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
pub const RTC_CK8M_ENABLE_WAIT_DEFAULT: u8 = 5;

impl WakeSource for TimerWakeupSource {
fn add(&self, _sleep_config: &mut RtcSleepConfig) {}
fn prepare(&self, rtc: &Rtc, triggers: &mut WakeTriggers) {
fn apply(&self, rtc: &Rtc, triggers: &mut WakeTriggers, _sleep_config: &mut RtcSleepConfig) {
triggers.set_timer(true);
let rtc_cntl = unsafe { &*esp32::RTC_CNTL::ptr() };
let clock_freq = RtcClock::get_slow_freq();
Expand All @@ -66,10 +65,9 @@ impl WakeSource for TimerWakeupSource {
}

impl<'a, P: Pin> WakeSource for Ext0WakeupSource<'a, P> {
fn add(&self, sleep_config: &mut RtcSleepConfig) {
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);
}
fn prepare(&self, _rtc: &Rtc, triggers: &mut WakeTriggers) {
triggers.set_ext0(true);
let pin = self.to_rtc_pin().unwrap();
unsafe {
Expand Down Expand Up @@ -236,6 +234,7 @@ impl<'a, P: Pin> WakeSource for Ext0WakeupSource<'a, P> {
}

bitfield::bitfield! {
#[derive(Clone, Copy)]
pub struct RtcSleepConfig(u32);
impl Debug;
/// force normal voltage in sleep mode (digital domain memory)
Expand Down Expand Up @@ -373,7 +372,7 @@ impl RtcSleepConfig {
}
}

pub(super) fn apply(&self, rtc: &Rtc) {
pub(crate) fn apply(&self, rtc: &Rtc) {
self.base_settings(rtc);
// like esp-idf rtc_sleep_init()
unsafe {
Expand Down
98 changes: 2 additions & 96 deletions esp-hal-common/src/rtc_cntl/sleep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use crate::{gpio::Pin, Rtc};

#[cfg_attr(esp32, path = "rtc/esp32_sleep.rs")]
mod rtc_sleep;
#[cfg(esp32)]
use esp32 as pac;
pub use rtc_sleep::*;

#[derive(Debug, Default, Clone, Copy, PartialEq)]
Expand Down Expand Up @@ -69,24 +67,7 @@ impl<'a, P: Pin> Ext0WakeupSource<'a, P> {
}
}
}
// RTCIO_GPIO0_CHANNEL, //GPIO0
// RTCIO_GPIO2_CHANNEL, //GPIO2
// RTCIO_GPIO4_CHANNEL, //GPIO4
// RTCIO_GPIO12_CHANNEL, //GPIO12
// RTCIO_GPIO13_CHANNEL, //GPIO13
// RTCIO_GPIO14_CHANNEL, //GPIO14
// RTCIO_GPIO15_CHANNEL, //GPIO15
// RTCIO_GPIO25_CHANNEL, //GPIO25
// RTCIO_GPIO26_CHANNEL, //GPIO26
// RTCIO_GPIO27_CHANNEL, //GPIO27
// RTCIO_GPIO32_CHANNEL, //GPIO32
// RTCIO_GPIO33_CHANNEL, //GPIO33
// RTCIO_GPIO34_CHANNEL, //GPIO34
// RTCIO_GPIO35_CHANNEL, //GPIO35
// RTCIO_GPIO36_CHANNEL, //GPIO36
// RTCIO_GPIO37_CHANNEL, //GPIO37
// RTCIO_GPIO38_CHANNEL, //GPIO38
// RTCIO_GPIO39_CHANNEL, //GPIO39

bitfield::bitfield! {
#[derive(Default, Clone, Copy)]
pub struct WakeTriggers(u16);
Expand Down Expand Up @@ -116,80 +97,5 @@ bitfield::bitfield! {
}

pub trait WakeSource {
fn add(&self, sleep_config: &mut RtcSleepConfig);
fn prepare(&self, rtc: &Rtc, triggers: &mut WakeTriggers);
}

pub struct Sleep<'a> {
sleep_config: RtcSleepConfig,
wake_sources: heapless::Vec<&'a dyn WakeSource, 16>,
}

impl core::fmt::Debug for Sleep<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Sleep")
.field("sleep_config", &self.sleep_config)
.field(
"wake_sources",
&format_args!("#{}", self.wake_sources.len()),
)
.finish()
}
}

impl<'a> Default for Sleep<'a> {
fn default() -> Self {
Self {
sleep_config: Default::default(),
wake_sources: Default::default(),
}
}
}
impl<'a> Sleep<'a> {
pub fn new() -> Self {
Self {
..Default::default()
}
}

pub fn deep() -> Self {
Self {
sleep_config: RtcSleepConfig::deep(),
..Default::default()
}
}

pub fn add_wakeup_source(&mut self, wake_source: &'a impl WakeSource) -> Result<(), Error> {
wake_source.add(&mut self.sleep_config);
self.wake_sources
.push(wake_source)
.map_err(|_| Error::TooManyWakeupSources)?;
Ok(())
}

pub fn sleep(&mut self, rtc: &mut Rtc, delay: &mut crate::Delay) {
self.sleep_config.apply(rtc);
let mut wakeup_triggers = WakeTriggers::default();
for wake_source in &self.wake_sources {
wake_source.prepare(rtc, &mut wakeup_triggers)
}
use embedded_hal::blocking::delay::DelayMs;
delay.delay_ms(100u32);
unsafe {
let rtc_cntl = &*pac::RTC_CNTL::ptr();

rtc_cntl
.reset_state
.modify(|_, w| w.procpu_stat_vector_sel().set_bit());

// set bits for what can wake us up
rtc_cntl
.wakeup_state
.modify(|_, w| w.wakeup_ena().bits(wakeup_triggers.0.into()));

rtc_cntl
.state0
.write(|w| w.sleep_en().set_bit().slp_wakeup().set_bit());
}
}
fn apply(&self, rtc: &Rtc, triggers: &mut WakeTriggers, sleep_config: &mut RtcSleepConfig);
}