系列作者:嵌入式Jerry
视频教程请关注 B 站:"嵌入式Jerry"
一、引言
在嵌入式系统中,电源管理(Power Management, PM)是一个不可或缺的核心机制,它贯穿设备运行的每一个阶段。尤其在低功耗设计、移动终端、自动化控制等领域,PM 技术的合理使用决定了产品的稳定性、续航能力和热管理水平。
本篇我们将围绕 Linux 电源管理机制,结合 NXP i.MX8MP 平台,带你系统梳理 PM 子系统的组成与工作原理,并通过 regulator 框架完成一个典型的电源控制驱动开发实践。
二、电源管理概览
Linux 中的电源管理机制主要包括三类:
类型 | 说明 |
---|---|
System Suspend/Resume | 整体系统的挂起与恢复(如睡眠/唤醒) |
Runtime PM | 单个设备在工作状态下的动态电源管理(如不使用时自动关闭) |
Regulator Framework | 用于控制外部 PMIC 或 LDO 的电源管理子系统 |
我们重点关注后两者:runtime PM
与 regulator
框架,它们与驱动密切相关。
三、Regulator 框架原理解析
3.1 架构简图
text
+------------------+
| Regulator Core |
+--------+---------+
|
+-----------+------------+
| |
+------+-----+ +------+-----+
| 驱动接口层 | | 子系统使用 |
+------------+ +------------+
| |
+------+---------+ +------+--------+
| 具体 PMIC/LDO | | sound/i2c/etc|
+----------------+ +---------------+
3.2 驱动中如何使用 Regulator
- 设备树中定义 regulator
- 使用
regulator_get()
获取电源控制句柄 - 通过
regulator_enable()
/regulator_disable()
控制电源 - 使用
regulator_set_voltage()
设定输出电压(若支持)
3.3 典型设备树定义
dts
reg_audio_pwr: regulator-audio-pwr {
compatible = "regulator-fixed";
regulator-name = "audio-pwr";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-always-on;
};
四、实战:驱动中使用 regulator 控制电源
4.1 场景介绍
我们以控制 audio-pwr
电源为例,实现以下目标:
- 加载驱动时打开电源
- 卸载驱动时关闭电源
- 提供一个字符设备接口,通过用户空间控制电源状态
4.2 字符设备控制电源代码
c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/regulator/consumer.h>
#define DEV_NAME "mypower"
static dev_t devt;
static struct class *power_class;
static struct cdev power_cdev;
static struct regulator *reg;
static ssize_t power_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
char kbuf[4];
if (copy_from_user(kbuf, buf, len))
return -EFAULT;
if (kbuf[0] == '1') {
pr_info("enable power\n");
regulator_enable(reg);
} else {
pr_info("disable power\n");
regulator_disable(reg);
}
return len;
}
static struct file_operations power_fops = {
.owner = THIS_MODULE,
.write = power_write,
};
static int __init power_init(void)
{
int ret;
ret = alloc_chrdev_region(&devt, 0, 1, DEV_NAME);
if (ret) return ret;
cdev_init(&power_cdev, &power_fops);
cdev_add(&power_cdev, devt, 1);
power_class = class_create(THIS_MODULE, "mychar_class");
device_create(power_class, NULL, devt, NULL, DEV_NAME);
reg = regulator_get(NULL, "audio-pwr");
if (IS_ERR(reg)) {
pr_err("failed to get regulator\n");
return PTR_ERR(reg);
}
regulator_enable(reg);
pr_info("regulator enabled on init\n");
return 0;
}
static void __exit power_exit(void)
{
regulator_disable(reg);
regulator_put(reg);
device_destroy(power_class, devt);
class_destroy(power_class);
cdev_del(&power_cdev);
unregister_chrdev_region(devt, 1);
}
module_init(power_init);
module_exit(power_exit);
MODULE_LICENSE("GPL");
4.3 编译加载测试
bash
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
insmod mypower.ko
echo 0 > /dev/mypower # 关闭电源
echo 1 > /dev/mypower # 打开电源
五、Runtime PM 初探
5.1 原理与作用
Runtime PM 关注的是在设备"不使用"的时候能否挂起节能。例如:
- I2C 总线空闲时关闭
- LCD 没有显示内容时关闭背光
它是通过 pm_runtime_xxx()
系列 API 和设备状态跟踪机制实现的。
5.2 示例流程
c
static int my_probe(struct platform_device *pdev)
{
device_init_wakeup(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
...
return 0;
}
static int my_remove(struct platform_device *pdev)
{
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
...
return 0;
}
六、电源管理与设备模型、子系统的结合
层次 | 说明 |
---|---|
设备模型 | 定义 device 与 driver 的绑定机制 |
子系统(如 regulator) | 实现特定功能领域的统一管理 |
字符设备 | 提供用户空间访问方式 |
sysfs | 提供配置与控制接口 |
这些机制彼此协作,共同完成"驱动-设备-资源"之间的高效管理。
七、总结
电源管理是 Linux 驱动开发中极其关键的一环。通过 regulator 框架,我们可以轻松实现对 PMIC、电源管脚的统一管理;通过 runtime PM,可以在不影响功能的情况下最大限度节省功耗。结合字符设备接口和 sysfs,还可以让用户空间轻松参与电源控制。
在后续章节,我们将深入探讨 Runtime PM 与系统 suspend/resume 的集成机制,并展开对 wakeup source 的控制策略学习。
📢 后续训练预告
下一篇我们将进入:
Day 21:深入 Runtime PM 和唤醒机制:挂起、唤醒与低功耗设计的艺术
视频教程请关注 B 站:"嵌入式Jerry"
欢迎留言交流,共同进步!