华为电池核心之battery_model模块如果你做过 Android / Linux 设备,大概率见过这些现象:
问题不是 UI 写错了,而是:
真实世界的电池,本来就不“听话”。
battery_model 是一个“把真实电池变得看起来很乖”的软件模型。
硬件给我们的,其实是一些很不友好的原始数据:
电压(会随负载剧烈变化)
温度(慢半拍,还不线性)
剩余容量(会抖)
如果你直接把这些数据显示给用户——体验一定很差。
所以系统里一般会有两层:
一、模块概述 1.1 基本定位battery_model模块是华为电池管理系统的核心数据管理模块,负责电池型号识别、参数管理、品牌信息提取等关键功能。该模块作为电池系统的"身份证管理器",为其他电池相关模块提供统一的电池模型数据接口。
1.2 主要职责 二、核心功能详解 2.1 电池型号识别机制模块支持多种电池识别方式,按优先级顺序执行:
// 识别流程(battery_model.c:317-367)
类型匹配优先:通过电池SN类型字符串匹配
IIO电压读取:使用IIO子系统读取电池ID电压
ADC电压读取:通过传统ADC通道读取电压
默认值回退:所有方法失败时使用默认配置
2.1.1 类型匹配(bat_model_get_index_by_type) 2.1.2 电压匹配(bat_model_get_index_by_iio) 2.2 电池参数管理模块管理以下关键电池参数:
参数 函数 说明 最大电压 bat_model_get_vbat_max() 电池最大充电电压 设计FCC bat_model_get_design_fcc() 设计满充容量 实际FCC bat_model_get_fcc() 实际满充容量 技术类型 bat_model_get_technology() 电池技术(Li-ion等) 品牌信息 bat_model_get_brand() 电池品牌名称
2.3 电池阴极类型检测支持石墨/硅基电池识别:
enum {
BAT_MODEL_BAT_CATHODE_TYPE_INVALID = 0 ,
BAT_MODEL_BAT_CATHODE_TYPE_GRAPHITE,
BAT_MODEL_BAT_CATHODE_TYPE_SILICON,
BAT_MODEL_BAT_CATHODE_TYPE_MAX,
} ;
int bat_model_get_bat_cathode_type ( void ) ;
bool bat_model_match_silicon_battery ( void ) ;
bool bat_model_match_graphite_battery ( void ) ;
2.4 电池标识符匹配使用正则表达式匹配电池标识符:
static bool bat_model_identifier_match ( const char * identifier_pattern)
{
return power_regex_lite_is_matched ( identifier_pattern, token) ;
}
三、数据结构分析 3.1 核心数据结构 3.1.1 电池型号表结构(bat_model_table)
struct bat_model_table {
char name[ BAT_MODEL_NAME_LEN] ;
int id_vol_low;
int id_vol_high;
char sn_type[ BAT_MODEL_TYPE_LEN] ;
} ;
3.1.2 电池类型表结构(bat_types_table)
struct bat_types_table {
char types[ BAT_TYPES_LEN] ;
char identifier_pattern[ BAT_IDENTIFIER_PATTERN_LEN] ;
} ;
3.1.3 设备数据结构(bat_model_device)
struct bat_model_device {
struct device * dev;
struct bat_model_ops * ops;
struct bat_model_table tables[ BAT_MODEL_TABLE_ROWS] ;
struct bat_item_code si_item_codes[ BAT_MODEL_SI_ITEM_CODE_ROWS] ;
struct bat_types_table bat_types_tab[ BAT_TYPES_MAX_NUM] ;
struct mutex update_lock;
int si_item_codes_size;
int bat_num;
int bat_cathode_ext;
int table_size;
int id_adc_channel;
int id_index;
int default_index;
int fcc;
int design_fcc;
int vbat_max;
int technology;
unsigned int support_iio;
bool is_iio_init;
struct iio_channel * id_iio;
char brand[ BAT_MODEL_BRAND_LEN] ;
int bat_identifier_index;
int bat_identifier_len;
int is_qcom_fg;
} ;
3.2 操作函数接口(bat_model_ops)
struct bat_model_ops {
void * dev_data;
int ( * get_vbat_max) ( void * dev_data) ;
int ( * get_design_fcc) ( void * dev_data) ;
int ( * get_technology) ( void * dev_data) ;
int ( * is_removed) ( void * dev_data) ;
const char * ( * get_brand) ( void * dev_data) ;
} ;
四、关键算法实现 4.1 电池识别算法流程识别优先级:
bat_model_get_index() {
1. 尝试通过序列号识别 (bat_model_get_index_by_type)
└─> get_battery_type() 获取电池序列号
└─> 匹配 sn_type 字段
2. 尝试通过高通 FG 电压识别 (is_qcom_fg)
└─> power_platform_get_index_by_volt()
3. 尝试通过 IIO 通道识别 (support_iio)
└─> iio_read_channel_processed(id_iio, &id_volt)
4. 尝试通过 ADC 通道识别 (id_adc_channel)
└─> power_platform_get_adc_voltage()
5. 使用默认索引 (失败情况)
└─> 上报 DSM 异常
}
核心代码:
static void bat_model_get_index ( struct bat_model_device * di)
{
if ( ! bat_model_get_index_by_type ( di) )
return ;
if ( di-> is_qcom_fg)
if ( power_platform_get_index_by_volt ( & id_volt) >= 0 )
goto search_table;
if ( bat_model_get_index_by_iio ( di, & id_volt) >= 0 )
goto search_table;
id_volt = power_platform_get_adc_voltage ( di-> id_adc_channel) ;
search_table:
for ( i = 0 ; i < di-> table_size; i++ ) {
if ( ( id_volt >= di-> tables[ i] . id_vol_low) &&
( id_volt < di-> tables[ i] . id_vol_high) ) {
bat_model_set_brand ( di, i) ;
return ;
}
}
use_default:
bat_model_set_brand ( di, di-> default_index) ;
bat_model_report_dsm ( id_volt) ;
}
4.2 品牌信息解析算法从型号名称中提取品牌部分(第一个"_"前的内容)
解析FCC值(第二个"_"后的数字)
解析最大电压(第三个"_"后的数字,可选)
存储到设备数据结构中
bat_model_set_brand ( di, index) {
1. 提取品牌 ( 第1 段)
SUNWODA → di-> brand = "SUNWODA"
2. 提取容量 ( 第2 段)
4800 → di-> fcc = 4800 mAh
3. 提取最大电压 ( 第3 段)
4480 → di-> vbat_max = 4480 mV
}
示例:
型号名称: "SUNWODA_4800_4480"
解析结果:
brand = "SUNWODA"
fcc = 4800 mAh
vbat_max = 4480 mV
id_index = 匹配的索引
4.3 电池类型匹配算法 // 类型匹配流程(battery_model.c:193-227)
遍历电池类型表
查找匹配的类型字符串
获取对应的标识符模式
使用正则表达式匹配标识符
返回匹配结果
bat_model_get_bat_cathode_type ( ) {
1. 检查是否启用阴极扩展 ( bat_cathode_ext)
└─> 未启用 → 默认返回石墨基
2. 匹配硅基电池
└─> bat_model_match_silicon_battery ( )
└─> 读取电池标识符 ( get_battery_identifier)
└─> 正则匹配 bat_types_tab[ ] . identifier_pattern
└─> 匹配成功 → 硅基电池
3. 默认石墨基电池
}
DTS配置示例:
bat_types_pattern = <
"silicon" "^SI.*" // 硅基电池:标识符以 SI 开头
"graphite" "^GR.*" // 石墨基电池:标识符以 GR 开头
>;
电池识别示例:
场景 1:通过序列号识别
DTS 配置:
bat_id_table = <"SUNWODA_4800_4480" ... "004S">;
bat_cathode_ext = <1>;
识别流程:
1. get_battery_type() → "004"
2. bat_model_get_bat_cathode_type() → SILICON (硅基)
3. 追加后缀 → "004S"
4. 匹配成功 → index = 对应索引
5. 解析品牌 → brand = "SUNWODA", fcc = 4800
场景 2:通过 IIO 电压识别
DTS 配置:
bat_id_table = <"DESAY_4800_4480" 200000 400000 "005">;
support_iio = <1>;
识别流程:
1. iio_read_channel_processed() → 300000 μV (300mV)
2. 查找电压区间 → 200000 ≤ 300000 < 400000
3. 匹配成功 → tables[1]
4. 解析品牌 → brand = "DESAY", fcc = 4800
场景 3:ADC 识别失败,使用默认值
识别流程:
1. 所有识别方式失败
2. 使用 default_id_index = 0
3. brand = "Battery" (默认)
4. 上报 DSM 异常
五、配置选项 5.1 Kconfig配置
config HUAWEI_BATTERY_MODEL
bool "huawei battery model driver"
default n
help
Say Y here to enable battery model driver.
This driver provides a unified interface to battery model,
such as: battery name, rated capacity, etc.
It shields battery model differences between platforms.
5.2 设备树配置参数模块从设备树中读取以下配置参数:
参数 说明 默认值 bat_id_table 电池型号表(名称、电压范围、SN类型) - si_item_code SI项目代码表 - bat_types_pattern 电池类型与标识符模式映射表 - bat_cathode_ext 阴极扩展标志 0 bat_num 电池数量 1 design_fcc 设计满充容量 BAT_MODEL_INVALID_FCC id_adc_channel ADC通道号 BAT_MODEL_INVALID_CHANNEL default_id_index 默认索引 BAT_MODEL_DEFAULT_INDEX technology 技术类型 POWER_SUPPLY_DEFAULT_TECHNOLOGY bat_identifier_index 标识符索引 BAT_IDENTIFIER_INDEX (10) bat_identifier_len 标识符长度 BAT_IDENTIFIER_LEN (1) is_qcom_fg 高通电量计标志 0 support_iio IIO支持标志 0
设备树中的关键参数
battery_model {
compatible = "huawei,battery_model";
/* 电池 ID 映射表 (4 列: 型号名, 电压下限, 电压上限, 序列号类型) */
bat_id_table = <
"SUNWODA_4800_4480" 0 200000 "004" // ID 电压 0-200mV
"DESAY_4800_4480" 200000 400000 "005" // ID 电压 200-400mV
"ATL_4800_4480" 400000 600000 "006" // ID 电压 400-600mV
>;
/* SI 项目码 */
si_item_code = <"1234">;
/* 电池类型正则表 (2 列: 类型名, 正则模式) */
bat_types_pattern = <
"silicon" "^SI.*" // 硅基电池
"graphite" "^GR.*" // 石墨基电池
>;
/* 基础配置 */
bat_num = <1>; // 电池数量
bat_cathode_ext = <1>; // 启用阴极扩展识别
design_fcc = <4800000>; // 设计容量 (μAh)
id_adc_channel = <5>; // ADC 通道号
default_id_index = <0>; // 默认索引
technology = <1>; // POWER_SUPPLY_TECHNOLOGY_LION
/* 标识符配置 */
bat_identifier_index = <10>; // 标识符起始位置
bat_identifier_len = <1>; // 标识符长度
/* 平台相关 */
is_qcom_fg = <0>; // 是否高通 FG 平台
support_iio = <1>; // 是否支持 IIO 读取
};
六、与其他模块的交互关系 6.1 上游依赖模块
模块 交互方式 功能 power_platform 函数调用 获取ADC电压、高通平台电压 IIO子系统 IIO通道 读取电池ID电压 power_dts 设备树解析 加载配置参数 power_dsm 事件报告 电池识别失败诊断
6.2 下游服务模块
模块 交互方式 功能 battery_core 函数调用 提供电池型号、参数、品牌信息 power_supply 接口注册 电池属性查询接口 电池健康评估 数据查询 电池老化参数基准
6.3 关键交互接口 6.3.1 与battery_core的交互
int bat_model_get_vbat_max ( void ) ;
int bat_model_get_design_fcc ( void ) ;
int bat_model_get_technology ( void ) ;
const char * bat_model_get_brand ( void ) ;
int power_platform_get_adc_voltage ( int channel) ;
int power_platform_get_index_by_volt ( int * volt) ;
6.3.3 与power_dsm的交互
static void bat_model_report_dsm ( int id_vol)
{
unsigned char type[ 4 ] = { 0 } ;
char buf[ 128 ] = { 0 } ;
if ( power_cmdline_is_factory_mode ( ) )
return ;
get_battery_type ( type, BAT_MODEL_TYPE_LEN) ;
snprintf ( buf, sizeof ( buf) - 1 ,
"batt type=%s, id_vol=%d" , type, id_vol) ;
power_dsm_report_dmd ( POWER_DSM_BATTERY_DETECT,
POWER_DSM_BATTERY_DETECT_ERROR_NO, buf) ;
}
七、导出接口API 7.1 获取电池参数
int bat_model_get_vbat_max ( void ) ;
int bat_model_get_design_fcc ( void ) ;
int bat_model_get_technology ( void ) ;
int bat_model_is_removed ( void ) ;
const char * bat_model_get_brand ( void ) ;
const char * bat_model_name ( void ) ;
int bat_model_get_bat_cathode_type ( void ) ;
7.2 操作回调注册
struct bat_model_ops {
void * dev_data;
int ( * get_vbat_max) ( void * dev_data) ;
int ( * get_design_fcc) ( void * dev_data) ;
int ( * get_technology) ( void * dev_data) ;
int ( * is_removed) ( void * dev_data) ;
const char * ( * get_brand) ( void * dev_data) ;
} ;
int bat_model_register_ops ( struct bat_model_ops * ops) ;
八、sysfs调试接口节点路径:
/sys/class/hw_power/battery/battery_model/
├── bat_cathode_type (R) - 电池阴极类型 (0=石墨, 1=硅)
Debug 节点(需 CONFIG_POWER_DEBUG):
/sys/kernel/debug/power/bat_model/
├── id (R) - 电池 ID 索引
├── name (R) - 电池型号名称
├── brand (R) - 电池品牌
├── vbat_max (R) - 最大电压
├── rated_fcc (R) - 额定容量
关键日志点:
battery type is ... - 序列号类型
id vol is ... - ID 电压读数
index=X,fcc=X,vbat_max=X,brand=X - 识别结果
九、初始化流程
bat_model_probe()
├── 1. 分配设备结构体 (kzalloc)
├── 2. 初始化默认数据
│ ├── vbat_max = 4400 mV
│ ├── fcc = 3000 mAh
│ ├── brand = "Battery"
│ └── id_index = -1 (未识别)
├── 3. 解析 DTS 配置
│ ├── bat_id_table (ID 映射表)
│ ├── si_item_code (SI 码)
│ ├── bat_types_pattern (类型正则)
│ └── IIO 通道初始化
├── 4. 创建 Sysfs 节点
├── 5. 注册 Debug 接口
└── 6. 设置全局指针 g_bat_model_dev
十、模块依赖
battery_model.c
├── get_battery_type() (batt_info_pub.h)
├── get_battery_identifier() (batt_info_pub.h)
├── power_platform_get_adc_voltage()
├── power_regex_lite_is_matched()
├── iio_channel_get() (Linux IIO 框架)
└── power_dsm_report_dmd() (DSM 异常上报)
十一、典型应用场景系统启动时识别电池型号
影响充电曲线选择
影响电池健康度算法
影响 UI 容量显示
电池更换检测
识别新电池型号
售后诊断
battery_model模块是华为在电池管理领域技术积累的集中体现,通过精心的架构设计和算法优化,为移动设备提供了高性能、高可靠性、高安全性的电池模型管理解决方案。