休眠唤醒 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 函数,二分法定位问题
相关推荐
小白不想画工图44 分钟前
银河麒麟V10系统安装QT5.12
linux·开发语言·qt·银河麒麟
IT爱学堂1 小时前
新版Linux零基础入门到高手Rocky版本-替换CentOS(完结)
linux·运维·centos
kkkkkkkkkk_Z1 小时前
学嵌入式和Linux应用编程|学习日记:计算机网络基础
linux·学习·计算机网络
ang7842 小时前
日常高频使用的 Ansible 命令,按使用频率和场景整理。
linux·运维·服务器
高亦真2 小时前
今天是学习嵌入式的第35天
linux·学习·算法
mounter6252 小时前
eBPF 驱动的云原生网络变革:Cilium 的前世今生与全机套接字迭代技术演进
linux·ebpf·linux kernel·kernel
赵庆明老师2 小时前
用同一个用户登录宝塔面板的ftp与Linux的sftp
linux·运维·服务器
oushaojun22 小时前
深入理解 Linux I2C 框架:内核子系统分层解析(转)
linux
不会就选b3 小时前
Linux之socket编程(六)----TCP-->模拟shell命令
linux·运维·tcp/ip