在嵌入式系统中,电源管理(Power Management)并不是“可选项”,而是实际部署中影响系统稳定性、功耗、安全性的重要一环。今天我们将以 Linux 电源管理框架 为基础,从理论结构、内核架构,再到典型驱动实战(如 regulator、suspend/resume、runtime PM)进行完整讲解。
我们先从几个实际场景开始思考:
这些需求背后,其实都依赖于 Linux 的电源管理子系统。
Linux 电源管理包含多个层次,我们可以从高到低划分为以下几类:
电源管理类别 | 对应机制 |
---|---|
系统电源管理(System PM) | suspend / hibernate |
运行时电源管理(Runtime PM) | 自动 suspend/resume |
设备电源管理(Device PM) | regulator、clk、gpio 控制等 |
SoC 电源域管理 | PM Domain(power domain)支持 |
它们之间是逐层调用、逐层配合的关系:
系统进入 suspend
└── 内核调度设备进入 suspend
└── 驱动实现 -> suspend() 回调
└── 控制 regulator / clk / GPIO / power-domain
Regulator 是 Linux 电源管理最核心的子系统之一,用于控制 PMIC 提供的电压通道(如 BUCKx、LDOx)。
devm_regulator_get()
获取指定供电通道// 在 probe 中获取电源
struct regulator *vdd_supply;
vdd_supply = devm_regulator_get(&pdev->dev, "vdd");
// 上电
regulator_enable(vdd_supply);
// 下电
regulator_disable(vdd_supply);
Runtime PM 支持“设备空闲时自动挂起”,比如 USB 摄像头、I2C 外设等。
pm_runtime_enable(&dev->dev);
开启 runtime 管理pm_runtime_get_sync()
保证设备上电pm_runtime_put_sync()
释放引用,设备可自动 suspendautosuspend_delay
实现自动挂起当系统整体进入睡眠,内核将调用所有驱动的 suspend()
/ resume()
回调,驱动必须正确实现。
static int xyz_suspend(struct device *dev)
{
// 关闭设备电源,保存上下文
return 0;
}
static int xyz_resume(struct device *dev)
{
// 恢复设备,重新上电
return 0;
}
static const struct dev_pm_ops xyz_pm_ops = {
.suspend = xyz_suspend,
.resume = xyz_resume,
};
static struct platform_driver xyz_driver = {
.driver = {
.name = "xyz",
.pm = &xyz_pm_ops,
},
};
buck2: regulator@2 {
compatible = "regulator-fixed";
regulator-name = "vdd_cpu";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <900000>;
};
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
cpu-supply = <&buck2>;
};
cpu-supply
使用 phandle 引用了buck2
,内核通过of_parse_phandle()
获取 regulator 设备。
struct regulator *vdd;
vdd = devm_regulator_get(&pdev->dev, "vdd"); // 由设备树 cpu-supply 解析
regulator_enable(vdd);
regulator_set_voltage(vdd, 900000, 900000);
复杂 SoC(如 i.MX8MP)中,多个模块共用电源域,必须通过 PM Domain 统一管理开关电源。
gpu: gpu@... {
...
power-domains = <&gpu_power_domain>;
};
dev_pm_domain_attach(&pdev->dev, true);
Linux 会根据 power-domains
自动判断何时上电、何时断电。
cat /sys/kernel/debug/regulator/regulator_summary
cat /sys/devices/.../power/runtime_status
cat /sys/devices/.../power/autosuspend_delay_ms
echo mem > /sys/power/state # 触发 suspend
内核会自动调用设备驱动中的 suspend 回调。
A:可能驱动未正确关闭电源资源,或调用了已经 suspend 的外围设备接口。
A:检查设备树是否定义了正确的 xxx-supply 属性,regulator 是否注册成功。
A:使用 runtime PM + autosuspend,即:
pm_runtime_set_autosuspend_delay(dev, 1000);
pm_runtime_use_autosuspend(dev);
电源管理不仅是一个子系统,而是“系统级驱动整合能力”的体现。驱动编写者必须具备以下能力:
视频教程请关注 B 站:“嵌入式 Jerry”
内容同步更新,实战演示更清晰!
如需继续输出 Day 16 博文内容,也可以告诉我主题,我们继续高强度特训。