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.

TMS320F28377S: Driverlib: sending and receiving data with I2C

Genius 5910 points

Part Number: TMS320F28377S

Hi,

I'm trying to figure out how to send a data sequence using I2C.

 I'm using the Driverlib library but the "examples" and the datasheet aren't any help how to send and receive a data package.

If I send this;

void PCA9555D_Config (uint32_t Base,uint16_t id,uint16_t inout)
{

    I2C_setSlaveAddress (Base,id);
    I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
    I2C_setDataCount (Base,5);
    I2C_sendStartCondition(Base);
    I2C_putData(Base, INV_P0);
    I2C_putData(Base, 0);
    I2C_putData(Base, 0);
    I2C_putData(Base, inout && 0x0F);
    I2C_putData(Base, (inout >> 8) && 0x0F);
    I2C_sendStopCondition (Base);
 }

This send out data. But stops after a couple of times. 1 resend it every second.

But after a couple of time the bus lock up. and the TX and RX Fito are full.

Can someone please explain what is stored in the FIFO and why they are filling up?

Thanks

EVS

edit:

Register set at bus lockup:

GRP( I2caRegs )    
    I2COAR    Unsigned / Readable,Writeable    0x0000    
    I2CIER    Unsigned / Readable,Writeable    0x0000    
    I2CSTR    Unsigned / Readable,Writeable    0x1E28    
    I2CCLKL    Unsigned / Readable,Writeable    0x0008    
    I2CCLKH    Unsigned / Readable,Writeable    0x0007    
    I2CCNT    Unsigned / Readable,Writeable    0x0005    
    I2CDRR    Unsigned / Readable,Writeable    0x0004    
    I2CSAR    Unsigned / Readable,Writeable    0x0080    
    I2CDXR    Unsigned / Readable,Writeable    0x0000    
    I2CMDR    Unsigned / Readable,Writeable    0x6E20    
    I2CISRC    Unsigned / Readable,Writeable    0x0000    
    I2CEMDR    Unsigned / Readable,Writeable    0x0001    
    I2CPSC    Unsigned / Readable,Writeable    0x0013    
    I2CFFTX    Unsigned / Readable,Writeable    0x7080    
    I2CFFRX    Unsigned / Readable,Writeable    0x3080    

  • EVS,

    When TXFFST = 16, it tells the you have 16 (8 bit data) in Transmit FIFO

    When RXFFST = 16, it tells you have received 16 (8 bit data) in Receive FIFO

    Looking at your I2CSTR, it suggests your I2C was addressed as slave by some other I2C Master. Are you expecting to receive some data from some other I2C Master? This is most likely the reason why your receive FIFO is full. Are you reading the I2CDRR register 16 times on a FIFO interrupt? This will clear the RX FIFO buffer ready to receive next sequence of data.

    Regards,
    Manoj
  • Manoj,

    Thanks for the reply.

    I'm really sure there is no other i2c master and the data is coming from inside the I2C hardware.

    If I modify the code to this:

    void PCA9555D_Config (uint32_t Base,uint16_t id,uint16_t inout)
    {

        I2C_setSlaveAddress (Base,id);
        I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
        I2C_setDataCount (Base,5);
        I2C_putData(Base, INV_P0);
        I2C_putData(Base, 0);
        I2C_putData(Base, 0);
        I2C_putData(Base, inout && 0x0F);
        I2C_putData(Base, (inout >> 8) && 0x0F);
        I2C_sendStartCondition(Base);
        I2C_sendStopCondition (Base);
        while  (I2C_getRxFIFOStatus (Base) != I2C_FIFO_RXEMPTY) I2C_getData (Base);
     }

    This  code produce a repeatable i2c message.

    Thinks I can't find in the documentation or in the examples:

    - What is the order I need to put the data, start, stop conditions?

    - I assume the RX fifo data is the read back information from the send data. How am i supposed to manage it? I think there may be issues with synchronization.

    - How do I send multi I2C messages in sequence?   Do I have to wait for the previous massage to finish (Which bit to check?)  or can I add it to the fifo.

    Thanks!

  • EVS,

    1) I reviewed your PCA9555D_Config function. The order you are using is correct. Also, you don't need to set START and STOP bit separately. You can set them together.

    2) RXFIFO buffer is filling up because you are receiving data from I2C bus. If you are not expecting this. Check whether you have selected Digital Loop Back (Is you DLB bit set, I2CMDR.DLB = 1?)

    3) If you want to send multiple I2C messages, you can use Repeat Mode (I2CMDR.RM) along with FIFO. When TXFIFO Status (TXFFST <= TXFFIL) you can generate interrupt to refill the TXFIFO for next set of transmission. Once you are done with sending all the messages send a STOP signal.

    Regards,
    Manoj
  • Manoj,

    Thanks for the detailed explanation.

    1) ok

    2) I added  I2C_disableLoopback (Base); at that solved the problem.

    3) Does this also work with multiple I2C ics? How is: I2C_setSlaveAddress and I2C_setDataCount added in the fifo?

    4) I still have problems reading I2C message:

    int16_t I2C_Read (uint32_t HWBase,uint16_t Slave_address,uint16_t Reg_address, uint16_t No_of_databytes, uint16_t Read_Array[])
    {uint16_t cnt;
        // Check if there is still a I2C message in progress of there is an other master active
        if ((I2C_getStopConditionStatus (HWBase) != 0 ) && (I2C_isBusBusy (HWBase) != 0)) return I2C_STP_NOT_READY_ERROR;
        // send request
        I2C_setConfig           (HWBase, I2C_MASTER_SEND_MODE);
        I2C_setSlaveAddress     (HWBase,Slave_address);
        I2C_setDataCount        (HWBase, 1);
        I2C_putData             (HWBase, Reg_address);
        I2C_setConfig           (HWBase,I2C_MDR_RM);
        I2C_sendStartCondition  (HWBase);
        // Read response
        I2C_setConfig           (HWBase, I2C_MASTER_RECEIVE_MODE);
        I2C_setDataCount        (HWBase,No_of_databytes);
        I2C_setSlaveAddress     (HWBase,Slave_address);
        I2C_sendStartCondition  (HWBase);
        I2C_sendStopCondition   (HWBase);
        for (cnt=0;cnt<No_of_databytes;cnt++)
        {
            while (I2C_getRxFIFOStatus (HWBase) == I2C_FIFO_RXEMPTY);
            Read_Array[cnt]= I2C_getData  (HWBase);
        }
        return I2C_SUCCESS;
    }
    Edit: new version: The problem is that expecten response is incorrect. I don't see the response adres send out.


    But I it doesn't work as expected. Suggestion what the problem is?

    Do I first send the Reg_address with I2C_setConfig  (HWBase, I2C_MASTER_SEND_MODE); and receive the data with:     I2C_setConfig    (HWBase, I2C_MASTER_RECEIVE_MODE); ?

    4)  Handling Nack. Is this correct

        if ((I2C_getStatus (HWBAse) && I2C_STS_NO_ACK) != 0)
                {
                    I2C_sendStopCondition   (HWBase);
                    I2C_clearStatus (HWBase,I2C_STS_NO_ACK);
                    
                }

    Does this release the bus?

    Thanks for your help!

    EVS

  • EVS,

    3) Yes, F28377S I2C supports multi-master I2Cs in bus.

         When TX FIFO is enabled, whatever is written into I2CDXR register populates FIFO. I2C Slave address and I2C Count register doesn't get   populated in FIFO.

    4) This is what I believe you should do

    //Below functions will do the following:-

    1) Send START bit

    2) Send Slave address in I2C bus + Write bit + Receive ACK bit from slave

    3) Send data in I2C bus + Receive ACK bit from slave + STOP bit (when I2CCNT will decrements to 0)

    I2C_setSlaveAddress     (HWBase,Slave_address);

    I2C_putData             (HWBase, data);

    I2C_setDataCount        (HWBase, 1);

    I2C_setConfig           (HWBase, I2C_MASTER_SEND_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    //Below functions will do the following:-

    1) Send START bit

    2) Send Slave address in I2C bus + Read bit + Receive ACK bit from slave

    3) Receive data in I2C bus + Receive ACK bit from master + ........ + STOP bit (When I2CCNT will decrements to 0)

    //You don't to re-define slave address since it is already configured above

    I2C_setDataCount        (HWBase,No_of_databytes);

    I2C_setConfig           (HWBase, I2C_MASTER_RECEIVE_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    5) Looks correct.

    Regards,

    Manoj

  • Manoj,

    Thanks for the detailed explanation.

    I modified my code as suggested:

    int16_t I2C_Read (uint32_t HWBase,uint16_t Slave_address,uint16_t Reg_address, uint16_t No_of_databytes, uint16_t Read_Array[])

    {uint16_t cnt;

       // Check if there is still a I2C message in progress of there is an other master active

       if ((I2C_getStopConditionStatus (HWBase) != 0 ) && (I2C_isBusBusy (HWBase) != 0)) return I2C_STP_NOT_READY_ERROR;

       // send request

       I2C_setSlaveAddress     (HWBase,Slave_address);

       I2C_setDataCount        (HWBase, 1);

       I2C_putData             (HWBase, Reg_address);

       I2C_setConfig           (HWBase, I2C_MASTER_SEND_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

       // Read response

       I2C_setDataCount        (HWBase,No_of_databytes);

       I2C_setConfig           (HWBase, I2C_MASTER_RECEIVE_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

       for (cnt=0;cnt<No_of_databytes;cnt++)

       {

           while (I2C_getRxFIFOStatus (HWBase) == I2C_FIFO_RXEMPTY);

           Read_Array[cnt]= I2C_getData  (HWBase);

       }

       return I2C_SUCCESS;

    }

    But it still doesn't work:

    The package ,I think, I need to send:

    send request:

    I2C address,  =>0X21  + R

    Register ID     =>   0

    response:

    I2C address  => Ox2 + W

    Data bye 1  => slave response

    Data byte 2 => slave response

    That is not response I got:

    I don't get the the read see the response I2c address in the message. So where did that got lost?

    Thanks,

     EVS

  • EVS,

    It is not clear from your reply what didn't work. Please describe your problem clearly. It is difficult to guess the problem from waveforms.

    1) Did master transmitter transfer put slave address, EEPROM address correctly?

    2) Are you exactly following read command format of PCA9555D?

    3) From the plot, after slave address 0x21, I do see read bit (High bit) and some data (0x0F). So, what exactly isn't working.

    4) Also, are you using RXFIFO?

    Regards,

    Manoj

  • Manoj,

    If you count the clock pulses the data count is incorrect. So the F28377SS is not sending all the I2C data.
    So I solved it with a wait between the first and second message.


    This is working code:
    int16_t I2C_Read (uint32_t HWBase,uint16_t Slave_address,uint16_t Reg_address, uint16_t No_of_databytes, uint16_t Read_Array[])
    {uint16_t cnt;
    // Check if there is still a I2C message in progress of there is an other master active
    if ((I2C_getStopConditionStatus (HWBase) != 0 ) && (I2C_isBusBusy (HWBase) != 0)) return I2C_STP_NOT_READY_ERROR;
    // send request
    I2C_setSlaveAddress (HWBase,Slave_address);
    I2C_setDataCount (HWBase, 1);
    I2C_putData (HWBase, Reg_address);
    I2C_setConfig (HWBase, I2C_MASTER_SEND_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    while (I2C_getStopConditionStatus (HWBase) != 0 );

    // Read response
    I2C_setDataCount (HWBase,No_of_databytes);
    I2C_setConfig (HWBase, I2C_MASTER_RECEIVE_MODE | I2C_MDR_STP | I2C_MDR_FREE | I2C_MDR_STT | I2C_MDR_IRS);

    for (cnt=0;cnt<No_of_databytes;cnt++)
    {
    while (I2C_getRxFIFOStatus (HWBase) == I2C_FIFO_RXEMPTY);
    Read_Array[cnt]= I2C_getData (HWBase);
    }
    return I2C_SUCCESS;
    }

    Waiting for any other control bit to get ready didn't work. The next message is send on top of the previous. As show in the scope picture in the last post. So You have to wait for the previous message to finish before sending the next one.
    If you see document SLVA704 page 7 there is a repeated start. But there is no way I got that to work. I even start to doubt if is even possible with the hardware.

    EVS
  • EVS,

    Good to know that the problem got resolved.

    Yes, you need to wait for all the bits to transmitted before reading back. F28377D works at 200MHz and I2C operates at much slower frequency in KHz. So, either wait till you get STOP bit (or) delay till all the bits are first transmitted before you read.

    Based on the forum post, it is clear we can do better job in I2C example we provide and make some clarifications in TRM. Thanks for your inputs. We will try to address this in future. I don't have timeline, but I will file a ticket to address this issue in future.

    I think I can close this post. But, please mark the threads which solved your problem for the benefit of other fellow engineers who have similar problem.

    Regards,
    Manoj