ESC
输入关键词搜索文章标题和内容

Linux电源管理框架详解:从休眠唤醒到Runtime PM

本文由 linuxROS 整理发布,首发于 linuxros.cn,转载请注明出处。

Linux电源管理框架详解:从休眠唤醒到Runtime PM

导读:电源管理是嵌入式设备的核心能力,直接影响续航和发热。本文系统梳理Linux电源管理框架,从Suspend/Resume到Runtime PM再到Power Domain,全篇干货。


一、顶级架构一句话总结

系统休眠(Suspend) + 运行时电源管理(Runtime PM) + 系统关机(Shutdown)

💡 提示:电源管理做得好,设备续航提升50%不是梦!


二、三分钟搞懂电源管理全景图

电源管理层次

用户空间 PM核心层 设备驱动 平台驱动
/sys/power/state kernel/power/ suspend/resume platform_pm_ops
power_supply 系统级PM runtime_pm genpd

↓ 最终到达 ↓

硬件层:CPU休眠、时钟门控、电源域

系统睡眠状态

状态 说明 功耗 唤醒时间
S0 正常运行 高 -
S1 待机(Power On Suspend) 中 快
S3 睡眠(Suspend to RAM) 低 中
S4 休眠(Suspend to Disk) 极低 慢
S5 软关机 极低 需重启

三、Suspend/Resume 休眠唤醒全流程

Suspend/Resume 时序流程

步骤 操作
1. 用户触发 echo mem > /sys/power/state
↓
2. 冻结进程 freeze_processes()
↓
3. 设备Suspend prepare → suspend → suspend_late → suspend_noirq
↓
4. 平台Suspend 关闭CPU、进入低功耗状态
↓
💤 休眠完成 系统进入低功耗,等待唤醒源

⚠️ 注意:callback函数执行顺序不可颠倒,否则会导致设备休眠异常。

dev_pm_ops 结构体定义

struct dev_pm_ops {
    int  (*prepare)(struct device *dev);
    void (*complete)(struct device *dev);

    int  (*suspend)(struct device *dev);
    int  (*resume)(struct device *dev);
    int  (*freeze)(struct device *dev);
    int  (*thaw)(struct device *dev);
    int  (*poweroff)(struct device *dev);
    int  (*restore)(struct device *dev);

    int  (*suspend_late)(struct device *dev);
    int  (*resume_early)(struct device *dev);
    int  (*suspend_noirq)(struct device *dev);
    int  (*resume_noirq)(struct device *dev);

    int  (*runtime_suspend)(struct device *dev);
    int  (*runtime_resume)(struct device *dev);
    int  (*runtime_idle)(struct device *dev);
};
### 驱动实现示例
static int my_suspend(struct device *dev)
{
    struct my_device_data *data = dev_get_drvdata(dev);

    /* 保存寄存器 */
    data->saved_reg = readl(data->base + REG_CTRL);
    /* 关闭时钟 */
    clk_disable_unprepare(data->clk);
    dev_info(dev, "Device suspended\n");
    return 0;
}
> ❌ **警告**:未校准寄存器直接休眠,会导致设备异常,严禁直接上线! ### dev_pm_ops 回调执行顺序 | 回调 | 说明 | |:-----|:-----| | prepare | 准备阶段,设备可拒绝挂起 | | ↓ Suspend 方向 | | suspend | 经典挂起回调(普通优先级) | | ↓ | | suspend_late | 后期挂起(已关闭中断) | | ↓ | | suspend_noirq | 中断关闭后的挂起(最深度) | > ✅ **总结**:回调顺序必须正确,否则会导致设备无法正常休眠或唤醒。 --- ## 四、Runtime PM 运行时电源管理 ### Runtime PM 状态机
RPM_ACTIVE(设备活跃) ←→ RPM_SUSPENDED(设备挂起)
- `pm_runtime_get_sync()` 唤醒设备 - `pm_runtime_put_sync()` 释放设备 ### 使用计数机制 | 计数类型 | 说明 | |:---------|:-----| | **usecount** | 设备被引用的次数,get时+1,put时-1 | | **childcount** | 活跃子设备数,阻止父设备挂起 | | **autosuspend** | 延迟挂起时间,避免频繁切换 | ### Runtime PM API
/* 初始化 */
void pm_runtime_init(struct device *dev);
void pm_runtime_enable(struct device *dev);
void pm_runtime_disable(struct device *dev);

/* 使用计数操作 */
int  pm_runtime_get_sync(struct device *dev);  /* 同步获取 */
int  pm_runtime_put_sync(struct device *dev);  /* 同步释放 */

/* 自动挂起 */
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);


---

## 五、Power Domain 电源域管理

### 设备树配置

/ {
    power-domains {
        pd_gpu: power-domain@0 {
            compatible = "xxx,power-domain";
            reg = <0>;
            #power-domain-cells = <0>;
        };
    };

    gpu@12340000 {
        compatible = "xxx,gpu";
        reg = <0x12340000 0x1000>;
        power-domains = <&pd_gpu>;
        clocks = <&clk_gpu>;
    };
};


### 电源域驱动

static int pd_power_on(struct generic_pm_domain *domain)
{
    /* 开启电源域 */
    return 0;
}

static struct generic_pm_domain my_domain = {
    .name = "my-domain",
    .power_on = pd_power_on,
    .power_off = pd_power_off,
};

/* 注册电源域 */
pm_genpd_init(&my_domain, NULL, false);


---

## 六、Suspend 操作与唤醒源配置

# 查看支持的睡眠状态
cat /sys/power/state

# 进入睡眠
echo mem > /sys/power/state    # Suspend to RAM
echo freeze > /sys/power/state # Freeze
echo disk > /sys/power/state   # Hibernate

# 查看唤醒源
cat /sys/power/wakeup_count


---

## 七、调试方法与常用命令

# 查看设备电源状态
cat /sys/devices/.../power/runtime_status

# 查看电源域状态
cat /sys/kernel/debug/pm_genpd/pm_genpd_summary

# 查看系统电源状态
cat /sys/power/pm_debug_messages


> 💡 **提示**:`CONFIG_PM_DEBUG` 和 `CONFIG_PM_SLEEP_DEBUG` 内核配置项记得打开!

---

## 八、驱动开发 checklist 清单

| 检查项 | 说明 |
|:-------|:-----|
| 实现suspend/resume | 保存/恢复寄存器 |
| 实现runtime_pm | 按需开关设备 |
| 正确处理使用计数 | get/put必须配对 |
| 设置自动挂起延迟 | 避免频繁切换 |
| 处理唤醒源 | 配置wakeup-source |

---

## 九、知识精华浓缩总结

> ✅ **核心结论**:电源管理 = 嵌入式设备的核心能力

- **系统休眠**:suspend/resume保存恢复设备状态
- **Runtime PM**:按需开关设备,动态节能
- **电源域**:批量管理一组设备的电源
- **唤醒源**:配置设备唤醒系统

**正确实现电源管理,是嵌入式产品续航的关键!**

---

觉得实用的话,点赞、在看、收藏一键安排,转给身边还在头疼电源管理的同事,一起少加班~
      

      

版权声明

作者linuxROS
协议本作品采用 CC BY-NC-SA 4.0 许可协议:署名-非商业性使用-相同方式共享
关注欢迎关注微信公众号 linuxROS,获取更多机器人 / 嵌入式 / Linux 干货
返回首页