1. 问题现象与背景分析
最近在调试基于RK3562+RK817电源管理芯片的嵌入式设备时,遇到了一个棘手的启动问题:当设备连接充电器时,如果用户长按电源键强制关机,再次上电后设备无法正常进入uboot阶段,直接"变砖"。这个故障在电池供电模式下不会出现,仅在充电状态下复现。
RK3562是瑞芯微推出的一款中端ARM处理器,广泛应用于平板电脑、工控设备和物联网终端。RK817是其配套的PMIC(电源管理集成电路),负责处理充电管理、DC-DC转换、RTC等功能。两者通过I2C总线通信,协同完成系统电源管理。
注意:这种充电状态下的异常关机问题,在嵌入式Linux设备中并不罕见,但不同平台的故障机理和解决方案差异很大。需要结合具体硬件设计分析。
2. 故障机理深度解析
2.1 充电状态下的电源时序异常
通过示波器抓取正常启动和故障场景下的电源时序,发现关键差异:
-
正常启动时序:
- VBUS(充电电压)先上电
- PMIC检测到VBUS后延迟200ms释放SYS_PWR(系统主电)
- CPU核心电压逐步建立
- 复位信号释放,CPU开始执行ROM code
-
异常关机后启动:
- VBUS持续存在(充电器未拔)
- 长按电源键触发PMIC强制关机
- 再次上电时SYS_PWR无延迟直接输出
- CPU核心电压建立过早,导致ROM code执行异常
2.2 RK817的充电管理特性
查阅RK817数据手册发现,其充电管理模块有个特殊设计:当检测到VBUS存在时,CHG_STAT引脚会保持高电平,此时如果触发强制关机,PMIC会进入"充电待机模式"而非完全断电。这种设计本意是避免频繁插拔充电器,但却影响了uboot的正常加载。
3. 解决方案设计与验证
3.1 硬件修改方案
最初尝试的硬件解决方案:
-
在VBUS检测电路上增加RC延迟(100KΩ+10μF)
- 实测效果:延迟约300ms,问题缓解但未根治
- 缺点:影响正常充电检测速度
-
修改PMIC的PWRON引脚电路
- 增加一个MOS管隔离充电状态下的信号干扰
- 需要改板,成本较高
3.2 软件解决方案
最终采用的uboot补丁方案更为经济可靠:
c复制// 在uboot的board_init_f()中添加充电状态检测
int check_charger_status(void)
{
int ret;
u8 val;
/* 初始化I2C总线 */
i2c_set_bus_num(0);
/* 读取RK817的POWER_EN寄存器 */
ret = i2c_read(0x20, 0xB1, 1, &val, 1);
if (ret) {
printf("I2C read error!\n");
return -1;
}
/* 检查CHG_STAT位 */
if (val & 0x08) {
printf("Charger connected, reset PMIC...\n");
/* 写POWER_EN寄存器强制复位 */
val |= 0x80;
i2c_write(0x20, 0xB1, 1, &val, 1);
mdelay(50);
}
return 0;
}
3.3 内核驱动的配套修改
为保证系统稳定性,还需要修改Linux内核中的RK817驱动:
c复制// drivers/power/supply/rk817_charger.c
static int rk817_charger_probe(struct platform_device *pdev)
{
// 添加充电状态下的关机处理回调
devm_kzalloc(&pdev->dev, sizeof(struct rk817_charger), GFP_KERNEL);
power_supply_get_by_phandle(pdev->dev.of_node, "monitored-battery");
INIT_DELAYED_WORK(&charger->otg_work, rk817_charger_otg_work);
// 新增关机状态检测
if (rk817_reg_read(charger->rk817, RK817_PWRON_STS) & 0x01) {
rk817_reg_write(charger->rk817, RK817_SYS_CFG, 0x40);
msleep(100);
}
...
}
4. 完整修复流程
4.1 操作步骤
-
获取uboot源码:
bash复制git clone https://github.com/rockchip-linux/u-boot.git cd u-boot git checkout -b rk3562_dev origin/next-dev -
应用补丁:
bash复制
patch -p1 < rk3562_charger_fix.patch -
编译配置:
bash复制make rk3562_defconfig make menuconfig # 确保以下选项启用: # CONFIG_PMIC_RK817=y # CONFIG_CMD_I2C=y -
编译烧写:
bash复制make -j8 ./tools/mkimage -T rksd -d tpl/u-boot-tpl.bin idbloader.img cat spl/u-boot-spl.bin >> idbloader.img sudo dd if=idbloader.img of=/dev/sdX bs=512 seek=64
4.2 关键参数说明
| 参数 | 地址 | 位域 | 功能描述 |
|---|---|---|---|
| POWER_EN | 0xB1 | BIT7 | PMIC全局复位 |
| CHG_STAT | 0xB1 | BIT3 | 充电状态指示 |
| SYS_CFG | 0x00 | BIT6 | 系统配置寄存器 |
5. 常见问题排查指南
5.1 补丁应用失败
现象:编译时报错undefined reference to i2c_read
解决方案:
- 检查uboot配置是否启用I2C:
bash复制
grep CONFIG_CMD_I2C .config - 确认板级支持文件中有I2C初始化代码:
c复制// board/rockchip/evb_rk3562/evb_rk3562.c int board_init(void) { /* I2C初始化 */ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); ... }
5.2 充电状态检测不准确
现象:设备仍偶尔无法启动
调试方法:
- 在uboot命令行手动读取PMIC寄存器:
bash复制
i2c md 0x20 0xB1.1 - 检查硬件上拉电阻:
- CHG_STAT引脚应有10KΩ上拉
- VBUS检测分压电阻建议为1MΩ+200KΩ
5.3 系统稳定性问题
现象:正常使用时随机重启
优化方案:
- 在PMIC中断处理中添加去抖:
c复制// 修改drivers/power/supply/rk817_charger.c static irqreturn_t rk817_charger_irq(int irq, void *data) { msleep(20); // 增加20ms去抖 ... } - 调整电源时序参数:
c复制// 修改uboot的include/configs/rk3562.h #define CONFIG_POWER_DELAY_MS 150
6. 经验总结与优化建议
经过两周的调试和验证,这套解决方案已在批量设备上稳定运行。几个关键经验值得分享:
-
电源时序调试技巧:
- 使用带协议分析功能的示波器(如Micsig TO1104)同时抓取VBUS、SYS_PWR和复位信号
- 在关键测试点焊接排针,避免探头接触不良导致误判
-
PMIC寄存器操作注意事项:
- RK817的I2C地址是0x20(7位地址)
- 写寄存器前必须先读取原始值,避免覆盖其他配置位
- 关键操作后建议添加50ms以上延迟
-
量产优化建议:
- 在PCBA测试阶段增加充电状态下的强制关机测试项
- 对PMIC固件进行定制,修改CHG_STAT的默认行为
- 在硬件设计上预留PMIC复位测试点
这个案例再次证明,嵌入式系统的电源管理问题往往需要软硬件协同解决。通过深入分析PMIC的工作机制,结合uboot的启动流程特点,最终找到了既可靠又经济的解决方案。