嵌入式Linux调试iic

🔍 溯源 ✍️ Jack | 📅 2025-01-07 | 👍 1 | 原帖↗
#知识星球 #立芯嵌入式 #来源/立芯星球 #技术/I2C调试 #技术/Linux调试 #质量/精华

原帖 | Jack | 2025-01-07 12:38 | 👍1 | 阅读约1

嵌入式Linux调试iic

分享最近遇到一个 i2c 问题

问题背景:这路 i2c 接的电量计,电量计芯片内部有很多 task 要跑,所以会用到 i2c 时钟延展特性:在传输过程中,允许从机在自己忙的时候拉低 SCL,迫使主机进入等待状态。

问题现象:在 uboot 阶段,有时钟延展,但是延展阶段有一个300mV的半高电平,因为从机下拉能力弱,上拉电阻和下拉电阻分压导致。这种处理方式一般是增大上拉电阻,半高电平可以降低。在 uboot 阶段修改内部上拉电阻,可以按照预期变化。

但是一旦进了 kernel,发现这个半高电平变成了800mV,虽然对通信没影响,但是时序不符合 sepc,所以要查。

针对进入 kernel 以后的 800mV 半高电平审查,发现一旦进了 kernel,SCL 和 SDA 的波形变得非常陡峭,也就是主机端驱动能力很强,所以从机拉不下来。主机端修改 kernel 阶段的内部上拉电阻,发现没有任何效果。

打印出 uboot 阶段和 kernel 阶段的 i2c 控制器寄存器进行对比,发现 i2c 用的两个 PIN 进 kernel 变成了 push-pull,而不是 open-drain 开漏。原因是以往项目这路 i2c 接的外设跑的是 3.4M,这个速度 PIN 是推挽模式,需要在本项目改成开漏。

检查过程中,容易误导人的点:

1.波形上 SCL 的时钟延展有200mV半高电平,但是 SDA 上从机拉的 ACK bit 半高电平是正常的,产生了一定的误导。

2.修改推挽输出的位置很隐蔽,不在 dts 里面,而是用其他手段附加上去的。只有把运行时设备树捞出来,才发现有这个属性配置(运行时设备树的获取方法见 设备树反编译调试)。

3.一开始一直在纠结上拉电阻阻值的修改是否生效,耽误了时间。


相关笔记