Skip to content

STM32: Alarms and sleep #4388

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 23 commits into from
May 13, 2021
Merged

STM32: Alarms and sleep #4388

merged 23 commits into from
May 13, 2021

Conversation

hierophect
Copy link
Collaborator

@hierophect hierophect commented Mar 11, 2021

This PR adds light and deep sleep to the STM32 port. It makes minor changes to the internal APIs to match other pin-using modules, and includes changes to the STM32 peripheral structure to support new EXTI and RTC functionality.

Implemented features:

  • Extract EXTI from the PulseIn module and create /peripherals module
  • Extract RTC from Port and create /peripherals module
  • Light sleep via EXTI and RTC
  • Deep sleep via the WakeUp pin (PA00 only) and RTC
  • Changes all pin objects used by PinAlarm (across all ports) to use const, matching DigitalIO and similar modules.

The STM32 does not have a specialized Touch module, so TouchAlarm is not implemented. SleepMemory is not currently included, but will be in a follow-up PR.

@hierophect hierophect requested a review from dhalbert March 11, 2021 23:10
@hierophect
Copy link
Collaborator Author

hierophect commented Mar 21, 2021

sleep diagram

@dhalbert
Copy link
Collaborator

However, true deep sleep seems to not work with a lot of the alarm systems I use in fake deep sleep, is hard to log, and frequently disconnects my Jlink. The RTC also seems to retain problems across resets, so the chip also needs to be power cycled to get back up and running again, which further complicates things. I'd appreciate any other pairs of eyes on the problem.

I'm confused; is this problem now gone?

@dhalbert
Copy link
Collaborator

I'malso curious whether we should consider renaming the functionality of common_hal_alarm_light_sleep_until_alarms to simply common_hal_alarm_wait_until_alarms, since it doesn't really sleep any more than the circuitpython default, and try to fold more power saving into common_hal_alarm_light_sleep_until_alarms. STM32's STOP mode might be a good fit for this, as would the ESP32S2 light sleep feature.

The nRF52 sleep PR does have a true light sleep, so I think we could keep it. But it sounds like you're thinking there might be a "medium sleep" feature, which does take down certain peripherals and things like wifi.

@hierophect
Copy link
Collaborator Author

hierophect commented Mar 23, 2021

@dhalbert sorry Dan, I hadn't updated the original PR message since I fixed my issues. My original thinking was that the term "light sleep" might be better suited to more power saving tasks, since the ESP32S2 light sleep saves no power compared to time.sleep, and I thought the same would be true for STM32. But since Scott argued that we can still put in manual clock gating into other ports, I think our current situation is fine.

I wouldn't be opposed to nailing down some official guidelines before I get into the RP2040 stuff. Each port defines light and deep sleep to mean different things so we're on our own for defining exactly what we want the terms to mean.

As far as I understand things:

  • ESP32S2
    • light sleep: says it should only be clock gating things, but in practice it irrecoverably shuts down things like WIFI, so we can't treat it as clock gating
    • deep sleep: power gates all peripherals and ram
  • STM32:
    • sleep: just another word for WFI, saves basically no power compared to time.sleep
    • stop: clock gates all peripherals but the RTC, but loses no state. The HSE oscillator is turned off entirely to save power. Things like UART would be temporarily disabled.
    • standby: power gates all peripherals but the RTC
  • RP2040
    • sleep: allows independent clock gating of peripherals, but presumably does not turn off the HSE since you have the option of leaving them all
    • dormant: power gates peripherals

NRF I'm less confident defining one way or the other, you would know in more detail.

Deep sleep is pretty similar across all cases, so we can just define that as power gating and leave it at that. For light sleep we could do one of a couple definitions:

  • Do all possible power savings with clock gating, without powering anything down, losing any state, or disabling any desired peripherals. For STM32, this means we wouldn't be able to use STOP since turning off the HSE disables all peripherals without exception. Manually shutting down clocks could save a little power on STM32, ESP32-S2 doesn't save any power at all compared to regular running. This is what I'm assuming is our current definition.
  • Do all possible power savings with clock gating, without any state loss, with peripheral shutdown. Saves extra power on the STM32 via STOP, if I could find a power switch for the RP2040 HSE that might be viable too, still doesn't save anything on ESP32-S2 because it can't recover WIFI.
  • Do all possible power savings without powering off the regulator, accepting some permanent state loss. Would allow light sleep on the ESP32-S2.

We could potentially make either of the latter two options into "medium sleep" if the power savings ended up being significant. It might be justifiable if they'd lead to significant weeks/months of runtime on a single battery charge without losing collections of active data in RAM. But if I can get some good power savings out of regular light sleep with manual power gating, I don't think it'll be very high priority to spend extra effort just to turn off the HSE. I think this is what Scott was getting at after the meeting.

@hierophect hierophect marked this pull request as ready for review April 2, 2021 21:25
@hierophect
Copy link
Collaborator Author

@dhalbert this is (finally) finished and ready for review, whenever you have time. In particular, note the changes in 9240146, which handles the light sleep object assignment problem we talked about (not yet fixed for ESP32-S2).

@hierophect
Copy link
Collaborator Author

I've re-tested this with all the new 7.0.0 and NRF stuff merged in - all sleep types and modules are still working.

H7 compatibility problems in port.c and peripherals/exti
NRF build failures due to new use of const for PinAlarm pin objects
Isolated board flash overage on blackpill_with_flash, remove audio modules
@hierophect hierophect requested a review from jepler April 30, 2021 15:04
@dhalbert
Copy link
Collaborator

@hierophect Could you merge from upstream and fix the conflicts and also look at the few failed builds (looks like a missing include?)?

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

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

Sorry for the delay in reviewing this.
frozen/Adafruit_CircuitPython_HID and Adafruit_CircuitPython_SimpleMath should not be changing. They are probably behind the current versions. You might want to merge from upstream and then recheck these. You may need to pull them ahead by hand; make them match what is in main.

Do a make translate after you merge from upstream as well.

Thanks for all the commenting.

I did not test this on hardware, but I know you've done that extensively. I don't know the STM well enough to vet the details of the wakeup pin handling, etc., so I also did not check that. Again, your testing is the proof.

@hierophect
Copy link
Collaborator Author

frozen/Adafruit_CircuitPython_HID and Adafruit_CircuitPython_SimpleMath should not be changing. They are probably behind the current versions. You might want to merge from upstream and then recheck these.

Yes, the eternal "I forgot to update submodules after merging" problem, that I will never not forget to do. I should figure out how to tack on a shell script or something to auto-run it or post a warning or something after a git merge

@hierophect hierophect requested a review from dhalbert May 13, 2021 15:25
Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

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

Changes look good! Thanks - we'll merge now and you can then proceed on the API cleanup, etc.

@tannewt tannewt merged commit 35ee4ad into adafruit:main May 13, 2021
@hierophect hierophect deleted the stm-alarm branch May 13, 2021 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants