[Armadillo:03949] Re: armadillo-500 sysfs経由でI2Cドライバ制御

g-kihara email@hidden
2009年 1月 23日 (金) 14:09:27 JST


木原です。
お世話になっています。

誤記がありました。申し訳ございません。
弊社のデバイスについて、
任意のアドレスのデータを読む場合、

S| Slave | R/W=0 | ack | レジスタアドレス | ack | S | Slave | R/W=1 | 
Data(n)| ack | Data(n+1) | ack | ・・・・・|ack| Stop |

となっています。

しかし、linux-2.6.13/Documentation/i2c/i2c-protocolの
i2c_transferに関する説明によると、

They are just like the above transactions, but instead of a stop bit P
a start bit S is sent and the transaction continues. An example of
a byte read, followed by a byte write:

S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P     

となっており、一番初めのスレーブアドレス発行後に"Read"、
次のスレーブアドレス発行後には"Write"を出力しており、
弊社の仕様と異なっています。
I2C_M_REV_DIR_ADDR フラグを使えば、 Read/Write フラグを切り替える
ことができるようですが・・・

> レジスタアドレスの送信(指定)はどこでしているのでしょうか?

下記のi2ctest_attach() の コメント//送信
以下のところでおこなっています。
(テストがうまくいったら、
この送受信テスト箇所は切り離す予定です。)

0xE1がレジスタアドレスで、0x23が書き込むデータです。

static int
i2ctest_attach(struct i2c_adapter *adap)
{
 int ret;
 char tx[2];
 char rx[2];

 DEBUG_FUNC();

 printk("i2ctest_attach is called\n");

 ret = i2c_probe(adap, &addr_data, &i2ctest_detect_client);
 printk("i2c_probe=%d\n", ret);

 // 送信テスト
 tx[0] = 0xE1;  //レジスタアドレス
 tx[1] = 0x23;    //書き込むデータ
 i2ctest_TxData(tx, 2);

 // 受信テスト
 rx[0] = 0xE1;  //レジスタアドレス
 i2ctest_RxData(rx, 1);
 printk("rx=%x\n", rx[0]);
 printk("rx=%x\n", rx[1]);

 return ret;
}


以上




----- Original Message ----- 
From: "日本電子システムテクノロジー/高木" <email@hidden>
To: "Armadillo series general discussion list" 
<email@hidden>
Sent: Friday, January 23, 2009 10:09 AM
Subject: [Armadillo:03947] Re: armadillo-500 sysfs経由でI2Cドライバ制御


> お世話になっています。
> 高木です。
>
>
>> 木原です。
>> お世話になっています。
>> 早々のご返信ありがとうございます。
>>
>>> 通信の操作はターゲットとしているデバイスによって違う可能性があります。
>>> デバイスのマニュアルを確認してください。
>>
>> | START |  スレーブアドレス | R/W = 1 | ACK |  Data(n) | Data(n+1) |
>> ・・・・
>>
>> なので、アクセスしたいアドレスを送信してやれば、デバイスから
>> データがおくられてくるはずなのですが・・。
>>
>
> レジスタアドレスの送信(指定)はどこでしているのでしょうか?
>
> スレーブアドレスはI2Cデバイスが持つアドレスなので
> 別途アクセスしたいレジスタアドレスの指定が必要かと思います。
>
>
> ちなみに私がターゲットにしたデバイスでは次の操作になっています。
>
> Read Phase1(レジスタアドレス指定)
> START | スレーブアドレス | W=0 | ACK | レジスタアドレス | ACK | STOP
>
> Read Phase2(データRead)
> START | スレーブアドレス | R=1 | ACK | Data | ACK | STOP
>
>
>>>
>>> ちなみに私が扱ったデバイスではまず、アクセスしたいアドレスだけ送ります。
>>> この時はflag=0でi2c_transferを実行。
>>>
>>> 次にflag=I2C_M_RDとしてi2c_transferを実行することで
>>> buf[0]にデータが格納されました。
>>
>> ご教示いただいた手法でやってみましたが、期待した値はかえってきませんでし
>> た。
>>
>> そこで、下記に示したi2ctest_RxData()で受信テストを行ったところ、
>>
>> msgs[0].buf[0] ・・・ 0xff
>> msgs[0].buf[1]・・・ 0x1e
>> msgs[1].buf[0]・・・ 0xe1
>> msgs[1].buf[1]・・・ 0x23
>>
>> のようになっていることがわかりました。
>> msgs[1].buf[1]にわたしが期待するデータ(レジスタに書き込んだ値)が入って
>> いました。
>> なにゆえにmsgs[1]のbufにはいっているのか(^^; ?
>
> 以下のプログラムではmsgs[1].bufが初期化されていないのではないでしょうか?
> また、i2c_transferの最後の引数が1なのでmsgsの要素数は1で処理されていますので 
> 
> msgs[1]は何もされていないと思います。
>
>> 最初にダミーリードをおこなわないといけないということなのでしょうか?
>> 明日またトライしてみます。
>
> i2c_transfer関数でダミーリードの処理はされています。
>
> i2c_transferの実体のコードを読むとどのように処理されているかが判るので
> 一度確認してみてはいかがでしょうか。
>
> i2c_transferの実体はdrivers/i2c/busses/i2c-armadillo5x0.cの
> i2c_armadillo5x0_xferです。
>
>> int
>> i2ctest_RxData(char *rxData, int length)
>> {
>>        int ret;
>>        u8 buf[2];
>>        struct i2c_msg msgs[2];
>>
>>        msgs[0].addr = test_i2c_client.addr;
>>        msgs[0].flags = I2C_M_RD;
>>        msgs[0].len   = 1;
>>        msgs[0].buf   = rxData;
>>
>>        down(&mutex);
>>        ret = i2c_transfer(test_i2c_client.adapter, msgs, 1);
>>
>>        printk("RxData msgs[0].buf[0]=%x\n", msgs[0].buf[0]);
>>        printk("RxData msgs[0].buf[1]=%x\n", msgs[0].buf[1]);
>>        printk("RxData msgs[1].buf[0]=%x\n", msgs[1].buf[0]);
>>        printk("RxData msgs[1].buf[1]=%x\n", msgs[1].buf[1]);
>>
>>        if(ret == 1){
>>                printk("RxData succedded!!!\n");
>>        }else if (ret >= 0){
>>                ret = -1;
>>                printk("RxData failed!!!\n");
>>        }
>>        up(&mutex);
>>
>>        return ret;
>> }
>>
>>
>> 以上
>>
>>
>>>
>>>
>>> ■転送
>>> static int XXX_i2c_write(struct i2c_client *c, unsigned char addr,
>>> unsigned char value)
>>> {
>>>    struct i2c_msg msg[2];
>>>    char buf[2];
>>>    int ret;
>>>
>>>    buf[0] = addr;
>>>    buf[1] = value;
>>>
>>>    msg[0].addr  = c->addr;
>>>    msg[0].len   = 2;
>>>    msg[0].buf   = buf;
>>>    msg[0].flags = 0;
>>>
>>>    ret = i2c_transfer(c->adapter, msg, 1);
>>>    if (ret >= 0)
>>>    {
>>>        return 0;
>>>    }
>>>
>>>    return ret;
>>> }
>>>
>>> ■受信
>>> static int XXX_i2c_read(struct i2c_client *c, unsigned char addr)
>>> {
>>>    struct i2c_msg msg[2];
>>>    char buf[2];
>>>    int ret;
>>>
>>>    buf[0] = addr;
>>>
>>>    msg[0].addr  = c->addr;
>>>    msg[0].len   = 1;
>>>    msg[0].buf   = buf;
>>>    msg[0].flags = 0;
>>>    ret = i2c_transfer(c->adapter, &msg[0], 1);
>>>    if (ret >= 0)
>>>    {
>>>    }
>>>    else
>>>    {
>>>        return ret;
>>>    }
>>>
>>>    msg[1].addr  = c->addr;
>>>    msg[1].len   = 1;
>>>    msg[1].buf   = buf;
>>>    msg[1].flags = I2C_M_RD;
>>>
>>>    ret = i2c_transfer(c->adapter, &msg[1], 1);
>>>    if (ret >= 0)
>>>    {
>>>        return buf[0];
>>>    }
>>>
>>>    return ret;
>>>
>>> }
>>>
>>>
>>>> いつもお世話になっております。
>>>> 山本です。
>>>>
>>>>> i2c_msg構造体のメンバflagsですが、
>>>>> i2c.hのi2c_msg構造体のコメントを読んだところ、どれにも該当
>>>>> しないので0としました。
>>>>
>>>> 送信時は0でよいですが、受信時は「I2C_M_RD」を使用するようです。
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> armadillo mailing list
>>>> email@hidden
>>>> http://lists.atmark-techno.com/cgi-bin/mailman/listinfo/armadillo
>>>>
>>>>
>>>
>>>
>>> _______________________________________________
>>> armadillo mailing list
>>> email@hidden
>>> http://lists.atmark-techno.com/cgi-bin/mailman/listinfo/armadillo
>>
>> _______________________________________________
>> armadillo mailing list
>> email@hidden
>> http://lists.atmark-techno.com/cgi-bin/mailman/listinfo/armadillo
>>
>>
>
>
> _______________________________________________
> armadillo mailing list
> email@hidden
> http://lists.atmark-techno.com/cgi-bin/mailman/listinfo/armadillo 




armadillo メーリングリストの案内