I2C是经常使用的一种bus方式,工程师们也经常调试I2C驱动设备;总会碰到各种各样的问题;
最令人头疼的一种问题,就是非常小概率I2C数据报错,又不好重现,怎么处理呢? 好在linux提供一种非常
牛逼的方法,可以在总线被挂住的情况下恢复,然后设备可以继续使用。下面就把相关的代码列举下。
但是你的平台是否配置此功能需要验证下,并打开相关的功能。
Linux I2C 总线驱动恢复机制!从代码看,非常明确的解释了I2C的工作机制和原理。
#define RECOVERY_CLK_CNT 9
static int i2c_generic_recovery(struct i2c_adapter *adap)
{
int i = 0, val = 1, ret = 0;
if (bri->prepare_recovery)
bri->prepare_recovery(adap);
bri->set_scl(adap, val);
ndelay(RECOVERY_NDELAY);
/*
* By this time SCL is high, as we need to give 9 falling-rising edges
*/
while (i++ < RECOVERY_CLK_CNT * 2) {
if (val) {
/* Break if SDA is high */
if (bri->get_sda && bri->get_sda(adap))
break;
/* SCL shouldn't be low here */
if (!bri->get_scl(adap)) {
dev_err(&adap->dev, "SCL is stuck low, exit recovery\n");
ret = -EBUSY;
break;
}
}
val = ! val; ///// 0 1 0 1 波形高低
bri->set_scl(adap, val);
ndelay(RECOVERY_NDELAY);
}
bri->get_sda = get_sda_gpio_value;
bri->get_scl = get_scl_gpio_value;
bri->set_scl = set_scl_gpio_value;
文件: kernel-4.4/drivers/i2c/i2c-core.c
虽然在非不得已情况下,可以使用此方法,当然开着这个功能也很实用;但是,最好的办法
还是把根本的问题解决好,这样不会留下什么后遗症。很多情况下是同一组I2C下,挂了多组设备,之间
没有协调好,另外上拉电阻硬件工程师没有算好,大部分他们也只是抄问厂商参考上拉电阻值,而不会
在统一大局下,协调所有同组I2C上设备调好匹配需求,多个上拉电阻就会造成并联,阻值就会变小。
这样就会出现同一路I2C下,有的设备不稳定,或者出现一些奇异的问题事件,低概率问题,
基本上很难查,一般这种问题的根因都是 基本原理没有过关。