一、简介:为什么电源管理在瑞芯微 + RT-Linux 上必须重做?
场景痛点:
工业视觉网关 7×24 运行,风扇尺寸受限,CPU 温度 > 85℃ 直接降频,实时帧率掉包。
电池供电的 AGV 小车,休眠电流每降 10 mA,续航多 1 小时,但唤醒后须 2 ms 内恢复控制环。
芯片背景: 瑞芯微 RK3568/RK3588 采用 ARM 大小核 + Mali GPU + NPU,官方 BSP 默认面向 Android,电源策略偏重“性能”,PREEMPT-RT 打补丁后
cpuidle与dvfs出现 5~20 ms 延迟,不满足 SIL/PL 实时要求。文章价值: 提供一套“实时优先 + 功耗次优”的量化方法,可复用到 RK3xxx 全系,适配边缘视觉、运动控制、车载 ECU 等场景。
二、核心概念:6 个关键词先搞懂
| 关键词 | 一句话 | 瑞芯微对应驱动 |
|---|---|---|
cpuidle | 内核层空闲状态管理,C0/C1/C2…越深越省电,唤醒越久 | drivers/cpuidle/cpuidle-arm.c |
dvfs | 动态调频/调压,OPP 表在 DTB | drivers/opp/+rk3568.dtsi |
pm_qos | 电源质量投票机制,实时任务可“反对”降频 | kernel/power/pm_qos.c |
wake_lock | 强制阻止系统进入 suspend(RT 常用) | drivers/power/wakelock.c |
latency_tolerance | RT 线程设置容忍延迟,cpuidle 据此选最深状态 | sched_setattr() |
suspend-to-idle | 纯软件休眠,未下电 DDR,唤醒 < 2 ms | echo freeze > /sys/power/state |
三、环境准备:10 分钟搭好开发机
1. 硬件
RK3568 核心板(2×A55@1.8 GHz + Mali-G52)
12 V/2 A 电源 + 串口线 + 散热片(无风扇实验更直观)
2. 软件
| 组件 | 版本 | 获取 |
|---|---|---|
| 官方 SDK | RK Linux 4.19 / 5.10 | 瑞芯微 GitLab |
| PREEMPT-RT 补丁 | rt28/rt30 | kernel.org |
| 交叉工具链 | gcc-arm-10.3 | apt install gcc-arm-linux-gnueabihf |
| 测试工具 | rt-tests / pm_test | 下文一键脚本 |
3. 一键打补丁 & 编译(可复制)
#!/bin/bash # rt_pm_build.sh set -e SDK=~/proj/rk3568-linux-5.10 RT_PATCH=patch-5.10-rt30.patch cd $SDK wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/$RT_PATCH patch -p1 < $RT_PATCH # 开启 RT + CPU_IDLE ./scripts/config -e CONFIG_PREEMPT_RT \ -e CONFIG_CPU_IDLE \ -e CONFIG_ARM_CPUIDLE make ARCH=arm64 rockchip_defconfig make ARCH=arm64 Image dtbs -j$(nproc)输出Image&rk3568-evb.dtb复制到 SD 卡即可启动。
四、应用场景(≈300 字)
边缘视觉质检工控机
在 3C 产线,RK3568 驱动 2 路 GigE 相机(2×500 万像素,15 fps),运行 YOLO v5-n 缺陷检测模型,同时通过 EtherCAT 控制 6 轴机械臂。产线节拍 6 s/件,允许视觉处理时间 ≤ 1 s,机械臂轨迹插补周期 1 ms。
白天生产高峰需全速运行;夜班订单少,系统进入“低功耗待机”,唤醒时间必须 < 2 ms,否则第一个产品漏检。
本方案通过“大小核分区 + suspend-to-idle + dvfs 抑制”三件套,实现:
满载功耗 8.2 W → 空闲 2.1 W
唤醒延迟 1.3 ms(含 DDR 自刷新退出)
实时检测线程始终绑定大核,频率锁定 1.4 GHz,保证 1 ms 插补不被 cpufreq 打断。
五、实际案例与步骤:从“耗电 8 W”到“2 W”且实时不掉帧
所有脚本放
/opt/rt_pm/,可写成 systemd 服务,开机自启。
5.1 测量基线:功耗&延迟双指标
# 1. 功耗:INA3221 板载芯片 cat /sys/class/power_supply/rk3568-bat/current_now cat /sys/class/power_supply/rk3568-bat/voltage_now # 2. 延迟:cyclictest 采样 60 s sudo cyclictest -p95 -m -Sp90 -i200 -d60s > cyclictest.log &记录:满载 Max Latency = 68 μs,功耗 8.2 W。
5.2 第 1 步:关闭 LED & 无用外设(硬功耗)
# 关闭心跳 LED echo 0 > /sys/class/leds/working/trigger # 关闭 HDMI(视觉工控无显示器) echo off > /sys/class/drm/card0-HDMI-A-1/status功耗 ↓ 0.4 W。
5.3 第 2 步:大核跑 RT,小核跑非实时(分区)
# 实时检测线程绑定 core2(大核) taskset -c 2 ./detect_app # 其余用户态进程迁移到 core0-1 echo 0-1 > /sys/fs/cgroup/cpuset/nonrt/cpus echo 3 > /sys/fs/cgroup/cpuset/rt/cpus确保detect_app即使休眠唤醒,也只在大核调度。
5.4 第 3 步:pm_qos 禁止深度 idle
/* 代码片段:detect_app.c */ #include <sys/ioctl.h> #include <linux/pm_qos.h> int main() { int fd = open("/dev/cpu_dma_latency", O_WRONLY); int32_t target = 0; /* 0 μs = 不允许 C2+ */ write(fd, &target, sizeof(target)); /* 主循环 */ }效果:cpuidle 停留在 C1,退出延迟 < 20 μs,功耗增加 0.15 W,可接受。
5.5 第 4 步:dvfs “上限抑制”——只降一半
# 查看可用 OPP cat /sys/devices/system/cpu/cpu2/cpufreq/scaling_available_frequencies # 把最高频从 1.8 GHz 降到 1.4 Ghz(50% 负载够用) echo userspace > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor echo 1416000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_setspeed功耗 ↓ 1.1 W,检测帧率保持 15 fps 不掉。
5.6 第 5 步:suspend-to-idle 夜班模式
#!/bin/bash # enter_idle.sh # 1. 保存当前 cpufreq cpupower frequency-set -g userspace # 2. 设置唤醒源 GPIO(按钮) echo GPIO_ACTIVE_LOW > /sys/power/wakeirq # 3. 进入 freeze echo freeze > /sys/power/state唤醒时间测量:
time echo freeze > /sys/power/state # real 0m0.001s电流从 680 mA → 180 mA(@12 V),单晚 8 h 节电 ≈ 0.04 kWh,百台产线年省 1500 元电费。
六、常见问题与解答(FAQ)
| 问题 | 现象 | 解决 |
|---|---|---|
cyclictestMax 延迟 > 200 μs | 深度 C-state 未禁止 | 写cpu_dma_latency或pm_qos_add_request() |
| 唤醒后串口乱码 | 串口波特率被重新初始化 | 在设备树保留uart2时钟,关clk_ignore_unused |
| 功耗降了但帧率掉 | 频率被锁太低 | 用performancegovernor 或提升最低频率 |
| 无法进入 freeze | 打印Freezing of tasks failed | 某驱动持有 spinlock,打 RT 补丁或更新到 5.15-rt30 |
| Suspend 电流仍 300 mA | DDR 未进入自刷新 | 检查regulator-suspend-microvolt设置 |
七、实践建议与最佳实践
先测延迟,再测功耗
实时性一旦破坏,省电再多也白搭。分区明确
大核=RT,小核= housekeeping,互不抢占。governor 阶梯策略
白天performance,夜班powersave+上限抑制,脚本自动 cron 切换。使用 devfreq
对 GPU/NPU 同样设上限,避免 Mali 满载拖垮电源 IC。版本锁定
把设备树、pm_qos 值、唤醒源写进 Yocto 层,防止 OTA 后被覆盖。日志留痕
每次 suspend/唤醒记录到/var/log/pm.log,方便审计与故障回溯。
八、总结:一张脑图带走全部要点
瑞芯微 RT-Linux 电源管理 ├─ 测量:cyclictest + INA3221 ├─ 分区:大核 RT / 小核 housekeeping ├─ 策略: │ ├─ 外设断电 │ ├─ pm_qos 禁深 C-state │ ├─ dvfs 上限抑制 │ └─ suspend-to-idle 夜班 ├─ 工具:cpupower / rt-tests / pm_test └─ 目标:实时不掉帧,功耗降 60%实时与低功耗并非二选一——只要遵循“分区→抑制→休眠”三步法,你就能在瑞芯微平台上做出毫秒级响应、瓦特级功耗的工业级产品。立刻复制脚本跑一遍,把数据记录进 Git,下一版硬件即使无风扇,也能安静、稳定、实时地奔跑!