休眠唤醒 standby 调试

更多内容可以加入Linux系统知识库套餐(教程+视频+答疑)

休眠唤醒(Power Management)是嵌入式驱动的常见痛点------板子睡死了、唤不醒、唤醒后外设不正常...本文从原理到调试工具,带你搞定 Linux standby 休眠唤醒调试。

一、Linux 休眠方式

Linux 支持多种休眠状态,从浅到深:

状态 说明 功耗 唤醒速度
freeze 冻结用户态 + 停止 I/O,CPU 还在运行 最快
standby 待机,CPU 断电,内存保持
mem Suspend to RAM,内存自刷新,CPU/外设断电 较快
disk Suspend to Disk,内存写入磁盘,完全断电 最低 最慢

嵌入式常用的是 mem(STR,Suspend to RAM),也就是我们常说的"待机"。

二、休眠唤醒流程

🌙 休眠过程:

复制代码
用户空间触发休眠 (echo mem > /sys/power/state)
    ↓
冻结用户态进程
    ↓
调用各设备驱动的 .suspend 回调
    ↓
关闭非唤醒中断
    ↓
CPU 进入低功耗状态
    ↓
内存自刷新,板子进入待机

☀️ 唤醒过程:

复制代码
唤醒源触发中断(按键/定时器/网络等)
    ↓
CPU 恢复运行
    ↓
调用各设备驱动的 .resume 回调
    ↓
恢复用户态进程
    ↓
系统恢复正常运行

三、驱动 PM 操作接口

驱动通过 dev_pm_ops 结构体实现休眠唤醒回调:

复制代码
static const struct dev_pm_ops my_dev_pm_ops = {
    .suspend = my_suspend,     // 休眠
    .resume  = my_resume,      // 唤醒
    .freeze  = my_freeze,      // 冻结
    .thaw    = my_thaw,        // 解冻
    .prepare = my_prepare,     // 休眠前准备
    .complete = my_complete,   // 唤醒后完成
};

static struct platform_driver my_driver = {
    .probe  = my_probe,
    .remove = my_remove,
    .driver = {
        .name = "my_device",
        .pm = &my_dev_pm_ops,  // 关联 PM 操作
    },
};

四、常用调试手段

🔧 1. no_console_suspend

休眠时控制台默认会关闭,导致你看不到休眠过程中的打印。在 bootargs 中添加:

复制代码
no_console_suspend

这样休眠过程中串口控制台保持开启,可以看到完整的休眠唤醒日志。

🔧 2. initcall_debug + no_console_suspend

更详细的设备休眠/唤醒调试信息:

复制代码
initcall_debug no_console_suspend ignore_loglevel

🔧 3. wakeup_sources 唤醒源

查看哪些设备可以唤醒系统,以及是谁唤醒了系统:

复制代码
# 查看所有唤醒源
cat /sys/kernel/debug/wakeup_sources

# 查看唤醒计数
cat /sys/power/wakeup_count

# 查看最后一次唤醒原因(平台相关)
cat /sys/kernel/debug/suspend_stats

🔧 4. wake_lock 唤醒锁

系统持有唤醒锁时不会进入休眠。调试"睡不下去"的问题:

复制代码
# 查看当前持有的唤醒锁
cat /sys/power/wake_lock
cat /sys/power/wake_unlock

# Android 系统常用
dumpsys power | grep WAKE_LOCK

五、休眠失败常见原因

问题 可能原因 排查方向
睡不下去 有唤醒锁未释放 查看 /sys/power/wake_lock
睡不下去 某个驱动 suspend 返回失败 开 no_console_suspend 看日志
睡死了 唤醒源未正确配置 检查唤醒源是否使能、极性是否正确
唤醒后外设异常 驱动 resume 有问题 检查寄存器是否恢复、时钟是否重新使能
自动唤醒 有干扰信号触发中断 查看 wakeup_sources 中的 event_count

六、autosleep 自动休眠

Android 等系统使用 autosleep 机制,没有唤醒锁时自动进入休眠:

复制代码
# 查看/设置自动休眠模式
cat /sys/power/autosleep
echo mem > /sys/power/autosleep

# 唤醒锁阻止休眠
echo my_wakelock > /sys/power/wake_lock
# 释放唤醒锁
echo my_wakelock > /sys/power/wake_unlock

七、调试步骤总结

第1步:确认能否正常休眠

复制代码
echo mem > /sys/power/state

第2步:如果睡不下去,开启调试日志

复制代码
# bootargs 添加
no_console_suspend initcall_debug ignore_loglevel

第3步:检查唤醒源

复制代码
cat /sys/kernel/debug/wakeup_sources

第4步:逐个驱动排查

复制代码
# 去掉驱动的 suspend/resume 函数,二分法定位问题
相关推荐
未济2 天前
linux 配置环境变量
linux
傲世仙尊2 天前
目录即文件-Ext文件系统收尾篇
linux·c语言
_艾伦 耶格尔.2 天前
进程间通信
linux
Liuqy-052 天前
Linux IO编程——静态库、动态库
linux
彧azz2 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
-梅2 天前
linux(8) 软硬链接
linux·运维·服务器
AIgorithmGEEK2 天前
[Linux]线程三部曲(上):一个执行流的诞生——从操作系统一路拆到 pthread_create
linux·线程·pid
琥珀色糖2 天前
SimlpeHttp
linux·服务器
qeen872 天前
【Linux】操作系统之进程介绍(二)
linux·笔记·学习·进程
Zenova EdgeOS2 天前
Linux ss 工业边缘网络分析实战
linux·python·边缘计算·工业网关