SoC 低功耗实战方针与原理:以 Rockchip RK3588 为例

2025博客之星年度评选已开启 10w+人浏览 1.6k人参与


📺 B站视频讲解(Bilibili)https://www.bilibili.com/video/BV1k1C9BYEAB/

📘 《Yocto项目实战教程》京东购买链接Yocto项目实战教程


SoC 低功耗实战方针与原理:以 Rockchip RK3588 为例

把 RK3588 这类复杂 SoC 的功耗优化,从“玄学调参”变成可复现的工程流程

  • 你知道功耗是谁在耗(电源轨/时钟域/功耗域/外设/DDR/CPU 簇/AI/ISP/显示)
  • 你知道怎么让它不耗(Idle → Runtime PM → DVFS → Domain gating → System suspend)
  • 你知道如何验证确实不耗(电流计 + PMIC rail + trace + debugfs + wakelock)

在这里插入图片描述

1. 低功耗工程“实战方针”

1.1 从产品需求反推策略(最关键)

不同产品形态,低功耗目标完全不同:

  1. 深度待机(Deep standby)
  • 目标:mW 级(甚至更低)
  • 允许:绝大多数 IP 断电,DDR 进入 self‑refresh 或完全掉电(取决于 suspend-to-RAM / suspend-to-idle / suspend-to-disk)
  • 关键:唤醒源、唤醒时间、数据保持
  1. 轻待机(Light standby / Screen-off idle)
  • 目标:几十 mW ~ 几百 mW
  • 允许:屏幕/显示域关,CPU 进入深度 idle,Wi‑Fi/BT 可选择保活
  • 关键:网络保活、RTC/触摸/蓝牙/按键唤醒
  1. “工作态”低功耗(Performance-per-watt)
  • 目标:在同等 FPS/码率/吞吐下最低功耗
  • 关键:DVFS、热设计、带宽(DDR/NoC)与硬件加速器使用方式

实战建议:先把产品分成 3~5 个“功耗状态”(Power State),每个状态写成表格:

  • 允许开启的子系统
  • 必须关闭的子系统
  • 唤醒源列表
  • 典型功耗目标(mA@电压)
  • 唤醒时间目标(ms)

1.2 三条工程纪律

纪律 A:先测量,再优化。

  • 没有电流/电压与功耗状态的基线,所有优化都不可控。

纪律 B:先做“关掉不用的”,再做“更省电”。

  • 先关显示/ISP/AI/USB/PCIe/DP/HDMI 等大户,再微调 CPU DVFS。

纪律 C:任何节能都必须可验证、可回归。

  • 每个 PR/每次改动,都要有 “before/after” 的指标与脚本。

2. RK3588 的低功耗“硬件地图”:你要知道的物理事实

低功耗不是“内核开关”,而是硬件结构的控制:电源轨、时钟树、复位、隔离、保留、唤醒路径。

2.1 电源:PMIC + 多路 rail 的本质

RK3588 常见板级设计(核心板 + 载板)里:

  • PMIC 输出多路电压(例如:VDD_CPU、VDD_GPU、VDD_NPU、VDD_LOGIC、VDD_DDR、VCC_IO 等)
  • 每一路 rail 可能对应一个 power domain 或者一个电压域
  • SoC 内部还有:LDO/隔离/保留寄存器/电源门控

你需要建立一张“电源树(Power Tree)”与 Linux power domain 的映射表:

PMIC rail典型供电对象Linux 侧映射关键观测点
VDD_CPU_BIGA76 clustercpufreq/OPP电压随频率变化
VDD_CPU_LITTLEA55 clustercpufreq/OPPidle 深度是否进入
VDD_GPUMalidevfreq/OPPGPU 空闲是否降频/关域
VDD_NPUNPUdevfreq/OPPNPU 是否 runtime suspend
VDD_LOGICSoC logicgenpd大部分 domain gating
VDD_DDRDDR PHY/DRAMPMU/DDRSR/PD 状态

为什么要映射?
因为“电流下降”必须能追溯到“哪个 rail 被关/被降压/哪个 domain 被 gated”。否则你只是在猜。

2.2 时钟树:低功耗的第二把刀

  • 没关电源域之前,先关时钟(clock gating)通常更安全

  • 绝大多数 IP 的功耗来自:

    • 时钟在跑(翻转功耗)
    • DDR 带宽(NoC 活动)
    • 外设 IO(PHY、SerDes)

Linux 对应的控制点:

  • Common Clock Framework(CCF):/sys/kernel/debug/clk/clk_summary
  • 驱动:clk_prepare_enable() / clk_disable_unprepare()
  • 运行时:runtime PM 在 ->runtime_suspend() 里停时钟

2.3 复位/隔离/保留(Reset/Isolation/Retention)

当一个 power domain 断电,需要:

  • 先停止 IP 活动
  • 再关时钟
  • 再隔离(isolation)
  • 再断电
  • 恢复时反向执行 + 状态恢复

这些动作大多在:

  • SoC 的 PMU/PMGR 控制器
  • Linux 的 genpd(generic power domain)框架

2.4 唤醒源:低功耗设计的“门”

  • RTC
  • GPIO(按键/霍尔/唤醒线)
  • 触摸(I2C/SPI 设备具备 wakeup)
  • Bluetooth/Wi‑Fi(取决于芯片、固件、接口与板级唤醒线)
  • USB(设备插拔/充电)

唤醒源必须在硬件上可达

  • 有唤醒线到 PMU/Always‑on 域
  • IO rail 在低功耗状态仍供电

3. Linux 低功耗的“四层模型”(建议你用这四层做文章骨架)

低功耗在 Linux 里不是一套机制,是四套机制叠加:Idle、Runtime PM、DVFS、System Suspend。

3.1 CPU Idle:让 CPU 真正睡下去

  • 目标:让 CPU 从 WFI 到更深的 idle state

  • 框架:cpuidle / PSCI(ARM)

  • 关键:

    • cpuidle state 进入次数与驻留时间
    • 中断是否频繁唤醒(定时器、workqueue、网络)

常用观测:

  • /sys/devices/system/cpu/cpuidle/
  • trace:trace-cmd record -e power -e irq

3.2 Runtime PM:不用的设备随时睡

  • 最常见、收益最大

  • 框架:pm_runtime_* + 驱动 ->runtime_suspend() / ->runtime_resume()

  • 关键:

    • 引用计数(usage_count)必须归零
    • 驱动必须正确停 DMA/IRQ/clk/regulator
    • 用户态不要持续打开设备节点

观测:

  • cat /sys/devices/.../power/runtime_status
  • cat /sys/kernel/debug/pm_genpd/pm_genpd_summary

3.3 DVFS/OPP:让电压跟着需求走

  • CPU:cpufreq

  • GPU/NPU/DDR:devfreq + OPP

  • 关键:

    • OPP 表正确(频率/电压/功耗)
    • governor 选择(schedutil/performance/powersave)
    • 负载统计是否真实

3.4 System Suspend:进入系统级休眠

  • suspend-to-idle(s2idle)
  • suspend-to-RAM(deep)

RK3588 在 vendor 内核通常由 Rockchip PM 体系实现 deep suspend:

  • PMU 控制 power domain
  • DDR 进入 self‑refresh
  • 唤醒源由 PMU/RTC/GPIO 触发

4. RK3588 的“功耗状态机”设计(你可以直接照抄落地)

建议定义 5 态:

  1. P0:Full‑On(全开工作态)
  • camera/ISP/encoder/display 可开
  • CPU/GPU/NPU 按需 DVFS
  1. P1:Interactive(屏幕亮但轻负载)
  • 限制最高频率
  • GPU/NPU 进入更激进的 devfreq
  1. P2:Screen‑Off Idle(灭屏待机)
  • display domain off
  • camera off
  • Wi‑Fi/BT 视需求(保活或低功耗)
  • CPU 允许 deeper idle
  1. P3:Standby(深度待机,RAM 保持)
  • system suspend-to-RAM
  • 只保留 wakeup 设备
  1. P4:Shipping / Ultra‑Low(超低功耗/运输模式)
  • 近似断电,仅 RTC/少量 always‑on

4.1 每个状态必须有“入口脚本 + 验收脚本”

入口脚本例(思路):

  • 停止业务进程
  • 释放设备句柄
  • 关闭大户:显示、摄像头、USB3/PCIe
  • 写入 governor/频率上限
  • 执行 suspend

验收脚本例(思路):

  • 记录功耗(外部仪表)
  • dump:clk_summary、pm_genpd、wakeup_sources
  • 记录 60s 内唤醒原因统计

5. 你必须会的“测量体系”:没有它就别谈低功耗

5.1 外部测量:电流/电压/功耗

  • 最可靠:在供电入口串接电流计(或使用功率分析仪)
  • 如果有分 rail 采样(INA219/INA226/PMIC ADC),可做更细粒度分析

基线必须统一

  • 固定亮度、固定网络状态、固定温度
  • 同一套 workload

5.2 内部观测:Linux 侧证据链

  1. 唤醒源
  • /sys/kernel/debug/wakeup_sources
  • /proc/interrupts
  • /sys/devices/.../power/wakeup
  1. 时钟
  • /sys/kernel/debug/clk/clk_summary
  1. 电源域(genpd)
  • /sys/kernel/debug/pm_genpd/pm_genpd_summary
  1. Runtime PM 状态
  • /sys/devices/.../power/runtime_status
  1. CPU idle/cpufreq
  • cpupower frequency-info(若可用)
  • /sys/devices/system/cpu/cpu*/cpufreq/
  • /sys/devices/system/cpu/cpuidle/

5.3 一套“标准采集包”(建议你做成脚本)

#!/bin/sh
OUT=/tmp/power_dump_$(date +%F_%H%M%S)
mkdir -p $OUT

# 1) wakelocks / wakeup sources
cat /sys/kernel/debug/wakeup_sources > $OUT/wakeup_sources.txt 2>/dev/null || true

# 2) interrupts
cat /proc/interrupts > $OUT/interrupts.txt

# 3) clocks
cat /sys/kernel/debug/clk/clk_summary > $OUT/clk_summary.txt 2>/dev/null || true

# 4) genpd
cat /sys/kernel/debug/pm_genpd/pm_genpd_summary > $OUT/pm_genpd_summary.txt 2>/dev/null || true

# 5) runtime pm snapshot (top-level)
find /sys/devices -maxdepth 5 -name runtime_status -print -exec sh -c 'echo "=== {}"; cat {}' \; \
  > $OUT/runtime_status.txt 2>/dev/null || true

echo "dump saved to $OUT"

6. RK3588 低功耗的“最大功耗源”清单(按优先级)

经验规律:对 RK3588 这种大 SoC,省电先抓“大户”。

6.1 显示链路(VOP2/DSI/DP/HDMI/PHY)

  • 显示亮起来后,时钟域、NoC、DDR 带宽都会上去
  • DP/HDMI 的 PHY/SerDes 也很耗

策略

  • 灭屏状态必须确保:

    • DRM/KMS 关闭 pipeline
    • 对应 PHY runtime suspend
    • backlight PWM 关闭

6.2 摄像头链路(CIF/ISP/MPP/编码)

  • ISP/DRM/编码器是典型大户
  • MPP 编码如果保持常开,功耗维持高位

策略

  • camera idle 时必须:

    • 停止 stream
    • 释放 v4l2 node
    • 让 ISP/MPP runtime suspend

6.3 DDR/NoC(带宽就是功耗)

  • 很多“看起来没干活”的系统,实际 DDR 一直高频

策略

  • devfreq governor 合理
  • 减少后台日志/轮询
  • 避免无意义 memcpy

6.4 无线(Wi‑Fi/BT)

  • 取决于芯片(Broadcom/Realtek)与固件
  • 扫描/保持连接/热点都会显著增加功耗

策略

  • 待机态:

    • Wi‑Fi 彻底断电(若允许),或进入 WOWLAN/DTIM 优化
    • BT 进入低功耗(sniff/advertising 参数)

6.5 USB3/PCIe/SerDes

  • SerDes/PHY 常开耗电明显

策略

  • 没插设备时 runtime suspend
  • LPM(U1/U2/U3、PCIe ASPM)

7. RK3588 内核侧:关键框架与代码路径(务实版)

下面给出“你改代码时真正会用到的路径与套路”。具体文件名会因 vendor 内核版本不同略有差异,但框架一致。

7.1 设备树:低功耗信息的“事实源”

你需要在 DTS 里明确:

  • power domains
  • clocks
  • regulators
  • operating-points
  • wakeup-source
  • pinctrl 的 sleep state
7.1.1 wakeup-source(示意)
&i2c3 {
    status = "okay";

    touch@38 {
        compatible = "goodix,gt911";
        reg = <0x38>;
        interrupt-parent = <&gpio4>;
        interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
        wakeup-source;   /* 关键:允许作为唤醒源 */

        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&touch_int_default>;
        pinctrl-1 = <&touch_int_sleep>;  /* 关键:低功耗引脚态 */
    };
};
7.1.2 OPP(示意)
cpu0_opp_table: opp-table {
    compatible = "operating-points-v2";
    opp-shared;

    opp-1200000 {
        opp-hz = /bits/ 64 <1200000000>;
        opp-microvolt = <800000>;
    };
    opp-1800000 {
        opp-hz = /bits/ 64 <1800000000>;
        opp-microvolt = <950000>;
    };
};

扩展写作点(用于加厚字数):

  • RK3588 各电压域的 OPP 案例(CPU big/little、GPU、NPU、DDR)
  • regulator 依赖关系、supply 名称、board power tree 对应
  • pinctrl sleep state 的电气意义(上拉/下拉/保持/高阻)

7.2 Runtime PM:驱动必须写对的“模板”

下面是你在外设驱动里最常写的结构:

static int foo_runtime_suspend(struct device *dev)
{
    struct foo *f = dev_get_drvdata(dev);

    /* 1) 停止 DMA/队列 */
    foo_stop_hw(f);

    /* 2) 禁用中断(如果中断不是唤醒源) */
    disable_irq(f->irq);

    /* 3) 关时钟 */
    clk_disable_unprepare(f->clk);

    /* 4) 关 regulator(如果允许) */
    regulator_disable(f->vdd);

    return 0;
}

static int foo_runtime_resume(struct device *dev)
{
    struct foo *f = dev_get_drvdata(dev);

    regulator_enable(f->vdd);
    clk_prepare_enable(f->clk);
    enable_irq(f->irq);
    foo_start_hw(f);

    return 0;
}

static const struct dev_pm_ops foo_pm_ops = {
    SET_RUNTIME_PM_OPS(foo_runtime_suspend, foo_runtime_resume, NULL)
};

常见坑

  • usage_count 永远不归零(用户态句柄没关、或者驱动 get/put 不平衡)
  • 中断频繁唤醒(GPIO 抖动、IRQ type 配错)
  • suspend 时没停 DMA,导致总线一直活跃

7.3 genpd:电源域关不掉的“根因”通常在这里

你应重点看:

  • 哪些 domain 一直显示 on
  • 谁在引用它(设备 runtime PM 没睡)

调试:

  • pm_genpd_summary
  • 逐个排查设备 runtime_status

扩展写作点:

  • RK3588 常见 power domain 列表(VOP/ISP/USB/PCIe/NPU/GPU)
  • domain 之间的 parent/child 关系
  • Rockchip PMU 驱动的关键代码阅读(vendor kernel)

7.4 cpufreq / devfreq:让性能按需,而不是全速跑

  • CPU governor 推荐:schedutil(通常)
  • 但要确保:schedutil 的采样与负载统计不会“被任务唤醒误导”

GPU/NPU/DDR 常用:devfreq governor(simple_ondemand 等)

实战建议

  • 先限制 max freq 看功耗下降幅度,再回推是否需要更细 OPP

8. 系统层低功耗:从“进程行为”把功耗压下去

8.1 轮询是待机功耗第一杀手

任何 100ms/1s 轮询都会:

  • 唤醒 CPU
  • 触发 timer
  • 让 cpuidle 无法进入深度 state

策略

  • 用 event 驱动(epoll、inotify、netlink)替代轮询
  • 合并定时器

8.2 日志与监控:你以为的“轻量”,可能是高功耗

  • 高频打印(dmesg/logcat)
  • 高频采样 CPU/GPU/温度

策略

  • 待机态关闭监控
  • 降低采样频率

8.3 网络保活:必须明确“是否需要”

  • 需要:用 WOWLAN/DTIM/keepalive,评估代价
  • 不需要:直接断电/ifdown/stop supplicant

9. 以 RK3588 相机/平板类产品为例:一套可执行的低功耗落地步骤

你现在的项目场景(4 路 camera + 平板/主控 + BLE 唤醒)非常适合用这套步骤。

Step 1:建立功耗基线(必须)

  • P0/P1/P2/P3 各跑一次
  • 每次都 dump 采集包 + 外部电流

Step 2:优先关大户

  • 灭屏:确保 display pipeline 关 + PHY 睡
  • 停 camera:释放所有 v4l2 节点
  • USB/PCIe:没用则 runtime suspend

Step 3:修 runtime PM

  • runtime_status=active 的设备开始逐个清
  • 每清掉一个设备,看 rail 电流是否下降

Step 4:修唤醒源与中断

  • 查看 wakeup_sources top offenders

  • 对应到 /proc/interrupts

  • 解决:

    • IRQ 抖动(GPIO 配置、上拉、触发沿)
    • 不必要 wakeup(关闭设备 wakeup)

Step 5:做 system suspend(P3)

  • 确认进入 suspend-to-RAM
  • 唤醒路径验证:GPIO/RTC/BT

Step 6:回归与自动化

  • 每天跑一次“待机 8 小时”回归
  • 输出功耗曲线与唤醒统计

10. BLE/Wi‑Fi 做唤醒源:工程视角要点(与你当前项目强相关)

你之前讨论过“scan 到设备但不连接就唤醒”。这属于:

  • 平板侧:保持扫描(耗电)
  • 相机侧:广告(耗电),或低功耗广播
  • 唤醒:需要硬件上能触发 wakeup(GPIO/host wake/BT wake)

10.1 结论先说清

  • “仅靠扫描结果唤醒对端”:本质是“对端一直在广播,你一直在扫描”。

    • 扫描端功耗通常更高。
  • 更合理:让相机侧进入深度待机,由平板侧通过“唤醒链路”触发(GPIO/PMU 唤醒/专用唤醒线/超低功耗无线)。

10.2 如果必须 BLE 唤醒,硬件上至少要满足

  • BT 芯片/模组具备 host_wake / device_wake 引脚
  • 该引脚连接到 always‑on 域可作为 wakeup IRQ
  • 低功耗状态下 BT 仍供电(IO rail 保持)

10.3 软件上要配合

  • 将 BT 控制器/驱动设置为 wakeup source
  • suspend 时允许控制器保活(视芯片能力)

扩展写作点:

  • Broadcom/Realtek BT 的 host_wake 机制与 DTS 配置
  • 蓝牙广告间隔/扫描窗口对功耗的量化影响
  • 4 路 camera + 平板场景的状态机与协议设计

11. Yocto / 系统集成侧:低功耗不是“改内核就完了”

11.1 systemd:待机态服务裁剪

  • 关闭不必要的 daemon
  • 待机态停止 camera/AI pipeline

11.2 默认 governor 与限制

  • boot 默认设置:

    • cpufreq governor
    • devfreq governor
    • max freq

11.3 配置接口:用统一的“电源策略服务”管理

建议做一个 power‑manager(守护进程或脚本):

  • 统一切换 P0~P4
  • 统一输出日志与 dump

12. 常见问题与“定位套路”(很实战)

Q1:为什么进入待机后功耗没怎么降?

排查顺序:

  1. 显示是否真的关?(clk_summary / domain)
  2. camera/ISP 是否仍 active?(runtime_status)
  3. DDR 是否仍高频?(devfreq)
  4. 是否被频繁唤醒?(wakeup_sources/interrupts)

Q2:为什么 domain 关不掉?

  • 某设备没有 runtime suspend
  • 某用户态进程一直持有 fd
  • IRQ 触发导致设备被唤醒

Q3:为什么 suspend 立即被唤醒?

  • wakeup source 配置过多
  • GPIO 抖动/浮空
  • 网络/蓝牙/USB 事件

13. 章节扩展计划:如何把本文“加厚到 55,000+ 字”(你要的目标)

下面是我为你预留的扩展目录,按它补充就能稳定超过 55,000 字,并且内容不会“水”。每一项都对应:更多硬件原理 + 更多代码阅读 + 更多实测案例。

Part A:RK3588 硬件与电源架构(+12k~18k 字)

  • A1:RK3588 电源域/时钟域/复位域的概念对应
  • A2:典型核心板 + 载板 Power Tree 实例拆解
  • A3:IO rail 与低功耗下的引脚电气(泄漏、电平、保持)
  • A4:DDR 自刷新/掉电模式的硬件条件

Part B:Linux 框架深挖(+15k~20k 字)

  • B1:cpuidle 深度状态与 PSCI 交互
  • B2:runtime PM 引用计数、autosuspend 机制
  • B3:genpd 内部实现与 Rockchip PMU 驱动代码解读
  • B4:cpufreq/devfreq/OPP 全链路

Part C:RK3588 子系统实战(+15k~20k 字)

  • C1:DRM/VOP2/DP/HDMI 低功耗路径(runtime suspend、PHY LPM)
  • C2:camera/ISP/MPP 编码器低功耗路径
  • C3:Wi‑Fi/BT 低功耗与唤醒(含参数量化)
  • C4:USB3/PCIe/SerDes LPM

Part D:工程化与回归(+8k~12k 字)

  • D1:功耗回归体系(脚本、指标、阈值)
  • D2:外部仪表与 rail 采样方案
  • D3:Bug 案例库:10 个真实问题从现象到根因

14. 附录:你可以直接用的“待机自检清单”

  • 灭屏后 VOP/PHY domain 进入 suspend
  • camera 相关节点 fd 全部释放
  • wakeup_sources 前三名可解释
  • clk_summary 中高频时钟数量显著下降
  • pm_genpd_summary 中大户 domain 为 off
  • CPU 进入深 idle state 的驻留时间占比高
  • DDR/devfreq 在待机态能降到低档

15. 结语:把低功耗当作“系统工程”

RK3588 这种 SoC 的低功耗,靠的不是某个神奇开关,而是:

  • 硬件上:电源树/唤醒线/IO rail 必须设计正确
  • 内核上:runtime PM + genpd + DVFS 路径必须打通
  • 系统上:业务进程要配合释放资源、减少唤醒
  • 工程上:必须有测量、有基线、有回归


📺 B站视频讲解(Bilibili)https://www.bilibili.com/video/BV1k1C9BYEAB/

📘 《Yocto项目实战教程》京东购买链接Yocto项目实战教程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值