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.

CCS/AM4379: I2C issue

Part Number: AM4379
Other Parts Discussed in Thread: TMDSEVM437X, AM4372

Tool/software: Code Composer Studio

Hello TI experts,

I'm using the AM4379 custom board(VARSOMAM43) and i'm trying to interface AD5933 through I2C. 

I used i2cdetect command in order to read the slave address and was able to read the address 0x0D successfully. upon running the command i2cdump, I was even able to see the data in all the registers. 

I have written a simple code to read the value from the register 0x82 which should give me the value which is exactly what i saw in the terminal (upon executing i2cdump). But for some reason the code gives me 0 every time. 

can someone please tell me what's wrong.

Note: I haven't initialized any I2C pins manually. If that has to be done, please suggest me how to do that.

-Thanks

//============================================================================
// Name        : test_A.cpp
// Author      : Adarsh Kumar
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <stdio.h>
#include <string.h>
#include <stdlib.h> // system()
#include <unistd.h> // sleep()
#include <fcntl.h>  // oflag like O_RDWR
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

char Readbyte(char address);



char file_I2C1_DEV[30] = "/dev/i2c-0";
int  file;

int addr_AD5933 = 0b00001101;      // The I2C address of AD5933

int main()
{
    printf("I2C Interface Project!\n");

    if((file = open(file_I2C1_DEV,O_RDWR)) < 0)
    {
        perror("Failed to open the i2c bus");
        exit(1);
    }

    if(ioctl(file,I2C_SLAVE,addr_AD5933) < 0)
    {
        printf("Failed to acquire bus access and/or talk to slave.\n");
        exit(1);
    }

char temp;

        temp = Readbyte(82);
        printf("%d\n",temp);
        sleep(1);

}

char Readbyte(char address)
{
    char data;
    char buf[10] = {0};

    buf[0] = address;

    if(write(file,buf,1) != 1)
    {
        /* ERROR HANDLING: i2c transaction failed */
        printf("Failed to write to the i2c bus.\n");
    }

    // Using I2C Read
    if (read(file,buf,1) != 1)
    {
        /* ERROR HANDLING: i2c transaction failed */
        printf("Failed to read from the i2c bus.\n");
        }
    else
    {
        data = buf[0];
        }

    //BCD To Decimal Conversion
    if(address == 0)    //remove MSB bit in case of second
    {
        data = (((data & 0x70) >> 4) * 10) + (data & 0x0F);
    }
    else
    {
        data = (((data & 0xF0) >> 4) * 10) + (data & 0x0F);
   }

    return data;

}




  • Hi Adarsh,

    Do you use AM437x PSDK Linux? If yes, which version? Latest version is 6.01 (kernel 4.19.59) and is available at below location:

    http://software-dl.ti.com/processor-sdk-linux/esd/AM437X/latest/index_FDS.html


    You can configure i2C pinmux registers in your linux main DTS file. For example, check below file where AM437x GP EVM (TMDSEVM437X) i2c pins are setup:

    {PSDK}/board-support/linux-kernel/arch/arm/boot/dts/am437x-gp-evm.dts

    &am43xx_pinmux {

    i2c0_pins: i2c0_pins {
            pinctrl-single,pins = <
                AM4372_IOPAD(0x988, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_sda.i2c0_sda */
                AM4372_IOPAD(0x98c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)  /* i2c0_scl.i2c0_scl */
            >;
        };

        i2c1_pins: i2c1_pins {
            pinctrl-single,pins = <
                AM4372_IOPAD(0x95c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_cs0.i2c1_scl */
                AM4372_IOPAD(0x958, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2)  /* spi0_d1.i2c1_sda  */
            >;
        };

    }

    In general, if i2c-tools (i2cdetect, i2cdump, i2cset, i2cget) are working fine, while your custom userspace application fails, this is indication of userspace application error, which is beyond the scope of this forum support.

    What I can suggest you is to compare I2C module and pinmux registers settings between i2c-tools usage and custom application usage. There might be some difference, which can give you some debug directions. You can also measure with scope AM437x I2C pins and compare the signals between i2c-tools usage and custom application usage.

    Regards,
    Pavel

  • Thanks Pavel.

    I had some silly userspace application mistakes and its resolved. I just used IOCTL command inorder to read the data and its working absolutely fine.can you please tell how can I write the data into the register in the similar manner by looking at my code?

    -Thanks 

    #include <stdio.h>
    #include <stdlib.h>
    #include<string.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <linux/i2c.h>
    #include <linux/i2c-dev.h>
    #include <unistd.h>
    #include<sys/stat.h>
    #include<errno.h>
    
    #include <sys/ioctl.h>
    
    int main(int argc, char *argv[])
    {
        struct i2c_msg i2cmsg[2];
        unsigned char data_index = 128;
        unsigned char data_space = 0;
            i2cmsg[0].addr = 0x0d;
            i2cmsg[0].flags = 0;
            i2cmsg[0].len = sizeof(data_index);
            i2cmsg[0].buf = &data_index;
    
            i2cmsg[1].addr = 0x0d;
            i2cmsg[1].flags = I2C_M_RD;
            i2cmsg[1].len = sizeof(data_space);
            i2cmsg[1].buf = &data_space;
    
        struct i2c_rdwr_ioctl_data msg_rdwr;
        msg_rdwr.msgs = i2cmsg;
        msg_rdwr.nmsgs = 2;
        int file=open("/dev/i2c-1",O_RDWR);
        if (file < 0) {
               /* ERROR HANDLING: you can check errno to see what went wrong */
                perror("Failed to open the i2c bus");
                    exit(1);
            }
        int result_2 = ioctl(file, I2C_SLAVE, 0x0d);
            if (result_2 < 0) {
                printf("Failed to acquire bus access and/or talk to slave.\n");
                /* ERROR HANDLING; you can check errno to see what went wrong */
                    exit(1);
            }
    
    
       int result_1 = ioctl(file, I2C_RDWR, &msg_rdwr);
        if (result_1 < 0) {
            printf("Failed to acquire bus access and/or talk to slave.\n");
            /* ERROR HANDLING; you can check errno to see what went wrong */
                exit(1);
        }
    
            printf("0x%02X\n",data_space);
            close(file);
            return 0;
    }
    
    

  • Thanks Pavel,

    This solved my issue.

    Is there any flag in i2c-dev.h/ i2c.h that automatically sets once the transmission is successful? I mean just like the arduino has Wire.endTransmission() which returns 0 upon successful transmission. 


    -Thanks

  • Adarsh Kumar said:
    Is there any flag in i2c-dev.h/ i2c.h that automatically sets once the transmission is successful? I mean just like the arduino has Wire.endTransmission() which returns 0 upon successful transmission. 

    This question is NOT TI specific, this is generic Linux question. I would suggest you to check/ask in some generic/mainline Linux forum.

    Regards,
    Pavel