MT8735 andorid7.0 充电调试总结(2)——电池驱动流程关键代码分析
2017-12-06 21:02
1896 查看
battery_common.c首先是进行电池驱动的一些初始化工作,之后调用函数
kthread_run(bat_thread_kthread,NULL, "bat_thread_kthread");创建一个线程。这个线程每10秒钟执行一次,里面会调用BAT_thread();在这个函数里面完成的电池驱动的大部分主要事务。
//Battery_common.c (drivers\kernel-3.18\drivers\power\mediatek)1548442017/11/1
void BAT_thread(void)
{
static kal_bool battery_meter_initilized = KAL_FALSE;
static int first_time_update;
if (battery_meter_initilized == KAL_FALSE) {
battery_meter_initial();/* move from battery_probe() to decrease booting time */
BMT_status.nPercent_ZCV = battery_meter_get_battery_nPercent_zcv();
battery_meter_initilized = KAL_TRUE;
}
mt_battery_charger_detect_check();
if (fg_battery_shutdown)
return;
mt_battery_GetBatteryData();
if (fg_battery_shutdown)
return;
if (BMT_status.charger_exist == KAL_TRUE)
check_battery_exist();
mt_battery_thermal_check();
mt_battery_notify_check();
if (first_time_update == 0) {
mt_battery_update_status();
if (BMT_status.charger_exist == KAL_TRUE) {
mt_battery_CheckBatteryStatus();
mt_battery_charging_algorithm();
}
first_time_update = 1;
} else {
if (BMT_status.charger_exist == KAL_TRUE && !fg_battery_shutdown) {
mt_battery_CheckBatteryStatus();
mt_battery_charging_algorithm();
}
mt_battery_update_status();
}
mt_kpoc_power_off_check();
}
下面着重分析这里面的函数
battery_meter_initial();完成电池电量、zcv和电池内阻的初始化工作。
signed int battery_meter_initial(void)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
static kal_bool meter_initilized = KAL_FALSE;
mutex_lock(&FGADC_mutex);
if (meter_initilized == KAL_FALSE) {
#ifdef MTK_MULTI_BAT_PROFILE_SUPPORT
fgauge_get_profile_id();
#endif
#if defined(SOC_BY_AUXADC)
g_auxadc_solution = 1;
table_init();
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_AUXADC done\n");
#endif
#if defined(SOC_BY_HW_FG)
fgauge_initialization();
fgauge_algo_run_init();
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_HW_FG done\n");
#endif
#if defined(SOC_BY_SW_FG)
g_auxadc_solution = 1;
table_init();
oam_init();
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_SW_FG done\n");
#endif
meter_initilized = KAL_TRUE;
}
mutex_unlock(&FGADC_mutex);
return 0;
#endif
我们先看一下有硬件电量计(定义SOC_BY_HW_FG)的执行流程。
函数fgauge_initialization和fgauge_algo_run_init做的工作有一些重复,主要完成的操作有:
1. 初始化电量计
2. 在fgauge_construct_battery_profile_init里面根据cust_battery_meter_table.h里面的信息重构zcv表格,分50个等级,每2%一级。
3. 读取电池温度,电池容量等信息。并根据当前温度重构电池内阻表和zcv表。
4. 读取闭路电压,并用函fgauge_compensa
b4a6
te_battery_voltage_recursion计算出开路电压,主要是做了一个电压补偿,具体的原理我现在也不是很明白,大家有空的话,可以研究一下。之后用开路电压查找zcv表计算电池剩余容量。
5. 调用函数battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV,&gFG_voltage),直接从PMIC读取电池的开路电压,并计算电池剩余容量。
6. 读取rtc里面保存的电量值和从4和5里面计算出来的电量值做对比判断,选择合适的电量值作为电池的初始电量。
(a)函数mt_battery_charger_detect_check完成充电器是否插入的判断。
(b)函数mt_battery_GetBatteryData主要完成电池信息的获取,获取电池电压,电流和温度等信息。过程中会调用函数fgauge_algo_run,此函数输出的log信息对调试电池电量不准的问题有很大的帮助。
mt_battery_GetBatteryData()读取电池相关信息:电压、电流、充电器电压、电池温度,通过SOC
= battery_meter_get_battery_percentage();来获取电池电量百分比。里面会调fgauge_algo_run()这个函数来循环获取电量值,原理上与dod0值的获取类似
这个log打印了大部分我们需要的信息,有充电状态,电流,电量计数值,zcv计算电量,电量计计算电量等等。当机器用的是硬件电量计的时候,zcv计算的电量实际上在这里只是起到参考作用,并不会影响系统的电量显示和使用。如果软件zcv表格是正确的,但这里的zcv计算电量和电量计计算电量相差比较大,这时候就要考虑调节电池容量的大小,一般在放电过程中zcv计算电量比电量计计算电量大,就要适当的增加电池容量,反之则减少。
电池容量设的太小,会出现电量显示1%时还能用很久的现象,太大则会出现低电量时电量下降的很快,或还没到0%就关机了。
(c)函数mt_battery_thermal_check则实现温度的监控,当电池问题高于设定温度,一般是60度时系统会强制关机。
(d)函数mt_battery_notify_check则实现温度,电压和电量等一些异常并通知android层,最终提示给用户。
(e)当有充电器插入时,系统会运行mt_battery_CheckBatteryStatus检查电池的一些状态,从而决定充电与否,里面包含了高低温,充电器电压,是否在通话状态和充电时间等检测。
(f)函数mt_battery_charging_algorithm完成充电算法。这里两种充电方式,一是PMIC充电的Liner_charging和外部充电IC的Switch_charging。一般来说Switch_charging的充电电流要比Liner_charging大。mt_battery_charging_algorithm()完成充电算法:PMIC充电的Liner_charging和外部充电IC的Switch_charging
两种充电方式的主流程其实区别不大,基本都包含了预充电,恒流充电,满电判断和二次充电。
有时候会出现充满电时,电池电压偏低的情况,这时候可以适当提高充电电压或者减少充电截止电流。
Liner_charging主流程:
Swicth_charging主流程:
(e)函数mt_battery_update_status主要实现将电池,充电等状态更新到android层,如电量,充电器是否插入等等。
当电量比较低的时候battery_update里面会调用到mt_battery_0Percent_tracking_check 电池电压小于SYSTEM_OFF_VOLTAGE时,BMT_status.UI_SOC减少到0,这时android上层会接收到电量等于0的更新,并发送命令关闭机器。
(f)mt_kpoc_power_off_check()实现关机充电时对charger的检测
以上就是电池驱动的大体流程
总结:
大家只要搞清楚BAT_thread()这个函数,应该对整个充放电流程就比较清晰了。至于HW/SWFuel
gague这两种电量计在软件上的具体区别:
kthread_run(bat_thread_kthread,NULL, "bat_thread_kthread");创建一个线程。这个线程每10秒钟执行一次,里面会调用BAT_thread();在这个函数里面完成的电池驱动的大部分主要事务。
//Battery_common.c (drivers\kernel-3.18\drivers\power\mediatek)1548442017/11/1
void BAT_thread(void)
{
static kal_bool battery_meter_initilized = KAL_FALSE;
static int first_time_update;
if (battery_meter_initilized == KAL_FALSE) {
battery_meter_initial();/* move from battery_probe() to decrease booting time */
BMT_status.nPercent_ZCV = battery_meter_get_battery_nPercent_zcv();
battery_meter_initilized = KAL_TRUE;
}
mt_battery_charger_detect_check();
if (fg_battery_shutdown)
return;
mt_battery_GetBatteryData();
if (fg_battery_shutdown)
return;
if (BMT_status.charger_exist == KAL_TRUE)
check_battery_exist();
mt_battery_thermal_check();
mt_battery_notify_check();
if (first_time_update == 0) {
mt_battery_update_status();
if (BMT_status.charger_exist == KAL_TRUE) {
mt_battery_CheckBatteryStatus();
mt_battery_charging_algorithm();
}
first_time_update = 1;
} else {
if (BMT_status.charger_exist == KAL_TRUE && !fg_battery_shutdown) {
mt_battery_CheckBatteryStatus();
mt_battery_charging_algorithm();
}
mt_battery_update_status();
}
mt_kpoc_power_off_check();
}
下面着重分析这里面的函数
battery_meter_initial();完成电池电量、zcv和电池内阻的初始化工作。
signed int battery_meter_initial(void)
{
#if defined(CONFIG_POWER_EXT)
return 0;
#else
static kal_bool meter_initilized = KAL_FALSE;
mutex_lock(&FGADC_mutex);
if (meter_initilized == KAL_FALSE) {
#ifdef MTK_MULTI_BAT_PROFILE_SUPPORT
fgauge_get_profile_id();
#endif
#if defined(SOC_BY_AUXADC)
g_auxadc_solution = 1;
table_init();
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_AUXADC done\n");
#endif
#if defined(SOC_BY_HW_FG)
fgauge_initialization();
fgauge_algo_run_init();
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_HW_FG done\n");
#endif
#if defined(SOC_BY_SW_FG)
g_auxadc_solution = 1;
table_init();
oam_init();
bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_SW_FG done\n");
#endif
meter_initilized = KAL_TRUE;
}
mutex_unlock(&FGADC_mutex);
return 0;
#endif
我们先看一下有硬件电量计(定义SOC_BY_HW_FG)的执行流程。
函数fgauge_initialization和fgauge_algo_run_init做的工作有一些重复,主要完成的操作有:
1. 初始化电量计
2. 在fgauge_construct_battery_profile_init里面根据cust_battery_meter_table.h里面的信息重构zcv表格,分50个等级,每2%一级。
3. 读取电池温度,电池容量等信息。并根据当前温度重构电池内阻表和zcv表。
4. 读取闭路电压,并用函fgauge_compensa
b4a6
te_battery_voltage_recursion计算出开路电压,主要是做了一个电压补偿,具体的原理我现在也不是很明白,大家有空的话,可以研究一下。之后用开路电压查找zcv表计算电池剩余容量。
5. 调用函数battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV,&gFG_voltage),直接从PMIC读取电池的开路电压,并计算电池剩余容量。
6. 读取rtc里面保存的电量值和从4和5里面计算出来的电量值做对比判断,选择合适的电量值作为电池的初始电量。
(a)函数mt_battery_charger_detect_check完成充电器是否插入的判断。
(b)函数mt_battery_GetBatteryData主要完成电池信息的获取,获取电池电压,电流和温度等信息。过程中会调用函数fgauge_algo_run,此函数输出的log信息对调试电池电量不准的问题有很大的帮助。
mt_battery_GetBatteryData()读取电池相关信息:电压、电流、充电器电压、电池温度,通过SOC
= battery_meter_get_battery_percentage();来获取电池电量百分比。里面会调fgauge_algo_run()这个函数来循环获取电量值,原理上与dod0值的获取类似
这个log打印了大部分我们需要的信息,有充电状态,电流,电量计数值,zcv计算电量,电量计计算电量等等。当机器用的是硬件电量计的时候,zcv计算的电量实际上在这里只是起到参考作用,并不会影响系统的电量显示和使用。如果软件zcv表格是正确的,但这里的zcv计算电量和电量计计算电量相差比较大,这时候就要考虑调节电池容量的大小,一般在放电过程中zcv计算电量比电量计计算电量大,就要适当的增加电池容量,反之则减少。
电池容量设的太小,会出现电量显示1%时还能用很久的现象,太大则会出现低电量时电量下降的很快,或还没到0%就关机了。
(c)函数mt_battery_thermal_check则实现温度的监控,当电池问题高于设定温度,一般是60度时系统会强制关机。
(d)函数mt_battery_notify_check则实现温度,电压和电量等一些异常并通知android层,最终提示给用户。
(e)当有充电器插入时,系统会运行mt_battery_CheckBatteryStatus检查电池的一些状态,从而决定充电与否,里面包含了高低温,充电器电压,是否在通话状态和充电时间等检测。
(f)函数mt_battery_charging_algorithm完成充电算法。这里两种充电方式,一是PMIC充电的Liner_charging和外部充电IC的Switch_charging。一般来说Switch_charging的充电电流要比Liner_charging大。mt_battery_charging_algorithm()完成充电算法:PMIC充电的Liner_charging和外部充电IC的Switch_charging
两种充电方式的主流程其实区别不大,基本都包含了预充电,恒流充电,满电判断和二次充电。
有时候会出现充满电时,电池电压偏低的情况,这时候可以适当提高充电电压或者减少充电截止电流。
Liner_charging主流程:
Swicth_charging主流程:
(e)函数mt_battery_update_status主要实现将电池,充电等状态更新到android层,如电量,充电器是否插入等等。
当电量比较低的时候battery_update里面会调用到mt_battery_0Percent_tracking_check 电池电压小于SYSTEM_OFF_VOLTAGE时,BMT_status.UI_SOC减少到0,这时android上层会接收到电量等于0的更新,并发送命令关闭机器。
(f)mt_kpoc_power_off_check()实现关机充电时对charger的检测
以上就是电池驱动的大体流程
总结:
大家只要搞清楚BAT_thread()这个函数,应该对整个充放电流程就比较清晰了。至于HW/SWFuel
gague这两种电量计在软件上的具体区别:
相关文章推荐
- MT8735 andorid7.0 充电调试总结(3)——移植外部充电IC bq24298
- MT8735 andorid7.0 充电调试总结(1)——MTK电源管理(MT6318)
- mt8735 andorid7.0 lcm调试总结
- 一个FTP客户的简单的代码流程+简要总结分析
- MTK平台下Battery驱动分析及充电流程
- linux驱动调试之段错误分析_根据pc值确定出错的代码位置
- Android状态栏显示电池状态代码流程分析
- MapReduce关键流程代码分析
- MTK平台下Battery驱动分析及充电流程
- S3c2410软件调试总结、启动代码分析大杂烩
- dm9000驱动代码流程分析
- LED设备驱动二之重要代码和调试问题分析
- S3C2410软件调试总结和启动代码分析
- android电池充电以及电量检测驱动分析
- wince dm9000驱动代码流程分析--转载
- android电池充电以及电量检测驱动分析
- android电池充电以及电量检测驱动分析
- android电池充电以及电量检测驱动分析
- [Android6.0][RK3399] 电池系统(三)电量计 CW2015 驱动流程分析【转】
- 【转】android电池(五):电池 充电IC(PM2301)驱动分析篇