【发布时间】:2016-05-06 19:27:56
【问题描述】:
我想从需要多次启动操作来读取其寄存器值的 i2c 从机读取。
在某种程度上,我在 Linux 内核 3.18.21 中跟踪了 I2C 驱动程序,我发现它不支持多启动操作,并且我无法从这个 I2C 从设备(以太网供电管理器 PD69104B1)中读取。
如果需要此 i2c 从站或其他任何需要,我仍在寻找可以扩展驱动程序的方法。
我使用 i2c-tools 3.2.1。 我试试
$ i2cdump -y 0 0x20
但我可以看到相同的值,这意味着它每次都读取第一个寄存器。
$ i2cget -y 0 0x20 0x12
或任何其他寄存器地址返回与第一个寄存器相同的值。
这个slave支持两个读操作:
- 字节读写地址得到它的值,但这需要多开始
- 块读取 - 开始读取,i2c 从机将按顺序给出寄存器值,如 0x00 0x01....(第一个寄存器,第二个,第三个,第四个...等)
我尝试了所有可能的方法:
i2c_smbus_access()i2c_smbus_write_byte()i2c_smbus_read_block_data()write()read()
但随后大部分时间 i2c 总线进入超时错误和挂起情况。
有人知道如何在 Linux 中实现这一点吗?
更新0:
此 I2C 从机需要唯一的读取周期:
-
改变方向:S Addr Wr [A] RegAddress [A] S Addr Rd [A] [RegValue] P
-
短读:S Addr Rd [A] [RegValue] P
这里从 i2c 从站返回的最后一个值不要期望 ACK。
我尝试使用 I2C_M_NO_RD_ACK 但没有太多帮助。我读了一些值,然后得到 FF。
这个 POE I2C 从设备在 SCL 上的 i2c 时间超过 14 毫秒,这有点令人怀疑。这看起来像 i2c 非标准,因为 i2c 可以在 0HZ 上工作,即 SCL 可以由 master 拉伸,只要它想要。 Linux 绝对不是实时操作系统,因此无法保证实现此超时,并且可能会发生 i2c 从 SCL 超时重置。这就是我目前的结论!
使用的 I2C 消息符号来自: https://www.kernel.org/doc/Documentation/i2c/i2c-protocol
【问题讨论】:
-
几件事:您使用的是哪种 SoC/HW?某些 i2c 主机控制器可能不支持重复启动(这就是他们的驱动程序可能没有重复启动代码的原因)。查看支持
REPEAT_START的Tegra-I2C driver,因为Tegra I2C 主机控制器支持重复启动模式。另外像i2cset/i2cget这样的用户空间工具相当简单,可能不支持i2c操作的重复启动模式。 -
@TheCodeArtist 看起来 OP 只是使用不正确的 API 来发送重复启动。我在回答中添加了关于用户空间方法的注释。
-
@TheCodeArtist 它的联发科 MT7621A SoC。已经,我还在检查 i2c 主机控制器或其驱动程序是否不支持重复启动。
-
@SamProtsenko 我也在尝试使用这个 ioctl I2C_RDWR 但 I2C_M_NOSTART 看起来有些新。我会尝试的。谢谢
标签: linux linux-kernel driver device i2c