I2C関連

I2C 関連

とりあえず、kernel の DEBUG メッセージより。ついでに、Sound 周りも…。

I2C周りの情報源

kernel ソースの Documentation/i2c/ 以下に拡張子は無いがテキストファイルがある。
kernel/Documentation/i2c/
のだが…、私は未だ読んでない。。。これからです…。

I2Cに繋がっているものは??

後述している kernel の DEBUG 関連を有効にした後、dmesg より、I2C関連を抜粋した。
I2C adapter driver [MSM I2C adapter-PRI] forgot to specify physical device
i2c-adapter i2c-0: adapter [MSM I2C adapter-PRI] registered
i2c-adapter i2c-0: client [SH_touchpanel] registered with bus id 0-0015
i2c-adapter i2c-0: client [akm8973]       registered with bus id 0-001c
i2c-adapter i2c-0: client [SH_SMB380]     registered with bus id 0-0038
i2c-adapter i2c-0: client [SH_qwerty_key] registered with bus id 0-0044
i2c-adapter i2c-0: client [tps65023]      registered with bus id 0-0048
I2C adapter driver [MSM I2C adapter-AUX] forgot to specify physical device
i2c-adapter i2c-1: adapter [MSM I2C adapter-AUX] registered
と言う事らしい。(メッセージが出てくるのは個別ドライバあるモノだと思われる。…、たぶん)

リンク先は有ってるかどうかは不明。
/dev/i2c-0
id 0-0015 SH_touchpanel タッチパネル
id 0-0018 不明
id 0-001c akm8973 3軸電子コンパス http://www.asahi-kasei.co.jp/akm/japanese/product/ak8973nbs/ak8973nbs.html
                  ↑これかな。データシートは非公式しか見つからなかった。
id 0-0038 SMB380 加速度 http://www.bosch-sensortec.com/content/language1/downloads/SMB380_Flyer_Rev1.3.pdf
id 0-0044 SH_qwerty_key キーボード
id 0-0048 tps65023 電源周り http://focus.tij.co.jp/jp/docs/prod/folders/print/tps65023.html
id 0-005b 不明(音源周り? SpAmp?)
id 0-0062 不明


I2C と Sound の DEBUG を有効にする。

実機から、config.gz を取得して、PCで展開。
それを、.conf にリネームして
$ make ARCH=arm CROSS_COMPILE=../../froyo_orig/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi- menuconfig
CROSS_COMPILE=のディレクトリは環境依存なので適宜変更の事。
Device Drivers --->
を選択、
I2C support --->
を選択、以下を有効にする。
[*] I2C Core debugging messages
[*] I2C Algorithm debugging messages
[*] I2C Bus debugging messages
[*] I2C Chip debugging messages
<Exit> で一つ戻って、
Sound card support --->
を選択
Advanced Linux Sound Architecture --->
を選択、以下を有効にする。
[*] Debug
[*] More verbose debug
[*] Enable PCM ring buffer overrun/underrun debugging
[*] Enable PCM ring buffer overrun/underrun debugging
<Exit> で戻って、
Save an Alternate Configuration File
.config
に保存して、<Exit>

I2C周りのDEBUGをさらに詳しく出力させる。

改変したファイル
drivers/i2c/i2c-dev.c
  • i2cdev_read と i2cdev_write で buf の内容を1バイトずつ16進数で表示させている。
  • 初期はbuf=で改行していたが、全行に buf[%d]= とつけるように変更した。
$ diff -ubB i2c-dev.c.orig i2c-dev.c
--- i2c-dev.c.orig	2011-02-09 01:19:18.614087449 +0900
+++ i2c-dev.c	2011-02-10 02:50:08.953117738 +0900
@@ -25,7 +25,7 @@
    only fair to recognize him as co-author -- Frodo */
 
 /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
-
+#define DEBUG 1
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -138,7 +138,9 @@
 {
 	char *tmp;
 	int ret;
-
+#ifdef DEBUG
+	int i;
+#endif
 	struct i2c_client *client = (struct i2c_client *)file->private_data;
 
 	if (count > 8192)
@@ -154,6 +156,13 @@
 	ret = i2c_master_recv(client,tmp,count);
 	if (ret >= 0)
 		ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
+
+#ifdef DEBUG
+	for(i=0;i<(int)count;i++) {
+	  pr_debug("i2c-dev:buf[%d]=0x%02X\n",i,(unsigned int)tmp[i]&0xff);
+	}
+#endif
+
 	kfree(tmp);
 	return ret;
 }
@@ -163,6 +172,9 @@
 {
 	int ret;
 	char *tmp;
+#ifdef DEBUG
+	int i;
+#endif
 	struct i2c_client *client = (struct i2c_client *)file->private_data;
 
 	if (count > 8192)
@@ -180,6 +192,13 @@
 		iminor(file->f_path.dentry->d_inode), count);
 
 	ret = i2c_master_send(client,tmp,count);
+
+#ifdef DEBUG
+	for(i=0;i<(int)count;i++) {
+	  pr_debug("i2c-dev:buf[%d]=0x%02X\n",i,(unsigned int)tmp[i]&0xff);
+	}
+#endif
+
 	kfree(tmp);
 	return ret;
 }

kernel/drivers/i2c/busses/i2c-msm.c
  • ログがすごい量になったので、個別ドライバが判明しているアドレスの DEBUG 情報を出力させないようにした。
  • grep -i i2c dmesg.txt 等と出来るように、ヘッダを追加している。
$ diff -ubB i2c-msm.c.orig i2c-msm.c
--- i2c-msm.c.orig	2011-02-10 01:40:32.314943342 +0900
+++ i2c-msm.c	2011-02-10 01:39:22.513606231 +0900
@@ -39,7 +39,7 @@
 #include <mach/sharp_smem.h>
 #endif /* FEATURE_SHLOCAL_SHI2C */
 
-#define DEBUG 0
+//#define DEBUG 0
 
 #ifdef FEATURE_SHLOCAL_SHI2C
 
@@ -143,7 +143,7 @@
 static void
 dump_status(uint32_t status)
 {
-	printk("STATUS (0x%.8x): ", status);
+	printk("i2c-msm: STATUS (0x%.8x): ", status);
 	if (status & I2C_STATUS_BUS_MASTER)
 		printk("MST ");
 	if (status & I2C_STATUS_BUS_ACTIVE)
@@ -270,7 +277,13 @@
 	int err = 0;
 
 #if DEBUG
+	if( dev->msg->addr != 0x15 &&
+	    dev->msg->addr != 0x1c &&
+	    dev->msg->addr != 0x38 &&
+	    dev->msg->addr != 0x44 &&
+	    dev->msg->addr != 0x48 ) {
 	dump_status(status);
+	}
 #endif
 
	spin_lock(&dev->lock);


kernel/drivers/i2c/i2c-core.c
  • ログ出力の抑制。非常に原始的。
$ diff -ubB i2c-core.c.orig i2c-core.c
--- i2c-core.c.orig	2011-02-10 01:53:07.143133972 +0900
+++ i2c-core.c	2011-02-10 01:21:50.693613883 +0900
@@ -1036,11 +1036,17 @@
 	if (adap->algo->master_xfer) {
 #ifdef DEBUG
 		for (ret = 0; ret < num; ret++) {
+		  if( msgs[ret].addr != 0x15 &&
+		      msgs[ret].addr != 0x1c &&
+		      msgs[ret].addr != 0x38 &&
+		      msgs[ret].addr != 0x44 &&
+		      msgs[ret].addr != 0x48  ) {
 			dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
 				"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
 				? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
 				(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
 		}
+		}
 #endif
 
 		if (in_atomic() || irqs_disabled()) {


kernel を makeする

$ make ARCH=arm CROSS_COMPILE=../../froyo_orig/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-
エラーが出たので、
drivers/i2c/busses/i2c-msm.c:42:1: error: "DEBUG" redefined
drivers/i2c/chips/akm8973.c:54:1: error: "DEBUG" redefined
drivers/i2c/chips/smb380.c:28:1: error: "DEBUG" redefined
上記3つのファイル内の #define DEBUG をコメントアウトした。
boot.img化、ubi化、実機へ転送、リブート。

I2C周りのDEBUG情報の見方


dmesg でDEBUGメッセージを確認すると
<7>[ 9.810313] i2c-adapter i2c-0: ioctl, cmd=0x704, arg=0x00
<7>[ 9.810326] i2c-adapter i2c-0: ioctl, cmd=0x703, arg=0x62
<7>[ 10.267413] i2c-adapter i2c-0: ioctl, cmd=0x703, arg=0x5b
のようにでてくる。cmd の 0x703 、 0x704は
kernelヘッダの
linux/i2c-dev.h
において、
#define I2C_SLAVE	0x0703	/* Use this slave address */
#define I2C_TENBIT	0x0704	/* 0 for 7 bit addrs, != 0 for 10 bit */
のように定義されている。

また、argは、下記のようなコードを書けば出てくる。(と思う。まだ試していない^^;)
#include <linux/i2c-dev.h> //#include <linux/i2c.h>
(省略)
int fd,addr;

fd = open("/dev/i2c-0", O_RDWR);
int addr = 0x62; /* I2C address */
ioctl(fd, I2C_SLAVE, addr);
(省略)

I2C周りのDEBUG情報の見方(その2)

dmesg で DEBUG 情報を見てみると、下記のような STATUS が出てきた。(ログ出力を抑制したため現在は出ない。)
<7>[    1.010060] i2c-adapter i2c-0: master_xfer[0] W, addr=0x1c, len=1
<7>[    1.010073] i2c-adapter i2c-0: master_xfer[1] R, addr=0x1c, len=1
<4>[    1.010120] STATUS (0x00006700): MST ACT 
<4>[    1.010166] STATUS (0x00006b00): MST ACT 
<4>[    1.010213] STATUS (0x00007b01): MST ACT WR_FULL 
<4>[    1.010240] STATUS (0x00006302): MST ACT RD_FULL 
全く見方が分からないので、出力箇所を調べてみた。
最初の、master_xfer~の
i2c-adapter i2c-0: master_xfer[0] W, addr=0x1c, len=1
部分は、
kernel/drivers/i2c/i2c-core.c
1037行~1044行付近
#ifdef DEBUG
		for (ret = 0; ret < num; ret++) {
			dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
				"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
				? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
				(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
		}
#endif
で出力されている。

次に、
STATUS (0x00007b01): MST ACT WR_FULL 
等の部分だが、MST ACT WR_FULL は I2C 素人の私は何の事かさっぱり分からない。
出力該当部分を探したところ、
kernel/drivers/i2c/busses/i2c-msm.c
142行~167行付近
#if DEBUG
static void
dump_status(uint32_t status)
{
	printk("i2c-msm: STATUS (0x%.8x): ", status);
	if (status & I2C_STATUS_BUS_MASTER)
		printk("MST ");
	if (status & I2C_STATUS_BUS_ACTIVE)
		printk("ACT ");
	if (status & I2C_STATUS_INVALID_WRITE)
		printk("INV_WR ");
	if (status & I2C_STATUS_ARB_LOST)
		printk("ARB_LST ");
	if (status & I2C_STATUS_PACKET_NACKED)
		printk("NAK ");
	if (status & I2C_STATUS_BUS_ERROR)
		printk("BUS_ERR ");
	if (status & I2C_STATUS_RD_BUFFER_FULL)
		printk("RD_FULL ");
	if (status & I2C_STATUS_WR_BUFFER_FULL)
		printk("WR_FULL ");
	if (status & I2C_STATUS_FAILED)
		printk("FAIL 0x%x", (status & I2C_STATUS_FAILED));
	printk("\n");
} 
#endif
となっていた。(上記の改変を含む)
.config の
CONFIG_LOG_BUF_SHIFT=17
を増やすと良いのだろうか?
現状では128KBのリングバッファになっているようだ。
話を戻すと、STATUSの数値とその各項目は上記の箇所で出力されていた。
具体的な定義は同一ファイル内において、下記のように定義されているようだ。
enum {
	I2C_WRITE_DATA          = 0x00,
	I2C_CLK_CTL             = 0x04,
	I2C_STATUS              = 0x08,
	I2C_READ_DATA           = 0x0c,
	I2C_INTERFACE_SELECT    = 0x10,

	I2C_WRITE_DATA_DATA_BYTE            = 0xff,
	I2C_WRITE_DATA_ADDR_BYTE            = 1U << 8,
	I2C_WRITE_DATA_LAST_BYTE            = 1U << 9,

	I2C_CLK_CTL_FS_DIVIDER_VALUE        = 0xff,
	I2C_CLK_CTL_HS_DIVIDER_VALUE        = 7U << 8,

	I2C_STATUS_WR_BUFFER_FULL           = 1U << 0,
	I2C_STATUS_RD_BUFFER_FULL           = 1U << 1,
	I2C_STATUS_BUS_ERROR                = 1U << 2,
	I2C_STATUS_PACKET_NACKED            = 1U << 3,
	I2C_STATUS_ARB_LOST                 = 1U << 4,
	I2C_STATUS_INVALID_WRITE            = 1U << 5,
	I2C_STATUS_FAILED                   = 3U << 6,
	I2C_STATUS_BUS_ACTIVE               = 1U << 8,
	I2C_STATUS_BUS_MASTER               = 1U << 9,
	I2C_STATUS_ERROR_MASK               = 0xfc,

	I2C_INTERFACE_SELECT_INTF_SELECT    = 1U << 0,
	I2C_INTERFACE_SELECT_SCL            = 1U << 8,
	I2C_INTERFACE_SELECT_SDA            = 1U << 9,
	I2C_STATUS_RX_DATA_STATE            = 3U << 11,
	I2C_STATUS_LOW_CLK_STATE            = 3U << 13,
};

ん~、DUMP出来てない値があるような気がする。。。


間違いが多く含まれているかもしれません、何かお気づきの点が有りましたら、Twitterか下記まで。
コメント
名前:
コメント:

すべてのコメントを見る










(2011/02/10 1:58 Audio関連よりI2C関連部分を分離変更)
最終更新:2011年03月07日 23:19
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。