MTK电量统计与充电模式分析
1.初始化电量,关机后插入充电器(sw fg)
bat_thread_kthread
BAT_thread
battery_meter_initial();
table_init(); 主要是根据温度得到内阻R的表和OCV表
oam_init();
battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable); //停止充电
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &gFG_voltage); //HW_OCV
ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &g_booting_vbat); //VBAT电压
gFG_capacity_by_v = fgauge_read_capacity_by_v(gFG_voltage); //以这个为主
vbat_capacity = fgauge_read_capacity_by_v(g_booting_vbat);
¥第一个判断
if (bat_is_charger_exist() == KAL_TRUE) //充电器存在
if (((gFG_capacity_by_v == 100) && (vbat_capacity < CUST_POWERON_MAX_VBAT_TOLRANCE(90))) //(HW_OCV_C == 100 && VBAT_C < 90)
|| (abs(gFG_capacity_by_v - vbat_capacity) > CUST_POWERON_DELTA_VBAT_TOLRANCE)) //HW_OCV_C - VBAT_C +-30, 绝对值
gFG_voltage = g_booting_vbat; //使用VABT电压
gFG_capacity_by_v = vbat_capacity; //使用VBAT的容量
}
}
gFG_capacity_by_v_init = gFG_capacity_by_v; //第一个判断得到的电池容量
dod_init
gFG_capacity_by_sw_ocv = gFG_capacity_by_v; //第一个判断得到的电池容量
battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &gFG_voltage); //HW_OCV
gFG_capacity_by_v = fgauge_read_capacity_by_v(gFG_voltage); //第二次得到HW_OCV容量
¥第二个判断
if ((abs(gFG_capacity_by_v_init - gFG_capacity_by_v) > 5) && (bat_is_charger_exist() == KAL_TRUE)) {
gFG_capacity_by_v = gFG_capacity_by_v_init; //第一次判断得到的容量比第二次HW_OCV绝对值大5,则使用第一次
}
g_rtc_fg_soc = get_rtc_spare_fg_value(); //得到rtc电量
¥第三个判断
if (((g_rtc_fg_soc != 0) && (((abs(g_rtc_fg_soc - gFG_capacity_by_v)) <= CUST_POWERON_DELTA_CAPACITY_TOLRANCE)
|| (abs(gFG_capacity_by_v_init - g_rtc_fg_soc) < abs(gFG_capacity_by_v - gFG_capacity_by_v_init))))
|| ((g_rtc_fg_soc != 0)
&& (g_boot_reason == BR_WDT_BY_PASS_PWK || g_boot_reason == BR_WDT
|| g_boot_reason == BR_TOOL_BY_PASS_PWK || g_boot_reason == BR_2SEC_REBOOT
|| g_boot_mode == RECOVERY_BOOT)))
gFG_capacity_by_v = g_rtc_fg_soc;
B = gFG_capacity_by_v_init - g_rtc_fg_soc < gFG_capacity_by_v - gFG_capacity_by_v_init ) //abs(第一次判断得到的容量 - rtc) < abs (第二次判断得到的容量 - 第一次判断得到的容量)。
化简: A = ((g_rtc_fg_soc != 0) && (((abs(g_rtc_fg_soc - gFG_capacity_by_v)) <= CUST_POWERON_DELTA_CAPACITY_TOLRANCE)
|| (abs(gFG_capacity_by_v_init - g_rtc_fg_soc) < abs(gFG_capacity_by_v - gFG_capacity_by_v_init))))
( g_rtc_fg_soc 不等于0) && ( g_rtc_fg_soc - gFG_capacity_by_v //绝对值小于20 || B)
C = ((g_rtc_fg_soc != 0) && (g_boot_reason == BR_WDT_BY_PASS_PWK || g_boot_reason == BR_WDT
|| g_boot_reason == BR_TOOL_BY_PASS_PWK || g_boot_reason == BR_2SEC_REBOOT
|| g_boot_mode == RECOVERY_BOOT))
总判断 = A || C 成立,就使用rtc电量 ,这里我们这样调节CUST_POWERON_DELTA_CAPACITY_TOLRANCE, g_rtc_fg_soc
if (gFG_capacity_by_v == 0 && bat_is_charger_exist() == KAL_TRUE) { //开机后电量不可能为0
gFG_capacity_by_v = 1;
二.运行时电量计算,第一次开机,或者关机充电也需要进入(D5算法基本不需要容量,只是逼近ocv)
mt_battery_GetBatteryData();
bat_vol = battery_meter_get_battery_voltage(KAL_TRUE);
battery_meter_get_battery_percentage
oam_run();
battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &vol_bat);
oam_i_1 = (((oam_v_ocv_1 - vol_bat) * 1000) * 10) / oam_r_1; /* 0.1mA */
oam_i_2 = (((oam_v_ocv_2 - vol_bat) * 1000) * 10) / oam_r_2; /* 0.1mA */ 这都是battery_meter_initial初始化得到的值
oam_d_1 = oam_d0 + (oam_car_1 * 100 / 10) / gFG_BATT_CAPACITY_aging; //这就是得到的初始化电量
oam_v_ocv_1 = vol_bat + mtk_imp_tracking(vol_bat, oam_i_2, 5); //得到内阻的补偿
mtk_imp_tracking
ret_compensate_value = ((ori_current) * (gFG_resistance_bat + R_FG_VALUE + FG_METER_RESISTANCE)) / 1000; //两个重要参数
oam_d_3 = fgauge_read_d_by_v(oam_v_ocv_1); //得到容量
........经错一系列的计算逼近得到oam_d_5
SOC = 100 - oam_d_5
BMT_status.SOC = SOC; //赋值电量
三.更新电量
mt_battery_update_status();
battery_update(&battery_main);
if ((BMT_status.charger_exist == KAL_TRUE) && (BMT_status.bat_charging_state != CHR_ERROR))
mt_battery_100Percent_tracking_check //显示充电到100%的条件
if (BMT_status.bat_full == KAL_TRUE) //这个为KAL_TRUE,四.检查充电状态这里改变这个状态
/* increase UI percentage every xxs */
if (timer_counter >= (cust_sync_time / BAT_TASK_PERIOD)) { //大于等于1就可以了
timer_counter = 1;
BMT_status.UI_SOC++;
} else {
timer_counter++;
return resetBatteryMeter;
}
set_rtc_spare_fg_value(BMT_status.UI_SOC); //设置RTC,不小于1
mt_battery_update_EM //更新上层读取的文件节点,有的已经在前面更新了
bat_data->BAT_CAPACITY = BMT_status.UI_SOC; //电量
power_supply_changed(bat_psy); //更新sysfs内容,供上层读取
四.检查充电状态
if (BMT_status.charger_exist == KAL_TRUE)
mt_battery_charging_algorithm(); //Switch_charging.c (kernel-3.10\drivers\power\mediatek)
case CHR_CC:
BAT_ConstantCurrentModeAction(); //恒流充电状态下
if (charging_full_check() == KAL_TRUE) { //这里是检查bq24296是否是充满状态,如果是
BMT_status.bat_charging_state = CHR_BATFULL;
BMT_status.bat_full = KAL_TRUE;
g_charging_full_reset_bat_meter = KAL_TRUE;
charging_full_check
battery_charging_control(CHARGING_CMD_GET_CHARGING_STATUS, &status);
ret_val = bq24296_get_chrg_stat();
if(ret_val == 0x3) //如果等于3就是充满了
*(kal_uint32 *)data = KAL_TRUE;
五.检测充电模式
mt_battery_charger_detect_check
if (upmu_is_chr_det() == KAL_TRUE) //如果charge存在,主要是查看pmic的寄存器
mt_charger_type_detection();
battery_charging_control(CHARGING_CMD_GET_CHARGER_TYPE, &CHR_Type_num);
charging_get_charger_type //Charging_hw_fan5405.c (kernel-3.10\drivers\misc\mediatek\power\mt6735)
/********* Step initial ***************/
hw_bc11_init(); //单独分析1, BC11协议初始化
if(1 == hw_bc11_DCD()) //单独分析2,检测是否是标准充电器
/********* Step A1 ***************/
相应的寄存器描述if(1 == hw_bc11_stepA1()) //单独分析3,检测是不是苹果充电器,苹果充电器,D+,和D-不是短接*(CHARGER_TYPE*)(data) = APPLE_2_1A_CHARGER;,//苹果2.A充电器esle*(CHARGER_TYPE*)(data) = NONSTANDARD_CHARGER; //不标准充电器else/********* Step A2 ***************/if(1 == hw_bc11_stepA2()) //单独分析4,标准充电器就是D+,D-短接,用到BC1.X标准,附件有/********* Step B2 ***************/if(1 == hw_bc11_stepB2()) //单独分析5*(CHARGER_TYPE*)(data) = STANDARD_CHARGER;else*(CHARGER_TYPE*)(data) = CHARGING_HOST;else*(CHARGER_TYPE*)(data) = STANDARD_HOST;hw_bc11_done //结束检测Charger_Detect_Release(); 、、
单独分析1
hw_bc11_init(); //BC1.1协议初始化
Charger_Detect_Init
//turn on USB reference clock.
usb_enable_clock(true);
//wait 50 usec.
udelay(50);
/* RG_USB20_BC11_SW_EN = 1'b1 */
USBPHY_SET8(0x1a, 0x80);
//RG_bc11_BIAS_EN=1 //进行一些寄存器的设置,初始化状态
bc11_set_register_value(PMIC_RG_BC11_BIAS_EN,1);
//RG_bc11_VSRC_EN[1:0]=00
bc11_set_register_value(PMIC_RG_BC11_VSRC_EN,0);
//RG_bc11_VREF_VTH = [1:0]=00
bc11_set_register_value(PMIC_RG_BC11_VREF_VTH,0);
//RG_bc11_CMP_EN[1.0] = 00
bc11_set_register_value(PMIC_RG_BC11_CMP_EN,0);
//RG_bc11_IPU_EN[1.0] = 00
bc11_set_register_value(PMIC_RG_BC11_IPU_EN,0);
//RG_bc11_IPD_EN[1.0] = 00
bc11_set_register_value(PMIC_RG_BC11_IPD_EN,0);
//bc11_RST=1
bc11_set_register_value(PMIC_RG_BC11_RST,1);
//bc11_BB_CTRL=1
bc11_set_register_value(PMIC_RG_BC11_BB_CTRL,1);
单独分析2
hw_bc11_DCD
//RG_bc11_IPU_EN[1.0] = 10,,
bc11_set_register_value(PMIC_RG_BC11_IPU_EN,0x2);
//RG_bc11_IPD_EN[1.0] = 01,,
bc11_set_register_value(PMIC_RG_BC11_IPD_EN,0x1);
//RG_bc11_VREF_VTH = [1:0]=01,,
bc11_set_register_value(PMIC_RG_BC11_VREF_VTH,0x1);
//RG_bc11_CMP_EN[1.0] = 10
bc11_set_register_value(PMIC_RG_BC11_CMP_EN,0x2);
wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT);,得到结果
单独分析3
//RG_bc11_IPD_EN[1.0] = 01
bc11_set_register_value(PMIC_RG_BC11_IPD_EN,0x1);
//RG_bc11_VREF_VTH = [1:0]=00
bc11_set_register_value(PMIC_RG_BC11_VREF_VTH,0x0);
//RG_bc11_CMP_EN[1.0] = 01
bc11_set_register_value(PMIC_RG_BC11_CMP_EN,0x1);
wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT); //获取结果
单独分析4
hw_bc11_stepA2
//RG_bc11_VSRC_EN[1.0] = 10
bc11_set_register_value(PMIC_RG_BC11_VSRC_EN,0x2);
//RG_bc11_IPD_EN[1:0] = 01
bc11_set_register_value(PMIC_RG_BC11_IPD_EN,0x1);
//RG_bc11_VREF_VTH = [1:0]=00
bc11_set_register_value(PMIC_RG_BC11_VREF_VTH,0x0);
//RG_bc11_CMP_EN[1.0] = 01
bc11_set_register_value(PMIC_RG_BC11_CMP_EN,0x1);
wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT); //得到结果
单独分析5
hw_bc11_stepB2
//RG_bc11_IPU_EN[1:0]=10
bc11_set_register_value(PMIC_RG_BC11_IPU_EN,0x2);
//RG_bc11_VREF_VTH = [1:0]=01
bc11_set_register_value(PMIC_RG_BC11_VREF_VTH,0x1);
//RG_bc11_CMP_EN[1.0] = 01
bc11_set_register_value(PMIC_RG_BC11_CMP_EN,0x1);
wChargerAvail = bc11_get_register_value(PMIC_RGS_BC11_CMP_OUT);
六.CK3_01插入usb测试
1.插入usb,台式电脑
Charger_Detect_Init
hw_bc11_DCD()
hw_bc11_stepA2()
step A2 : Standard USB Host!
hw_bc11_done()
所以这里是STANDARD_HOST类型
[BAT_thread]Cable in, CHR_Type_num=1
充电的电流就是:
g_temp_input_CC_value = USB_CHARGER_CURRENT; //500ma
g_temp_CC_value = USB_CHARGER_CURRENT;
2.插入标准充电器
Charger_Detect_Init
hw_bc11_init()
hw_bc11_DCD()
hw_bc11_stepA2()
hw_bc11_stepB2()
step B2 : STANDARD CHARGER!
hw_bc11_done()
[BAT_thread]Cable in, CHR_Type_num=4
充电的电流就是
g_temp_input_CC_value = AC_CHARGER_CURRENT; //2A
g_temp_CC_value = AC_CHARGER_CURRENT;
七.充电协议BC1.2
MTK Fuel Gauge算法分析
Attachment List