阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

如何debug通信协议 I2C 子系统

34次阅读
没有评论

共计 3575 个字符,预计需要花费 9 分钟才能阅读完成。

导读 在应该收到 ACK 信号的时候没有收到 ACK 信号,i2c controller 就会产生一个 ACK error 的中断,告诉 i2c driver 发生了 ACK error。通常情况是 slave 本身的问题。

I2C 常见有两种错误:I2C ACK error、I2C timeout

一、I2C ACK error

在应该收到 ACK 信号的时候没有收到 ACK 信号,i2c controller 就会产生一个 ACK error 的中断,告诉 i2c driver 发生了 ACK error。通常情况是 slave 本身的问题。

如何 debug 通信协议 I2C 子系统

1、检查 device 是否存在,i2c bus number 和 device address 是否正确。示例如下:i2c number 为 6,addr 为 0x28:

[31.092951][xxx]i2c i2c-6:addr:0x28,ACK error

2、检查 device 是否已经上电使能,以及正确的 init。

3、检查 i2c speed 是否适配,speed 大于 device 支持的 max speed 也会造成 ACK Error。降低速度,如果仍然可以工作的话就说明是 clk 相关问题。

4、检查 i2c device 信号电平是否与 AP 匹配。

5、GPIO check 以下几个部分:

  • GPIO 电流驱动能力。
  • GPIO 工作模式是否是 I2C 模式。
  • GPIO 是否有内部上拉电阻。
  • GPIO 默认电平状态。
  • 从 i2c spec 看,如下情况 NACK 是正常的。

    I2C 写

    如何 debug 通信协议 I2C 子系统

    主机向从机发送数据时,最后一个 Byte 数据时,从机可能应答也可能非应答,但不怎样主机都可以产生停止条件,如果主机在向从机发送数据(甚至包括从机地址在内)时检测到从机非应答,则会及时停止传输。

    I2C 读

    如何 debug 通信协议 I2C 子系统

    主机从从机接收数据时,最后一个 Byte 数据时,主机不回应该从机,即 NACK。

    二、I2C timeout

    当 I2C 传输发生 timeout 时,一般 kernel log 会有类似如下打印:

    [48.197718][xxx]i2c i2c-1: addr:0xa,transfer timeout

    如何 debug 通信协议 I2C 子系统

    1、GPIO check 以下几个部分。

  • GPIO 电流驱动能力。
  • GPIO 工作模式是否是 I2C 模式。
  • GPIO 是否有内部上拉电阻。
  • GPIO 默认电平状态。
  • 2、排查 slave 顺序。

  • log 中第一个发生 timeout 的 slave。
  • 有 power 控制和 reset 控制的 slave。
  • other slave。
  • 复现问题后,可以手动将相应外设去掉,确认是哪个外设将 i2c bus 拉住,再与供应商沟通,debug 一下该 IC 状态,理清拉住 i2c bus 原因。

    三、i2c-tools

    i2c-tools 也很好用,这个工具工具博主上次写过,参考以下文章:

    ​​手把手教你使用 i2c-tools。​

    四、常见问题
    1、同一条 i2c bus 上所有的外设的 i2c addr 要不同

    (1)相同 address 注册时冲突.

    [2.059184][xxx]i2c i2c-1:Failed to register i2c client 24c02 at 0x51(-16) 
    [2.059189][xxx]i2c i2c-1:Can't create device at 0x51

    对应的错误码是 -16。

    /kernel-5.10/include/uapi/asm-generic/errno-base.h
    #define EPERM   1 /* Operation not permitted */
    #define ENOENT   2 /* No such file or directory */
    #define ESRCH   3 /* No such process */
    #define EINTR   4 /* Interrupted system call */
    #define EIO   5 /* I/O error */
    #define ENXIO   6 /* No such device or address */
    #define E2BIG   7 /* Argument list too long */
    #define ENOEXEC   8 /* Exec format error */
    #define EBADF   9 /* Bad file number */
    #define ECHILD  10 /* No child processes */
    #define EAGAIN  11 /* Try again */
    #define ENOMEM  12 /* Out of memory */
    #define EACCES  13 /* Permission denied */
    #define EFAULT  14 /* Bad address */
    #define ENOTBLK  15 /* Block device required */
    #define EBUSY  16 /* Device or resource busy */
    ......

    可以执行 ls /sys/bus/i2c/devices 查看对应的 i2c-1 下是否已经有注册相同的 address 的外设。

    若返回 -11,-EAGAIN。代表总线正忙,或无法申请到总线锁。如果总线正忙,请 retry 等待,或查看是哪个 device 一直在发送。如果无法申请到总线锁,请查看是否在中断函数或原子上下文调用了 i2c_transfer。

    (2)隐藏的 i2c address,即外设存在多个 i2c addr 或外设 HW bug,导致 i2c 通讯异常。

    示例:eeprom 在 i2c-1 上注册了 0x50 地址,而 type c 虽然注册到 0x60 地址,但对 0x50 也能产生响应,type c 拉低了 SDA,从而 timeout。

    debug 方法:

  • 软件上确认数据及对应的 driver 是否正确。
  • 硬件上逐一去掉外设,确认是哪个外设导致。
  • 2、示波器 ACK 的地方有毛刺

    slave 在第 9 个 clk 产生 ACK 应答后,换成 mater 端来控制时产生的毛刺。此毛刺不会影响 I2C 总线读写时序,无需处理。

    即 slave 和 master 控制总线切换间隔,没有人控制总线,带来的毛刺。

    3、半高电平

    在外接上拉电阻的情况下,有 enable 内部下拉电阻,导致总线上有半高电平。

    4、总线上电平拉不到地

    master 端发送数据时电平拉不到地,可以增大驱动电流或者上拉电阻。

    slave 端拉不到地,可以咨询供应商看是否能增大 slave 端驱动电流或者上拉电阻。

    5、RK 平台 I2C debug

    来源于 firefly。

    https://wiki.t-firefly.com/zh_CN/Firefly-RK3399/driver_i2c.html

    I2C 通信失败,出现 log:“timeout, ipd: 0x00, state: 1”

    请检查硬件上拉是否给电。

    调用 i2c_transfer 返回值为 -6?

    返回值为 -6 表示为 NACK 错误,即对方设备无应答响应,这种情况一般为外设的问题,常见的有以下几种情况:

  • I2C 地址错误,解决方法是测量 I2C 波形,确认是否 I2C 设备地址错误;
  • I2C slave 设备不处于正常工作状态,比如未给电,错误的上电时序等;
  • 时序不符合 I2C slave 设备所要求也会产生 Nack 信号。
  • 当外设对于读时序要求中间是 stop 信号不是 repeat start 信号的时候,该如何处理?

    这时需要调用两次 i2c_transfer, I2C read 拆分成两次,修改如下:

    static int i2c_read_bytes(struct i2c_client *client, u8 cmd, u8 *data, u8 data_len) {struct i2c_msg msgs[2];
         int ret;
         u8 *buffer;
         buffer = kzalloc(data_len, GFP_KERNEL);
         if (!buffer)
             return -ENOMEM;
         msgs[0].addr = client->addr;
         msgs[0].flags = client->flags;
         msgs[0].len = 1;
         msgs[0].buf = &cmd;
         ret = i2c_transfer(client->adapter, msgs, 1);
         if (ret adapter->dev, "i2c read failed\n");
                kfree(buffer);
           return ret;
          }
          msgs[1].addr = client->addr;
          msgs[1].flags = client->flags | I2C_M_RD;
          msgs[1].len = data_len;
          msgs[1].buf = buffer;
          ret = i2c_transfer(client->adapter, &msgs[1], 1);
          if (ret adapter->dev, "i2c read failed\n");
          else
            memcpy(data, buffer, data_len);
          kfree(buffer);
          return ret;
    }

    相信以上的 I2C debug 方法已经能为大家解决大部分问题,如果还是没解决,一般是芯片问题或者原厂底层 code bug,可以找芯片原厂支持。

    阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

    腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

    代金券:在阿里云专用满减优惠券

    正文完
    星哥说事-微信公众号
    post-qrcode
     0
    星锅
    版权声明:本站原创文章,由 星锅 于2024-07-25发表,共计3575字。
    转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
    【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
    阿里云-最新活动爆款每日限量供应
    评论(没有评论)
    验证码
    【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中