對于便攜設(shè)備來說,電源管理更加的重要,因為電池電量有限,容易電量焦慮。除了省電管理外,還需要對電池進行監(jiān)控管理和充放電管理,這樣保護好電池和系統(tǒng),能用的更久。
1. Power supply框架都做些什么
這里我們以安卓為例:
APP 層:該部分屬于電量上報的最后的環(huán)節(jié)。其主要工作是:監(jiān)聽系統(tǒng)廣播并對 UI 作出相應(yīng)更新,包括電池電量百分比,充電狀態(tài),低電提醒,led 指示燈,異常提醒等。
FrameWork 層:本層的 Battery 服務(wù)使用 Java 代碼寫成,運行在 FrameWork 中的SystemServer 進程。該系統(tǒng)服務(wù)的主要作用是:監(jiān)聽電池信息變化消息,并將該消息以系統(tǒng)廣播的形式轉(zhuǎn)發(fā)至 Android 系統(tǒng)中各處。
Native 層:Healthd 守護進程屬于 Android Native 層的一個系統(tǒng)服務(wù),負責接受 Kernel Driver 層上報的 uevent 事件,對電池信息和充電狀態(tài)實時監(jiān)控。
Kernel 層:本層屬于電池的驅(qū)動部分,由 Charger-manager 驅(qū)動、充電 IC 驅(qū)動、Fuel 驅(qū)動構(gòu)成,負責與硬件交互,注冊 Power supply 屬性,并生成 uevent 上報 Native 層。包含充電狀態(tài)管理、電量統(tǒng)計與更新。
關(guān)機充電
關(guān)機充電是單獨啟動的一個 linux 應(yīng)用,通過系統(tǒng)調(diào)用直接讀取 sysfs 來獲取電池信息,init 進程會根據(jù)啟動模式來啟動 charge 服務(wù),不會啟動 android 相關(guān)進程。
我們這里只關(guān)注kernel層:
power supply framework在kernel/drivers/power/下。內(nèi)核抽象出來power supply子系統(tǒng)為驅(qū)動提供了統(tǒng)一的框架。功能包括:
1.抽象PSY設(shè)備的共性,向用戶空間提供統(tǒng)一的API
2.為底層PSY驅(qū)動的編寫,提供簡單、統(tǒng)一的方式。同事封裝并實現(xiàn)公共邏輯。
power supply class位于drivers/power/目錄中,主要由3部分組成(可參考下圖的軟件架構(gòu)):
1)power supply core,用于抽象核心數(shù)據(jù)結(jié)構(gòu)、實現(xiàn)公共邏輯。位于drivers/power/power_supply_core.c中。
2)power supply sysfs,實現(xiàn)sysfs以及uevent功能。位于drivers/power/power_supply_sysfs.c中。
3)power supply leds,基于linux led class,提供PSY設(shè)備狀態(tài)指示的通用實現(xiàn)。位于drivers/power/power_suppply_leds.c中。
最后,驅(qū)動工程師可以基于power supply class,實現(xiàn)具體的PSY drivers,主要處理平臺相關(guān)、硬件相關(guān)的邏輯。這些drivers都位于drivers/power/目錄下。
2. 相關(guān)數(shù)據(jù)結(jié)構(gòu)和接口
2.1 數(shù)據(jù)結(jié)構(gòu)
struct power_supply:用于抽象PSY設(shè)備
/* include/linux/power_supply.h */ struct power_supply { const struct power_supply_desc *desc;//PSY描述符 char **supplied_to; size_t num_supplicants; char **supplied_from; size_t num_supplies; struct device_node *of_node; /* Driver private data */ void *drv_data; /* private */ struct device dev; struct work_struct changed_work; struct delayed_work deferred_register_work; spinlock_t changed_lock; bool changed; bool initialized; bool removing; atomic_t use_cnt; #ifdef CONFIG_THERMAL struct thermal_zone_device *tzd; struct thermal_cooling_device *tcd; #endif #ifdef CONFIG_LEDS_TRIGGERS struct led_trigger *charging_full_trig; char *charging_full_trig_name; struct led_trigger *charging_trig; char *charging_trig_name; struct led_trigger *full_trig; char *full_trig_name; struct led_trigger *online_trig; char *online_trig_name; struct led_trigger *charging_blink_full_solid_trig; char *charging_blink_full_solid_trig_name; #endif };
struct power_supply_desc:該描述符定義了psy的屬性
/* Description of power supply */ struct power_supply_desc { const char *name;//PSY name enum power_supply_type type;//PSY類型 enum power_supply_usb_type *usb_types;//usb類型 size_t num_usb_types;//usb類型個數(shù) enum power_supply_property *properties;//該PSY具有的屬性列表 size_t num_properties;//屬性的個數(shù) /* * Functions for drivers implementing power supply class. * These shouldn't be called directly by other drivers for accessing * this power supply. Instead use power_supply_*() functions (for * example power_supply_get_property()). */ int (*get_property)(struct power_supply *psy,//用于獲取psy屬性的回調(diào)函數(shù) enum power_supply_property psp, union power_supply_propval *val); int (*set_property)(struct power_supply *psy,//用于設(shè)置psy屬性的回調(diào)函數(shù) enum power_supply_property psp, const union power_supply_propval *val); /* * property_is_writeable() will be called during registration * of power supply. If this happens during device probe then it must * not access internal data of device (because probe did not end). */ int (*property_is_writeable)(struct power_supply *psy,//返回指定的屬性值是否可寫(用于sysfs) enum power_supply_property psp); void (*external_power_changed)(struct power_supply *psy);//當一個PSY設(shè)備存在并且屬性發(fā)生改變時,power supply core會調(diào)用該回調(diào)函數(shù),通知PSY driver,以便讓它做出相應(yīng)的處理 void (*set_charged)(struct power_supply *psy); /* * Set if thermal zone should not be created for this power supply. * For example for virtual supplies forwarding calls to actual * sensors or other supplies. */ bool no_thermal; /* For APM emulation, think legacy userspace. */ int use_for_apm; };
power_supply_battery_info:管理靜態(tài)電池參數(shù)的推薦結(jié)構(gòu)
2.2 接口
power_supply_core.c主要負責設(shè)備狀態(tài)變化邏輯,power_supply_sysfs.c主要負責文件節(jié)點相關(guān)邏輯。
power_supply_changed:在驅(qū)動中檢測到硬件狀態(tài)發(fā)生變化,會通過該函數(shù)調(diào)度起psy中的changed_work。該工作隊列負責發(fā)送notifier(內(nèi)核內(nèi)不同模塊之間)和通過uevent進行change上報。
void power_supply_changed(struct power_supply *psy) { unsigned long flags; dev_dbg(&psy->dev, "%s ", __func__); spin_lock_irqsave(&psy->changed_lock, flags); psy->changed = true; pm_stay_awake(&psy->dev); spin_unlock_irqrestore(&psy->changed_lock, flags); schedule_work(&psy->changed_work); } EXPORT_SYMBOL_GPL(power_supply_changed);
power_supply_register:通過調(diào)用__power_supply_register負責注冊一個psy設(shè)備,一般在設(shè)備驅(qū)動的probe流程中調(diào)用
power_supply_get_by_name:通過名字獲取PSY指針
power_supply_put:釋放獲取到的PSY指針,與power_supply_get_by_name成對使用
3. 充電驅(qū)動
Charge Manger、Fuel Gauge、Charge IC,這三部分作為獨立的設(shè)備驅(qū)動均注冊到 Power-supply 中,每一個設(shè)備為單獨的 PSY。PSY 之間可以通過 power supply 屬性相互訪問。
fuel-gauge 跟 charge-ic是服務(wù)于 charge-manger,charge-manger 不需要了解硬件細節(jié),僅通過獲取相應(yīng)功能的 PSY 設(shè)備實例,通過這個 PSY 的屬性獲取相應(yīng)信息。
3.1 Charger Manager
Charger Manager 是充電的控制策略層,主要負責:
修復(fù)并更新電量百分比。
充電流程管理(charging,notcharging,discharging,full 充電狀態(tài)轉(zhuǎn)換管理)。
安全管理(Ovp,Health,Charge Time out)。
溫控管理(Jeita 功能,thermal 限流)。
電池電量顯示策略(充放電曲線)。
電池容量管理(容量自學(xué)習功能)。
Charger Manager 以“battery”名字注冊至 Power Supply 架構(gòu),會讀寫 Fuel Gauge 和 Charger IC 的 Power supply 屬性。
charger-manager { compatible = "charger-manager"; cm-name = "battery"; cm-poll-mode = <2>; //”_cm_monitor”輪詢模式 cm-poll-interval = <15000>;//”_cm_monitor”輪詢時間間隔 cm-battery-stat = <2>;//電池在位檢測方法,電壓法 cm-fullbatt-vchkdrop-ms = <30000>;//充滿電后,檢查復(fù)充條件的周期 cm-fullbatt-vchkdrop-volt = <84000>;//滿電后復(fù)充電壓條件 cm-fullbatt-voltage = <4350000>;//軟件滿電電壓判斷閾值,必須配置 cm-fullbatt-current = <120000>;;//軟件滿電電流判斷閾值,必須配置 cm-fullbatt-capacity = <100>;//電池滿電時百分比 cm-num-chargers = <1>;//charger ic數(shù)量 //cm-chargers = "sc2721_charger"; cm-chargers = "fan54015_charger";//charger ic名字 cm-fuel-gauge = "sc27xx-fgu";//fgu名字 /* in deci centigrade */ cm-battery-cold = <200>; cm-battery-cold-in-minus; cm-battery-hot = <800>; cm-battery-temp-diff = <100>; /* Allow charging for 6hr */ cm-charging-max = <36000000>; /* recovery charging after stop charging 45min */ cm-discharging-max = <2700000>; /* the interval to feed charger watchdog */ cm-wdt-interval = <0>; /* drop voltage in microVolts to allow shutdown */ cm-shutdown-voltage = <3470000>;//低電關(guān)機電壓 /* when 99% of the time is exceeded, it will be forced to 100% */ cm-tickle-time-out = <1500>; /* how much time to allow capacity change */ cm-one-cap-time = <60>;//允許電量增加1%最快時間 /* when the safe charging voltage is exceeded, stop charging */ cm-charge-voltage-max = <6500000>;//充電器過壓保護電壓閾值 /* drop voltage in microVolts to restart charging */ cm-charge-voltage-drop = <700000>;//復(fù)充電壓條件 //Jeita 溫控策略 cm-jeita-temp-table = <1000 1030 700000 4200000>, //不同溫度范圍內(nèi)的充電電流和充電截止電壓 <1150 1180 2000000 4400000>, //默認最大充電電流為2A <1450 1420 2000000 4400000>, //充電電壓為4.35V <1600 1570 700000 4200000>; regulator@0 { cm-regulator-name = "vddgen0"; cable@0 { cm-cable-name = "USB"; extcon = <&extcon_gpio>; }; }; };
充電溫控策略說明
電池溫度T(℃) | 充電電流 ICC(mA) | 充電截止電壓 VEOC(mV) |
---|---|---|
T≤0 | 700 | 4200 |
0
2000 |
4400 |
|
15≤T<45 | 2000 | 4400 |
45≤T<60 | 700 | 4200 |
T≥60 | 0 | 4200 |
bat: battery { compatible = "simple-battery"; charge-full-design-microamp-hours = <3900000>;//電池容量uAh charge-term-current-microamp = <200000>;//截止充電電流 constant_charge_voltage_max_microvolt = <4400000>;//截止充電電壓 factory-internal-resistance-micro-ohms = <115000>;//電池內(nèi)阻 voltage-min-design-microvolt = <3561000>;//Vocv低報警電壓 //電池容量 – 溫度補償表 capacity-temp-table = <60 100>, <40 100>, <25 100>, <0 100>, <(-10) 80>; //電池內(nèi)阻值 – 溫度補償表 resistance-temp-table = <60 60>, <40 70>, <25 100>, <0 328>, <(-20) 887>; };
3.2 Fuel Gauge
PMIC部分主要負責:
庫倫計電量積分
充電器類型獲取
電池在位檢測
開機電壓管理
內(nèi)阻 – 溫度,容量 – 溫度等補償算法
sc27xx_fuel_gauge 以“sc27xx-fgu”名字注冊至 Power supply 架構(gòu),提供屬性給 Charger Manager 讀寫。
pmic_fgu: fgu@a00 { compatible = "sprd,sc27xx-fgu", "sprd,sc2731-fgu"; reg = <0xa00>; bat-detect-gpio = <&pmic_eic 9 0>; nvmem-cell-names = "fgu_calib"; nvmem-cells = <&fgu_calib>; io-channels = <&pmic_adc 0>, <&pmic_adc 14>, <&pmic_adc 16>; io-channel-names = "bat-temp", "charge-vol", "charger-cur"; interrupt-parent = <&sc2721_pmic>; interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; monitored-battery = <&bat>; sprd,calib-resistance-real = <20000>;//庫侖計芯片真實采樣電阻 sprd,calib-resistance-spec = <20000>;//庫侖計芯片規(guī)格電阻 };
3.3 Charger IC
Charger IC 主要負責以下具體內(nèi)容:
打開/關(guān)閉充電
設(shè)置充電電流
設(shè)置截止充電電壓點
打開/關(guān)閉 OTG
以 Fan54015 為例,將“fan54015_charger”名字注冊至 Power supply 架構(gòu)。提供屬性給 Charger Manager讀寫。
&i2c3 { status = "okay"; clock-frequency = <400000>; fan54015_chg: charger@6a { compatible = "fairchild,fan54015_chg"; reg = <0x6a>; phys = <&hsphy>; monitored-battery = <&bat>; extcon = <&extcon_gpio>; vddvbus:otg-vbus { regulator-name = "vddvbus"; }; }; };
4. 怎樣基于power supply class編寫PSY driver
最后從PSY driver的角度,說明一下怎么基于power supply class編寫驅(qū)動:
(1)根據(jù)硬件spec,確定PSY設(shè)備具備哪些特性,并把他們和enum power_supply_property對應(yīng)。
(2)根據(jù)實際情況,實現(xiàn)這些properties的get/set接口。
(3)定義一個struct power_supply 變量,并初始化必要字段后,調(diào)用power_supply_register或者power_supply_register_no_ws,將其注冊到kernel中。
(4)根據(jù)實際情況,啟動設(shè)備屬性變化的監(jiān)控邏輯,例如中斷,輪詢等,并在發(fā)生改變時,調(diào)用power_supply_changed,通知power suopply core。
power supply子系統(tǒng)的引入 以市面上一款常見的的平板方案來看一看,進入平板的sys/class/power_supply/目錄下
可以看到這里有三個****PSY設(shè)備,分別對應(yīng)USB充電器DC充電器,和電池。
進入battery目錄下,發(fā)現(xiàn)下面有各種各樣的屬性,另外兩個atc260x-usb 、atc260x-wall目錄下分別也是這樣。
然后在內(nèi)核中找到對應(yīng)的代碼,進行學(xué)習,然后仿制一個出來就可以。以battery驅(qū)動為例來分析。
static int __init atc260x_gauge_init(void)
atc260x_gauge_probe(struct platform_device *pdev)
soc_post_process(struct atc260x_gauge_info *info)
power_supply_register(struct device *parent, struct power_supply *psy)
power_supply_changed(struct power_supply *psy)
在相關(guān)的函數(shù)上打點斷點,然后就可以學(xué)習了。
后記:
Linux內(nèi)核博大精深,里面的機制太多了,不調(diào)試或者工作涉及根本學(xué)不精。可以了解了解概念和數(shù)據(jù)結(jié)構(gòu)。遇到了先調(diào)試,必須知道了再去查資料研究,學(xué)不完,根本學(xué)不完。。。
-
電源管理
+關(guān)注
關(guān)注
116文章
6319瀏覽量
145613 -
接口
+關(guān)注
關(guān)注
33文章
8873瀏覽量
152932 -
Linux
+關(guān)注
關(guān)注
87文章
11414瀏覽量
212256 -
安卓
+關(guān)注
關(guān)注
5文章
2140瀏覽量
58167 -
電池
+關(guān)注
關(guān)注
84文章
10874瀏覽量
133252
原文標題:電源管理入門-17 Power supply子系統(tǒng)
文章出處:【微信號:OS與AUTOSAR研究,微信公眾號:OS與AUTOSAR研究】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
電源管理入門-Regulator驅(qū)動是什么?Regulator的作用是什么?

電源管理入門:Power Domain管理

External-Sync Power Supply
HIGH CURRENT OFF LINE POWER SUPPLY
ATX Switching power supply 開關(guān)電源電路
Power Supply and Ground Design for a WiFi Transceiver
什么是穩(wěn)壓電源(Regulated Power Supply)
高通平臺power_supply 框架下添加第三方充電IC的驅(qū)動方法 精選資料分享
【學(xué)習打卡】OpenHarmony的電源管理服務(wù)子系統(tǒng)介紹
Power Supply Management—Principles
防火墻原理入門

Power Supply Topologies電源拓撲結(jié)構(gòu)
個人導(dǎo)航設(shè)備的電源管理子系統(tǒng)設(shè)計

評論