做硬件调试这些年,我越来越认同一句话:电源管理芯片调好了,板子就成功了一半;调不好,CPU、DDR、外设全都会用各种奇怪的方式教你做人。RK806S 是 RK 平台方案里非常常见的一颗 PMIC,在 RK3588、RK3568 这类主控的参考设计里出现率极高,负责给核心域、DDR 域、逻辑域、IO 域提供多路 BUCK 和 LDO 电源,同时承担上电时序控制、下电时序控制、待机低功耗切换这些关键职责。这篇文章围绕 RK806S 的实际调试过程展开,从 I2C 通路建立、寄存器配置、上电时序验证、动态调压,到待机功耗排查,完整记录我调试中碰到的问题和处理思路。内容面向硬件工程师、嵌入式驱动工程师,以及刚接触 RK 平台电源部分的同学,文章里涉及的命令和步骤都来自真实操作,可以直接参考复现。
1. RK806S 在整套硬件方案中的角色与调试边界
1.1 为什么电源管理芯片的问题最难查
很多初次接触 RK 平台的人,会把 PMIC 想得很简单:不就是上电输出几路电压嘛。真正开始调试就会发现,PMIC 的问题几乎不会单独出现,它总是以“系统起不来”“DDR 训练失败”“跑着跑着重启”“待机电流异常”这种间接方式暴露出来。RK806S 这类多路输出的 PMIC,内部寄存器动辄上百个,每一路输出电压、工作模式、上下电延时、过流保护阈值、电源正常指示引脚,全部可以通过 I2C 配置。更麻烦的是,它和主控之间的配合是双向的:主控通过 I2C 写寄存器控制 PMIC,PMIC 又通过复位信号、电源正常信号、中断引脚反过来影响主控状态。一旦链路中的任何一个环节不对,表现出来的现象就会非常绕。
我自己的经验是,调 PMIC 第一件事不是着急测波形,而是先把“调试边界”画清楚。RK806S 本身不管主控内部怎么跑,它只负责输出正确的电压、按正确的顺序上下电、响应 I2C 配置和睡眠唤醒指令。主控启动失败,不一定是 PMIC 的问题,也可能是 clock、DDR 配置、存储初始化的问题。反过来,主控能跑起来但电压跌落严重,那大概率要从 PMIC 的布局布线和负载端去找原因。把问题边界分清楚,才不会在错误的方向上浪费一整天。
1.2 拿到板子后,第一件事是核对电源树而不是写代码
我记得第一次调 RK3588 + RK806S 的板子,上来就想赶紧跑一个 I2C 读写脚本,看看芯片活着没有。结果折腾了半天,发现 I2C 地址都没找对,后来静下心把原理图打开,重新梳理电源树,才发现参考设计和实际板卡有几路 LDO 的供电来源接得不一样。
所以我的建议是,无论你多着急,先把下面这张表理出来:
| 电源轨 | 去向 | 默认电压 | 最大负载电流 | 滤波电容 | 使能来源 | 备注 |
|---|---|---|---|---|---|---|
| DCDC_REG1 | VDD_CPU | 0.9V | 8A | 4 x 22uF | PMIC 内部时序 | 核心供电,动态调压 |
| DCDC_REG2 | VDD_GPU | 0.9V | 6A | 4 x 22uF | PMIC 内部时序 | 动态调压 |
| DCDC_REG3 | VDD_LOGIC | 0.8V | 4A | 2 x 22uF | PMIC 内部时序 | 常供电轨 |
| DCDC_REG4 | VDD_DDR | 1.1V | 6A | 4 x 22uF | PMIC 内部时序 | DDR 供电 |
| LDO1 | VCC_1V8 | 1.8V | 200mA | 1 x 1uF | GPIO 控制 | 外设 IO 域 |
| LDO2 | VCC_3V3_SD | 3.3V | 300mA | 1 x 1uF | GPIO 控制 | SD 卡供电 |
这张表不用多复杂,但每一路电源轨的去向、默认电压、最大电流、使能来源必须标清楚。调试过程中遇到任何异常,先回到这张表确认“这一路到底是谁在用”,比直接查寄存器高效得多。
2. 建立 I2C 通路:调 PMIC 的第一道门槛
2.1 最小调试环境与工具准备
RK806S 的控制接口是 I2C,所以调 PMIC 的第一步,就是把 I2C 通路打通。我最常用的方式是通过主控的 Linux 系统直接操作 I2C 设备节点,也就是在系统能起来的前提下,用 i2c-tools 去读写 PMIC 寄存器。如果系统连早期启动阶段都过不去,那就需要借助逻辑分析仪或者外接的 I2C 调试工具来抓总线波形,确认主控到底有没有和 PMIC 正常通信。
下面是我调试 RK806S 时固定会准备的一套工具:
- 开发板 + 能正常进入 Linux 命令行或者至少能停住 bootloader 的系统
- 串口线,用于查看系统日志,确认 I2C 驱动是否注册成功
- i2c-tools 工具集,里面包含 i2cdetect、i2cget、i2cset、i2cdump 这些命令
- 示波器,至少 100MHz 带宽,用来抓电源开关波形和纹波
- 电子负载或者大功率电阻,用来模拟负载电流变化
- 逻辑分析仪,调试早期上电时序和分析 I2C 波形非常有用
这里有一个容易忽略的细节:如果板子用的是 RK806S 的默认配置,PMIC 的 I2C 从机地址通常是固定的,但不同批次或者不同硬件版本可能通过外部引脚选择不同的地址位。拿到板子先别急着照着参考设计写死地址,打开原理图确认一下地址引脚的实际接法,再去扫描总线。
2.2 寄存器读写实操:从探测地址到批量配置
进入系统终端后,第一步是扫描 I2C 总线,找到 PMIC 挂在哪条总线上、地址是多少。以 RK3588 为例,PMIC 一般挂在 I2C0 上,可以用下面的命令扫描:
i2cdetect -y 0如果 PMIC 在总线上,输出里会在对应地址位置显示设备编号。常见地址是 0x49 或者 0x4B,具体取决于硬件设计。扫描结果里出现的每一个地址都要对照原理图确认是什么设备,避免读错了芯片。
确认地址之后,就可以直接读寄存器了:
# 读取 PMIC 0x00 地址寄存器的值 i2cget -y 0 0x49 0x00 # 写入一个寄存器,把 0x15 写入地址 0x01 i2cset -y 0 0x49 0x01 0x15写寄存器的时候要非常小心,尤其是涉及电压设置、使能控制和时序配置的寄存器,写错一个 bit,板子可能当场就没电了。我自己习惯在修改之前先做一次完整的寄存器 dump,把当前所有寄存器值保存下来,这样改乱了随时能恢复:
i2cdump -y 0 0x49 > rk806s_reg_dump_before.txt调试过程中需要反复切换电压或者开关某一路输出时,写一个批量操作的 shell 脚本会方便很多。下面是我常用的一个简单脚本,用来快速把 VDD_CPU 切换到指定电压:
#!/bin/bash # 切换到 0.9V,具体寄存器地址和 bit 定义以 datasheet 为准 # 这里只是演示 i2cset 的批量操作思路 ADDR=0x49 REG_VSEL0=0x21 REG_VSEL1=0x22 echo "Current VSEL0: $(i2cget -y 0 $ADDR $REG_VSEL0)" echo "Current VSEL1: $(i2cget -y 0 $ADDR $REG_VSEL1)" echo "Setting VDD_CPU to 0.9V ..." i2cset -y 0 $ADDR $REG_VSEL0 0x90 i2cset -y 0 $ADDR $REG_VSEL1 0x90 echo "Verifying ..." i2cget -y 0 $ADDR $REG_VSEL0 i2cget -y 0 $ADDR $REG_VSEL1这个脚本虽然简单,但能帮你避免一条一条敲命令敲到手酸,而且每次修改都留痕,后面排查问题能少走很多弯路。
2.3 I2C 不通读回全 0xFF 的常见原因
I2C 调试中遇到最多的问题,不是不会读写寄存器,而是读写结果不符合预期。最常见的一种情况是 i2cdetect 扫描不到设备,或者读回的数据全是 0xFF。我总结过一份排查对照表:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 扫描不到设备 | PMIC 未上电 | 用万用表量 PMIC 主供电引脚电压 |
| 扫描不到设备 | I2C 地址判断错误 | 对照原理图确认地址引脚配置 |
| 扫描不到设备 | SDA/SCL 接反 | 用示波器看总线波形,确认数据线信号 |
| 读回全是 0xFF | I2C 上拉电阻没焊 | 测量 SDA/SCL 静态电平,应为高电平 |
| 读回全是 0x00 | PMIC 处于复位状态 | 检查复位引脚和使能引脚电平 |
| 读写不稳定 | 总线电平不匹配 | 确认 I2C 总线电压域和 PMIC IO 电压域一致 |
| 写入后读回不对 | 寄存器是只读或者需要先解锁 | 查阅 datasheet,确认是否需要写保护解锁 |
尤其要注意 I2C 上拉电阻。PMIC 调试板经常是从大板上飞线出来的,飞线一长,总线寄生电容变大,如果没有合适的上拉电阻,波形上升沿会变得很缓,通信就容易出错。我遇到过一块板子,I2C 波形正常时能通,摸一下排线就断,最后发现是 FPC 排线太长,上拉电阻用的是 10K,换成 2.2K 之后问题就消失了。
3. 上电时序与寄存器配置:最容易翻车的环节
3.1 上电时序错乱的典型表现
RK806S 的核心功能之一,是保证各路上电顺序符合主控的要求。RK 平台的 SoC 对电源时序有明确要求,核心供电、DDR 供电、逻辑供电、IO 供电之间必须满足一定的先后关系和延时。理论上,PMIC 内部有可编程的时序控制寄存器,只要按参考设计配置好,默认就不会出问题。但在实际项目中,上电时序翻车的概率依然很高,原因往往是硬件设计改了供电网络,却没有同步修改 PMIC 的时序配置。
时序错乱的表现通常不是“完全没电”,而是“系统起了一半就死掉”。比如 U-Boot 已经打印了一部分日志,到 DDR 初始化阶段卡死;或者是 Linux 内核解压到一半,突然系统掉电重启。这种问题最迷惑人的地方在于它不是必现的,有时候加电能起来,有时候起不来,温度稍高一点故障率就明显上升。
3.2 配置寄存器之前先厘清三张表
调试上电时序,我个人的习惯是先整理三张表,再动寄存器:需求表、时序表、默认值表。需求表来自 SoC 的数据手册,写明各电源轨的上电顺序和延时要求;时序表来自 RK806S 的数据手册,列清楚 PMIC 提供的延时档位和控制方式;默认值表则是从板子上实际 dump 出来的寄存器值,用来确认现在的配置到底是什么。
| 电源轨 | SoC 要求的上电顺序 | RK806S 对应输出 | 延时要求 |
|---|---|---|---|
| VDD_LOGIC | 第 1 个上电 | DCDC_REG3 | 0ms |
| VDD_DDR | 第 2 个上电 | DCDC_REG4 | 延迟 1ms |
| VDD_CPU | 第 3 个上电 | DCDC_REG1 | 延迟 2ms |
| VDD_GPU | 第 4 个上电 | DCDC_REG2 | 延迟 3ms |
| VCC_1V8 | 第 5 个上电 | LDO1 | 延迟 4ms |
这里说的延时只是示例,真实项目中要以主控 datasheet 的时序图为准。RK806S 内部有专门的时序控制寄存器,通过配置 DVS 和 power down/up sequence 相关的寄存器,可以让每一路在指定延时后启动。写这些寄存器之前,必须把当前配置 dump 出来备份,因为 RK806S 很多寄存器带有写保护或者只有在特定状态下才能修改,直接写可能不生效。
3.3 用逻辑分析仪和示波器验证时序是否符合预期
配置完寄存器,不能只看系统能起来就当完成。我用示波器单次触发模式同时抓几路关键的电源轨,确认实际的上下电顺序和延时和预期一致。示波器通道不够的时候,可分两组抓,比如第一组抓 VDD_LOGIC、VDD_DDR、VDD_CPU、VDD_GPU,第二组抓 LDO 和 IO 电源。
抓波形这一步能发现很多隐蔽问题。有一次我配置的延时完全按照需求表来,但示波器显示 DCDC_REG4 实际比 DCDC_REG3 先起来,查了半天发现是 PMIC 不同的输出共用了同一个电源正常信号,使能逻辑实际上被拉低了。如果只靠系统能不能跑来判断时序,这种问题很难发现,但用波形一眼就能看出来。
4. 用波形和数据定位调压异常的完整排查链路
4.1 从寄存器状态到输出波形,证据链要完整
RK806S 支持动态调压,也就是主控可以根据 CPU/GPU 负载实时调整供电电压,这也是低功耗设计的关键。但动态调压调试中,最常遇到的问题就是“电压调下去了,系统直接挂掉”或者“电压纹波大得离谱”。
我排查这类问题有一个固定的顺序:先读寄存器确认电压设置是否真的变了,再用示波器看输出波形确认实际电压是否和寄存器一致,最后带负载看瞬态响应。寄存器状态、实测波形、负载电流,这三者必须能对上,证据链才算完整。很多工程师只看了寄存器就下结论,结果发现波形和寄存器完全对不上,浪费了大量时间在排查驱动代码上。
4.2 负载瞬态跌落过大的排查顺序
如果你用电子负载给某一路快速加上大电流,示波器上看到输出电压跌落超过规定值,这就是典型的负载瞬态响应问题。RK806S 本身有环路补偿和响应速度设计,但板级实现的差异会直接影响瞬态性能。我按照下面的顺序排查:
- 检查输出电容数量是否足够,容量是否和参考设计一致,特别要注意电容的直流偏压特性,小封装陶瓷电容在高压下实际容量会明显下降
- 检查反馈采样点位置,反馈走线应该从负载端单独引出,不能靠近电感或者开关节点
- 检查电感饱和电流是否足够,电感量偏小会导致电流纹波变大,加剧电压跌落
- 确认 PMIC 当前工作在 PWM 还是 PFM 模式,轻载 PFM 模式的瞬态响应天生比 PWM 模式差
- 确认负载变化斜率是否超出 PMIC 环路带宽的能力范围
我印象特别深的一次,是板子轻载时电压很稳,一跑压力测试就重启,最后用热成像仪发现电感温度明显偏高,换了一颗饱和电流更高的电感之后,问题彻底解决。硬件调试很多时候就是一分证据说一分话,波形和数据拿到手了,问题基本就藏不住。
4.3 动态调压没生效的几种常见误区
动态调压没生效,最常见的原因不是 PMIC 坏了,而是软件侧配置没对上。Linux 内核里 regulator 框架管理所有电压调节设备,CPU 调频调压时,内核会找到对应的 regulator 实例,然后调用 ops 去修改 PMIC 寄存器。很多人配了 DTS 之后发现电压纹丝不动,问题往往出在下面几个方面:
- DTS 中 regulator 节点没有正确关联到 CPU/GPU 的电源域
- regulator 的 min/max 电压范围写得太窄,调压请求被框架拒绝
- 没有配置 regulator-allow-set-load 或者设置了 regulator-boot-on 但没设置 regulator-always-on
- CPUFreq 的 frequency table 指定的电压和 PMIC 实际支持的电压档位不匹配
下面是一段典型的 DTS 配置参考,实际项目中需要根据自己的硬件方案调整节点路径和电压档位:
&rk806 { vcc1-supply = <&vcc5v0_sys>; regulators { vdd_cpu: dcdc-reg1 { regulator-name = "vdd_cpu"; regulator-min-microvolt = <650000>; regulator-max-microvolt = <1450000>; regulator-init-microvolt = <900000>; regulator-ramp-delay = <2500>; regulator-always-on; regulator-state-mem { regulator-off-in-suspend; }; }; }; };如果寄存器看起来在变,但实际输出电压不变,优先怀疑 PMIC 的 VSEL 引脚工作模式。RK806S 有的版本支持通过硬件引脚直接选择电压档位,当引脚电平锁定了一个档位时,I2C 写入可能不会生效,或者需要先配置寄存器把控制权切换到 I2C。
5. 待机功耗与睡眠模式的调试细节
5.1 低功耗电流测量的两个坑
低功耗调试是 PMIC 调试里最磨人的环节。系统进入睡眠状态后,整板电流应该在几十毫安甚至更低,但很多板子实际测出来高得离谱。这里有两个非常容易踩的坑:一是测量方法不对,二是没分清各路电流的去向。
测量待机电流时,不能直接把万用表串进电源里就完事。睡眠状态下电流是动态变化的,有瞬态尖峰,普通万用表的积分响应会让读数偏大或者跳变。我习惯用两种方式交叉验证:一种是用高精度的台式万用表串联测量平均电流,另一种是用示波器电流探头配合一个极小的采样电阻抓取电流波形,看有没有周期性尖峰。周期性尖峰通常意味着某个外设还在周期性地唤醒工作。
5.2 睡眠唤醒后电压漂移和系统不复位的排查
待机功耗调试中另一个常遇到的问题,是系统睡眠唤醒后行为异常,比如唤醒后 USB 设备识别不到、DDR 数据出错、甚至唤醒即死机。这类问题的根源往往是 PMIC 在睡眠状态下把某一路供电切掉了,但主控和外设之间的电平状态没有正确保存或者没有正确恢复。
排查这类问题时,我会在进入睡眠前和唤醒后分别 dump 一遍 PMIC 的关键寄存器,对比哪些电压轨的状态发生了变化,再配合主控的 gpio 状态、外设的供电要求综合判断。还有一个高频原因是 PMIC 的 sleep mode 配置把某一路关掉了,但 DTS 里没有对应的 regulator-state-mem 配置,导致内核在睡眠时发出的请求和 PMIC 实际执行的行为不一致。
我自己遇到过一次特别隐蔽的情况:系统唤醒后,PMIC 输出电压确实恢复到了正常值,但示波器显示电压上升过程非常慢,平台侧已经初始化完成了电压还没稳。最后确认是睡眠前 PMIC 进入了 power save 模式,唤醒时没有及时切回 PWM 模式,响应速度跟不上主控的初始化节奏。这种问题从寄存器日志完全看不出来,必须靠波形定位。
5.3 调试记录和工作流:把经验固化成流程
RK806S 调试到了后期,真正让项目受益的,不只是解决了眼前的问题,而是把调试过程固化成了可复用的工作流。我现在每调一块新板子,都会建立一个专门的调试记录目录,里面至少包含三个文件:寄存器初始 dump、每次修改的操作记录、最终验证的完整寄存器 dump。Linux 下用一条命令就能把整个 PMIC 的寄存器状态全部保存下来:
i2cdump -y 0 0x49 > rk806s_final_config.txt另外我会在系统起来之后,用脚本把 PMIC 的关键寄存器读取结果打印到串口日志里,这样后续测试过程中只要拿到一份日志,就能快速判断 PMIC 的配置状态是否符合预期。
这套流程看起来简单,但在实际项目中非常有用。有一次量产阶段出现批次性不良,工厂反馈一批板子待机电流偏大,我拿到板子以后第一件事就是对比寄存器 dump,结果发现两批货的 PMIC 默认寄存器值不一致,问题一下定位到了物料版本差异,而不是板级设计问题。如果当初没有留好寄存器基线,这种问题可能要排查好几天。
调试 PMIC 这类芯片,说到底拼的是耐心和细节。每一个异常现象背后,都有一套完整的因果关系等着你去挖掘。把 I2C 通路打稳,把寄存器配置和波形验证结合起来,把每次修改都记录下来,你会发现所谓玄学问题,大部分最后都落在了一个具体的电阻、一条 PCB 走线或者一个寄存器 bit 上。