Skip to content

core: Automatically select the lowest possible LPM mode #2927

@jnohlgard

Description

@jnohlgard

We have currently the following logical power modes in RIOT:

Mode Comment
LPM_ON MCU is active.
LPM_IDLE MCU is idle.
LPM_SLEEP MCU in sleep mode.
LPM_POWERDOWN MCU is powered down.
LPM_OFF MCU is off.
LPM_UNKNOWN status unknown/unavailable

Currently, LPM_IDLE is activated when the idle thread is scheduled to run. This makes sense logically, but it is not optimal. This led me to implement the LPM driver for Kinetis [#2605] in such a way that it only checks if the requested mode was LPM_ON and return quickly, or for any other mode it will begin examining which modes are available given the set of peripherals active at the moment (using the atomic counters from #2321) and then pick the lowest possible sleep mode.
I would like to move this logic to the idle thread to let all platforms benefit from this automatic low power mode selection.

For Cortex-M platforms the modes are quite straightforward to map onto hardware modes. RUN, WAIT and STOP would correspond to the top three modes in the table above. For Kinetis it would be possible to further extend this and use VLPS or LLS modes for LPM_POWERDOWN and LPM_OFF. Each of these mappings would still need to be platform dependent since each platform has its own power modes and requirements, but the logic to choose between them could be centralized in the core LPM handler.

The plan:

  • Introduce lpm_[un]inhibit_idle, lpm_inhibit_sleep etc. similar to the implementation in kinetis: Add LPM implementation #2605 which will inhibit the given mode and any lower modes.
  • Let the peripheral drivers themselves tell the system if the peripheral is active and what power modes it requires in order to function. This is done by calling lpm_inhibit_xxx, for example an SPI driver in master mode might only be able to transmit if we are in WAIT mode or higher, then we call lpm_inhibit_sleep before beginning each transfer and then lpm_uninhibit_sleep after the transfer is completed.

Q: What was the original intent behind LPM_OFF? Is it supposed to turn off the MCU permanently, like when you do a shut down on a PC, or is it intended to be "resumable"?

Questions? Comments?

Metadata

Metadata

Assignees

Labels

Area: coreArea: RIOT kernel. Handle PRs marked with this with care!Area: pmArea: (Low) power managementType: enhancementThe issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions