华为充电管理之电池核心
battery_core.c 是华为电源管理框架的电池核心驱动,负责:
电池状态监控与数据采集
Power Supply 框架接口实现
电池健康度管理
UI 电量显示控制
一、核心数据结构
struct bat_core_capacity_level {
int min_cap;
int max_cap;
int level;
};
struct bat_core_monitor_para {
int min_cap;
int max_cap;
int interval;
};
struct bat_core_config {
int voltage_now_scale;
int voltage_max_scale;
int charge_fcc_scale;
int charge_rm_scale;
int coul_type;
int temp_type;
int work_para_cols;
int ntc_compensation_is;
struct bat_core_monitor_para work_para[BAT_CORE_WORK_PARA_ROW];
struct compensation_para temp_comp_para[BAT_CORE_NTC_PARA_LEVEL];
};
struct bat_core_data {
int exist;
int charge_status;
int health;
int ui_capacity;
int capacity_level;
int temp_now;
int cycle_count;
int fcc;
int voltage_max_now;
int capacity_rm;
};
struct bat_core_device {
struct device *dev;
struct power_supply *main_psy;
struct power_supply *aux_psy;
int work_interval;
struct delayed_work monitor_work;
struct wakeup_source *wakelock;
struct mutex data_lock;
struct notifier_block event_nb;
struct bat_core_config config;
struct bat_core_data data;
};
驱动核心对象是 struct bat_core_device *di(全局 g_bat_core_dev 也会保存一份)。
二、关键功能模块
2.1 Power supply属性接口
static enum power_supply_property bat_core_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CHARGE_FULL,
};
属性获取函数:
bat_core_get_prop(): 根据 coul_type (主/辅电池) 从库仑计读取数据
支持双电池系统 (COUL_TYPE_MAIN / COUL_TYPE_AUX)
2.2电池状态管理
核心 getter 函数:
| 函数 | 功能 | 数据来源 |
|---|
| bat_core_get_status() | 充电状态 | di->data.charge_status |
| bat_core_get_health() | 健康状态 | di->data.health |
| bat_core_get_temp() | 电池温度 | bat_core_temp() |
| bat_core_get_voltage_now() | 实时电压 | coul_interface |
| bat_core_get_ui_capacity() | UI 电量 | bat_ui_capacity() |
电量等级映射
// UI 电量 → 电量等级转换
0-5% → CRITICAL (危险)
5-15% → LOW (低)
15-95% → NORMAL (正常)
95-100% → HIGH (高)
100% → FULL (满)
2.3定期监控机制
static void bat_core_work(struct work_struct *work)
{
__pm_wakeup_event(di->wakelock, jiffies_to_msecs(HZ));
bat_core_update_data(di);
bat_core_update_work_interval(di);
queue_delayed_work(system_freezable_power_efficient_wq, &di->monitor_work,
msecs_to_jiffies(di->work_interval));
}
动态监控策略:
bat_core_update_work_interval(di) 让监控刷新频率随电量变化:
如果 health unknown:直接用 BAT_CORE_WORK_INTERVAL_ABNORMAL
如果 DTS 没配 work_interval_para:用默认 BAT_CORE_WORK_INTERVAL_NORMAL
否则读取 work_interval_para(min_cap、max_cap、interval),匹配当前 ui_capacity,选择对应 interval
// DTS 配置示例
work_interval_para = <
0 20 5000 // 0-20%: 5秒
20 80 10000 // 20-80%: 10秒
80 100 5000 // 80-100%: 5秒
>;
这个动态监控测率
根据电量区间动态调整监控频率
低电量时缩短间隔 (快速响应)
正常电量可延长间隔 (省电)
低电/异常状态更频繁刷新,高电/稳定状态降低刷新频率省电。
2.4 温度补偿算法
2.4.1 温度读取入口
bat_core_temp(di) 是统一入口:
static int bat_core_temp(struct bat_core_device *di)
{
if (temp_type == BAT_CORE_TEMP_TYPE_MIXED) {
bat_temp_get_temperature(BAT_TEMP_MIXED, &raw_temp);
} else {
raw_temp = coul_interface_get_battery_temperature();
raw_temp = bat_core_ntc_compensation_temp(di, raw_temp, bat_curr);
}
}
2.4.2 NTC 补偿参数来自 DTS
bat_core_parse_temp_para() 从 device tree 读取:
补偿逻辑里会根据当前电流(abs(cur_temp))查表/计算,最终输出补偿后的温度,并打印:
temp_compensation=... temp_no_comp=... ichg=...
防止大电流充电时温升影响温度读数
补偿参数通过 DTS 配置
2.5 健康度的判定
static void bat_core_update_health(struct bat_core_device *di)
{
if (!di->data.exist) {
health = POWER_SUPPLY_HEALTH_UNKNOWN;
} else if (temp_now == BAT_CORE_TEMP_UNKNOWN) {
health = POWER_SUPPLY_HEALTH_UNKNOWN;
} else if (bat_fault_is_cutoff_vol()) {
health = POWER_SUPPLY_HEALTH_UNDERVOLTAGE;
bat_fault_send_under_voltage_event();
} else if (temp_now < BAT_CORE_COLD_TEMP) {
health = POWER_SUPPLY_HEALTH_COLD;
} else if (temp_now > BAT_CORE_OVERHEAT_TEMP) {
health = POWER_SUPPLY_HEALTH_OVERHEAT;
} else {
health = POWER_SUPPLY_HEALTH_GOOD;
}
}
bat_core_update_health(di) 负责把 di->data.health 更新为标准 power_supply health:
判定顺序大致是:
电池不在位:HEALTH_UNKNOWN
温度未知:HEALTH_UNKNOWN
如果 bat_fault_is_cutoff_vol():HEALTH_UNDERVOLTAGE,并触发 bat_fault_send_under_voltage_event()
温度过低 < BAT_CORE_COLD_TEMP:HEALTH_COLD
温度过高 > BAT_CORE_OVERHEAT_TEMP:HEALTH_OVERHEAT
否则:HEALTH_GOOD
并且只在变化时打印 “health change from x to y”。
2.6 充电状态更新
static void bat_core_update_charge_status(struct bat_core_device *di, int status)
{
if ((status == POWER_SUPPLY_STATUS_CHARGING) &&
(di->data.ui_capacity == BAT_CORE_CAPACITY_FULL)) {
cur_status = POWER_SUPPLY_STATUS_FULL;
}
if (di->data.charge_status != cur_status) {
di->data.charge_status = cur_status;
power_supply_sync_changed("Battery");
power_supply_sync_changed("battery");
}
}
2.7 事件驱动的状态更新
驱动会注册一个事件通知:
power_event_bnc_register(POWER_BNT_CHARGING, &di->event_nb);
回调是 bat_core_event_notifier_call(),把事件映射为充电状态:
POWER_NE_CHARGING_START → POWER_SUPPLY_STATUS_CHARGING
POWER_NE_CHARGING_STOP → DISCHARGING
POWER_NE_CHARGING_SUSPEND → NOT_CHARGING
static int bat_core_event_notifier_call(struct notifier_block *nb,
unsigned long event, void *data)
{
switch (event) {
case POWER_NE_CHARGING_START:
status = POWER_SUPPLY_STATUS_CHARGING;
break;
case POWER_NE_CHARGING_STOP:
status = POWER_SUPPLY_STATUS_DISCHARGING;
break;
case POWER_NE_CHARGING_SUSPEND:
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
break;
}
bat_core_update_charge_status(di, status);
}
然后进 bat_core_update_charge_status(di, status):
这一步非常关键:它让系统/上层(包括 framework/界面)立刻感知状态变更,而不是等下一个 work 周期。
2.8 双库仑计支持
DTS 里会读 coul_type:
COUL_TYPE_MAIN
COUL_TYPE_AUX
或者两者都注册
bat_core_reg_guage_psy() 会按配置注册:
battery_gauge
battery_gauge_aux
并且 bat_core_get_prop() 会通过 psy == di->aux_psy 来区分 type(main/aux),对同一套属性返回不同来源的数据。
2.9 电池故障通知
驱动注册了 bat_fault_register_ops(&g_bat_core_fault_ops),注册到故障管理模块
当 bat_core_fault_notify(event) 收到:POWER_NE_COUL_LOW_VOL
会 mod_delayed_work(..., 0) 立刻调度一次 monitor_work,把低压状态尽快刷新给系统。
bat_fault_register_ops(&g_bat_core_fault_ops);
static const struct bat_fault_ops g_bat_core_fault_ops = {
.notify = bat_core_fault_notify,
};
static void bat_core_fault_notify(unsigned int event)
{
struct bat_core_device *di = g_bat_core_dev;
if (!di)
return;
switch (event) {
case POWER_NE_COUL_LOW_VOL:
mod_delayed_work(system_freezable_power_efficient_wq, &di->monitor_work,
msecs_to_jiffies(0));
break;
default:
break;
}
hwlog_info("fault event notify=%d\n", event);
}
其实就是通知链,当其他模块call chain时会调用到这里
比如在bat_fault_cutoff_vol_event_handle中
static void bat_fault_cutoff_vol_event_handle(struct bat_fault_device *di)
{
bat_fault_notify(POWER_NE_COUL_LOW_VOL);
}
三、DTS配置解析
bat_core_parse_dts() {
coul_type = COUL_TYPE_MAIN | COUL_TYPE_AUX | COUL_TYPE_BOTH
temp_type = BAT_CORE_TEMP_TYPE_RAW_COMP | BAT_CORE_TEMP_TYPE_MIXED
ntc_compensation_is = 1
ntc_temp_compensation_para = <
1000 -2
2000 -5
>
voltage_now_scale = 1000000
voltage_max_scale = 1000000
charge_fcc_scale = 1000
}
四、初始化流程
bat_core_probe()
├── 1. 分配设备结构体
├── 2. 解析 DTS 配置
├── 3. 初始化数据 (默认值)
├── 4. 注册 Power Supply 操作集
├── 5. 注册充电事件通知
├── 6. 注册 battery_gauge PSY
├── 7. 创建唤醒锁
├── 8. 启动监控任务
└── 9. 注册故障回调
五、模块依赖
battery_core.c
├── coul_interface (库仑计接口)
├── bat_ui_capacity (UI 电量算法)
├── bat_model (电池模型)
├── bat_temp (温度管理)
├── bat_fault (故障检测)
└── power_supply (Linux 电源框架)
六、调试接口
查看日志关键字: battery_core
监控节点:
关键函数打点:
七、流程图
<script setup>
import umlUrl from './images/UML_battery_core.svg?url'
</script>
高清大图:流程图高清