一、i2c_tool

i2c-tool是Linux应用层调试I2C设备(特别是E2PROM)的利器,这个工具是开源的,并且几乎可以交叉编译到任何Linux系统上。
它是一个工具集,具体包括如下工具:

i2cdetect: i2c总线探测工具,探测总线上的I2C设备
i2cdump:i2c总线dump工具
i2cget:i2c读取工具
i2cset: i2c写入工具
i2ctransfer:自定义I2C消息发送

下载 & 编译

i2c_tool下载地址

源码解压如下:
在这里插入图片描述
如果是交叉编译到开发板,则需要修改makefile文件,主要做了以下修改:

  • PREFIX 是i2c_tool编译后安装的目录前缀,改为./output
  • sbindir = $(PREFIX)/i2c_tools 编译产物生成目录改为$(PREFIX)/i2c_tools
  • 增加COMPILE_PREFIX:=arm-linux-gnueabihf-,指向实际使用的交叉工具链
  • CC ?= $(COMPILE_PREFIX)gcc ;AR ?= $(COMPILE_PREFIX)ar ;STRIP ?= $(COMPILE_PREFIX)strip
  • 为了调试方便,这些工具使用静态库编译,好处是工具可以直接运行而不需要考虑库依赖,静态库的配置如下:
    BUILD_DYNAMIC_LIB ?= 0
    BUILD_STATIC_LIB ?= 1
    USE_STATIC_LIB ?= 1

完整的makefile如下:

# I2C tools for Linux
#
# Copyright (C) 2007-2012  Jean Delvare <jdelvare@suse.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

DESTDIR	?=
PREFIX	?= ./output
bindir	= $(PREFIX)/bin
sbindir	= $(PREFIX)/i2c_tools
mandir	= $(PREFIX)/share/man
man3dir	= $(mandir)/man3
man8dir	= $(mandir)/man8
incdir	= $(PREFIX)/include
libdir	= $(PREFIX)/lib

INSTALL		:= install
INSTALL_DATA	:= $(INSTALL) -m 644
INSTALL_DIR	:= $(INSTALL) -m 755 -d
INSTALL_PROGRAM	:= $(INSTALL) -m 755
LN		:= ln -sf
RM		:= rm -f
COMPILE_PREFIX:=arm-linux-gnueabihf-

CC	?= $(COMPILE_PREFIX)gcc
AR	?= $(COMPILE_PREFIX)ar
STRIP	?= $(COMPILE_PREFIX)strip

CFLAGS		?= -O2
# When debugging, use the following instead
#CFLAGS		:= -O -g
CFLAGS		+= -Wall
SOCFLAGS	:= -fpic -D_REENTRANT $(CFLAGS)

BUILD_DYNAMIC_LIB ?= 0
BUILD_STATIC_LIB ?= 1
USE_STATIC_LIB ?= 1

ifeq ($(USE_STATIC_LIB),1)
BUILD_STATIC_LIB := 1
endif

ifeq ($(BUILD_DYNAMIC_LIB),0)
ifeq ($(BUILD_STATIC_LIB),0)
$(error BUILD_DYNAMIC_LIB and BUILD_STATIC_LIB cannot be disabled at the same time)
else
USE_STATIC_LIB := 1
endif
endif

KERNELVERSION	:= $(shell uname -r)

.PHONY: all strip clean install uninstall

all:

EXTRA	:=
#EXTRA	+= eeprog py-smbus
SRCDIRS	:= include lib eeprom stub tools $(EXTRA)
include $(SRCDIRS:%=%/Module.mk)

编译 & 安装

make  #编译
make install # 安装
make clean #清除之前编译结果

执行make install后,生成的工具都在i2c-tools-4.3/output/i2c_tools/目录下,将它们拷贝到开发板,即可直接运行。

二、开发板调试

内核需要支持i2c-dev设备,否则i2c-tool无法使用。
在这里插入图片描述

开启内核配置后/dev/i2c有如下设备即可

[root@rk3288:/]# ls /dev/i2c*
/dev/i2c-0  /dev/i2c-1  /dev/i2c-2  /dev/i2c-3  /dev/i2c-4  /dev/i2c-6

开发板设备树描述如下,并且I2C1上已经接了一个E2PROM AT24C08.

&i2c1
{
       status = "okay";  
       clock-frequency = <100000>;
	at24c02: at24c08@50 {
		compatible = "atmel,24c08";
		reg = <0x50>;
	};
};

同时在/sys/devices/platform/ff140000.i2c/i2c-1目录下也是能看到该设备的。

[root@rk3288:/sys/devices/platform/ff140000.i2c/i2c-1]# ls
1-0050         device   name        of_node  subsystem
delete_device  i2c-dev  new_device  power    uevent

[root@rk3288:/sys/devices/platform/ff140000.i2c/i2c-1/1-0050]# cat name
24c08

接下来就可以使用i2c-tools进行调试了。

i2cdetect

i2cdetect用于扫描设备的 I2C 总线。 它输出一个表,其中包含指定总线上检测到的设备列表。 I2CBUS 表示要扫描的 I2C 总线的编号或名称,应与 i2cdetect -l列出的总线之一相对应。 可选参数 FIRST 和 LAST限制扫描范围(默认:从 0x08 到 0x77)。
由于没有标准的 I2C 检测命令,i2cdetect 使用任意 SMBus 命令(即 SMBus 快速写入和 SMBus 接收字节)来探测设备。 默认情况下,使用的命令是被认为对每个地址最安全的命令。

Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]
-y
禁用交互模式。 默认情况下,i2cdetect 会在处理 I2C 总线之前等待用户的确认。 使用此标志时,将直接执行操作。这主要是为了在脚本中使用。
-a
强制扫描非常规地址。 不建议。
-q
使用 SMBus“快速写入”命令进行探测。 不建议。 众所周知,这会损坏许多 IBM Thinkpad 笔记本电脑上的 Atmel AT24RF08 EEPROM。
-r
使用 SMBus“接收字节”命令进行探测。 不建议。 众所周知,这会将 SMBus 锁定在各种只写芯片上(最显着的是地址 0x69 处的时钟芯片)。
-F
显示适配器实现的功能列表并退出。
-V
显示版本并退出。
-l
输出已安装总线的列表。 
I2CBUS
指定i2c总线,整形,1即代表i2c1
FIRST LAST
探测地址的范围,如果不指定,默认探测 0x08 to 0x77
[root@rk3288:/sys/devices/platform/ff140000.i2c/i2c-1/1-0050]# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 52 53 -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

结果显示在0x50,0x51,0x52,0x53这4个地址都探测到了i2c设备,但是实际上只有一个AT24C08挂在i2c1总线下。
这是因为我的设备是at24c08,它的设备地址如下图8K所示:
在这里插入图片描述
at24c08的大小是8Kbit,也就是1024字节,超过了256字节,所以需要通过页寻址,总共分为4页,每页256字节。
P1P0就是页片选位,由于A2引脚接地,故at24c08有4个有效设备地址。

i2cget

i2cget 用于读取通过 I2C 总线(或 SMBus)可见的寄存器。

i2cget [-f] [-y] [-a] i2cbus chip-address [data-address [mode]]
-V
显示版本并退出。
-F
强制访问设备,即使它已经很忙。 默认情况下,i2cget 将拒绝访问已经在内核驱动程序控制下的设备。
使用这个标志是危险的,它会严重混淆有问题的内核驱动程序。
它还可能导致 i2cget 返回无效值。因此,仅当您知道自己在做什么时,风险自负。
-y
禁用交互模式。 默认情况下,i2cget 会在处理 I2C 总线之前等待用户的确认。
使用此标志时,将直接执行操作.这主要是为了在脚本中使用。 谨慎使用。
-a
允许使用 0x00 - 0x070x78 - 0x7f 之间的地址。 不建议。
i2cbus 
指定i2c总线,整数,1即代表i2c1
chip-address
指定该总线上芯片的地址,是一个介于 0x080x77 之间的整数。
data-address
指定要从该芯片上读取的地址,它是一个介于 0x000xFF 之间的整数。如果省略,将读取当前活动的寄存器
mode
如果指定,模式参数是字母 b、w 或 c 之一,分别对应于读字节数据、读字数据或写字节/读字节。
如果省略 mode 参数,i2cget 默认为读取字节数据

读取i2c1总线,设备地址为0x50的设备中地址为0x02的值

i2cget -y 0x50 0x02
[root@rk3288:/]# i2cget -y 1 0x50 0x02
0x12

[root@rk3288:/]# i2cget -y 1 0x50 0x02 w
0x1312
i2cset

i2cset 用于设置通过 I2C 总线可见的寄存器。

i2cset [-f] [-y] [-m mask] [-r] [-a] i2cbus chip-address data-address [value] ... [mode]
-V
显示版本并退出。
-F
强制访问设备,即使它已经很忙。默认情况下,i2cset 将拒绝访问已经在内核驱动程序控制下的设备。
使用这个标志是危险的,它会严重混淆有问题的内核驱动程序。
它还可能导致 i2cset 静默写入错误的寄存器。因此,仅当您知道自己在做什么时,风险自负。
-y
禁用交互模式。默认情况下,i2cset 会在处理 I2C 总线之前等待用户的确认。
使用此标志时,将直接执行操作。这主要是为了在脚本中使用。
-m 掩码
掩码参数(如果指定)描述值的哪些位将实际写入数据地址。
掩码中设置为 1 的位取自值,而设置为 0 的位将从数据地址中读取并因此由操作保留。
请注意,此参数假定指定模式的读写操作对于您正在访问的设备是对称的。
这可能是也可能不是,因为 I2C 和 SMBus 都不能保证这一点。
-r
写入后立即读回值,并将结果与​​写入的值进行比较。这曾经是默认行为。与选项 -m 的限制相同。
-a
允许使用 0x00 - 0x070x78 - 0x7f 之间的地址。不建议。
i2cbus 
指定i2c总线,整数,1即代表i2c1
chip-address
指定该总线上芯片的地址,是一个介于 0x080x77 之间的整数。
data-address
指定要向写入该芯片的地址,它是一个介于 0x000xFF 之间的整数。
value
如果指定则代表需要写入芯片data-address的值。
如果省略此参数,则发出短写。 对于大多数芯片,它只是设置一个指向目标位置的内部指针,但实际上并不写入该位置。 
但是对于少数芯片,特别是具有单个寄存器的简单芯片,这种简短的写入是实际写入。 
如果 mode 参数是 s 或 i,则可以指定多个值。
mode
如果指定,字母 b、w、s 或 i 之一,分别对应于单个字节、16 位字、SMBus 块写入或 I2C 块写入的写入大小。 
对于 SMBus 和 I2C 块写入,写入大小由value参数的数量决定。
如果省略 mode 参数,i2cset 默认为不带 PEC 的字节模式。提供的值必须在指定数据类型的范围内(字节和块写入为 0x00-0xFF,字为 0x0000-0xFFFF)。 
另一种可能的模式是 c,它不写入任何值(所谓的短写)。您通常不必指定此模式,因为它是未提供值时的默认值,除非您还想启用 PEC。

i2c1总线设备地址为0x50的设备中,地址为0x02的位置写入0x98

i2cset -y 1 0x50 0x02 0x98
[root@rk3288:/]# i2cset -y 1 0x50 0x02 0x98
[root@rk3288:/]# i2cget -y 1 0x50 0x02
0x98

i2c1总线设备地址为0x50的设备中,地址为0x02的位置写入16 bit数据 0xAABB

i2cset -y 1 0x50 0x02 0xAABB w
[root@rk3288:/]# i2cset -y 1 0x50 0x02 0xAABB w
[root@rk3288:/]# i2cget -y 1 0x50 0x02 w
0xaabb
i2cdump

i2cdump 用于检查通过 I2C 总线可见的寄存器。

i2cdump [-f] [-r first-last] [-y] [-a] i2cbus address [mode [bank [bankreg]]]
-V
显示版本并退出。
-f
强制访问设备,即使它已经很忙。 默认情况下,i2cdump 将拒绝访问已经在内核驱动程序控制下的设备。 
使用这个标志是危险的,它会严重混淆有问题的内核驱动程序。 
它还可能导致 i2cdump 返回无效结果。 因此,仅当您知道自己在做什么时,风险自负。
-r first-last
限制被访问的寄存器范围。 
此选项仅适用于模式 b、w、c 和 W。对于模式 W,first 必须是偶数,last 必须是奇数。
-y
禁用交互模式。 默认情况下,i2cdump 会在处理 I2C 总线之前等待用户的确认。 
使用此标志时,将直接执行操作。 这主要是为了在脚本中使用。
-a
允许使用 0x00-0x07和0x78-0x7f 之间的地址。不建议。
i2cbus 
指定i2c总线,整数,1即代表i2c1
address 
指定该总线上芯片的地址,是一个介于 0x08 和 0x77 之间的整数。
mode 
如果指定,字母 b、w、s 或 i 之一,分别对应于单个字节、16 位字、SMBus 块、I2C 块的读取大小。 
c 模式有点不同,它连续读取所有字节,对于具有地址自动递增功能的芯片很有用,例如 EEPROM。 
W 模式也比较特殊,与 w 类似,只是读命令只会在偶数寄存器地址上发出; 这再次主要用于 EEPROM。
如果省略,默认以字节模式读取。
bank  bankreg
bank 和 bankreg 参数在 W83781D 和类似芯片上很有用(在撰写本文时,所有 Winbond 和 Asus 芯片)。 
bank 是 07 之间的整数,bankreg 是 0x00 到 0xFF 之间的整数(默认值:0x4E)。 
W83781D datasheet提供了有关bank选择的更多信息。

读取i2c1总线,设备地址为0x50的设备中地址从0x00~0xFF的值.。

i2cdump -y 1 0x50
[root@rk3288:/]# i2cdump -y 1 0x50
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 10 11 bb aa 04 05 06 07 08 09 00 01 02 03 04 05    ??????????.?????
10: 10 11 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 0a 0b    ????????????????
20: ff ff ff ff 10 11 12 13 ff ff ff ff ff ff ff ff    ....????........
30: 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c    ???.????????????
40: 10 10 10 10 11 12 13 13 13 ff ff ff ff ff ff ff    ?????????.......
50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
70: 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c    ???.????????????
80: 0f 00 01 10 11 12 13 06 07 08 09 0a 0b 0c 0d 0e    ?.??????????????
90: 02 03 04 05 06 07 0f 00 00 00 01 00 01 02 00 01    ???????...?.??.?
a0: 12 13 09 08 09 0a 08 09 0a 0b 0c 0d 0e 0f 10 11    ????????????????
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
c0: 05 06 07 ff ff ff ff ff 00 01 02 00 01 02 03 04    ???......??.????
d0: 08 09 0a 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 ff    ???????????????.
e0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09    ??????.?????????
f0: 00 01 02 03 04 05 10 11 12 13 0a 0b 0c 0d 0e 0f    .???????????????

读取i2c1总线,设备地址为0x50的设备中地址从0x00~0x7F的值.。

[root@rk3288:/]# i2cdump -y -r 0x00-0x7f 1 0x50 b
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 10 11 bb aa 04 05 06 07 08 09 00 01 02 03 04 05    ??????????.?????
10: 10 11 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 0a 0b    ????????????????
20: ff ff ff ff 10 11 12 13 ff ff ff ff ff ff ff ff    ....????........
30: 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c    ???.????????????
40: 10 10 10 10 11 12 13 13 13 ff ff ff ff ff ff ff    ?????????.......
50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
70: 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c    ???.????????????

参考

  1. Manpages of i2c-tools in Debian unstable
  2. I2C Tools Wiki
Logo

更多推荐