在linux3.10内核中i2c_register_adapter的adap->bus_recovery_info是如何设置呢?
本文是原「蜗窝讨论区」的历史存档(2016-08-26),来自版块「Linux kernel技术问答」,共 5 帖。讨论区已停止服务,此处仅供查阅。
RT 在内核中,看到有这么一个恢复的动作,但是如何去设置并在i2c模块注册过程中,先发9个脉冲恢复总线不清楚!!!
对了,忘记补充问题的背景了。
【问题背景】在当前使用的单板中,有概率性的单板启动失败,反复复位。重新上下电后回复。
【问题原因】打开内核的DEBUG_ll, 发现是在内核的i2c总线在操作pca9555过程中超时,也就是总线由于莫名原因SDA被拉低,i2c控制器判断总线状态为Busy,从而超时,导致单板复位。 我想,am3352的i2c1总线外挂了四片pca9555,所以这种问题的概率就大些了。
【定位过程】硬件工程师将i2c1于pca9555之间线路断开,pca侧 sda线一直是拉低,而i2c控制器侧恢复高电平。 从而推断: 在操作i2c总线过程中,pca9555回复ack,拉低sda,而此时正巧单板复位,scl时钟信号无效。sda会被pca9555,一直拉低。 因此造成了总线的异常状态。
【解决方案】 具体链接: http://www.voidcn.com/blog/yuyin86/article/p-4745473.html 6、 无应答信号(NACK)
在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个 NACK,NACK有两种用途:a、一般表示接收器未成功接收数据字节;b、当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。
【解决方案代码合入】 为了合理,有效并优雅的解决问题,需要对i2c驱动架构有一定了解,所以在梳理驱动过程中发现,在i2c_register_adapter的adap->bus_recovery_info 做了总线恢复的相关动作。
因此设置下应该就OK了,明天自己验证下~
内核本身,好像配置下就OK了,明天再单板上验证下就OK了。
Linux内核做的真心不错呀~ 理解驱动的代码很重要
728330453 写道: 内核本身,好像配置下就OK了,明天再单板上验证下就OK了。
Linux内核做的真心不错呀~ 理解驱动的代码很重要
:cool: cool
具体关于i2c总线的自恢复功能配置,参见Linux4.7.2版本,顺便说一句 我这里用的是ti的芯片,所以对比i2c-omap.c和i2c-core.c就可以啦~ / * Waiting on Bus Busy / static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap) { unsigned long timeout;
timeout = jiffies + OMAP_I2C_TIMEOUT;
while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
if (time_after(jiffies, timeout))
return i2c_recover_bus(&omap->adapter);
msleep(1);
}
return 0;
}
不过仍然还有疑惑的地方
1、/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
驱动中i2c的超时间设置为1s, 看门狗的复位时间也就1.6s--->以为这个值蛮危险的!!!
且i2c总线上挂载了外设,总线忙时,也会存在超时时间!
这样的话 i2c总线被从机挂死的话,内核启动就会失败!
关于这个时间是如何得来的呢?
后面需要看看,是否需要根据实际i2c的读写情况,重新设置超时时间!!!
728330453 写道: 具体关于i2c总线的自恢复功能配置,参见Linux4.7.2版本,顺便说一句 我这里用的是ti的芯片,所以对比i2c-omap.c和i2c-core.c就可以啦~ / * Waiting on Bus Busy / static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap) { unsigned long timeout;
timeout = jiffies + OMAP_I2C_TIMEOUT;
while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
if (time_after(jiffies, timeout))
return i2c_recover_bus(&omap->adapter);
msleep(1);
}
return 0;
}
不过仍然还有疑惑的地方
1、/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
驱动中i2c的超时间设置为1s, 看门狗的复位时间也就1.6s--->以为这个值蛮危险的!!!
且i2c总线上挂载了外设,总线忙时,也会存在超时时间!
这样的话 i2c总线被从机挂死的话,内核启动就会失败!
关于这个时间是如何得来的呢?
后面需要看看,是否需要根据实际i2c的读写情况,重新设置超时时间!!!
i2c 1s超时,看门狗1.6s,也就是说还有600ms的剩余时间,我觉得对现代的CPU来说足够了。 另外,这个超时时间,可能只考虑普通的运行场景,没有考虑启动过程(调度被禁止了)。
