Skip to content

nrf/modules/machine: Implement deepsleep() #13367

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

cwalther
Copy link
Contributor

@cwalther cwalther commented Jan 5, 2024

Replace the previous dummy implementation of machine.deepsleep() with one that invokes the nRF's deep sleep state System OFF. The argument is ignored, nRF microcontrollers are incapable of waking on a timer as all clocks are off in the deep sleep state.

Pins are configured as wake sources using an additional argument sense to the machine.Pin constructor. This choice is up for debate, it seemed appropriate because it internally is a matter of GPIO configuration. I also considered using the unused wake argument to Pin.irq(), but rejected that because the configuration has nothing to do with IRQs. Another possibility would be a special function in the nrf module, akin to esp32.wake_on_ext0().

machine.reset_cause() returns the newly added DEEPSLEEP_RESET, like on other ports – the previous mapping to PWRON_RESET seemed wrong.

I am unsure where to document this, as there is no port-specific documentation for the nrf port. Should I add a Quick reference for the nRF51/52 section just for this?

Tested on nRF52832 (DS-D6) and nRF52840 (ItsyBitsy).

Copy link

github-actions bot commented Jan 5, 2024

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS

@cwalther
Copy link
Contributor Author

cwalther commented Jan 5, 2024

OK, apparently this doesn’t work on the nRF9160. Will investigate.

Copy link

codecov bot commented Jan 5, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.39%. Comparing base (d694ac6) to head (9705dd4).

❗ Current head 9705dd4 differs from pull request most recent head 821da37. Consider uploading reports for the commit 821da37 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #13367      +/-   ##
==========================================
- Coverage   98.39%   98.39%   -0.01%     
==========================================
  Files         161      161              
  Lines       21200    21078     -122     
==========================================
- Hits        20860    20739     -121     
+ Misses        340      339       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@cwalther
Copy link
Contributor Author

cwalther commented Jan 5, 2024

Builds on all boards now. No idea if it works on the nRF9160, as I don’t have one to test, but apart from the different register its System OFF mode looks similar.

@robert-hh
Copy link
Contributor

Pins are configured as wake sources using an additional argument sense to the machine.Pin constructor.

When implementing lightsleep/deepsleep for the SAMD port, I went for taking all pins as wake-up source which had IRQ enabled. That avoids another Pin argument. Besides that, an additional argument may better be called wakeup instead of sense and matching state names, no matter how nrf calls it internally.

@cwalther
Copy link
Contributor Author

Rebased on master to deal with the STATIC removal, no other changes required.

@dpgeorge
Copy link
Member

Thanks for the contribution.

Is it possible to split up the second commit into two commits:

  • one that implements deepsleep
  • one that adds the sense argument to Pin constructors

The first part there can be merged easily. The change to Pin needs more thought with respect to the API, because other ports would need to follow it.

Replace the previous dummy implementation of machine.deepsleep() with one
that invokes the nRF's deep sleep state "System OFF". The argument is
ignored, nRF microcontrollers are incapable of waking on a timer as all
clocks are off in the deep sleep state.

There is no way yet to wake from deep sleep except using the reset pin, a
way to configure GPIO pins as wake sources is to be added in a subsequent
commit.

machine.reset_cause() returns the newly added DEEPSLEEP_RESET, like on
other ports – the previous mapping to PWRON_RESET seemed wrong.

Signed-off-by: Christian Walther <cwalther@gmx.ch>
Pins are configured as wake sources for deep sleep using an additional
port-specific argument "sense" to the machine.Pin constructor.

Signed-off-by: Christian Walther <cwalther@gmx.ch>
@cwalther
Copy link
Contributor Author

Splitting seems like a good way forward, done. Not thoroughly tested yet, will do that in a few days.

I agree that how to configure pins for waking needs more thought and discussion.

@jonnor
Copy link
Contributor

jonnor commented Jul 28, 2024

Can the deepsleep commit be merged?
It would make for a good improvement on the NRF52x chips - as they are most relevant for low-power stuff (especially BLE).

@julien123123
Copy link

So, I've been looking at putting my NRF52840 Xiao board into deep sleep. @cwalther's implementation does indeed put the nrf52 to sleep, but it still consumes a lot of current. After looking for a reason on Arduino forums, I found that the Xiao board has a qspi flash memory chip on it, and it needs to be put to sleep. Arduino people have had success using Adafruit SPIflash library that sends command 0xB9 to the qspi chip, then de-initing the qspi interface. In Nordic's documentation, they also show a way to do it with the registers. I don't know if many nrf boards use qspi flash memory, but I feel like for the deepsleep() function to be consistant with other ports, the qspi should be put to sleep also.

I'd propose a change myself, but I'm not well versed in C, and I haven't been able to put the flash chip to sleep only using micropython. I wonder if something in the drivers keeps it from entering sleep mode, since it would prevent micropython from working properly.

@cwalther
Copy link
Contributor Author

cwalther commented Aug 4, 2024

Good point. There does seem to be precedent for board-specific deep-sleep handling dealing with SPI flash in some STM32 boards using the MICROPY_BOARD_ENTER_STANDBY macro. So I agree that this could be added here too. However, I would consider that an additional change that can go in a separate pull request (based on this one), and I currently have no plans to work on this in the near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants