对于现代便携设备而言,电源管理的重要性不言而喻。想象一下,当你正在用手机处理重要工作或玩游戏时突然电量告急,那种焦虑感想必大家都深有体会。作为嵌入式开发者,我们需要从硬件到软件构建一套完整的电源管理体系,让设备在有限的电池容量下发挥最大效能。
典型的便携设备电源管理系统需要解决三大核心问题:
在Android系统中,这套管理体系被划分为四个清晰的层次,就像一座精心设计的金字塔:
这一层是我们最熟悉的部分,主要负责:
核心工作机制是通过监听系统广播(如ACTION_BATTERY_CHANGED)获取电源状态更新。这里有个实用技巧:应用应该注册动态广播而非静态广播,因为电池状态变化可能非常频繁。
BatteryService是这个层的核心组件,它像一位尽职的邮差:
特别值得注意的是,BatteryService运行在system_server进程中,这意味着它拥有较高的系统权限,可以访问底层硬件信息。
Healthd守护进程是这个层的关键角色,它的工作流程如下:
在Android 8.0之后,Healthd被重构为Health 2.0 HAL,采用更模块化的设计,方便厂商定制。
这是我们今天要重点剖析的部分。内核中的Power Supply子系统就像一位会说多种语言的翻译官,它:
这个精巧的设计使得上层应用无需关心硬件细节,只需通过标准接口就能获取电源信息。
走进drivers/power/目录,我们会发现Power Supply子系统由三个核心部分组成:
核心逻辑(power_supply_core.c)
Sysfs接口(power_supply_sysfs.c)
LED指示(power_supply_leds.c)
这种模块化设计使得子系统可以灵活扩展,厂商可以根据需要选择实现哪些功能。
这个结构体就像PSY设备的"身份证",记录了设备的所有关键信息:
c复制struct power_supply {
const struct power_supply_desc *desc; // 设备描述符
struct device dev; // 关联的设备结构
struct work_struct changed_work; // 状态变化工作队列
bool changed; // 状态变化标志
// ... 其他成员省略 ...
};
在实际开发中,我们通常会把这个结构体嵌入到自己的设备私有数据结构中,实现面向对象的设计。
这个描述符定义了PSY设备的"能力清单":
c复制struct power_supply_desc {
const char *name; // 设备名称
enum power_supply_type type; // 设备类型(电池/USB/无线等)
enum power_supply_property *properties;// 支持的属性列表
size_t num_properties; // 属性数量
int (*get_property)(...); // 属性读取回调
int (*set_property)(...); // 属性设置回调
// ... 其他成员省略 ...
};
开发新驱动时,我们需要仔细填写这个描述符,告诉子系统我们的设备能做什么。
c复制// 注册PSY设备
struct power_supply *power_supply_register(
struct device *parent,
const struct power_supply_desc *desc,
const struct power_supply_config *cfg);
// 注销PSY设备
void power_supply_unregister(struct power_supply *psy);
注册流程通常发生在驱动的probe函数中。这里有个重要细节:注册时会自动创建sysfs属性文件,所以desc中的properties数组必须提前初始化好。
c复制void power_supply_changed(struct power_supply *psy);
当检测到硬件状态变化(如插拔充电器)时,驱动应该调用这个函数。它会:
在实际项目中,这个函数通常在中断处理程序或轮询定时器中被调用。
现代便携设备的充电系统通常采用三层架构:
策略层(Charger Manager)
计量层(Fuel Gauge)
执行层(Charger IC)
这种分层设计使得各模块职责清晰,便于维护和调试。
Charger Manager是充电系统的大脑,它的设备树配置通常包含这些关键参数:
dts复制charger-manager {
compatible = "charger-manager";
cm-name = "battery";
cm-poll-interval = <15000>; // 15秒轮询间隔
cm-fullbatt-voltage = <4350000>; // 满电电压4.35V
cm-fullbatt-current = <120000>; // 截止电流120mA
cm-jeita-temp-table = < // JEITA温度补偿表
1000 1030 700000 4200000 // 低温区间
1450 1420 2000000 4400000 // 常温区间
1600 1570 700000 4200000>; // 高温区间
// ... 其他配置省略 ...
};
温度补偿是充电管理的重点难点。上表中的参数含义是:
电池计量IC驱动通常需要实现这些功能:
c复制static enum power_supply_property sc27xx_fgu_props[] = {
POWER_SUPPLY_PROP_STATUS, // 充电状态
POWER_SUPPLY_PROP_VOLTAGE_NOW, // 实时电压
POWER_SUPPLY_PROP_CURRENT_NOW, // 实时电流
POWER_SUPPLY_PROP_CAPACITY, // 剩余容量
// ... 其他属性 ...
};
static int sc27xx_fgu_get_property(...) {
switch (psp) {
case POWER_SUPPLY_PROP_CAPACITY:
// 实现电量计算算法
val->intval = calculate_capacity();
break;
// ... 其他case处理 ...
}
}
电量计算是其中最复杂的部分,通常需要考虑:
以常见的开关充电IC为例,关键操作包括:
c复制static int fan54015_set_charging(struct power_supply *psy, bool enable)
{
// 控制充电使能引脚
if (enable)
regmap_set_bits(regmap, FAN54015_CONTROL0, EN_CHG);
else
regmap_clear_bits(regmap, FAN54015_CONTROL0, EN_CHG);
// 通知状态变化
power_supply_changed(psy);
return 0;
}
实际项目中还需要处理:
定义设备属性
c复制static enum power_supply_property my_psy_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
// ... 添加其他支持的属性 ...
};
实现回调函数
c复制static int my_psy_get_property(...)
{
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
val->intval = gpiod_get_value(charger_detect_gpio);
break;
// ... 其他属性处理 ...
}
return 0;
}
注册PSY设备
c复制static int my_psy_probe(...)
{
struct power_supply_config cfg = { .drv_data = private_data };
psy_desc = devm_kzalloc(dev, sizeof(*psy_desc), GFP_KERNEL);
psy_desc->name = "my_charger";
psy_desc->type = POWER_SUPPLY_TYPE_USB;
psy_desc->properties = my_psy_props;
psy_desc->num_properties = ARRAY_SIZE(my_psy_props);
psy_desc->get_property = my_psy_get_property;
psy = devm_power_supply_register(dev, psy_desc, &cfg);
// ... 错误处理 ...
}
实现状态监控
c复制static irqreturn_t charger_detect_irq(int irq, void *devid)
{
struct my_private_data *data = devid;
power_supply_changed(data->psy);
return IRQ_HANDLED;
}
Sysfs接口检查
bash复制# 查看所有PSY设备
ls /sys/class/power_supply/
# 查看具体属性
cat /sys/class/power_supply/battery/voltage_now
Uevent监控
bash复制# 监控电源相关事件
udevadm monitor --property --subsystem=power_supply
内核日志分析
bash复制dmesg | grep power_supply
属性读取返回-EINVAL
状态变化未通知上层
电量显示不准确
这是一种高级充电策略,可以:
实现要点:
c复制static void update_charge_current(struct charger_device *chg)
{
int system_load = calculate_system_load();
int available_current = input_current_limit - system_load;
if (available_current > 0)
charger_dev_set_charging_current(chg, available_current);
else
charger_dev_enable(chg, false);
}
通过监控这些参数评估电池健康状态(SoH):
可以在驱动中实现:
c复制static int calculate_soh(struct battery_info *info)
{
int soh = 100 * info->current_full_cap / info->design_cap;
soh -= info->resistance_growth / 1000;
return clamp(soh, 0, 100);
}
现代充电IC通常支持多种快充协议:
驱动需要:
避免高频轮询消耗CPU资源:
c复制// 在设备树中配置合理的轮询间隔
cm-poll-interval = <15000>; // 15秒
// 驱动中使用delayed_work实现轮询
static void poll_worker(struct work_struct *work)
{
struct my_data *data = container_of(work, struct my_data, poll_work.work);
// 执行轮询操作
check_status();
// 重新调度
schedule_delayed_work(&data->poll_work, msecs_to_jiffies(data->poll_interval));
}
合理使用中断替代轮询:
c复制// 注册充电状态变化中断
data->irq = gpiod_to_irq(data->status_gpio);
ret = request_irq(data->irq, charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"charger_status", data);
对于复杂的电源拓扑,可以使用通知链:
c复制// 注册通知链
BLOCKING_NOTIFIER_HEAD(power_supply_notifier);
// 发送通知
blocking_notifier_call_chain(&power_supply_notifier, event, psy);
必须实现的保护措施:
c复制static void safety_monitor(struct charger_device *chg)
{
if (voltage > max_voltage) {
charger_dev_enable(chg, false);
log_error("Over voltage detected!");
}
// ... 其他检查 ...
}
保护敏感电池参数:
c复制static int verify_calibration_data(struct fgu_data *data)
{
if (data->calib_resistance < MIN_RESISTANCE ||
data->calib_resistance > MAX_RESISTANCE)
return -EINVAL;
// ... 其他校验 ...
}
模拟器测试
硬件在环测试
构建自动化测试脚本:
python复制class ChargerTest(unittest.TestCase):
def test_charging_sequence(self):
# 模拟插入充电器
write_sysfs("online", "1")
time.sleep(1)
# 验证充电状态
status = read_sysfs("status")
self.assertEqual(status, "Charging")
必须覆盖的场景:
随着无线充电普及,驱动需要:
AI在电源管理的应用:
为新型电池做准备:
电源管理是嵌入式系统中最具挑战性的领域之一,需要开发者具备跨学科知识。通过深入理解Power Supply子系统的设计原理和实现细节,我们可以构建出更高效、更安全的电源管理系统。记住,好的电源管理应该像优秀的管家一样——既能让设备发挥最佳性能,又能确保能源的高效利用。