Zynq-7000 SoC,I2C - I2C 主机生成无效的读取事务处理

(1楼)解决方案

judyzhong 在 星期三, 06/13/2018 - 11:49 发表。

描述:

当 I2C 控制器作为主机工作并发出读取事务处理(即作为主接收器)时会出现此问题。

HOLD 位当设置 (i2c.Control_reg0[HOLD])时会阻止控制器在传输结束时发出 STOP 条件。

相反,当 transfer_size(i2c.Transfer_size_reg0)为 0 时,SCL 将保持为低电平,直到软件决定接下来怎么做。

如果控制器保持 SCL 为低电平过了超时时限(参见 i2c.Time_out_reg0[TO]),就会从从器件错误地发送额外 16 字节的读取数据。

transfer_size 寄存器会损坏并转移到 0xFF。

如 FIFO 中有空间,额外字节会保存在 FIFO 中。

即便超时中断被禁用也会发生这个问题。

影响:HOLD 位主要用于两种情况:

  • 在进行重复启动时。
  • 读取后不丢失 I2C 接口的二次传输,使用 HOLD 位,不先发出 STOP 条件就启动二次传输。

  • 在进行大型读取传输时。
  • 读取大于 255B 时需要 transfer_size 寄存器进行重新编程。
    方法就是让 transfer_size 缩减为 0 再将其重新编程为更高值。

    应当注意的是,此问题只有在软件不能及时服务 I2C 控制器时才出现。(也就是在超时前)

    不过,如果真的出现了这个问题,就会发生不必要的数据传输。

    根据系统不同和特定的传输,其影响可能很严重,也可能没什么影响。

    解决方法:

    将 i2c.Time_out_reg0 设置为更大值可让这个问题出现的几率下降,使得软件有更多时间响应 I2C 事件。

    不过这不能完全避免这个问题。

    要避免这个问题,软件不能让 transfer_size 在 HOLD 位设置时缩减为 0。

    该规则禁止使用以上影响部分(a)中介绍的重复启动特性。

    软件可避免以上情境(b),方法是将大型读取传输拆分为多个单独的传输。

    这或许需要高级协议支持,以将事务处理重组为原始的全尺寸。

    如果 transfer_size 为 0 时小心避免 HOLD 位设置,是有可能支持大型读取传输的。

    如前所述,I2C 接口必须静默,这样才能重新编程 transfer_size。

    解决办法利用了 FIFO 填满时总线将静默的事实。

    因此,使用的方法是:
    1. 驱动器必须跟踪从当前传输数据块的 FIFO 读取了多少数据。
    2. 剩余 17B 数据时就应停止从 FIFO 读取。
    3. 随后应一直等到 transfer_size=1。由于还剩 17B 数据,这说明 FIFO 装满 16B 数据。
    4. 这时 I2C 接口将静默(最后一个字节数据还没传输),而驱动器可重新编程 transfer_size。
    5. 驱动器随后可照常从 FIFO 读取数据并从第 (2) 步继续。

    受影响的配置:采用 I2C 作为主机的系统。

    解决办法:无修复计划。
    请参考(Xilinx 答复 47916) - Zynq-7000 SoC 芯片修订版差异。