Power Management
Todo
This needs to be updated to account for the different governors besides the activity-based one.
NuttX supports a simple power management (PM) sub-system which:
Monitors activity from drivers (and from other parts of the system), and
Provides hooks to place drivers (and the whole system) into reduce power modes of operation.
The PM sub-system integrates the MCU idle loop with a collection of device drivers to support:
Reports of relevant driver or other system activity.
Registration and callback mechanism to interface with individual device drivers.
IDLE time polling of overall driver activity.
Coordinated, global, system-wide transitions to lower power usage states.
Low Power Consumption States. Various “sleep” and low power consumption states have various names and are sometimes used in conflicting ways. In the NuttX PM logic, we will use the following terminology:
NORMAL
The normal, full power operating mode.
IDLE
This is still basically normal operational mode, the system is, however,
IDLE
and some simple simple steps to reduce power consumption provided that they do not interfere with normal Operation. Simply dimming the a backlight might be an example some that that would be done when the system is idle.STANDBY
Standby is a lower power consumption mode that may involve more extensive power management steps such has disabling clocking or setting the processor into reduced power consumption modes. In this state, the system should still be able to resume normal activity almost immediately.
SLEEP
The lowest power consumption mode. The most drastic power reduction measures possible should be taken in this state. It may require some time to get back to normal operation from
SLEEP
(some MCUs may even require going through reset).
-
enum pm_state_e
These various states are represented with type
pm_state_e
ininclude/nuttx/power/pm.h
.
Power Management Domains. Each PM interfaces includes a
integer domain number. By default, only a single power domain is
supported (CONFIG_PM_NDOMAINS=1
). But that is configurable;
any number of PM domains can be supported. Multiple PM domains
might be useful, for example, if you would want to control power
states associated with a network separately from power states
associated with a user interface.
Interfaces
All PM interfaces are declared in the file include/nuttx/power/pm.h
.
-
void pm_initialize(void)
Called by MCU-specific one-time logic at power-on-reset in order to initialize the power management capabilities. This function must be called very early in the initialization sequence before any other device drivers are initialized (since they may attempt to register with the power management subsystem).
-
int pm_domain_register(int domain, FAR struct pm_callback_s *cb)
Called by a device driver in order to register to receive power management event callbacks from specific domain. Refer to the Callbacks section for more details.
- Parameters:
domain – Identifies the target register domain
cb – An instance of
pm_callback_s
providing the driver callback functions.
- Returns:
Zero (
OK
) on success; otherwise a negatederrno
value is returned.
-
int pm_register(FAR struct pm_callback_s *callbacks)
Called by a device driver in order to register to receive power management event callbacks. Refer to the Callbacks section for more details.
Compatible kept, only register to PM_IDLE_DOMAIN by marcro.
- Parameters:
callbacks – An instance of
pm_callback_s
providing the driver callback functions.
- Returns:
Zero (
OK
) on success; otherwise a negatederrno
value is returned.
-
int pm_domain_unregister(int domain, FAR struct pm_callback_s *cb)
Called by a device driver in order to unregister previously registered power management event from specific domain. callbacks. Refer to the Callbacks section for more details.
Input Parameters:
- Parameters:
domain – Identifies the target unregister domain
cb – An instance of
pm_callback_s
providing the driver callback functions.
- Returns:
Zero (
OK
) on success; otherwise a negatederrno
value is returned.
-
int pm_unregister(FAR struct pm_callback_s *callbacks)
Called by a device driver in order to unregister previously registered power management event callbacks. Refer to the Callbacks section for more details.
Compatible kept, only unregister with PM_IDLE_DOMAIN by marcro.
Input Parameters:
- Parameters:
callbacks – An instance of
pm_callback_s
providing the driver callback functions.
- Returns:
Zero (
OK
) on success; otherwise a negatederrno
value is returned.
-
void pm_activity(int domain, int priority)
Called by a device driver to indicate that it is performing meaningful activities (non-idle). This increment an activity count and/or will restart a idle timer and prevent entering reduced power states.
- param domain:
Identifies the domain of the new PM activity
- param priority:
Activity priority, range 0-9. Larger values correspond to higher priorities. Higher priority activity can prevent the system from entering reduced power states for a longer period of time. As an example, a button press might be higher priority activity because it means that the user is actively interacting with the device.
Assumptions: This function may be called from an interrupt handler (this is the ONLY PM function that may be called from an interrupt handler!).
-
enum pm_state_e pm_checkstate(int domain)
Called from the MCU-specific IDLE loop to monitor the power management conditions. This function returns the “recommended” power management state based on the PM configuration and activity reported in the last sampling periods. The power management state is not automatically changed, however. The IDLE loop must call
pm_changestate()
in order to make the state change.These two steps are separated because the platform-specific IDLE loop may have additional situational information that is not available to the PM sub-system. For example, the IDLE loop may know that the battery charge level is very low and may force lower power states even if there is activity.
NOTE: That these two steps are separated in time and, hence, the IDLE loop could be suspended for a long period of time between calling
pm_checkstate()
andpm_changestate()
. The IDLE loop may need to make these calls atomic by either disabling interrupts until the state change is completed.- param domain:
Identifies the PM domain to check
- return:
The recommended power management state.
-
int pm_changestate(int domain, enum pm_state_e newstate)
This function is used by platform-specific power management logic. It will announce the power management power management state change to all drivers that have registered for power management event callbacks.
- Parameters:
domain – Identifies the domain of the new PM state
newstate – Identifies the new PM state
- Returns:
0 (
OK
) means that the callback function for all registered drivers returnedOK
(meaning that they accept the state change). Non-zero means that one of the drivers refused the state change. In this case, the system will revert to the preceding state.
Assumptions: It is assumed that interrupts are disabled when this function is called. This function is probably called from the IDLE loop… the lowest priority task in the system. Changing driver power management states may result in renewed system activity and, as a result, can suspend the IDLE thread before it completes the entire state change unless interrupts are disabled throughout the state change.
-
void pm_idle(pm_idle_handler_t handler)
This function provide standard pm idle work flow for up_idle. Called from the chip bsp and should only focus on handle the system state changed.
- Parameters:
handler – The execution after PM_IDLE_DOMAIN state changed
-
void pm_idle_unlock(void)
This function provide assist of smp pm idle work progress, for pm sequence other cores will not release before the core hold cpus lock. Call this function to release SMP idle cpus lock.
-
bool pm_idle_lock(int cpu)
This function provide assist of smp pm idle work progress, for pm sequence other cores will not release before the core hold cpus lock. Call this function to ensure other core will not run until released.
- Parameters:
cpu – The current CPU, used to update cpu_set_t
- Returns:
true, Current CPU is the first one woken from sleep, should handle system domain restore process also. false, Current CPU is not the first one woken from sleep, should only handle cpu domain restore process.
Assumptions: Restore operation pm_changestate(, PM_RESTORE) will done inside pm_idle. Handler don’t have to care about it.
Callbacks
-
type pm_idle_handler_t
This type declare is provide for pm_idle interface. Handle the pm low power action and execution. Possible execution for long time because of WFI inside.
for not SMP case.
typedef void (*pm_idle_handler_t)(enum pm_state_e systemstate);
- Param systemstate:
Indicate the new system power state.
for SMP case.
typedef bool (*pm_idle_handler_t)(int cpu, enum pm_state_e cpustate, enum pm_state_e systemstate);
- Param cpu:
Indicate the current working cpu.
- Param cpustate:
Indicate the current cpu power state.
- Param systemstate:
Indicate the new system power state. If not the lastcore enter idle, systemstate always PM_RESTORE. If not PM_RESTORE, handler should cover system pm operations.
-
struct pm_callback_s
This struct includes the pointers to the driver callback functions. This structure is defined
include/nuttx/power/pm.h
. These callback functions can be used to provide power management information to the driver.
-
int (*prepare)(FAR struct pm_callback_s *cb, int domain, enum pm_state_e pmstate)
Request the driver to prepare for a new power state. This is a warning that the system is about to enter into a new power state. The driver should begin whatever operations that may be required to enter power state. The driver may abort the state change mode by returning a non-zero value from the callback function.
- param cb:
Returned to the driver. The driver version of the callback structure may include additional, driver-specific state data at the end of the structure.
- param domain:
Identifies the activity domain of the state change
- param pmstate:
Identifies the new PM state
- return:
Zero (
OK
) means the event was successfully processed and that the driver is prepared for the PM state change. Non-zero means that the driver is not prepared to perform the tasks needed achieve this power setting and will cause the state change to be aborted. NOTE: Theprepare()
method will also be called when reverting from lower back to higher power consumption modes (say because another driver refused a lower power state change). Drivers are not permitted to return non-zero values when reverting back to higher power consumption modes!
-
void (*notify)(FAR struct pm_callback_s *cb, int domain, enum pm_state_e pmstate)
Notify the driver of new power state. This callback is called after all drivers have had the opportunity to prepare for the new power state.
- param cb:
Returned to the driver. The driver version of the callback structure may include additional, driver-specific state data at the end of the structure.
- param domain:
Identifies the activity domain of the state change
- param pmstate:
Identifies the new PM state
The driver already agreed to transition to the low power consumption state when when it returned
OK
to theprepare
call.