简介
Zephyr
2.0的版本之后对电源管理子系统做了一个框架性的修改,因此如果你用的是Zephyr
2.0以下的版本,请参考官方的文档,本篇介绍的2.0版本以后的电源管理框架。电源管理子系统
提供的接口
和API
设计为独立于体系结构
和SOC
。这使得电源管理实现能够轻松适应不同的SOC和架构。
电源管理的原理
一般情况下OS
的thread
有效工作时间是不能占满CPU
工作时间的,在其等待的时候有一个idle thread
会占用CPU
,将idle thread
占用CPU的运行时间转为CPU idle
,达到省电的目的。
上图示例了一个跑了3个thread: Ta,Tb,Tc
。这三个thread
根据实际的应用情况调度,在t1,t2,t3
这三个时间段这3个thread
都不需要工作,在Normal
的状态下,Idle thread
将占用这3个时间段的CPU
,让CPU
空转。当引入电源管理后,一旦3个thread
不工作转到idle
时,idle thread
会自动检测下一次thread
工作的时间,设置timer
,然后让CPU
进入idle
,当timer
超时就唤醒CPU
,继续调度工作。以t1
为例:当Tc
调度结束后进入idle thread
, idle thread
计算到下一次Tb
被调度的时间间隔t1
, 以t1
设置timer
,然后让CPU进入idle
,t1
时间到后timer
中断产生唤醒CPU
,切换到Tb
开始运行。
系统电源管理状态
源码路径在include/pm/state.h
:
enum pm_state {
/**
* @brief Runtime active state
*
* The system is fully powered and active.
*
* @note This state is correlated with ACPI G0/S0 state
*/
PM_STATE_ACTIVE,
/**
* @brief Runtime idle state
*
* Runtime idle is a system sleep state in which all of the cores
* enter deepest possible idle state and wait for interrupts, no
* requirements for the devices, leaving them at the states where
* they are.
*
* @note This state is correlated with ACPI S0ix state
*/
PM_STATE_RUNTIME_IDLE,
/**
* @brief Suspend to idle state
*
* The system goes through a normal platform suspend where it puts
* all of the cores in deepest possible idle state and *may* puts peripherals
* into low-power states. No operating state is lost (ie. the cpu core
* does not lose execution context), so the system can go back to where
* it left off easily enough.
*
* @note This state is correlated with ACPI S1 state
*/
PM_STATE_SUSPEND_TO_IDLE,
/**
* @brief Standby state
*
* In addition to putting peripherals into low-power states all
* non-boot CPUs are powered off. It should allow more energy to be
* saved relative to suspend to idle, but the resume latency will
* generally be greater than for that state. But it should be the same
* state with suspend to idle state on uniprocesser system.
*
* @note This state is correlated with ACPI S2 state
*/
PM_STATE_STANDBY,
/**
* @brief Suspend to ram state
*
* This state offers significant energy savings by powering off as much
* of the system as possible, where memory should be placed into the
* self-refresh mode to retain its contents. The state of devices and
* CPUs is saved and held in memory, and it may require some boot-
* strapping code in ROM to resume the system from it.
*
* @note This state is correlated with ACPI S3 state
*/
PM_STATE_SUSPEND_TO_RAM,
/**
* @brief Suspend to disk state
*
* This state offers significant energy savings by powering off as much
* of the system as possible, including the memory. The contents of
* memory are written to disk or other non-volatile storage, and on resume
* it's read back into memory with the help of boot-strapping code,
* restores the system to the same point of execution where it went to
* suspend to disk.
*
* @note This state is correlated with ACPI S4 state
*/
PM_STATE_SUSPEND_TO_DISK,
/**
* @brief Soft off state
*
* This state consumes a minimal amount of power and requires a large
* latency in order to return to runtime active state. The contents of
* system(CPU and memory) will not be preserved, so the system will be
* restarted as if from initial power-up and kernel boot.
*
* @note This state is correlated with ACPI G2/S5 state
*/
PM_STATE_SOFT_OFF
};
- PM_STATE_ACTIVE: 设备运行状态
- PM_STATE_RUNTIME_IDLE: 运行时空闲空闲状态,
- PM_STATE_SUSPEND_TO_IDLE: 挂起到空闲状态
- PM_STATE_STANDBY: 低功耗状态,外设会进入低功耗,且cpu下电
- PM_STATE_SUSPEND_TO_RAM: 系统资源被放置在RAM中,唤醒需要重启后操作RAM来进行恢复
- PM_STATE_SUSPEND_TO_DISK: 系统资源被放置在DISK中,唤醒需要重启后操作DISK来进行恢复
- PM_STATE_SOFT_OFF: 完全断电
以上的设备状态按照数值大小进行排序,数值约到降低的功耗越多。
设备电源管理状态
源码路径zephyr/include/pm/device.h
/** @brief Device power states. */
enum pm_device_state {
/** Device is in active or regular state. */
PM_DEVICE_STATE_ACTIVE,
/**
* Device is in low power state.
*
* @note
* Device context is preserved.
*/
PM_DEVICE_STATE_LOW_POWER,
/**
* Device is suspended.
*
* @note
* Device context may be lost.
*/
PM_DEVICE_STATE_SUSPENDED,
/**
* Device is suspended (forced).
*
* @note
* Device context may be lost.
*/
PM_DEVICE_STATE_FORCE_SUSPEND,
/**
* Device is turned off (power removed).
*
* @note
* Device context is lost.
*/
PM_DEVICE_STATE_OFF,
/** Device is being resumed. */
PM_DEVICE_STATE_RESUMING,
/** Device is being suspended. */
PM_DEVICE_STATE_SUSPENDING,
};
- PM_DEVICE_STATE_ACTIVE: 设备处于活动状态
- PM_DEVICE_STATE_SUSPENDED: 设备已挂起
- PM_DEVICE_STATE_FORCE_SUSPEND: 设备强制挂起
- PM_DEVICE_STATE_SUSPENDING: 设备正在挂起
- PM_DEVICE_STATE_OFF: 设备以断电,上下文丢失
- PM_DEVICE_STATE_LOW_POWER: 设备进入低功耗
- PM_DEVICE_STATE_RESUMING: 设备正在恢复
- PM_DEVICE_STATE_SUSPENDING: 设备已经恢复中
电源状态约束
当我们在操作一些外设的时候,可能会因为IO阻塞而进入到休眠,这样可能会导致我们数据的丢死,更加糟糕的是会导致系统崩溃,因此Zephyr
提供了对电源状态进行约束的API:
/**
* @brief Set a constraint for a power state
*
* @details Disabled state cannot be selected by the Zephyr power
* management policies. Application defined policy should
* use the @ref pm_constraint_get function to
* check if given state is enabled and could be used.
*
* @note This API is refcount
*
* @param [in] state Power state to be disabled.
*/
void pm_constraint_set(enum pm_state state);
/**
* @brief Release a constraint for a power state
*
* @details Enabled state can be selected by the Zephyr power
* management policies. Application defined policy should
* use the @ref pm_constraint_get function to
* check if given state is enabled and could be used.
* By default all power states are enabled.
*
* @note This API is refcount
*
* @param [in] state Power state to be enabled.
*/
void pm_constraint_release(enum pm_state state);
/**
* @brief Check if particular power state is enabled
*
* This function returns true if given power state is enabled.
*
* @param [in] state Power state.
*/
bool pm_constraint_get(enum pm_state state);
- pm_constraint_set: 这是电源状态不能被电源管理策略选择,也就是说不能在此状态进入低功耗
- pm_constraint_release: 释放电源状态,可以被电源管理策略选择
- pm_constraint_get: 获取当前的电源状态的约束
电源管理策略
Zephyr
的默认电源管理策略为Residency
。该策略其实就是在进入idle
任务中获取下一个调度任务的时间,然后根据时间来计算出需要进入到哪一个电源管理状态,最后根据电源管理状态来执行电源管理函数。Zephyr
同时还可以支持用户自定义的电源管理策略。在zephyr/tests/subsys/pm/power_mgmt/
中给出了一个例子可以参考一下。
启动电源管理的配置
如果需要启用电源管理需要在prj.conf
中设置:
//启动电源管理
CONFIG_PM=y
//启用设备电源管理
CONFIG_PM_DEVICE=y
//启动运行时设备电源管理
CONFIG_PM_DEVICE_RUNTIME=y
//启动电源管理域
CONFIG_PM_DEVICE_POWER_DOMAIN=y
电源管理的分类
目前Zephyr可以通过如下两种方式来实现电源管理:
- 系统电源管理
- 设备电源管理
以上两种电源管理都可以通过主动系统调用和自动系统调用两种方式来实现对电源的管理。