i2c-tool
是Linux应用层调试I2C设备(特别是E2PROM)的利器,这个工具是开源的,并且几乎可以交叉编译到任何Linux系统上。
它是一个工具集,具体包括如下工具:
i2cdetect: i2c总线探测工具,探测总线上的I2C设备
i2cdump:i2c总线dump工具
i2cget:i2c读取工具
i2cset: i2c写入工具
i2ctransfer:自定义I2C消息发送
源码解压如下:
如果是交叉编译到开发板,则需要修改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
#
# 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
用于扫描设备的 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字节。
P1
、P0
就是页片选位,由于A2
引脚接地,故at24c08
有4个有效设备地址。
i2cget 用于读取通过 I2C 总线(或 SMBus)可见的寄存器。
i2cget [-f] [-y] [-a] i2cbus chip-address [data-address [mode]]
-V
显示版本并退出。
-F
强制访问设备,即使它已经很忙。 默认情况下,i2cget 将拒绝访问已经在内核驱动程序控制下的设备。
使用这个标志是危险的,它会严重混淆有问题的内核驱动程序。
它还可能导致 i2cget 返回无效值。因此,仅当您知道自己在做什么时,风险自负。
-y
禁用交互模式。 默认情况下,i2cget 会在处理 I2C 总线之前等待用户的确认。
使用此标志时,将直接执行操作.这主要是为了在脚本中使用。 谨慎使用。
-a
允许使用 0x00 - 0x07 和 0x78 - 0x7f 之间的地址。 不建议。
i2cbus
指定i2c总线,整数,1即代表i2c1
chip-address
指定该总线上芯片的地址,是一个介于 0x08 和 0x77 之间的整数。
data-address
指定要从该芯片上读取的地址,它是一个介于 0x00 和 0xFF 之间的整数。如果省略,将读取当前活动的寄存器
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 用于设置通过 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 - 0x07 和 0x78 - 0x7f 之间的地址。不建议。
i2cbus
指定i2c总线,整数,1即代表i2c1
chip-address
指定该总线上芯片的地址,是一个介于 0x08 和 0x77 之间的整数。
data-address
指定要向写入该芯片的地址,它是一个介于 0x00 和 0xFF 之间的整数。
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 用于检查通过 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 是 0 到 7 之间的整数,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 ???.????????????