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 read using CSL

Other Parts Discussed in Thread: TMS320C6472, TMS320C6670, PCF8574

Hi,I'm using C6472, CCS3.3, and I would like to write a simple I2C read routine.

I tried the example code that came with the CSL library and it worked fine (write and read back in loopback mode).

I need a simple read. I tried to modify the example code with no success. I tried other examples from the web with no success either.

Here is partial code. I removed many of the status return checks to simplify the reading.

My problem is that the read register (RRDY bit) is never ready! Do I have to start by  transmitting the slave address, or its is sent automatically? Please help.

void I2C_init(void) {

    CSL_Status         status;
    CSL_I2cObj      i2cObj;
    CSL_I2cHwSetup  hwSetup;

    hwSetup.mode           = CSL_I2C_MODE_MASTER;
    hwSetup.dir            = CSL_I2C_DIR_TRANSMIT;
    hwSetup.addrMode       = CSL_I2C_ADDRSZ_SEVEN;        //7bits addressing mode
    hwSetup.sttbyteen      = CSL_I2C_STB_DISABLE;        //DISABLE == disable start byte (Normal mode)
    hwSetup.ownaddr        = CSL_I2C_SLAVE_ADDR;        //address used to talk to this DSP chip
    hwSetup.ackMode        = CSL_I2C_ACK_ENABLE;
    hwSetup.runMode        = CSL_I2C_FREE_MODE_DISABLE;    //DISABLE == stop at breakpoint
    hwSetup.repeatMode     = CSL_I2C_REPEAT_MODE_DISABLE;//DISABLE == no repeat mode
    hwSetup.loopBackMode   = CSL_I2C_DLB_DISABLE;        //DISABLE == digital loopback mode is disabled
    hwSetup.freeDataFormat = CSL_I2C_FDF_DISABLE;        //DISABLE == use 7/10bits addressing mode
    hwSetup.resetMode      = CSL_I2C_IRS_ENABLE;         //ENABLE  == put in reset
    hwSetup.bcm            = CSL_I2C_BCM_DISABLE;        //DISABLE == disable back compatibility
    hwSetup.inten          = 0x00;                       //interrupt enable mask
    hwSetup.clksetup       = &clksetup;                    //prescaler and clock setup

    CSL_i2cInit(NULL);
    sI2C_Handle = CSL_i2cOpen(&i2cObj, CSL_I2C, NULL, &status);
    CSL_i2cHwSetup(sI2C_Handle, &hwSetup);
    CSL_i2cHwControl(sI2C_Handle, CSL_I2C_CMD_OUTOFRESET, NULL);
}

uint16_t I2C_read(uint16_t endPoint, uint8_t *data_p, uint16_t length) {
    
     int16_t timecount, timeout = 0x1000;
    CSL_Status status = CSL_SOK;       
    uint16_t response;   
    uint32_t BbResponse;    //busy bit
    uint32_t cmd_arg;   
    uint8_t  endPointAddress;

    // set address of the slave device
    endPointAddress == 0x40;
    CSL_i2cHwControl(sI2C_Handle, CSL_I2C_CMD_SET_SLAVE_ADDR, &endPointAddress);   
    CSL_i2cHwControl(sI2C_Handle, CSL_I2C_CMD_SET_DATA_COUNT,&length);   
  
    // Configure Options for Receiving - Master Reciever mode
//  CSL_i2cHwControl(sI2C_Handle, CSL_I2C_MODE_MASTER,NULL); //master
    CSL_i2cHwControl(sI2C_Handle, CSL_I2C_CMD_DIR_RECEIVE,NULL); //receive
    CSL_i2cHwControl(sI2C_Handle, CSL_I2C_CMD_ENABLE,NULL); //enable
    CSL_i2cHwControl(sI2C_Handle, CSL_I2C_CMD_START,NULL);   //start

    // Wait for the transfer to start
    do {
        CSL_i2cGetBusBusy(sI2C_Handle,&BbResponse);
    } while(BbResponse != 1);
   
    while(length) {     //receive all data words
        CSL_i2cGetHwStatus(sI2C_Handle, CSL_I2C_QUERY_NACKSNT, &response);    //check NACK
        if ( response != 0x0001 ) {   

            CSL_i2cGetHwStatus(sI2C_Handle, CSL_I2C_QUERY_ACS_RDY, &response);   //check ARDY
            if (response != CSL_I2C_ACS_READY ) { //we still have more data to read

                CSL_i2cGetHwStatus(sI2C_Handle, CSL_I2C_QUERY_RX_RDY, &response);   //check RRDY (can't get past this point)
                if ( response == CSL_I2C_RX_READY ) {   
                    CSL_i2cRead(sI2C_Handle,data_p++);  //Read Data
                    length --;   
   
                    // Clear Receive Ready field
                    do{
                        cmd_arg=CSL_I2C_CLEAR_RRDY;   
                        CSL_i2cHwControl(sI2C_Handle,CSL_I2C_CMD_CLEAR_STATUS,&cmd_arg);   
                        CSL_i2cGetHwStatus(sI2C_Handle, CSL_I2C_QUERY_RX_RDY, &response);
                    }while(response==CSL_I2C_RX_READY);   
                }//if Rx ready   
            }//if ARDY: we still have data to read
   
            // Check for Arbitration Lost
            CSL_i2cGetHwStatus(sI2C_Handle,CSL_I2C_QUERY_AL, &response);   
            if ( response == CSL_I2C_ARBITRATION_LOST ) {  
                return 1001;   
            }
   
            /* Check for NACK */   
            CSL_i2cGetHwStatus(sI2C_Handle,CSL_I2C_QUERY_NACKSNT, &response);   
            if ( response == 0x0001 )   return 1002;   
  
            /* Check for Register Access Ready - Good Condition */   
            CSL_i2cGetHwStatus(sI2C_Handle,CSL_I2C_QUERY_ACS_RDY, &response);//why ARDY!=1?     
            if ( response == CSL_I2C_ACS_READY ) {   
                do{
                    cmd_arg=CSL_I2C_CLEAR_ARDY;   
                    CSL_i2cHwControl(sI2C_Handle,CSL_I2C_CMD_CLEAR_STATUS,&cmd_arg);   
                    CSL_i2cGetHwStatus(sI2C_Handle,CSL_I2C_QUERY_ACS_RDY, &response);
                }while(response == CSL_I2C_ACS_READY);   
                return 0;   
            }
        } // if NACK
    } //for all data

    // I2C Timeout
    return 2002;
}



  • does anyone has a simple I2C receive function (read a single value from a a specific I2C slave address. No need to write anything to that I2C slave)?

    A quick help is appreciated.

    thanks.

  • Hello,

    You can download a working example here http://linux-c6x.org/files/releases/ibl-1.0/ , the file iss ibl-1.0-src.tar.gz

    File is under \src\util\i2cRead

    regards,

    David

     

  • Thank you David, The link that you have sent contained many examples that helped me better understand how to use the I2C interface.

    However, the values used to clear/set/access the different I2C bits (as described in ibl-1.0-src\src\hw\i2c\i2cloc.h) do not match the SPRUE11c.pdf bits position!

    I'm using the TMS320C6472 DSP processor.

    khaled.

  • Do you mean these ones? I checked and it matched the bit definition in the document Rev C, page 22.

    /* Bit field definitions */
    #define I2C_REG_STR_FIELD_BB(x)    BOOT_READ_BITFIELD((x), 12, 12)
    #define I2C_REG_STR_FIELD_NACK(x)  BOOT_READ_BITFIELD((x),  1,  1)
    #define I2C_REG_STR_FIELD_ARDY(x)  BOOT_READ_BITFIELD((x),  2,  2)
    #define I2C_REG_STR_FIELD_XRDY(x)  BOOT_READ_BITFIELD((x),  4,  4)
    #define I2C_REG_STR_FIELD_RRDY(x)  BOOT_READ_BITFIELD((x),  3,  3)

  • No, I mean those

    /* Individual register definitions */
    #define I2C_VAL_REG_MDR_RESET       0x4000
    #define I2C_VAL_REG_MDR_SLVRCV      0x40A0
    #define I2C_VAL_REG_MDR_MSTRCV      0x64A0
    #define I2C_VAL_REG_MDR_MSTRCVSTOP  0x4CA0
    #define I2C_VAL_REG_MDR_MSTXMT      0x46A0
    #define I2C_VAL_REG_MDR_MSTXMTSTRT  0x66A0
    #define I2C_VAL_REG_MDR_MSTXMTSTOP  0x4CA0

    khaled.

  • khaled,

    The code works fine, please  continue using the code as is. I will check with doc team about documentation.

    regards,

    David

  • I am writing an i2c interface for TMS320C6670, trying to write to and read from M24M01 EEPROM.  On my i2cWrite, I set up the slave register and write two bytes of addresses (most significant byte first) and check for the acknowledgement (by checking ICSTR>ICXRDY). 

    It seems that I would have to write extra 2bytes following the data for my write to work.  Also, I would have to write extra 2 bytes when I am doing a read. 

    On Write: set up transmit, write 2byte address--write data(N-bytes)--write 2bytes (of any values)

    On Read: write 2byte address-- write 2bytes (of any values)--set up receive--read N byte of data.

    From the documentation, it doesn't seem that I would need to write the extra 2bytes.

    Please let me know if I am doing anything wrong or why writing those extra bytes corrects the read and write to the EEPROM.

  • Do you have this issue with existing i2cread in the IBL? If not, then you can compare the code difference to find it out.

  • compare it to what code?

    ibl-1.0-src\src\hw\i2c\i2c.c??

  • util\i2cRead\I2cread.c and util\i2cWrite\I2Cwrite.c and \src\hw\i2c folder. If you can reuse the working code as is, there is no need to reinvent them.

  • Hi David

    spend more time looking at the different registers and its starting to make sens to me :-)

    However, I have one problem left in order to get my code to run:

    In sprue11c.pdf (page 15, table 1, description of the operating modes), In the Master-receiver mode description, it states "This mode can only be entered from the master-transmitter mode, the I2C module must first transmit a command to the salve". 

    In my case, there is no command to send to the I2C slave. My slave documentation specifies that I need to use the following sequence

    | S | Slave address | R | Ack | data (1 byte) | Ack | P |

    As you can see, my slave do not take a command.

    Is there is a way to force the DSP I2C module to go from master-transmit mode into master-receive mode without having to transmit a command?

    khaled.

  • Khaled,

    I'm not sure I follow exactly. If you have a slave device then if you don’t send a command then how does it know when to start sending you data?

     But in general you can easily setup the i2c on the device to slave receive mode by writing this value to the mdr register:

     #define I2C_VAL_REG_MDR_SLVRCV      0x40A0

     Now the i2c peripheral will accept data that arrives as long as the data was proceeded with an i2c address. In that case the other device must send the command and address before sending any data. That really isn’t the way a slave works, however.

    regards,

    David

  • Hi David,

    This particular slave does not need a command to start sending data back. All what it needs is its address followed by a read bit and the clock (from the DSP master).

    You can check the data sheets. Its a TI remote 8bits I/O expander PCF8574 http://www.ti.com/product/pcf8574

    Khaled.

  • Looking at addresses 0xD0D0 to 0xD0D4 on M224M01 EEPROM, are those addresses write protected?  I am able to write to 0xD0D5 and above but I I do have an issue writing and reading back the same value to the 0xD0D0.