Android PM suspend&resume

Android PM suspend&resume
电源管理主要体现在以下方面:
1.低功耗模式:对于现在的嵌入式芯片,都提供了各种低功率模式,如:提供了STOP,WAIT,DEEP SLEEP等功率状态,为不同的系统应用使用不同的功率模式提供了很好的解决方案。同时,除DEEP SLEEP模式外,在动态电源管理中,大大提高了其他模式之间的转换速度。
2.动态电压与频率调整模式:在动态功率模式中,通过提供不同的电压,不同的系统时钟频率,芯片可以工作于不同的主频上,可以根据系统的负载情况,动态调 整芯片的工作状态,只要能满足系统运行需要即可,从而避免了系统一直高速运行下的功率浪费。
3.时钟与电源开关:对于一嵌入式系统,可能存在很多外围设备,但它们不需要同时使用,对于不需要使用的设备,可以停止给它们提供时钟与电源,或让相应的 设备进入DEEP SLEEP状态,仅仅提供最基本的时钟和电压,达到减少功耗的目的。

Android的电源管理还是比较简单的, 主要就是通过锁和定时器来切换系统的状态,使系统的功耗降至最低,整个系统的电源管理架构图如下: (注该图来自Steve Guo)

Kernel层[针对AndroidLinux2.6.28内核]:

1、初始化suspend和resume函数
static struct platform_driver mxcbl_driver = {
        .probe = mxcbl_probe,
        .remove = mxcbl_remove,
        .suspend = mxcbl_suspend,
        .resume = mxcbl_resume,
        .driver = {
                   .name = "mxc_mc13892_bl",
                   },
};
2、系统Suspend和resume的函数流程
取一个例子
加入suspend和resume
mxc_board_init-->mxc_init_bl()-->platform_device_register()-->platform_device_add()-->device_add()-->device_pm_add()-->, 最终加入到了dpm_list的链表中,在其中的dpm_suspend和dpm_suspend中通过遍历这个链表来进行查看哪个device中包含 suspend和resume项。

系统唤醒和休眠
其主要代码在下列位置:
Drivers/base /main.c
kernel/power /main.c
kernel/power/wakelock.c
kernel/power/earlysuspend.c
arch/arm/mach-mx51/pm.c
其对Kernel提供的接口函数有
EXPORT_SYMBOL(wake_lock_init); //初始化Suspend lock,在使用前必须做初始化
EXPORT_SYMBOL(wake_lock); //申请lock,必须调用相应的unlock来释放它
static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);//定时时间到,加入到suspend队列中;
EXPORT_SYMBOL(wake_unlock); //释放lock
EXPORT_SYMBOL_GPL(device_power_up);//打开特殊的设备
EXPORT_SYMBOL_GPL(device_power_down);//关闭特殊设备
EXPORT_SYMBOL_GPL(device_resume);//重新存储设备的状态;
EXPORT_SYMBOL_GPL(device_suspend);:保存系统状态,并结束掉系统中的设备;
EXPORT_SYMBOL(register_early_suspend); //注册early suspend的驱动
EXPORT_SYMBOL(unregister_early_suspend); //取消已经注册的early suspend的驱动

函数的流程如下所示:
应用程序通过对state_store的写入操作可以使系统进行休眠的状态。pm_states包括 PM_SUSPEND_ON,PM_SUSPEND_STANDBY,PM_SUSPEND_M满足个状态。
当状态位PM_SUSPEND_ON的状态的时候,调用request_suspend_state();当满足休眠的状态的时候,调用 queue_work(suspend_work_queue,&early_suspend_work),调用了early_suspend, 然后在其中通过wake_unlock()启动了expire_timer定时器,当定时时间到了,则执行expire_wake_locks,将 suspend_work加入到队列中,分析到这里就可以知道了early_suspend_work和suspend_work这两个队列中函数的先后 顺序了,suspend调用了pm_suspend,通过判断当前的状态,选择enter_state(),在enter_state中,经过了 suspend_prepare,suspend_test和suspend_device_and_enter(),在 suspend_device_and_enter中调用了device_suspend来保存状态和结束系统的设备,到了dpm_suspend中结束 所有的device。到了这里,我们就又可以看见在初始化的时候所看到的队列dpm_list。下面调用了 disable_nonboot_cpus(),然后调用suspend_enter(),进入并且请求进入休眠态,在此期间,关闭所有的中断。然后调用 mx51_suspend_enter进入低功耗模式。

唤醒resume的过程后续分析。。。。。。

Android的电源管理主要是通过Wake lock来实现的,在最底层主要是通过如下队列来实现其管理:
LIST_HEAD(dpm_list);


Android的电源的几个状态如下:


系统正常开机后进入到AWAKE状态, Backlight会从最亮慢慢调节到用户设定的亮度,系统screen off timer(settings->sound & display-> Display settings -> Screen timeout)开始计时,在计时时间到之前,如果有任何的activity事件发生,如Touch click, keyboard pressed等事件, 则将Reset screen off timer, 系统保持在AWAKE状态. 如果有应用程序在这段时间内申请了Full wake lock,那么系统也将保持在AWAKE状态, 除非用户按下power key. 在AWAKE状态下如果电池电量低或者是用AC供电screen off timer时间到并且选中Keep screen on while pluged in选项,backlight会被强制调节到DIM的状态.
如果Screen off timer时间到并且没有Full wake lock或者用户按了power key,那么系统状态将被切换到NOTIFICATION,并且调用所有已经注册的g_early_suspend_handlers函数, 通常会把LCD和Backlight驱动注册成early suspend类型,如有需要也可以把别的驱动注册成early suspend, 这样就会在第一阶段被关闭. 接下来系统会判断是否有partial wake lock acquired, 如果有则等待其释放, 在等待的过程中如果有user activity事件发生,系统则马上回到AWAKE状态;如果没有partial wake lock acquired, 则系统会马上调用函数pm_suspend关闭其它相关的驱动, 让CPU进入休眠状态.
系统在Sleep状态时如果检测到任何一个Wakeup source, 则CPU会从Sleep状态被唤醒,并且调用相关的驱动的resume函数,接下来马上调用前期注册的early suspend驱动的resume函数,最后系统状态回到AWAKE状态.这里有个问题就是所有注册过early suspend的函数在进Suspend的第一阶段被调用可以理解,但是在resume的时候, Linux会先调用所有驱动的resume函数,而此时再调用前期注册的early suspend驱动的resume函数有什么意义呢?个人觉得android的这个early suspend和late resume函数应该结合Linux下面的suspend和resume一起使用,而不是单独的使用一个队列来进行管理.

posted @ 2011-01-06 14:30  天不会黑  阅读(1916)  评论(0编辑  收藏  举报