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 待机过程的函数调用流程图