技术专栏
linux休眠-电源管理过程梳理
概述
由于嵌入式设备自身的特点,设备运行功耗问题一直是产品设计首先要考虑的问题,尤其对于非长电设备。
本文主要讲述linux内核(2.6+),设备、系统休眠过程,理解的内核休眠过程,才能够更好的增加产品外设休眠逻辑和硬件平台休眠模块。
其主要分为以下几个方面:
1、soc电源管理,位于平台代码中,一般由厂家提供
2、外设电源管理,位于外设驱动中,按需增加接口
3、linux电源管理核心框架
以下分别进行描述
注册平台电源管理接口
一般位于arch/soc/pm*.c中,通过suspend_set_ops注册
static const struct platform_suspend_ops xxxx_pm_ops = {
.valid = xxxx_pm_valid,
.begin = xxxx_pm_begin,
.enter = xxxx_pm_enter,
.end = xxxx_pm_end,
.prepare = xxxx_suspend_prepare,
.finish = xxxx_suspend_finish,
};
static int __init pm_init(void)
{
suspend_set_ops(&xxxx_pm_ops);
return 0;
}
suspend_set_ops过程如下:
kernel/power/suspend.c
suspend_set_ops(const struct platform_suspend_ops *ops)
// 将ops赋给全局suspend_ops,用于获取平台pm_ops回调接口
suspend_ops = ops;
// 初始化内核支持的休眠模式,即cat /sys/power/state得到的内容
pm_states[i] = pm_labels[j++];
注册外设驱动电源管理接口
外设驱动通过struct device_driver.pm将外设电源管理接口注册到内核中,具体如下:
1、外设驱动中实现struct device_driver.pm接口
static const struct dev_pm_ops xxxx_sdmmc_pm_ops = {
.suspend = xxxx_sdmmc_suspend,
.resume = xxxx_sdmmc_resume,
};
2、注册设备
device_register
//初始化device结构体
device_initialize
device_pm_init(dev);
// 初始化struct device.power结构体
device_pm_sleep_init
// 创建了dev->power.entry列表
device_pm_sleep_init
device_add
device_pm_add(dev);
// 将上面创建的dev->power.entry加入到dpm_list中,即将该device加入电源管理
list_add_tail(&dev->power.entry, &dpm_list);
dpm_list是内核中用于设备电源管理的链表,如果该列表中存在某个外设,则调用外设的pm相关接口,进行休眠操作
linux内核休眠整体过程
上面讲到将各个pm注册到内核的过程,那么何时调用,如何执行上述pm接口呢?
以echo mem > /sys/power/state,休眠设备为例,具体过程如下:
kernel/power/main.c
state_store
//解析传入的"mem"
decode_state(buf, n);
// 挂起系统
pm_suspend
enter_state
// 同步磁盘
sys_sync
suspend_prepare
// 挂起进程和内核线程
suspend_freeze_processes
suspend_devices_and_enter
// 进入平台代码中pm.c注册的ops.begin中
platform_suspend_begin
// 挂起控制台
suspend_console
// 挂起外设
dpm_suspend_start
// 执行device_driver.pm.prepare,即设备挂起前的准备工作
dpm_prepare
//判断device是否加入dpm_list中了
while (!list_empty(&dpm_list)) {
struct device *dev = to_device(dpm_list.next);
return container_of(entry, struct device, power.entry);
//如果加入了,则执行device.driver.pm.prepare
device_prepare
callback = dev->driver->pm->prepare;
if (callback)
ret = callback(dev);
// 挂起外设
dpm_suspend
//遍历所有设备
while (!list_empty(&dpm_prepared_list)) {
device_suspend
__device_suspend
//根据state得到driver.pm.suspend
callback = pm_op(dev->driver->pm, state);
// 调用driver.pm.suspend
dpm_run_callback(callback, dev, state, info);
//打印“PM: suspend of devices complete after” ,标志所有device suspend结束
dpm_show_time(starttime, state, NULL);
//函数在设备挂起之后调用,用于挂起系统
suspend_enter
// 执行平台pm.prepare
platform_suspend_prepare
// 执行设备的suspend_late,然后又将这些设备加入到dpm_late_early_list链表中。如果出现失败,则跳到platform_finish做恢复工作。
dpm_suspend_late
// 执行平台的prepare_late,做最后的准备工作
platform_suspend_prepare_noirq(state);
// 关闭非boot cpu(first cpu)
disable_nonboot_cpus
// 关中断
arch_suspend_disable_irqs
// 执行所有系统的suspend接口
syscore_suspend
// 执行平台的pm.enter接口
suspend_ops->enter
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包
点赞
收藏
评论
打赏
- 分享
- 举报
评论
0个
手气红包
暂无数据
相关专栏
-
浏览量:2020次2019-07-02 15:15:59
-
浏览量:1771次2019-07-04 14:04:31
-
浏览量:635次2023-11-24 15:35:13
-
浏览量:4790次2020-08-11 10:32:41
-
浏览量:2511次2020-10-29 17:55:50
-
浏览量:3194次2020-07-03 16:09:52
-
浏览量:8317次2021-01-20 17:04:49
-
浏览量:5009次2021-07-29 11:53:53
-
浏览量:3340次2021-04-02 09:43:51
-
浏览量:891次2023-11-17 11:33:55
-
浏览量:2382次2020-07-03 18:27:11
-
浏览量:4925次2021-07-26 17:38:48
-
浏览量:4276次2019-10-11 09:26:12
-
浏览量:1306次2020-06-09 16:21:19
-
浏览量:2604次2022-11-10 10:02:57
-
浏览量:4441次2021-11-20 15:17:49
-
浏览量:4275次2021-08-26 14:50:36
-
浏览量:915次2024-07-12 08:58:25
-
浏览量:1285次2019-05-16 16:41:47
置顶时间设置
结束时间
删除原因
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
打赏作者
阿帅
您的支持将鼓励我继续创作!
打赏金额:
¥1
¥5
¥10
¥50
¥100
支付方式:
微信支付
打赏成功!
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
审核成功
发布时间设置
发布时间:
请选择发布时间设置
是否关联周任务-专栏模块
审核失败
失败原因
请选择失败原因
备注
请输入备注