news 2026/7/30 3:25:12

总结echo mem 命令如何让 RK3576 进入低功耗:从内核入口追到 BL31

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
总结echo mem 命令如何让 RK3576 进入低功耗:从内核入口追到 BL31

📺B站 嵌入式孙老师:博主个人介绍
📘博主书籍-京东购买链接:Yocto项目实战教程
📘加博主微信,进技术交流群jerrydev


在 RK3576 上调试低功耗时,最常用的命令是:

echomem>/sys/power/state

它看起来只是向 sysfs 写入一个字符串,实际会启动完整的 System Suspend 流程:

Linux PM Core ↓ 设备驱动挂起 ↓ Regulator 配置 PMIC ↓ genpd 关闭部分 Power Domain ↓ PSCI SYSTEM_SUSPEND ↓ SMC 进入 BL31 ↓ RK3576 PMU 执行整机低功耗

我沿着当前 RK3576 Linux 6.1 内核代码把这条链路重新梳理了一遍。理解它的关键,不是记住所有函数,而是分清三条电源控制路径:

路径管理对象关键代码
RegulatorRK806 的 BUCK、LDO 等真实电压drivers/regulator/
Power DomainRK3576 内部 GPU、NPU、GMAC 等功能域drivers/soc/rockchip/pm_domains.c
PSCI / BL31 / PMUCPU、Logic、DDR、PLL 和整机待机时序drivers/firmware/psci/psci.c

这三条路径由 Linux PM 框架串联起来,但控制对象并不相同。本文中的函数和代码位置基于当前 RK3576 Linux 6.1 仓库整理。


一、mem是休眠入口,不是固定深度

/sys/power/state表示什么

设备上查看:

cat/sys/power/state

输出:

freeze mem

表示内核支持两个系统级休眠入口:

状态含义
freezeSuspend-to-Idle,主要冻结软件和设备
mem内存挂起入口,具体模式由mem_sleep决定

继续查看:

cat/sys/power/mem_sleep

当前系统输出:

s2idle [deep]

方括号表示当前选中的模式,因此现在执行:

echomem>/sys/power/state

实际进入的是deep

echo deep为什么不会立即休眠

下面这条命令:

echodeep>/sys/power/mem_sleep

只是在选择mem后续采用哪种模式,不会立即触发系统挂起。

二者分工很明确:

/sys/power/mem_sleep └─ 选择 s2idle 或 deep /sys/power/state └─ 真正触发休眠

当前已经显示:

s2idle [deep]

所以无需重复设置,直接执行即可:

echomem>/sys/power/state

mem在内核中如何转换

入口位于:

kernel/power/main.c

核心逻辑如下:

staticssize_tstate_store(...){state=decode_state(buf,n);if(state<PM_SUSPEND_MAX){if(state==PM_SUSPEND_MEM)state=mem_sleep_current;error=pm_suspend(state);}}

关键代码是:

if(state==PM_SUSPEND_MEM)state=mem_sleep_current;

实际处理过程为:

字符串 "mem" ↓ decode_state() ↓ PM_SUSPEND_MEM ↓ 替换成 mem_sleep_current ↓ pm_suspend()

所以,mem本身不是一个固定的硬件深度,它是一个通用入口。

在当前系统中:

mem_sleep_current = deep

因此这次会进入 RK3576 平台级 System Suspend。

deep与关机的区别

deep通常可理解为 Suspend-to-RAM:

CPU 停止运行或断电 Linux 暂停执行 普通外设 挂起或断电 DDR 进入自刷新 DDR数据 继续保留 唤醒后 从原来的运行位置继续

它不是关机。

关机:DDR数据丢失,下次重新启动Linux deep:DDR数据保留,唤醒后继续执行

二、RK3576 低功耗中的三条控制路径

Regulator:控制板上的真实电压

Regulator 是 Linux 通用电压管理框架。

RK806 内部的每一路 BUCK、LDO,都会作为一个 regulator 注册到内核,例如:

VDD_CPU VDD_GPU VDD_NPU VDD_LOGIC DDR相关电源 VCC_3V3 VCC_1V8

设备树可以配置某路电源在mem状态下保持或关闭:

regulator-state-mem { regulator-off-in-suspend; };

表示进入 Suspend 时关闭。

保持供电则配置:

regulator-state-mem { regulator-on-in-suspend; };

Regulator 的 PM 回调位于:

drivers/regulator/core.c

核心结构为:

staticconststructdev_pm_opsregulator_pm_ops={.suspend=regulator_suspend,};

在设备 PM 的dpm_suspend()阶段,内核会调用:

regulator_suspend()

它根据regulator-state-mem配置,通过对应的 PMIC 驱动设置 RK806 寄存器。

因此,这条路径管理的是:

某一路真实电压在休眠期间保持、关闭或切换到低功耗状态。

Rockchip PM 驱动还提供:

rockchip,regulator-on-in-mem; rockchip,regulator-off-in-mem; rockchip,regulator-on-before-mem;

例如:

rockchip,regulator-on-before-mem = <&vdd_npu_s0>;

它会在进入深睡前的suspend_late阶段临时打开指定 regulator,用来满足特定电源时序。

这不表示 NPU 在整个休眠期间继续工作。


Power Domain:控制 RK3576 内部功能域

Power Domain 管理的是 RK3576 芯片内部的功能模块,例如:

GPU NPU ISP VPU USB SDGMAC PHP 显示和视频模块

Rockchip 驱动位于:

drivers/soc/rockchip/pm_domains.c

核心关断函数是:

rockchip_pd_power(pd,false);

典型处理过程为:

设备停止业务 ↓ 等待总线空闲 ↓ 关闭模块时钟 ↓ 设置隔离 ↓ 关闭内部 Power Domain

这条路径操作的是 RK3576 内部 PMU 寄存器,不会直接通过 I²C 控制 RK806。

例如:

关闭 RK3576_PD_SDGMAC

只表示 SoC 内部的 GMAC 控制器域被关闭,不表示外部 Ethernet PHY 的 3.3V 电源一定断开。

两者属于不同层次:

GMAC Power Domain └─ RK3576芯片内部 PHY供电 └─ PMIC、MOS或Load Switch

Power Domain 通常在系统挂起后期参与。部分设备驱动在.suspend_noirq中调用:

pm_runtime_force_suspend();

随后由 genpd 判断域内设备是否已经全部空闲,再决定是否调用:

rockchip_pd_power(pd,false);

BL31 与 PMU:完成整机级休眠

Regulator 和普通 Power Domain 能关闭大量设备,但还不足以让整个 RK3576 进入深度待机。

系统级动作包括:

DDR进入自刷新 关闭CPU 关闭vdd_arm 关闭vdd_logic 关闭PLL 切换到32K 配置IO Retention 配置Sleep Pin 配置系统唤醒源

这些动作由 PSCI、BL31 和 RK3576 PMU 完成。

职责可以概括为:

层次主要职责
设备驱动停止业务、保存寄存器状态
Regulator配置 RK806 各路输出电压
Power Domain关闭 RK3576 内部功能域
BL31 / PMU完成 CPU、Logic、DDR、PLL 等系统级休眠

它们不是重复控制,而是从设备到整机逐层收尾。


三、沿着echo mem跟踪内核调用链

完整代码路径

echo mem > /sys/power/state ↓ state_store() ↓ pm_suspend() ↓ enter_state() ↓ suspend_prepare() ↓ dpm_suspend_start() ├─ dpm_prepare() └─ dpm_suspend() ↓ dpm_suspend_late() ↓ dpm_suspend_noirq() ↓ syscore_suspend() ↓ suspend_ops->enter() ↓ psci_system_suspend_enter() ↓ cpu_suspend() ↓ invoke_psci_fn() ↓ SMC进入BL31

Linux 先冻结进程

pm_suspend()进入:

suspend_prepare()

主要完成:

发送 PM_SUSPEND_PREPARE 通知 ↓ 冻结用户空间进程 ↓ 冻结可冻结的内核线程

这样可以防止休眠过程中,应用继续访问网络、存储、摄像头、USB 等设备。

设备 PM 分阶段执行

设备挂起不是一次完成,而是分四个阶段:

dpm_prepare() ↓ dpm_suspend() ↓ dpm_suspend_late() ↓ dpm_suspend_noirq()
阶段主要任务
prepare休眠前准备
suspend停止设备业务、保存状态
suspend_late处理依赖和电源时序
suspend_noirq普通中断关闭后的最终处理

Rockchip PM、Regulator 和 Power Domain,分别在这些阶段参与。


dpm_prepare():Rockchip 下发休眠策略

RK3576 的平台配置驱动位于:

drivers/soc/rockchip/rockchip_pm_config.c

它注册了:

staticconststructdev_pm_opsrockchip_pm_ops={.prepare=pm_config_prepare,.complete=pm_config_complete,.suspend_late=pm_config_suspend_late,.resume_early=pm_config_resume_early,};

dpm_prepare()阶段,调用:

pm_config_prepare()

它读取 DTS 中的:

rockchip,sleep-mode-config; rockchip,wakeup-config; rockchip,sleep-io-ret-config; rockchip,sleep-pin-config;
属性作用
sleep-mode-config决定系统休眠深度
wakeup-config配置可用唤醒源
sleep-io-ret-config配置需要保持状态的 IO 域
sleep-pin-config配置休眠时 Sleep Pin 状态

随后通过:

sip_smc_set_suspend_mode(...)

把这些参数提前交给 BL31。

简化后的逻辑如下:

sip_smc_set_suspend_mode(SUSPEND_MODE_CONFIG,sleep_mode,0);sip_smc_set_suspend_mode(WKUP_SOURCE_CONFIG,wakeup_config,0);

这里仅仅是在告诉 BL31:

真正进入休眠时应该关闭哪些资源、保留哪些唤醒源。

此时 Linux 和 CPU 仍然在运行,系统还没有真正睡下去。


dpm_suspend():应用 PMIC 休眠配置

进入:

dpm_suspend()

Linux 会遍历所有设备并调用.suspend()

Regulator 设备在这里调用:

regulator_suspend()

应用:

regulator-state-mem

所以,这一步可能真正修改 RK806 的休眠寄存器配置。

需要区分两件事:

pm_config_prepare() └─ 把平台低功耗参数交给BL31 regulator_suspend() └─ 配置PMIC各路BUCK/LDO状态

两者不是同一条代码路径。


dpm_suspend_late():处理最后阶段电源时序

随后进入:

dpm_suspend_late()

Rockchip 的:

pm_config_suspend_late()

会在这里执行。

例如:

rockchip,regulator-on-before-mem = <&vdd_npu_s0>;

指定的 regulator 会在这里临时打开。

这类配置用于满足进入深睡前的特殊硬件时序,不应理解为对应模块在待机期间仍然正常工作。


dpm_suspend_noirq():处理 Power Domain

接下来进入:

dpm_suspend_noirq()

此时普通设备中断基本已经关闭。

设备驱动可能通过:

pm_runtime_force_suspend();

触发 genpd 关闭对应功能域,最终进入:

rockchip_pd_power(pd,false);

这一步控制的是 RK3576 内部 Power Domain,不直接控制外部 PMIC 电压。


PSCI:从 Linux 进入 BL31

Linux 完成设备、Regulator 和普通 Power Domain 的处理后,会调用:

suspend_ops->enter(state);

在 RK3576 ARM64 平台中,对应:

psci_system_suspend_enter()

代码位于:

drivers/firmware/psci/psci.c

核心结构:

staticconststructplatform_suspend_opspsci_suspend_ops={.valid=suspend_valid_only_mem,.enter=psci_system_suspend_enter,};

进入函数:

staticintpsci_system_suspend_enter(suspend_state_tstate){returncpu_suspend(0,psci_system_suspend);}

cpu_suspend()保存 CPU 上下文,然后执行:

staticintpsci_system_suspend(unsignedlongunused){phys_addr_tpa_cpu_resume=__pa_symbol(cpu_resume);returninvoke_psci_fn(PSCI_FN_NATIVE(1_0,SYSTEM_SUSPEND),pa_cpu_resume,0,0);}

关键位置是:

invoke_psci_fn(PSCI_FN_NATIVE(1_0,SYSTEM_SUSPEND),...);

它最终触发 SMC:

Linux Kernel,EL1 │ │ PSCI SYSTEM_SUSPEND ▼ BL31,EL3

从这里开始,Linux 内核暂停运行。

后面的 DDR 自刷新、PLL 关闭、CPU 和 Logic 断电、唤醒等待,都由 BL31 和 RK3576 PMU 负责。Linux 内核代码跟踪到这里结束。


四、DTS 决定系统最终睡多深

三档核心休眠模式

RK3576 的定义位于:

include/dt-bindings/suspend/rockchip-rk3576.h

三档核心模式是:

#defineRKPM_SLP_ARMOFF_DDRPDBIT(2)#defineRKPM_SLP_ARMOFF_LOGOFFBIT(3)#defineRKPM_SLP_ARMOFF_PMUOFFBIT(4)
模式主要关闭范围功耗唤醒能力
ARMOFF_DDRPDARM及DDR控制相关部分较高较多
ARMOFF_LOGOFFARM、Logic较低较少
ARMOFF_PMUOFFARM、Logic、PMU1最低最少

核心规律是:

关闭资源越多 ↓ 待机功耗越低 ↓ 保留的硬件越少 ↓ 可用唤醒源越少

真正决定休眠深度的是:

rockchip,sleep-mode-config

而不是echo mem本身。

echo mem负责触发流程,BL31 最终执行哪种低功耗策略,由 DTS 配置决定。

时钟和 PMIC 附加配置

常见选项还有:

RKPM_SLP_PMU_PMUALIVE_32K RKPM_SLP_PMU_DIS_OSC RKPM_SLP_PMIC_LP RKPM_SLP_32K_EXT
配置作用
PMUALIVE_32KPMU Alive 域切换到 32K
DIS_OSC关闭 24M 晶振
PMIC_LP配置 PMIC 低功耗状态
32K_EXT使用外部 32K 时钟

关闭 24M 可以进一步降低功耗,但依赖 24M 的 USB、UART、PWM 等唤醒方式可能受到影响。

因此低功耗配置并不是“关闭得越多越好”,而是要在功耗、唤醒能力和恢复稳定性之间做取舍。

唤醒由 PMU 检测

进入深度休眠后:

CPU 停止运行或断电 Linux 停止执行 DDR 保持自刷新 PMU Always-On 继续工作 唤醒检测逻辑 继续工作

真正等待唤醒事件的不是 Linux,而是 RK3576 PMU。

以 GPIO0 唤醒为例:

外部 GPIO 事件 ↓ GPIO0 唤醒信号进入 PMU ↓ PMU 恢复电源和时钟 ↓ BL31 恢复 CPU 上下文 ↓ 跳转到 cpu_resume ↓ 返回 Linux

恢复阶段按相反顺序展开:

syscore_resume() ↓ dpm_resume_noirq() ↓ dpm_resume_early() ↓ dpm_resume() ↓ dpm_complete() ↓ 解冻用户进程

五、实战中如何确认低功耗是否生效

确认当前模式

cat/sys/power/statecat/sys/power/mem_sleep

预期输出:

freeze mem s2idle [deep]

执行休眠

echomem>/sys/power/state

查看 Linux 日志

唤醒后执行:

dmesg|grep-iE"PM:|suspend|resume|wakeup"

重点关注:

PM: suspend entry (deep) Freezing user space processes Suspending console(s) PM: suspend exit

查看 BL31 日志

DTS 中打开:

rockchip,sleep-debug-en = <1>;

串口中可能看到:

INFO: deep INFO: armoff_logoff INFO: pmu_pmualive_32k INFO: io_ret (...) INFO: sleep_pin: ... INFO: wake up status: ...

这些日志可以确认:

  • 是否进入deep
  • 实际使用哪种 ARMOFF 模式;
  • 是否切换到 32K;
  • IO Retention 是否配置;
  • Sleep Pin 是否生效;
  • 最终由哪个事件唤醒。

软件日志不能代替电压测量

日志只能说明软件流程执行到了哪里,不能证明所有板级电压都按预期变化。

仍需要实际测量:

VDD_CPU VDD_LOGIC DDR电源 24M晶振 Sleep Pin VCC_3V3_S0 VCC_3V3_S3 外部PHY和无线模块电源

特别是板级 MOS、Load Switch 和_S0_S3电源命名,最终都应以原理图和实测波形为准。


总结

RK3576 执行:

echomem>/sys/power/state

背后的完整过程是:

echo mem ↓ Linux PM Core冻结进程 ↓ 设备驱动停止业务 ↓ Rockchip PM驱动下发休眠参数 ↓ Regulator配置RK806电压状态 ↓ genpd关闭RK3576内部功能域 ↓ PSCI SYSTEM_SUSPEND ↓ SMC进入BL31 ↓ RK3576 PMU完成整机深度休眠

其中:

Regulator └─ 管理板级真实电压 Power Domain └─ 管理SoC内部功能模块 BL31 / PMU └─ 管理CPU、Logic、DDR、PLL和系统唤醒

echo mem不是一条直接关闭 PMIC 的命令,也不是单独触发某个 Power Domain。

它的作用是启动 Linux System Suspend,让软件、设备、电源和固件按照既定顺序逐层进入低功耗,最终由 BL31 和 RK3576 PMU 完成整机级休眠。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/30 3:23:13

Hot 100 --- 组合总和

本文概览&#xff1a;本文以LeetCode题目"组合总和"为例&#xff0c;讲解回溯法在可重复选择、结果不计顺序场景下的应用&#xff0c;以及和子集问题的对比一、题目二、题目分析 题目要求&#xff1a;给定一个无重复元素的正整数数组 candidates 和一个目标数 target…

作者头像 李华
网站建设 2026/7/30 3:22:29

企业如何防泄密?6 大企业防泄密方法,给企业加上 “安全锁”!

很多企业只加密文件&#xff0c;却忽略了后台自动存档泄密的大坑&#xff01;不少老板都在问透明加密软件都有哪些&#xff0c;今天结合真实企业泄密案例整理 6 款公认好用的透明加密软件推荐这几款透明加密软件静默防护不影响办公是 2026 年超实用的防护工具。一、安秉透明加密…

作者头像 李华
网站建设 2026/7/30 3:20:49

Spring Boot中统一设置HTTP请求头的最佳实践

1. 项目背景与核心需求在Web应用开发中&#xff0c;经常需要统一处理HTTP请求头信息。比如添加认证令牌、追踪ID、版本号等通用字段。如果每个Controller都手动处理这些逻辑&#xff0c;会导致大量重复代码。Spring Boot提供了多种拦截HTTP请求的机制&#xff0c;可以优雅地实现…

作者头像 李华
网站建设 2026/7/30 3:20:44

2026年免费降AI率工具实测:20款横评,这3款可以放心用

2个实测免费的降AIGC率工具&#xff0c;顺利通过ai率查重&#xff01; AI 检测本身就没有公开 算法 &#xff0c;降 AI 工具更像黑箱。如果降AI率连一次免费试用都不给&#xff0c;那风险太大了。万一AI率没有降下来&#xff0c;又不能退&#xff0c;少则几元多则几十。 对于学…

作者头像 李华
网站建设 2026/7/30 3:19:43

写给 2027 年的自己:云原生 AI 工程师应该提前准备什么

写给 2027 年的自己&#xff1a;云原生 AI 工程师应该提前准备什么 一、不是"学什么新技术"&#xff0c;是"什么能力在 2027 年不会贬值" 写技术博客的人喜欢做预测&#xff0c;但预测本身通常不准。更务实的问题是&#xff1a;哪些能力在快速变化的技术…

作者头像 李华