Android电池管理体系(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhou12314/article/details/79379276
电池管理在Android系统中是一个重要的组成部分,它起的主要作用是检测我们的电池状态,剩余电量实时更新,高温报警,低电量关机等功能的实现。
Android的电池管理模块,从内核层到Android的应用层我大概分为了4层来理解,从上到下依次为,应用展示层,framwork层,本地框架层,内核驱动层,计划用3篇文章从下到上对这四个模块进行一个大概的介绍。
                

本篇文章着重介绍Linux内核电池驱动的实现细节。
驱动部分大概概括下流程是这样的:
Android内核中的电池驱动采取的是linux 内核驱动中的 power_supply子系统框架进行上报电池状态。power_supply主要通过sys文件系统向用户层提供读取电池状态的接口,路径为 /sys/class/power_supply/ , 该目录下通常会有 ac , battery, usb 三个目录,代表给Android系统供电的三种能源类型,其中电池的状态就在battery的目录下,当电池状态变化的时候会通过uevent通知上层,然后上层通过读取该目录下相应的值来动态的显示电池状态。
以充电芯片bq27x00为例,驱动具体代码分析如下:
   定义设备结构体,里面包含struct power_supply这个结构体, 
struct bq27x00_device_info {
	struct device 		*dev;
	int			id;
	enum bq27x00_chip	chip;
	struct bq27x00_reg_cache cache;
	int charge_design_full;

	unsigned long last_update;
	struct delayed_work work;

	struct power_supply	bat;

	struct bq27x00_access_methods bus;

	struct mutex lock;
};

绑定I2C设备和驱动:
static int __init bq27x00_battery_init(void)
{
	int ret;

	ret = bq27x00_battery_i2c_init();  //初始化i2c驱动
	if (ret)
		return ret;

	ret = bq27x00_battery_platform_init();  //绑定i2c设备
	if (ret)
		bq27x00_battery_i2c_exit();

	return ret;


在i2c驱动的bq27x00_battery_probe的函数中,调用bq27x00_powersupply_init函数,对power_supply这个结构体进行填充并调用power_supply_register进行注册,初始化定时器队列INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll); 然后调用bq27x00_update通过i2c对电池状态数据进行请求,然后更新sys/class/power_supply下的节点
   
static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
{
	int ret;
        di->bat.name = name;
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = bq27x00_battery_props;
	di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
	di->bat.get_property = bq27x00_battery_get_property;
	di->bat.external_power_changed = bq27x00_external_power_changed;
        //初始化定时器队列
	INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
	mutex_init(&di->lock);

	ret = power_supply_register(di->dev, &di->bat);
	if (ret) {
		dev_err(di->dev, "failed to register battery: %d\n", ret);
		return ret;
	}

	dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);

	bq27x00_update(di);

	return 0;
}



在bq27x00_battery_poll中开启定时器队列定时调用bq27x00_update()更新电池状态数据
static void bq27x00_battery_poll(struct work_struct *work)
{
	struct bq27x00_device_info *di =
		container_of(work, struct bq27x00_device_info, work.work);

	bq27x00_update(di);

	if (poll_interval > 0) {
		/* The timer does not have to be accurate. */
               //通过改变poll_interval可以改变定时器轮询时间
		set_timer_slack(&di->work.timer, poll_interval * HZ / 4);
		schedule_delayed_work(&di->work, poll_interval * HZ);
	}
}


bq27x00_update中主要做的事情如下:
       static void bq27x00_update(struct bq27x00_device_info *di)
{
	struct bq27x00_reg_cache cache = {0, };
	bool is_bq27500 = di->chip == BQ27500;

	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
	if (cache.flags >= 0) {
		if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
			dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
			cache.capacity = -ENODATA;
			cache.energy = -ENODATA;
			cache.time_to_empty = -ENODATA;
			cache.time_to_empty_avg = -ENODATA;
			cache.time_to_full = -ENODATA;
			cache.charge_full = -ENODATA;
		} else {
//以下对电池状态进行读取
			cache.capacity = bq27x00_battery_reaad_rsoc(di);
			cache.energy = bq27x00_battery_read_energy(di);
			cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
			cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
			cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
			cache.charge_full = bq27x00_battery_read_lmd(di);
		}
		cache.temperature = bq27x00_battery_read_temperature(di);
		cache.cycle_count = bq27x00_battery_read_cyct(di);

		/* We only have to read charge design full once */
		if (di->charge_design_full <= 0)
			di->charge_design_full = bq27x00_battery_read_ilmd(di);
	}

	if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) {
		di->cache = cache;
                //对/sys/class/power_supply节点进行更新
		power_supply_changed(&di->bat);
	}

	di->last_update = jiffies;
}


猜你喜欢

转载自blog.csdn.net/zhou12314/article/details/79379276
今日推荐