1.电池曲线数据
高通平台:
FG电量计来计算电池电量
电池数据是电量计不可或缺的一部分
一个型号的电池数据是一份dts文件
2.电池数据分析
文件命名一般包含项目、厂商、电压、电容,如:xxx_xxx_xxmAh_xxx.dtsi
得到dtsi后可以根据情况做一些调整:电池电压,显示容量,电池ID电阻,热温度系数
Beta值,电池型号名称等内容需要修改/确认,如:黄色背景处数据
充电电流值和一些FG参数也需要关注,如蓝色标注
下面介绍一下这些节点:
qcom,max-voltage-uv:最大额定电压
qcom,nom-batt-capacity-mah:电池名义上的容量,单位mah,最新的好像不用这个节点了
qcom,batt-id-kohm:电池的电阻id
qcom,battery-beta:热温度系数Beta值,不太确定是做什么用的
qcom,battery-type:指出电池类型的字符串
qcom,fastchg-current-ma:指定最大的快速充电电流
qcom,fg-cc-cv-threshold-mv:从恒定电荷过度到恒定电压的一个电压阈值
qcom,fg-profile-data:一组十六进制的数据用来配置更加复杂的fuel gauge外设。有大量的参数用来配置硬件状态然后在软件中读取。
合入项目中:
项目一般是定义dts,然后通过#include dtsi 文件的方式扩展添加电池曲线。
如:某个项目中,是这样扩展电池曲线:
位置:kernel/msm-3.18/arch/arm/boot/dts/qcom/msm8909-mtp.dtsi
代码如下:
/ {
mtp_batterydata: qcom,battery-data {
qcom,rpull-up-kohm = <100>;
qcom,vref-batt-therm = <1800000>;
#include "batterydata-palladium.dtsi"
};
};
qcom,rpull-up-kohm : The vadc pullup resistor's resistance value in kOhms. vadc上拉电阻的阻值,单位是kohms
qcom,vref-batt-therm-uv : The vadc voltage used to make readings. vadc的电压,
正确识别出电池id是调试的基础:cat sys/class/power_supply/bms/battery_type
能够正确识别出电池厂商型号,对应正确的电池数据为检查通过。
3.充电模块配置
充电的大部分数据都需要在dts/dtsi里面配置
3.1电池最大充电电流(这部分有点不懂)
Qcom,fastchg-current-ma :Specifies the maximum fastcharge current.
Msm8952平台 是在电池数据中配置的,默认的代码逻辑是,PMI在pmi8950_charger:
qcom,qpnp-smbcharger模块中不配置数据。
compatible: Must be "qcom,qpnp-smbcharger"
检查方法:用adb方式检查
adb shell
echo 0x210F2 > sys/kernel/debug/spmi/spmi-0/address
cat data
数据表格如下:
3.2 AC充电器、usb充电电流
充电器的最大值来自于usb模块的设置;usb-pc的充电电流值同样来自于usb模块的设置,默认是500mA。
AC充电器与DC充电器的区别在于前者应用于交流电,而DC充电器应用直流电,AC充电器即交流电充电器,DC充电器则是直流充电器。
问题:usb模块的设置在哪里?
检查方式:使用电流检测仪器,接在usb线上可以直接读到电流数据。
3.3标准参数设置
充电ic的配置和电量计ic的配置dts,下面高亮的数据都是需要特定配置的。
qcom,qpnp-smbcharger {
spmi-dev-container; //默认 Must be included in the parent node to set up the spmi sub node devices.
compatible= "qcom,qpnp-smbcharger"; //模块名
#address-cells= <1>;
#size-cells= <1>;
qcom,iterm-ma= <100>; //停止充电截止电流,有FG后不再使用,默认配置
qcom,float-voltage-mv = <4400>; //充电电压(电池最大电压),会被电池数据覆盖,支持范围是3600mv到4500mv
qcom,resume-delta-mv= <100>; //回充电压,有FG后不再使用
qcom,bmd-pin-src= "bpd_thm_id"; //电池移除检测引脚配置,有四个值,但是不知道是干什么用的
//qcom,dc-psy-type= "Mains"; //DC_IN路充电,目前不使用
//qcom,dc-psy-ma= <1500>; //DC_IN路充电,目前不使用
qcom,bms-psy-name = "bms"; //必须定义,指向电量计名,用于报告电池容量的名称
qcom,battery-psy-name= "battery"; //需要,驱动代码有默认值,电池驱动注册的电池充电名字
qcom,thermal-mitigation= <1500 700 600 325>; //thermal_enginer的控制,不同thermal系统的电流极限值
qcom,vchg_sns-vadc= <&pmi8950_vadc>; //读取VCHG电压所需,可选,vadc节点的指针
qcom,vchg-adc-channel-id= <3>; //VCHG的通道,可选
qcom,pmic-revid= <&pmi8950_revid>; //PMI版本号。必须。pmic revid 模块的指针,需要特别指出,定义pmic 子类型
qcom,force-aicl-rerun; //AICL自动控制电流,需要,不懂
qcom,aicl-rerun-period-s= <180>; //AICL自动控制电流,时间间隔,需要
qcom,chg-inhibit-fg; //使用FG控制二次充电
qcom,autoadjust-vfloat; //检测充电时电池电压,需要
……
}
pmi8950_fg: qcom,fg {
spmi-dev-container;
compatible= "qcom,qpnp-fg"; //"qcom,qpnp-fg" for the FG driver.
#address-cells= <1>;
#size-cells= <1>;
qcom,resume-soc = <99>; //回充电量,启动二次充电的门限 soc to resume charging in percentage.
status= "okay";
qcom,bcl-lm-threshold-ma= <127>; //默认LPM-〉MPM LPM,MPM,HPM这三种模式的切换电流门限,不懂这三种模式
qcom,bcl-mh-threshold-ma= <405>; //默认 MPM-〉HPM
qcom,fg-iterm-ma= <150>; //显示100%电量的充电电流
qcom,fg-chg-iterm-ma= <100>; //硬件完全停止充电的电流
qcom,pmic-revid= <&pmi8950_revid>; //FG版本号,pmic revid模块的指针,用来定义pmic子类型
qcom,fg-cutoff-voltage-mv = <3400>; //关机电压,对应0%电压值;
//The voltage where the fuel gauge will steer the SOC to be zero.
qcom,fg-cc-cv-threshold-mv = <4390>; //CCàCV的电压值,影响100%电量显示
//This value should be 10 mV less than the float voltage configured in the charger.
//"qcom,autoadjust-vfloat"需要定义在charger driver中
qcom,cycle-counter-en;
qcom,capacity-learning-on;
qcom,vbat-estimate-diff-mv= <100>; //重启时OCV检测变化门限值
//qcom,fg-vbat-estimate-diff-mv 如果soc和电池的电流电阻的估计值不同于真实的电压值,则fuel gauge将重新做一个soc的估计当driver probes到时候
qcom,cl-max-increment-deciperc = <1>; //默认
qcom,cl-max-decrement-deciperc = <1>; //默认
qcom,fg-delta-soc =<1>; //电量触发中断百分比,就是电量改变多少后要上报
qcom,bad-battery-detection-enable;
qcom,hold-soc-while-full; //100%持满电锁,建议设置,电池充满就显示100%
qcom,thermal-coefficients= [B7 85 B2 49 71 35]; //NTC热温度系数用来读取电池热敏电阻,不知道做什么用的。重要。
qcom,cold-bat-decidegc= <(0)>; //HW-cold
qcom,cool-bat-decidegc= <(100)>; //SW-cool
qcom,hot-bat-decidegc =<550>; //HW-hot
qcom,warm-bat-decidegc= <450>; //Soft-warm
qcom,warm-bat-decidegc: Warm battery temperature in decidegC.
qcom,cool-bat-decidegc: Cool battery temperature in decidegC.
qcom,hot-bat-decidegc: Hot battery temperature in decidegC.
qcom,cold-bat-decidegc: Cold battery temperature in decidegC.
qcom,battery-data = <&qrd_batterydata>; //电池曲线加载,指向节点的指针,它包含电池曲线,用来支持charger/Fg
……
}
qcom,battery-data can also include any number of children nodes. These children nodes will be treated as battery profile data nodes.
自动输入限流器技术(AICL)
自动输入电流限制的功能是能够根据输入电源的提供,来选择最大电流选择的充电电流,能够将usb/ac/dc充电器相容。
根据充电芯片设定一个充电输入门限电压值,比如4.75v,当充电芯片的输入电压大于该门限电压值的时候,设置电流;
当输入电压没有下降或者是稍有下降但高于该门限电压时候,每次以100ma逐级提高充电器的输出电流,检测充电芯片的输入电压是否小于门限电压值,每次时间间隔为5~10ms,直到充电芯片的输入电压小于门限电压值,设定充电电流为前面一级或者前面两级较小电流充电,输入电压没有下降到该门限电压值,就以设定好的充电电流进行充电。保证以最大的充电电流,最小的时间完成充电,提高用户体验。
投票机制
充电的控制过程中有这样一种情况:比如你要设置一个输入电流限制的值,这个值跟温度有关系(温度高了你希望这个值小一点),跟充电器类型有关系,跟用户设置有关系,跟你是否用HVDCP有关系-->那么多决定因素,可是我们只可能设置一个值,有效的办法是这几种情况下都对应一个值,然后我们最终设置一个最小值,我们把每一个因素看成是一个clients,即选民,然后由选民进行vote,就像在这几个值中选择一个最合适的值。
completion机制
内核编程中常见的一种模式是,在当前线程之外需要初始化某个活动,然后等待该活动的结束。这个活动可以是:创建一个新的内核线程或者新的用户空间进程,对一个已有进程的某个请求,或者某种类型的硬件动作。我们可以用信号量来同步两个任务,内核有completion机制,他允许一个线程告诉另一个线程某个工作已经完成了。
completion---基于等待队列
同步函数一般都是成对出现,complete 和 wait_for_completion
read the followingregister to get nominal capacity of battery
Example reading register address 0
$ adb shell "echo 0 >/sys/kernel/debug/fg/sram/address"
$ adb shell "echo 4 >/sys/kernel/debug/fg/sram/count"
$ adb shell "cat/sys/kernel/debug/fg/sram/data"
this is the command to read FG SRAM register