首页 > 编程知识 正文

powersupplycontroller用途,日产轩逸e power价格

时间:2023-05-05 02:48:28 阅读:277819 作者:4493

概述

对于便携式设备,如手机或者pad来说,battery都是必不可少的一个组成部分。kernel中为了方便对battery的管理,专门提供了power supply framework。battery管理我觉得可以分开为两个部分,一个是电池监控(fuelgauge),另一个是充放电管理(charger),所以我们在内核中也是把它分成了两个驱动来管理。fuelgauge驱动主要是负责向上层android系统提供当前电池的电量以及健康状态信息等等,另外除了这个以外,它也向charger驱动提供电池的相关信息;charger驱动主要负责电源线的插拔检测,以及充放电的过程管理。对于battery管理,硬件上有电量计IC和充放电IC,当然有些厂家为了成本的考虑,也会把电量计和充放电功能集成到一个IC上,更有甚者,可能会把PMU功能也集成在一块硅面上,actions就有相关方案。

power supply 框架

内核中有power manager(PM)子系统和power supply子系统,这两者负责的内容是不同的,PM子系统是系统电源管理策略的解决方案,更多的关注功耗控制。

1.编译选项

power supply framework所在的内核目录如下:

kernel/drivers/power

首先来看一下power目录下的Makefile和Kconfig:

Makefile:

1 ccflags-$(CONFIG_POWER_SUPPLY_DEBUG) := -DDEBUG 2 3 power_supply-y := power_supply_core.o 4 power_supply-$(CONFIG_SYSFS) += power_supply_sysfs.o 5 power_supply-$(CONFIG_LEDS_TRIGGERS) += power_supply_leds.o 6 7 obj-$(CONFIG_POWER_SUPPLY) += power_supply.o

Kconfig:

1 menuconfig POWER_SUPPLY 2 bool "Power supply class support" 3 help 4 Say Y here to enable power supply class support. This allows 5 power supply (batteries, AC, USB) monitoring by userspace 6 via sysfs and uevent (if available) and/or APM kernel interface 7 (if selected below).

由上面的编译选项可以看出,要想使能power supply功能,我们需要在kernel defconfig中定义CONFIG_POWER_SUPPLY功能,主要编译的文件是power_supply_core.c,如果内核中还配置了SYSFS和LEDS_TRIGGERS,那么power_supply_sysfs.c和power_supply_leds.c也会一起编译到内核中。

2.power supply core

内核抽象了一个供电设备为struct power_supply,定义在kernel/include/linux/power_supply.h头文件中:

235 struct power_supply {236 const char *name;237 enum power_supply_type type;238 enum power_supply_property *properties;239 size_t num_properties;240 241 char **supplied_to;242 size_t num_supplicants;243 244 char **supplied_from;245 size_t num_supplies;246 #ifdef CONFIG_OF247 struct device_node *of_node;248 #endif249 250 int (*get_property)(struct power_supply *psy,251 enum power_supply_property psp,252 union power_supply_propval *val);253 int (*set_property)(struct power_supply *psy,254 enum power_supply_property psp,255 const union power_supply_propval *val);256 int (*property_is_writeable)(struct power_supply *psy,257 enum power_supply_property psp);258 void (*external_power_changed)(struct power_supply *psy);259 void (*set_charged)(struct power_supply *psy);260 261 /* For APM emulation, think legacy userspace. */262 int use_for_apm;263 264 /* private */265 struct device *dev;266 struct work_struct changed_work;267 spinlock_t changed_lock;268 bool changed;269 struct wake_lock work_wake_lock;270 #ifdef CONFIG_THERMAL271 struct thermal_zone_device *tzd;272 struct thermal_cooling_device *tcd;273 #endif274 275 #ifdef CONFIG_LEDS_TRIGGERS276 struct led_trigger *charging_full_trig;277 char *charging_full_trig_name;278 struct led_trigger *charging_trig;279 char *charging_trig_name;280 struct led_trigger *full_trig;281 char *full_trig_name;282 struct led_trigger *online_trig;283 char *online_trig_name;284 struct led_trigger *charging_blink_full_solid_trig;285 char *charging_blink_full_solid_trig_name;286 #endif287 };

核心层代码实现了一个power_supply_class,用于抽象power_supply设备,这样有助于设备模型的统一,并且针对该class,可以在core中做统一处理,也方便于对同种类型设备的管理。

power_supply向外提供了接口以供具体驱动来使用,主要接口如下:

309 extern struct power_supply *power_supply_get_by_name(const char *name);310 extern void power_supply_changed(struct power_supply *psy);311 extern int power_supply_am_i_supplied(struct power_supply *psy);312 extern int power_supply_set_battery_charged(struct power_supply *psy);313 extern int power_supply_set_current_limit(struct power_supply *psy, int limit);314 extern int power_supply_set_online(struct power_supply *psy, bool enable);315 extern int power_supply_set_present(struct power_supply *psy, bool enable);316 extern int power_supply_set_scope(struct power_supply *psy, int scope);317 extern int power_supply_set_charge_type(struct power_supply *psy, int type);318 extern int power_supply_set_supply_type(struct power_supply *psy,319 enum power_supply_type supply_type);320 extern int power_supply_is_system_supplied(void);321 extern int power_supply_register(struct device *parent,322 struct power_supply *psy);323 extern void power_supply_unregister(struct power_supply *psy);324 extern int power_supply_powers(struct power_supply *psy, struct device *dev);

上面的register和unregister接口是用来注册和反注册power supply设备的接口,当该power supply设备中有监测信息变化时,使用 power_supply_changed接口用来通知上层的android服务,这种通知机制采用的是netlink socket接口来实现的,具体实现参见该函数体。最终函数会通过netlink socket发送出来一系列的字符串,比如“POWER_SUPPLY_NAME=battery”,当上层daemon服务程序收到该提醒后,就会去读取相应驱动提供的sysfs接口文件来获取相应的信息。

3.power supply sysfs

power supply子系统定义了一系列的sysfs文件,这样做也是为了power supply设备的标准化。虽然power_supply_class定义的一系列sysfs文件,但是它们并不全部显示出来,而是通过不同的struct power_supply结构体来决定显示哪些sysfs节点。

238 enum power_supply_property *properties;239 size_t num_properties;

这两个成员是用来定义特定power supply设备所具有的属性的,也就是对应着sysfs节点文件。另外power supply设备还要定义get_property和set_property回调函数,用来把相关的设备信息传递给上层。

4.power supply led

对于power supply led功能,比较简单,framework只负责提供几个API以供其他驱动调用:

31 extern void power_supply_update_leds(struct power_supply *psy); 32 extern int power_supply_create_triggers(struct power_supply *psy); 33 extern void power_supply_remove_triggers(struct power_supply *psy);

从函数名字可以看出来,这几个API分别就是创建和删除led_trigger,以及触发led。这几个API的实现基于内核LED框架,我们在power_supply驱动中如果要使能LED显示功能,首先需要定义power_supply结构体中的一系列LED触发器的名字,然后调用power_supply_create_triggers来创建相应名称的led_trigger。那么这个trigger name该如何定义呢?

从led子系统的相关实现来说起,led子系统中把led抽象成了两种设备,分别是led设备和led trigger设备,led设备主要关注于如何操作LED使其亮或者灭,而led trigger顾名思义就是触发器,这两种设备是相互关联的,一个led设备可以对应多个触发器,一个led trigger设备也可以对应多个led设备。在power supply中我们仅仅创建了一个led trigger,那么要想将它和led设备关联起来,就需要一个led设备,并且该led的设备的default trigger名字要设置为该power supply相应的名字,由此在注册led trigger时才能将两者关联起来。那么在接下来的对led trigger的控制操作中,才会最终操作到对应的led设备上去。

fuelgauge & charger driver

通过对上面power supply的介绍,可以对内核中的框架用有个大致的了解,那么如何去编写fuelgauge和charger驱动呢?

其实内核只是提供了一个框架,我们通过相关的API接口,可以生成相同的sysfs文件,内核仅仅是定义了这些统一的模型以及一些标准的功能,那对于单个驱动,我们更关注的是如何驱动特定硬件来实现这些标准的功能。虽然各个环境都有不同,但是不管每个环境的硬件是什么,我们都需要根据datasheet,把硬件的功能封装起来,并最终抽象到一个power supply结构体中,然后注册到内核框架层中,由此来完成驱动。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。