基于DTL-RK3288 硬件平台的Android5.1电源休眠管理


Linux 电源管理机制为设备低功耗的实现提供了方法。
在不同内核版本Linux、Android,休眠机制、流程有所差异。这里DLT-RK3288 Android 5.1 源码为例。


标准Linux 的电源状态:
- On(on)                                               S0 -  Working  
                                                                      - 正常的工作状态
- Standby (standby)                              S1 -  CPU and RAM are powered but not executed   
                                                                        - CPU和DDR都供着电,但没执行任何命令。
- Suspend to RAM(mem)                        S3 -  RAM is powered and the running content is saved to RAM
                                                                        -  挂起到内存,简称待机。CPU、EMMC、LCD等都断了电,只有DDR供着电,以保存休眠前的工作状态。
- Suspend to Disk,Hibernation(disk)    S4 -  All content is saved to Disk and power down
                                                                        -  挂起到硬盘,简称休眠。机器运行状态保存到硬盘中,并关机。


DLT-RK3288的 kernel/include/linux/suspend.h 中 可以看到常用的几种状态
1. #define PM_SUSPEND_ON                ((__force suspend_state_t) 0)
2. #define PM_SUSPEND_FREEZE        ((__force suspend_state_t) 1)
3. #define PM_SUSPEND_STANDBY        ((__force suspend_state_t) 2)
4. #define PM_SUSPEND_MEM                ((__force suspend_state_t) 3)


休眠相关内核源码:
kernel/kernel/power/main.c
kernel/kernel/power/suspend.c
kernel/kernel/power/wakelock.c
kernel/kernel/power/autosleep.c
main.c 主要是向用户空间提供文件接口。文件接口有以下:

 


suspend.c 是进入休眠前所执行的代码。主要函数调用流程: pm_suspend -- enter_state -- suspend_prepare -- suspend_devices_and_enter 。
autosleep.c 主要负责自动进入休眠流程。
低版本的linux内核 还有earlysuspend.c,earlysuspend是假休眠(只关闭部分外设的电源)的一种机制,linux 3.10中已被抛弃。


如何进入休眠?
1、当autosleep开启,当所有wakelock都释放时,自动进入休眠。
     autosleep.c 中,try_to_suspend 函数调用 pm_get_wakeup_count ,执行:
1.  for (;;) {
2.                prepare_to_wait(&wakeup_count_wait_queue, &wait,
3.               TASK_INTERRUPTIBLE);


    可以看出,一直等到wakelock 被释放,pm_get_wakeup_count 才返回。进入调用 pm_suspend或hibernate休眠。
2、echo mem > /sys/power/state ,强制进入休眠。
       执行该命令,系统会直接进入休眠,不再判断是否有没释放的wakelock。(低版本内核中,执行该命令,仍需要等待wakelock释放)。


wakelock 是为休眠唤醒而存在的。可以查询相关资料进一步了解。
cat /sys/power/wake_lock可以看到当前哪个Android锁处于激活状态。(/sys/power/wake_lock 并不统计内核的锁)。


如何禁止自动进入休眠?
1、在驱动源码中,初始化一个wakelock,并上锁,不释放。
1. #include <linux/wakelock.h>
2. struct wake_lock no_suspend_lock;


内核中的锁类型很简单,只有WAKE_LOCK_SUSPEND。(低版本内核中多了WAKE_LOCK_IDLE)。
   缺点: 只能保证不进入休眠,屏幕却被灭了。


2、在Android中加锁
Android 定义了以下几种WakeLock类型:
       *  FULL_WAKE_LOCK    保持屏幕全亮、键盘背光灯点亮和CPU运行。
        *  SCREEN_BRIGHT_WAKE_LOCK   保持屏幕全亮和CPU运行。
        *  SCREEN_DIM_WAKE_LOCK   保持屏幕开启(但是让它变暗)和CPU运行。


        *  PARTIAL_WAKE_LOCK   保持CPU运行。

可以根据需要,申请不同的锁类型。




猜你喜欢

转载自blog.csdn.net/zpcindy/article/details/79993066
今日推荐