This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

I2C reading in userland application made on OMAP L138

Other Parts Discussed in Thread: OMAPL138

Hi, 

      I2c device is attached with OMAP L138 and made application to read i2c data. where OMAP L138 is master device and i2c device as slave device, i2c device is sending 2 bytes of data. I am able to read two i2c data bytes by using ioctl() and read function. In first attempt, i am able to read first two bytes but on second attempt, one byte is dropped and next two bytes are read. This result repeats on every consecutive reading of i2c device. How can i ensure that every consecutive reading should read every bytes without dropping any one byte reading?

Code i

void i2cread()

{

  int i2c_fd;
     ssize_t byte;
     char buffer[32];

   
    i2c_fd=open("/dev/i2c-1",O_RDWR);
    if(i2c_fd<0) {
        printf("File I2C Device Can't be Opened\n");
        return -1;
    }
    else {
        printf("File I2C Device is Opened\n");
    }
    if(ioctl(i2c_fd,I2C_SLAVE,0x48)<0) {
        printf("I2C Device Can't be Opened\n");
        ERROR_FXN_EXIT(i2c_fd);
    }
    else {
        printf("I2C Device is Opened\n");
    }        
    byte=read(i2c_fd,buffer,20);
    printf("%d. ",byte);
    if(byte<0){
         printf("\n");
    }
    else  {

    for(byte=0;byte<20;byte++)
         printf("%d ",buffer[byte]);
    printf("\n");
    }

}

On every time calling of i2cread function, i am reading one byte is missing. why is one byte missing?

suppose if give read function two times, then first time reading is OK, but during call of read function, then one byte is missing. what could be reason? can anyone throw light on it?

Regards,   

Learner.

  • Hi Learner,

    I would like to recommend you to run the I2C example which comes as a part of OMAPL138_StarterWare_1_10_03_03 package (along with OMAPl138 EVM).

    By some chance, if you have OMAPL138 EVM, using CCS, you can build, run and execute the I2C example on target which gives you a better understanding of I2C pinMux setup, configuration of modes and transmission through I2C.

    Once you get a good hold on I2C by code walk through and debugging the I2C example, you can try fixing the things missed out in your own code.

    You can download the OMAPL138_StarterWare_1_10_03_03 package from http://processors.wiki.ti.com/index.php/StarterWare

    Once installed, you will find the I2C examples at "..\OMAPL138_StarterWare_1_10_03_03\build\c674x\cgt_ccs\omapl138\evmOMAPL138\i2c"

     

    All the best,

    Shankari

     

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.
    --------------------------------------------------------------------------------------------------------

  • You are missing a close() but I don't think that is the cause. From your other posts, I am guessing your device is a TPS chip. That device does not support a simple read transaction. I think your device might need a "write restart read" transaction.  Below is an example of a "write restart read" transaction.

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

    void i2cread(void)
    {
      int i2c_fd;
      char buffer[20];
      unsigned char dev_addr = 0x48;
      unsigned char reg_addr = 0x00; /* Starting register address. */
      struct i2c_rdwr_ioctl_data iodata;
      struct i2c_msg             msg[2];

      i2c_fd=open("/dev/i2c-1",O_RDWR);
      if(i2c_fd<0) {
         printf("File I2C Device Can't be Opened\n");
         return -1;
      }
      printf("File I2C Device is Opened\n");

      msg[0].addr  = dev_addr;
      msg[0].flags = 0; /* WRITE */
      msg[0].len   = 1;
      msg[0].buf   = &reg_addr;

      msg[1].addr  = dev_addr;
      msg[1].flags = I2C_M_RD;
      msg[1].len   = sizeof(buffer);
      msg[1].buf   = buffer;

      iodata.msgs  = msg;
      iodata.nmsgs = 2;

      if(ioctl(g_dev, I2C_RDWR, &iodata) < 0) {
        printf("Start Write Restart Read Failed\n");
        goto err_exit;
      }

      for(byte=0;byte<sizeof(buffer);byte++)
         printf("%d ",buffer[byte]);
      printf("\n");

    err_exit:
      close(i2c_fd);

    }

  • How can i send only stop condition using ioctl(g_dev, I2C_RDWR, &iodata)?

  • I've never tried to do. Might be a flag for that. Check the i2c documentation in the kernel source. The write(), read() and ioctl(,I2C_RDWR,) calls all include the start and stop.

  • For what it is worth, I have found some somewhat "generic" I2C code in starterware under examples\lcdkOMAPL138\game\gameI2C.c and gameI2c.h - I will need to do some test code on my target board to read a register value of a PMIC chip. On the LCDK, there is a video chip that does have a chip ID that I will attempt to read - then change the address and register info to eventually attempt a read of the PMIC version register...
  • Not sure if that was a question or answer ... I have also used the StarterWare I2C bare metal code as well. I vaguely remember an IRQ driven version. No polled IO version.
  • Thanks, Norman.
    Yes, just discovered that StarterWareI2C forces interrupts on the user. I am not sure if a "polled" version of I2C exists for this part.
  • Most StarterWare examples are interrupt and/or DMA. I find the u-boot is usually good reference for simple polled IO code. If the processor is doing only one thing at a time, polled IO code uses the least amount of memory and is usually faster.