Skip to content

deep sleep api for esp32 #574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jul 14, 2023
Merged

deep sleep api for esp32 #574

merged 20 commits into from
Jul 14, 2023

Conversation

liebman
Copy link
Contributor

@liebman liebman commented Jun 3, 2023

This is an implementation of deep and light sleep for esp32. Included is a minimal implementation of RTCPin for RTC GPIO pins for Xtensa chips.

Wakeup sources implemented:

  • Timer - wake from sleep via RTC Timer
  • Ext0 - wake from sleep via single RTCPin
  • Ext1 - wake from sleep via one or more RTCPin

Examples for wake up:

  • esp32/examples/sleep_timer.rs
  • esp32/examples/sleep_timer_ext0.rs
  • esp32/examples/sleep_timer_ext1.rs

Most of the settings for sleep were pulled from esp-idf or gleaned by comparing register settings between esp-idf-hal and esp32-hal directly after an initial boot and after wakeup from sleep. Note in particular RtcSleepConfig::base_settings which are the RTC_CTRL differences after boot between esp-idf-hal and esp32-hal.

In Deep sleep I'm seeing about 0.15mA with a ESP32-WROOM32 module on a custom board.

Thank you!

Thank you for your contribution.
Please make sure that your submission includes the following:

Must

  • The code compiles without errors or warnings.
  • All examples work.
  • cargo fmt was run.
  • Your changes were added to the CHANGELOG.md in the proper section.
  • You updated existing examples or added examples (if applicable).
  • Added examples are checked in CI

Nice to have

  • You add a description of your work to this PR.
  • You added proper docs for your newly added features and code.

@jessebraham
Copy link
Member

Thanks for working on this, looking forward to it being ready for review! Please let me know if there is anything we can do to support you in the meantime.

@liebman
Copy link
Contributor Author

liebman commented Jun 6, 2023

@jessebraham I'd love thoughts on what the API should be - particularly with respect to ownership, for instance when you're going to wake using ext0 (RTC GPIO pin) the pin needs to be setup to be routed to RTC - and set in the RTC_IO ext_wakeup0 register - should that be handled in sleep or should that be separately managed by the user?

@liebman liebman force-pushed the esp32-sleep branch 2 times, most recently from b48671f to 31ba351 Compare June 11, 2023 16:36
@liebman liebman marked this pull request as ready for review June 11, 2023 16:44
@bugadani
Copy link
Contributor

Disclaimer: I'm just shouting in from the sidelines.

That is actually pretty nice, good job!

For what it's worth, I think I would still prefer if creating a wakeup source would immediately configure it. It wouldn't be hard from here - make the user create the WakeupTriggers object, then pass it to each WakeupSource constructor that immediately applies itself (or not if you want them reusable). Then, WakeupTriggers could be used to start the sleep, maybe.

The only difference would be that this way we wouldn't require dyn which I believe doesn't optimize pretty well. I'm not sure in this particular case which should be pretty simple but I think LLVM hasn't been particularly skilled in removing vtables at least a few releases ago.

@liebman
Copy link
Contributor Author

liebman commented Jun 11, 2023

I think I need to implement Drop for Ext0WakeupSource to at least set the pin back to the IO_MUX. Should i save the values for anything that I change to be restored at Drop?

@liebman
Copy link
Contributor Author

liebman commented Jun 12, 2023

For what it's worth, I think I would still prefer if creating a wakeup source would immediately configure it. It wouldn't be hard from here - make the user create the WakeupTriggers object, then pass it to each WakeupSource constructor that immediately applies itself (or not if you want them reusable). Then, WakeupTriggers could be used to start the sleep, maybe.

The only difference would be that this way we wouldn't require dyn which I believe doesn't optimize pretty well. I'm not sure in this particular case which should be pretty simple but I think LLVM hasn't been particularly skilled in removing vtables at least a few releases ago.

I like this idea, however I have some concerns: (apologies in advance for the rambling below)

There is also a RtcSleepConfig instance that would need to be passed in to apply. We could add WakeupTriggers to it.
This tracks what parts can be powered down during sleep and what is required to remain powered - and wake sources adjust this on apply. For instance Ext0 keeps the RTC Peripherals powered during sleep.

Also - what should happen if the a WakeSource instance dropped after it had been applied and before the sleep? We would need to undo the changes to RtcSleepConfig as well and if more than one wake source needs a particular setting how do you know when it can be undone.

Maybe make the apply method from the wake source return a RtcSleepConfig? Then the sleep method could take an array of RtcSleepConfig and apply them at sleep time. (still we have the issue of what to do when one was dropped before sleep....

EDIT: maybe make a SleepConfig like this?

pub struct SleepConfig {
    timer: Option<&TimerWakeupSource>,
    ext0: Option<&Ext0WakeupSource>,
}

To be passed to sleep() instead of the array.

@liebman
Copy link
Contributor Author

liebman commented Jun 16, 2023

well

#[derive(Default)]
pub struct SleepConfig<'a, P: RTCPin + Pin> {
    pub timer: Option<TimerWakeupSource>,
    pub ext0: Option<Ext0WakeupSource<'a, P>>,
}

has the issue that you have to specify a type for P even if ext0 is being set to None - we'd have to type erase it using dyn...

@bugadani
Copy link
Contributor

bugadani commented Jun 16, 2023

You can do a trick like I did in the object-chain crate, where you build up a type in compile time. It will not be very nice, though, and not very flexible.

@bjoernQ
Copy link
Contributor

bjoernQ commented Jul 13, 2023

My two cents: This looks already good and maybe we should just get it in a mergeable shape (checking comments and documentation) and merge it. Then the community can iterate on the API based on real use cases

I don't think having breaking API changes here in the future is going to be a big problem (like we currently have them everywhere)

@jessebraham
Copy link
Member

jessebraham commented Jul 13, 2023

I'm sort of leaning towards what @bjoernQ has said as well. We can nitpick the API as much as we want, but I think this is very useful already in its current state and we can open issues for any problems which have been identified. I'd prefer to have an imperfect solution than no solution at all :)

(Also I'm sorry it's taken us so long to come to this conclusion!)

I think if you're able to please rebase then this is probably pretty much good to go.

@bugadani
Copy link
Contributor

(Also I'm sorry it's taken us so long to come to this conclusion!)

Sorry for being a cause of delay here. I have some interest in adapting this PR to the S3, so I'd second getting this merged sooner than later.

Copy link
Contributor

@bjoernQ bjoernQ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - just want to wait for Jesse's approval before merging

Copy link
Member

@jessebraham jessebraham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you once again for all your work on this, LGTM!

@jessebraham jessebraham merged commit 37466fd into esp-rs:main Jul 14, 2023
@bugadani bugadani mentioned this pull request Jul 20, 2023
playfulFence pushed a commit to playfulFence/esp-hal that referenced this pull request Sep 26, 2023
* deep sleep api for esp32

* move to list of wakeup sources

* improve Ext0WakeupSource - still WIP

* add deep sleep with timer wakeup example
add Ext0 wakeup source (WIP/Non-working)

* removed alloc (using heapless now)

* Sleep: ext0 wakeup working

* add sleep_timer_ext0 example

* API change: move sleep into RTC as sleep, sleep_deep, sleep_light

* fix sleep examples for new API

* sleep only implemented for esp32 at this time

* sleep only implemented for esp32 at this time

* Implement a simple RTCPin trait to support sleep

* implement RTCPin for all xtensa SOC

* cargo fmt & update changelog

* fix change log order (accidentally swaped during rebase)

* implement Drop for Ext0WakeupSource

* added Ext1 wakeup source

* cargo fmt

* healpess was unused, removed

* fix pase macro usage
@dimpolo
Copy link
Contributor

dimpolo commented Dec 6, 2023

Hi, sorry for commenting on this closed issue.
What is the reason for the 100ms delay before going to sleep?

@liebman
Copy link
Contributor Author

liebman commented Dec 6, 2023

Hi, sorry for commenting on this closed issue. What is the reason for the 100ms delay before going to sleep?

In the examples? To make sure the print messages are sent before the UART is powered down.

@dimpolo
Copy link
Contributor

dimpolo commented Dec 6, 2023

Hi, sorry for commenting on this closed issue. What is the reason for the 100ms delay before going to sleep?

In the examples? To make sure the print messages are sent before the UART is powered down.

Sorry, I meant here: https://github.com/liebman/esp-hal/blob/a2b0941001a95366759009c3206b980423769e9e/esp-hal-common/src/rtc_cntl/mod.rs#L239

@liebman
Copy link
Contributor Author

liebman commented Dec 9, 2023

Hi, sorry for commenting on this closed issue. What is the reason for the 100ms delay before going to sleep?

In the examples? To make sure the print messages are sent before the UART is powered down.

Sorry, I meant here: https://github.com/liebman/esp-hal/blob/a2b0941001a95366759009c3206b980423769e9e/esp-hal-common/src/rtc_cntl/mod.rs#L239

I'd have to assume then that this was left in by mistake. Please open an issue so we don't loose track of this.

@liebman liebman deleted the esp32-sleep branch January 26, 2025 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants