FAQ: i2c Twi combined read write(2007-05-09)

Document created by Aaronwu Employee on Aug 28, 2013Last modified by sonic on Sep 8, 2013
Version 2Show Document
  • View in full screen mode

2007-05-09 14:40:18     i2c Twi combined read write

Berthold Bleier (AUSTRIA)

Message: 26150   

 

Hello,

 

I have a problem using i2c.

 

I am using the ADSP BF 537 and uClinux-distr-2007R and I have to communicate to a device(ADV7171) via i2c. I tried to communicate through i2c-dev Interface.

 

The Slave Address of my device: 0x2A

 

The Problem is that I can write to the device by using the write command, but the device don’t support the simple read command.

 

The read sequence of my device:

 

<S><Slave Addr><W/R=0><A(S)><Sub Addr><A(S)><S><Slave Addr><W/R=1><A(S)><Data><A(M)> …..<Data></A(M)><P>

 

S = start bit

 

P = stop bit

 

Slave Addr = 7 bit Slave Address : My device is on 0x2A

 

W/R   is on bit behind the slave address. For writing the bit is 0 for reading 1.

 

A(S) Slave Acknowledge

 

A(M) Master Acknowledge

 

/A(M) =No Master Acknowledge

 

You can see on the read sequence of my device, that I first have to write (slave Addr and Sub Addr) and after that I have to read without having a Stop bit in it.

 

The documentation of the i2c-dev gave me the information that I should use the combined read/write command:

 

Lt Dokumentation:

 

Combined transactions

 

====================

 

This corresponds to 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 Addr Wr [A] Data [A] P

 

With the command:

 

ioctl(file,I2C_RDWR,struct i2c_rdwr_ioctl_data *msgset)

 

The problem is that the command doesn’t work.

Can anyone help me please?

TranslateQuoteReplyEditDelete

 

 

2007-05-09 14:55:18     Re: i2c Twi combined read write

Berthold Bleier (AUSTRIA)

Message: 26151    Here you can see my sourcecode. I also placed a lot of printk in the i2c-core.c and i2c_bfin_twi.c to see, what the commands (open,write, ioctl) will  do if the program runs. I think that the 1.Part works, because the write command starts the master_send routine in the i2c_bfin_twi.c. The problem is the  write /read combined  command in the 2.Part.  It doesn´t work.

 

 

#include <stdio.h>

#include <sys/ioctl.h>

#include <stdlib.h>

#include <fcntl.h>

#include <errno.h>

#include <linux/i2c.h>

#include <linux/i2c-dev.h>

 

 

int main() {

        printf("I2C Test für ADV7171\n");

        int file;

        if ((file = open("/dev/i2c-0", O_RDWR )) < 0) {

                /* ERROR HANDLING; you can check errno to see what went wrong */

                printf("Cannot open Adapter");

                //exit(1);

 

        }

        // 1. Part

        printf("-------------------------------------------------------------------------------\n");

        int addr = 0x2A; /* The I2C address */

        if (ioctl(file,I2C_SLAVE,addr) < 0) {

                //ERROR HANDLING; you can check errno to see what went wrong

                printf("ioctl does not work\n");

                //exit(1);

        }

 

 

        __u8 reg = 0x02; /* Device register to access */

        __s32 res;

        char buf[10];

        char buf2[10];

        buf2[0]=0;

        buf2[1]=0;

        buf[0] = reg;

        buf[1] = 0x43; //  value to be wirtten on Reg 0x02

 

        if ( write(file,buf,2) != 2) {

              //printf("no");

              printf("Writing Error Register : %d \n",reg);

              // ERROR HANDLING: i2c transaction failed

        }

 

 

        //2.Part

        printf("-------------------------------------------------------------------------------\n");

 

        struct i2c_msg msgs1[2];

        msgs1[0] = { addr,0,0,buf};

        msgs1[1] = { addr,0,0,buf2};

 

        //struct i2c_rdwr_ioctl_data rdwr2 ={&receive,1};

        printf("Send: %ld\n",&send);

 

        msgs1[0].len = 1;

        msgs1.flags = 0;

        buf[0] = reg;

        buf[1] = 0x12;

        buf[2] = 0x23;

        msgs1[0].addr = 0x2A;

 

 

        msgs1[1].len = 1;

        msgs1[1].flags = I2C_M_RD;

        msgs1[1].addr = 0x2A;

 

 

        struct i2c_rdwr_ioctl_data rdwr ;

        rdwr.msgs= &msgs1[0];

        rdwr.nmsgs=2;

 

        printf("MSGs: %ld, %ld\n", rdwr.msgs,&msgs1[1]);

        printf("Start: \n");

        if (ioctl(file,I2C_RDWR,&rdwr) < 0) {

               printf("Could not read \n");

        }

        else

             printf("Result %lx\n",buf2[0]);

 

       printf("-------------------------------------------------------------------------------\n");

       return 0;

}

TranslateQuoteReplyEditDelete

 

 

2007-05-09 22:37:04     Re: i2c Twi combined read write

Jerry Zeng (CHINA)

Message: 26167    Hi Berthold,

 

Here is a link to our wiki,   docs.blackfin.uclinux.org/doku.php?id=i2c . Hope it is helpful to you.

 

BTW, the best way to debug i2c or spi interface is to use osciloscope. You can quickly find the timing sequence errors.

 

-Jerry

QuoteReplyEditDelete

 

 

2007-05-10 08:41:16     Re: i2c Twi combined read write

Berthold Bleier (AUSTRIA)

Message: 26195    Hi Jerry,

 

This Website did not help me, because I don't want to write a driver, I just want to access the i2c-device via user space as shown in the dist-Dokumentation.

 

By the way, I tried to use the user space commands for the SMBus, but I have problem to combile them:

 

#include <stdio.h>

#include <sys/ioctl.h>

#include <stdlib.h>

#include <fcntl.h>

#include <errno.h>

#include <linux/i2c.h>

#include <linux/i2c-dev.h>

//#include "i2c-dev1.h"

 

 

int main() {

    printf("I2C Test für ADV7171\n");

    int file;

    if ((file = open("/dev/i2c-0", I2C_SMBUS )) < 0) {

        /* ERROR HANDLING; you can check errno to see what went wrong */

        printf("Cannot open Adapter");

        //exit(1);

    }

 

    int addr = 0x2A; /* The I2C address */

    if (ioctl(file,I2C_SLAVE,addr) < 0) {

        //ERROR HANDLING; you can check errno to see what went wrong

        printf("ioctl does not work\n");

        //exit(1);

    }

 

 

    __u8 reg = 0x02; /* Device register to access */

    __s32 res;

    //char buf[10];

 

     i2c_smbus_write_byte_data(file,reg,0x20);

     res = i2c_smbus_read_byte_data(file,reg);

 

    if (res < 0) {

        printf("SMBUS read ERROR\n");

        // ERROR HANDLING: i2c transaction failed

    } else {

       printf("Result: %x\n",res);

    /* res contains the read word */

    }

    return 0;

}

 

 

The combiler messages:

undefined reference to `_i2c_smbus_write_byte_data'

undefined reference to `_i2c_smbus_read_byte_data'

 

but lt i2c-dev Documentation they should be avalible. I am sure , that the problem is to including the right files to the program, but they were never mentioned in the Documentation.

 

I hope anyone has a solution, how userspace commands work.

Please help

TranslateQuoteReplyEditDelete

 

 

2007-05-10 09:30:51     Re: i2c Twi combined read write

Andrea Federico (UNITED STATES)

Message: 26197    try to include my "i2c-dev.hh" file,

 

// #include <linux/i2c.h>

// #include <linux/i2c-dev.h>

#include "i2c-dev.hh"

i2c-dev.hh

QuoteReplyEditDelete

 

 

2007-05-11 08:30:33     Re: i2c Twi combined read write

Berthold Bleier (AUSTRIA)

Message: 34851    compiling of smbus commands works perfectly with your i2c-dev

 

thanks Andrea

TranslateQuoteReplyEditDelete

 

 

2007-05-22 11:15:19     Re: i2c Twi combined read write

Zhi Qiang Zhang (CHINA)

Message: 35449    Andrea,

 

I want to send 8 bytes data in once without calling 8 times of i2c_smbus_write_byte_data that will send STOP bit. I tried i2c_smbus_write_block_data, but it seems it would send STOP bit each time a byte was sent.

 

Can I use i2c_master_send to do this?

 

 

Regards,

ZhangZQ

QuoteReplyEditDelete

 

 

2007-05-23 23:24:39     Re: i2c Twi combined read write

Mike Frysinger (UNITED STATES)

Message: 35526    yes, i2c_master_send should allow you to do that

QuoteReplyEditDelete

 

 

2007-05-30 21:18:40     Re: i2c Twi combined read write

Zhi Qiang Zhang (CHINA)

Message: 35807    Mike,

 

Is it possible to call i2c_master_send in user space program.

 

 

Regards,

ZhangZQ

QuoteReplyEditDelete

 

 

2007-05-30 22:11:25     Re: i2c Twi combined read write

Mike Frysinger (UNITED STATES)

Message: 35810    of course not, it's a kernel function

 

if you want to do I2C from userspace, see linux-2.6.x/Documentation/i2c/dev-interface

QuoteReplyEditDelete

 

 

2007-05-31 22:19:53     Re: i2c Twi combined read write

Zhi Qiang Zhang (CHINA)

Message: 35876    Mike,

 

I read that document before, but found not function to read/write multiple bytes a time without sending STOP bit in userspace, if there is such function in userspace? Thanks.

 

 

Regards,

ZhangZQ

QuoteReplyEditDelete

 

 

2007-05-31 23:46:22     Re: i2c Twi combined read write

Sonic Zhang (CHINA)

Message: 35879   

 

You can use i2c SMBus command.

 

i2c_smbus_read_byte( file, value)

 

i2c_smbus_write_byte( file, 0x12)

 

i2c_smbus_read_word_data( file, register)

 

i2c_smbus_write_word_data( file, register, 0x1234)

 

i2c_smbus_read_byte_data( file, register)

 

i2c_smbus_write_byte_data( file, register, 0x12)

 

ioctl( file, I2C_RDWR, i2c_rdwr_ioctl_data)

 

...

 

 

QuoteReplyEditDelete

 

 

2007-05-31 23:56:23     Re: i2c Twi combined read write

Sonic Zhang (CHINA)

Message: 35880   

 

More:

 

ioctl( file, I2C_SMBUS, i2c_smbus_ioctl_data)

 

i2c_smbus_read_block_data( file, command, *values)

 

i2c_smbus_write_block_data( file, command, length, *values)

QuoteReplyEditDelete

 

 

2007-06-03 14:15:35     Re: i2c Twi combined read write

liou extrawave (TAIWAN)

Message: 35925    sorry, Mike

I will start a new thread

Thanks for your advice

RequiresAcrobat6.pdf

QuoteReplyEditDelete

 

 

2007-06-03 14:25:07     Re: i2c Twi combined read write

Mike Frysinger (UNITED STATES)

Message: 35926    please do not post new issues to existing threads ... you start new threads for new issues

 

you should put a scope on the I2C line to make sure the transmission is going out properly

QuoteReplyEditDelete

 

 

2007-06-04 10:42:29     Re: i2c Twi combined read write

Zhi Qiang Zhang (CHINA)

Message: 35953    Zhang,

 

I am very confused by i2c_smbus_read_i2c_block_data while it has no a parameter to specify how many bytes I want to read, how can I read 8 or 4 bytes without sending a STOP bit in each byte?

 

 

Regards,

ZhangZQ

QuoteReplyEditDelete

 

 

2007-06-04 22:29:06     Re: i2c Twi combined read write

Sonic Zhang (CHINA)

Message: 35976   

 

The return value is the actual data len you read.

 

 

QuoteReplyEditDelete

 

 

2007-06-04 22:45:13     Re: i2c Twi combined read write

Zhi Qiang Zhang (CHINA)

Message: 35978    But how can I specify the number of bytes I WANT TO read?

QuoteReplyEditDelete

 

 

2007-06-05 01:45:17     Re: i2c Twi combined read write

Mike Frysinger (UNITED STATES)

Message: 35990    i2c isnt exactly a bus meant for bulk transfers ... generally you know exactly how many things are going to be written and read

 

my guess is block read represents a single message: multiple data values without a stop bit ...

QuoteReplyEditDelete

 

 

2007-06-05 12:36:19     Re: i2c Twi combined read write

Zhi Qiang Zhang (CHINA)

Message: 36026    Zhang,

 

I found the bfin-twi-i2c driver is written by you, you must know this well, here is my code in the driver of one chipset using i2c,

 

        count = 8;

        printk(KERN_ALERT "at %u, count=%d\n", __LINE__, count);   // here is line 131

        if (client->adapter->algo->master_xfer)

        {

                data->data[0]   = 0x0;

                msg[0].addr     = client->addr;

                msg[0].flags    = client->flags & I2C_M_TEN;

                msg[0].len      = 1;

                msg[0].buf      = data->data;

 

                msg[1].addr     = client->addr;

                msg[1].flags    = client->flags & I2C_M_TEN;

                msg[1].flags    |= I2C_M_RD;

                msg[1].len      = count;

                msg[1].buf      = data->data;

 

                count = client->adapter->algo->master_xfer(client->adapter, msg, 2);

 

                printk(KERN_ALERT "at %u, count=%d\n", __LINE__, count); // here is line 150

                memcpy(buf, data->data, count);

                return count;

        }

        else

        {

                printk(KERN_ALERT "failed at %u\n", __LINE__);

                return 0;

        }

 

 

I want to read 8 bytes without sending stop bit, but here is the console output

at 131, count=8

at 150, count=2

at 131, count=6

at 150, count=2

at 131, count=4

at 150, count=2

at 131, count=2

at 150, count=2

48

49

48

49

48

49

48

49

 

the "48", "49" is the output from my test program. I want to read 8 bytes but only 2 bytes return, why? If it is possible I want to call you by phone, ok?

 

 

Regards,

ZhangZQ

Attachments

Outcomes