|  | .. _pm-system: | 
|  |  | 
|  | System Power Management | 
|  | ####################### | 
|  |  | 
|  | Introduction | 
|  | ************ | 
|  |  | 
|  | The kernel enters the idle state when it has nothing to schedule. | 
|  | Enabling :kconfig:option:`CONFIG_PM` allows the kernel to call upon the | 
|  | power management subsystem to put an idle system into one of the supported power states. | 
|  | The kernel requests an amount of time it would like to suspend, then the PM subsystem decides | 
|  | the appropriate power state to transition to based on the configured power management policy. | 
|  |  | 
|  | It is the application's responsibility to set up a wake-up event. | 
|  | A wake-up event will typically be an interrupt triggered by an SoC peripheral module. | 
|  | Examples include a SysTick, RTC, counter, or GPIO. | 
|  | Keep in mind that depending on the SoC and the power mode in question, | 
|  | not all peripherals may be active, and therefore | 
|  | some wake-up sources may not be usable in all power modes. | 
|  |  | 
|  | The following diagram describes system power management: | 
|  |  | 
|  | .. graphviz:: | 
|  | :caption: System power management | 
|  |  | 
|  | digraph G { | 
|  | compound=true | 
|  | node [height=1.2 style=rounded] | 
|  |  | 
|  | lock [label="Lock interruptions"] | 
|  | config_pm [label="CONFIG_PM" shape=diamond style="rounded,dashed"] | 
|  | forced_state [label="state forced ?", shape=diamond style="rounded,dashed"] | 
|  | config_system_managed_device_pm [label="CONFIG_PM_DEVICE" shape=diamond style="rounded,dashed"] | 
|  | config_system_managed_device_pm2 [label="CONFIG_PM_DEVICE" shape=diamond style="rounded,dashed"] | 
|  | pm_policy [label="Check policy manager\nfor a power state "] | 
|  | pm_suspend_devices [label="Suspend\ndevices"] | 
|  | pm_resume_devices [label="Resume\ndevices"] | 
|  | pm_state_set [label="Change power state\n(SoC API)" style="rounded,bold"] | 
|  | pm_system_resume [label="Finish wake-up\n(SoC API)\n(restore interruptions)" style="rounded,bold"] | 
|  | k_cpu_idle [label="k_cpu_idle()"] | 
|  |  | 
|  | subgraph cluster_0 { | 
|  | style=invisible; | 
|  | lock -> config_pm | 
|  | } | 
|  |  | 
|  | subgraph cluster_1 { | 
|  | style=dashed | 
|  | label = "pm_system_suspend()" | 
|  |  | 
|  | forced_state -> config_system_managed_device_pm [label="yes"] | 
|  | forced_state -> pm_policy [label="no"] | 
|  | pm_policy -> config_system_managed_device_pm | 
|  | config_system_managed_device_pm -> pm_state_set:e [label="no"] | 
|  | config_system_managed_device_pm -> pm_suspend_devices [label="yes"] | 
|  | pm_suspend_devices -> pm_state_set | 
|  | pm_state_set -> config_system_managed_device_pm2 | 
|  | config_system_managed_device_pm2 -> pm_resume_devices [label="yes"] | 
|  | config_system_managed_device_pm2 -> pm_system_resume [label="no"] | 
|  | pm_resume_devices -> pm_system_resume | 
|  | } | 
|  |  | 
|  | {rankdir=LR k_cpu_idle; forced_state} | 
|  | pm_policy -> k_cpu_idle [label="PM_STATE_ACTIVE\n(no power state meet requirements)"] | 
|  | config_pm -> k_cpu_idle [label="no"] | 
|  | config_pm -> forced_state [label="yes" lhead="cluster_1"] | 
|  | pm_system_resume:e -> lock:e [constraint=false lhed="cluster_0"] | 
|  | } | 
|  |  | 
|  |  | 
|  | Power States | 
|  | ============ | 
|  |  | 
|  | The power management subsystem defines a set of states described by the | 
|  | power consumption and context retention associated with each of them. | 
|  |  | 
|  | The set of power states is defined by :c:enum:`pm_state`. In general, lower power states | 
|  | (higher index in the enum) will offer greater power savings and have higher wake latencies. | 
|  |  | 
|  | Power Management Policies | 
|  | ========================= | 
|  |  | 
|  | The power management subsystem supports the following power management policies: | 
|  |  | 
|  | * Residency based | 
|  | * Application defined | 
|  |  | 
|  | The policy manager is the component of the power management subsystem responsible | 
|  | for deciding which power state the system should transition to. | 
|  | The policy manager can only choose between states that have been defined for the platform. | 
|  | Other constraints placed upon the decision may include locks disallowing certain power states, | 
|  | or various kinds of minimum and maximum latency values, depending on the policy. | 
|  |  | 
|  | More details on the states definition can be found in the | 
|  | :dtcompatible:`zephyr,power-state` binding documentation. | 
|  |  | 
|  | Residency | 
|  | --------- | 
|  |  | 
|  | Under the residency policy, the system will enter the power state which offers the highest | 
|  | power savings, with the constraint that the sum of the minimum residency value (see | 
|  | :dtcompatible:`zephyr,power-state`) and the latency to exit the mode must be | 
|  | less than or equal to the system idle time duration scheduled by the kernel. | 
|  |  | 
|  | Thus the core logic can be summarized with the following expression: | 
|  |  | 
|  | .. code-block:: c | 
|  |  | 
|  | if (time_to_next_scheduled_event >= (state.min_residency_us + state.exit_latency)) { | 
|  | return state | 
|  | } | 
|  |  | 
|  | Application | 
|  | ----------- | 
|  |  | 
|  | The application defines the power management policy by implementing the | 
|  | :c:func:`pm_policy_next_state` function. In this policy, the application is free | 
|  | to decide which power state the system should transition to based on the | 
|  | remaining time until the next scheduled timeout. | 
|  |  | 
|  | An example of an application that defines its own policy can be found in | 
|  | :zephyr_file:`tests/subsys/pm/power_mgmt/`. | 
|  |  | 
|  | .. _pm-policy-power-states: | 
|  |  | 
|  | Policy and Power States | 
|  | ------------------------ | 
|  |  | 
|  | The power management subsystem allows different Zephyr components and | 
|  | applications to configure the policy manager to block the system from transitioning | 
|  | into certain power states. This can be used by devices when executing tasks in | 
|  | background to prevent the system from going to a specific state where it would | 
|  | lose context. See :c:func:`pm_policy_state_lock_get`. | 
|  |  | 
|  | Examples | 
|  | ======== | 
|  |  | 
|  | Some helpful examples showing different power management features: | 
|  |  | 
|  | * :zephyr_file:`samples/boards/st/power_mgmt/blinky/` | 
|  | * :zephyr_file:`samples/boards/espressif/deep_sleep/` | 
|  | * :zephyr_file:`samples/subsys/pm/device_pm/` | 
|  | * :zephyr_file:`tests/subsys/pm/power_mgmt/` | 
|  | * :zephyr_file:`tests/subsys/pm/power_mgmt_soc/` | 
|  | * :zephyr_file:`tests/subsys/pm/power_states_api/` |