Android的电源管理

本文详细介绍了Linux内核中的电源管理原理,包括应用层操作、内核文件系统交互、电池供电驱动初始化及状态切换流程。重点分析了WakeLock机制、系统休眠与唤醒、GPIO配置、电池电压监测、电量采样与状态回调函数等关键概念,揭示了从电池供电驱动到电源状态管理的全过程。
摘要由CSDN通过智能技术生成


1.应用层操作

   PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); 

   PowerManager.WakeLock wl =pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); 

   wl.acquire(); //在释放之前,屏幕一直亮着(有可能会变暗,但是还可以看到屏幕内容) 

   wl.release();

 

<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DEVICE_POWER"/>


2.kernel中的文件

  在文件系统中有一个虚拟的文件:/sys/power/state

  向该文件写入字符串“mem”,则启动进入休眠的过程。

  向该文件写入字符串“on”,则手机退出休眠状态。

  state_store向文件写入字符串.

 

/kernel/kernel/power/earlysuspend.c //通用

/kernel/kernel/power/suspend.c //通用

/kernel/drivers/power/rk30_factory_adc_battery.c 电源的驱动实现, 与遥控驱动实现(remotectl)如出一辙.

/kernel/arch/arm/mach-rk30/board-rk30-box.c // 板级支持

int rk29_standby_led_suspend(void)

{

int i;

     //printk("\n+++yangchao+++func%s+++\n",__FUNCTION__);

#if 0

     int ret = 0;

     rk30_mux_api_set(STANDBY_MUX_NAME,STANDBY_MUX_MODE);

     ret =gpio_request(STANDBY_LED_GPIO, NULL);

     if (ret != 0) {

         printk("func %s,line %d: request gpio fail\n", __FUNCTION__, __LINE__);    

                gpio_free(STANDBY_LED_GPIO);

     }

     gpio_direction_output(STANDBY_LED_GPIO,0);

  #endif

  for (i=0; i<10; i++){

     gpio_set_value(STANDBY_LED_GPIO,i%2);

     msleep(100);

  }

     gpio_set_value(STANDBY_LED_GPIO,0);

     return 0;
}

 
 

3.kernel中几个文件之间的关系

3.1 从电池供电驱动入手, /kernel/drivers/power/rk30_adc_battery.c

rk30_adc_battery_data其中有中断号irq

#defineBATT_MAX_VOL_VALUE   8284 //满电时的电池电压   

#defineBATT_ZERO_VOL_VALUE  6800 //关机时的电池电压

#define BATT_NOMAL_VOL_VALUE  7600              

gpio_direction_output(pdata->charge_set_pin,pdata->charge_set_level);

 

rk30_adc_battery_platform_data.charge_set_pin充电级别设置

rk30_adc_battery_platform_data.dc_det_pin 充电级别寄存器

rk30_adc_battery_platform_data.charge_ok_pin 充电完成寄存器

什么关系? GPIO要研究一下. jiffies. INIT_WORK

jiffies为系统启动后的ticks. 除以时钟晶振频率即为秒数.

INIT_WORK是将中断处理函数加入工作队列, 实现对需要长时间处理的中断的延时调度.

3.2 电池供电驱动初始化函数:

rk30_adc_battery_probe

注意两个结构体:

rk30_adc_battery_data  *data

rk30_adc_battery_platform_data*pdata

在probe函数中, 为data分配空间. 然后把data赋值给全局变量gBatteryData.

并且data->pdata= data; 表示platform_data也被关联进入了全局的gBatteryData. 所以gBatteryData是一个非常重要的变量.

A.  rk30_adc_battery_io_init

这个函数初始化的是platform_data. 其中做的事情有:

初始化charge_set_pin, 这是充电控制引脚, 设置级别.

初始化dc_det_pin, 直流充电检测引脚.

初始化charge_ok_pin, 充电完成引脚.

初始化batt_low_pin, 低电量引脚.

以上四个引脚, 全部是GPIOPullUp.

B.  清空电压采样数组data->adc_samples

C.  注册电池状态回调函数

adc_register(0, rk30_adc_battery_callback, NULL);

此函数非常简单, 只是gBatteryData->adc_val= result;

问题: adc_val是电量多少的标识???

D.  供电方式注册. 包括USB供电, 电池供电, 直流供电

power_supply_register

直接会注册一个供电方式rk30_battery_supply.

从power_supply_register的内容来看, 可以注册多个供电方式. 主要任务是初始化power_supply结构体.

E.  wake_lock_init

F.  初始化data->wq, 电源工作队列

G.  rk30_adc_battery_timer_work

初始化定时器, 定时进行电量采样, 检查电量

H.  rk30_adc_battery_check

开机检查电池电量, 如果不够且有低电压保护功能, 则直接关机.

I.  将低电量中断信号的处理函数对应到lowerpower_work

rk30_adc_battery_lowerpower_delaywork对低电量时的处理

 

注册低电量中断响应函数

rk30_adc_battery_low_wakeup, 在这个函数中,实际上是将前面的函数加入工作队列gBatteryData->wq中.

3.3 电源系统管理核心/kernel/kernel/power/suspend.c

suspend.c是电源管理的核心模块. 其中有对几种模式的定义, 包括

const char *const pm_states[PM_SUSPEND_MAX] = {

#ifdef CONFIG_EARLYSUSPEND

   [PM_SUSPEND_ON]      = "on",

#endif

   [PM_SUSPEND_STANDBY] = "standby",

   [PM_SUSPEND_MEM]  = "mem",

};
以及基本不常用的hibernation模式(将所有数据写入disk, 然后关机).

 

核心变量struct platform_suspend_ops suspend_ops

A.  pm_suspend/enter_state 进入待机状态

总括性函数

B.  suspend_prepare待机之前的准备

在所有的待机被执行之前都会执行这一段代码, 主要是通知其他应用程序, 分配一个console, 以及停止其他进程.

C.  suspend_enter 待机完成之后执行这个函数

suspend_test(TEST_PLATFORM)

disable_nonboot_cpus

suspend_test(TEST_CPUS)

arch_suspend_disable_irqs

D.  suspend_devices_and_enter进入待机状态

3.4 待机在驱动层的实现/kernel/arch/arm/mach-rk30/pm.c

    rk30_pm_enter

static int__init rk30_pm_init(void)

    suspend_set_ops(&rk30_pm_ops);

 

static structplatform_suspend_ops rk30_pm_ops = {

   .enter     =rk30_pm_enter,

   .valid     =suspend_valid_only_mem,

   .prepare   =rk30_pm_prepare,

   .finish       =rk30_pm_finish,

};


suspend_valid_only_mem该函数表明只有mem的待机是被支持的, 即实现上电源管理只有两种状态, 一种是开机, 一种是mem的待机模式. 而suspend.c中定义的standby,hibernation并不支持.

rk30_pm_prepare,rk30_pm_finish只是对disable_hlt, enable_hlt的处理.

核心即是驱动层的rk30_pm_enter. 该函数主要是对GPIO的一些操作. 估计这些操作主要是对外部设备, 或者一些电量使用设备的判断操作.

 

3.5 state_store电源状态调用函数

该函数是写入待机状态, 主要调用了两个函数:

request_suspend_state

和enter_state

后者前面已经提及, 这里看一下request_suspend_state

       if (state == PM_SUSPEND_ON ||valid_state(state)) {

          error = 0;

          request_suspend_state(state);

       }, 


如果是请求待机, 则将early_suspend_work加入suspend_work_queue.

如果是开机, 则首先wake_lock(&main_wake_lock)禁止待机, 然后将late_resume_work加入suspend_work_queue.

suspend_work_queue是在wakelock.c中定义的任务队列:

suspend_work_queue= create_singlethread_workqueue("suspend");

3.6 待机过程的函数调用流程图

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值