Linux 的 I2C 指令

在 Linux 中,常使用的 i2c 工具指令有:
i2cdetect, i2cget, i2cset, i2cdump, i2ctransfer
以下將一一說明指令的功能。

又如果在 Driver 執行成功的情況下,會無法使用上述指令取得暫存器的值,因為此時該 I2C 裝置已被 Driver 佔用。

不過在 Driver 有實作 regmap 的情況下,可以利用 cat 指令,直接從系統資料夾 - /sys/kernel/debug/regmap/ 的 I2C bus - I2C slave Address 資料夾內的 registers 檔案來查看暫存器值。
例如 I2C bus 為 7,I2C slave Address 為 0x11,則透過 cat 讀取暫存器值的指令為:
# cat /sys/kernel/debug/regmap/7-0011/registers

registers 的個數是在 Driver - kernel/sound/soc/codecs/es8388.c 設定的,參數為 max_register,如下:

static const struct regmap_config es8388_regmap_config = {
    .reg_bits   = 8,
    .val_bits   = 8,
    .max_register   = ES8388_REG_MAX,
    .cache_type = REGCACHE_RBTREE,
};

 

 

i2cdetect

i2cdetect 指令是用來列出在 Linux 中,所有已知及可用的 I2C buses。

要列出全部的 I2CBUS,可以使用 -l 參數:
# i2cdetect -l
  i2c-10  i2c             ddc                                     I2C adapter
  i2c-6   i2c             rk3x-i2c                                I2C adapter
  i2c-4   i2c             rk3x-i2c                                I2C adapter
  i2c-11  i2c             ddc                                     I2C adapter
  i2c-2   i2c             rk3x-i2c                                I2C adapter
  i2c-0   i2c             rk3x-i2c                                I2C adapter
  i2c-9   i2c             fde50000.dp                             I2C adapter
  i2c-7   i2c             rk3x-i2c                                I2C adapter


要偵測特定的 I2C BUS 的所有 slave address 是否有裝置,可以使用 -a + bus_no 參數。
例如偵測在 I2C BUS 2 中,是否有裝置 :

# i2cdetect -y -a 2
       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
  00:                         -- -- -- -- -- -- -- --
  10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  20: -- -- UU -- -- -- -- -- -- -- -- -- -- -- -- --
  30: 30 -- -- -- -- -- 36 -- -- -- -- -- -- -- -- --
  40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  50: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- --
  60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  70: -- -- -- -- -- -- -- --

執行結果有以下 3 種情況:
  --: 表示經尋問該位址後,沒有得到回應。
  UU: 表示該位址被 driver 所使用,所以沒有尋問該位址,同時該位址很可能存在 I2C 裝置。
  address: 表示經尋問該位址後,有 I2C 裝置回應。

也可以直接指定特定的 I2C BUS 及特定的 slave address 來做偵測。
例如偵測 I2C BUS 2 中 slave address 60 (= 0x3c) 是否有裝置:

# i2cdetect -y 2 60 60
# i2cdetect -y 2 0x3c 0x3c
       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
  00:
  10:
  20:
  30:                                     --
  40:
  50:
  60:
  70:

 

但也不是每個 I2C 裝置一定會被 i2cdetect 偵測到,例如有些裝置是需要 init sequence 來啟動裝置的。

以 Camera OV5640 舉例來說,如果 init sequence 不正確,則 Camera OV5640 無法正常啟動,就不會對 i2cdetect 指令作回應,因為此時裝置還沒啟動。
init sequence 通常會由該裝置的 driver 負責執行,也就是說,如果 driver 有問題,會導致 Camera OV5640 無法順利啟動,也就無法被 i2cdetect 偵測到。

另外在執行 i2cdetect 時,如果遇到 timeout error,則可能是因為缺少 pull-up 電阻導致的,需要請 HW 確認。

 

 

i2cget

i2cget 指令可以用來讀取 I2C 裝置的特定暫存器位址的值。

例如要讀取 I2C BUS 2 中,slave address 為 0x22 的裝置,其暫儲器位址為 0x00 的值:
# i2cget -y 2 0x22 0x00
  0x23

 

 

i2cset

和 i2cget 相反,i2cset 指令可以用來寫入 I2C 裝置的特定暫存器位址的值。

例如要把 0x12 寫入 I2C BUS 2 中,slave address 為 0x22 的裝置,其暫儲器位址為 0x00 的值:
# i2cset -y 2 0x22 0x00 0x12

 

 

i2cdump

和 i2cget 類似,i2cdump 指令可以用來讀取 I2C 裝置的大範圍暫存器位址的值。

例如要讀取 I2C BUS 2 中,slave address 為 0x22 的裝置,其全部暫儲器位址的值:
# i2cdump -y 2 0x22

如果要指定暫儲器位址,只讀取前 16 bytes,可以使用 -r + first-last 參數:
# i2cdump -y -r 0x0-0xf 2 0x22

 

 

i2ctransfer

i2ctransfer 指令可以用來寫入或讀取 I2C 裝置的大範圍暫存器位址的值。
但是不管是要執行寫入還是讀取,都需要先進行寫入,也就是要先寫入位址(offset)。

例如要讀取 I2C BUS 2 中,slave address 為 0x22 的裝置,暫儲器位址從 0x02 開始,讀取 14 bytes:
# i2ctransfer -y 2 w1@0x22 0x02 r14 

例如要寫入 I2C BUS 2 中,slave address 為 0x22 的裝置,暫儲器位址從 0x01 開始,寫入 2 bytes 的值,分別為 0x10, 0x16:
# i2ctransfer -y 2 w3@0x22 0x01 0x10 0x16

 

讀寫 16-bit address 的暫存器

例如要讀取 I2C BUS 2 中,slave address 為 0x22 的裝置,暫儲器位址從 0x300a 開始,讀取 2 bytes:
# i2ctransfer -y 2 w2@0x22 0x30 0x0a r2 

例如要寫入 I2C BUS 2 中,slave address 為 0x22 的裝置,暫儲器位址從 0x300a 開始,寫入 2 bytes 的值,分別為 0x10, 0x16:
# i2ctransfer -y 2 w4@0x22 0x30 0x0a 0x10 0x16

 

 

 

Reference

I2C Utilities in Linux

[RK3399][Android7.1] 调试笔记 --- I2C读取错误unexpected irq in STOP: 0x10

 

文字內容 或 影像內容 部份參考、引用自網路,如有侵權,請告知。

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 silverwind1982 的頭像
    silverwind1982

    拾人牙慧

    silverwind1982 發表在 痞客邦 留言(0) 人氣()