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.

TMS320F28069: I2C FIFO overflow

Part Number: TMS320F28069

Hello,

 

we using a TMS320F28069 with an I2C IO-Expander.

Sometimes we have problems with the I2C interface. It seems that the FIFO is overflowing.

The value 0x09 and value (mostly 0x1C) should be sent. In the code the value 0x09 is always sent first (register of the IO expander).

We see with the LogicAnalyzer that values are sent in the wrong order (see screenshot).

 

 

Config:

void InitI2C ( void )

{

    I2caRegs.I2CSAR = I2C_SLAVE_ADDR;      // (0x20)

    I2caRegs.I2CPSC.all = 8;          // Prescaler - 10MHz

    I2caRegs.I2CMDR.bit.IRS = 1;   

    // The prescaled frequency  takes effect only when IRS is changed to 1.

    I2caRegs.I2CCLKL = 7;           // NOTE: must be non zero

    I2caRegs.I2CCLKH = 7;            // NOTE: must be non zero

    // --> 100.44 kHz I2C Speed

    I2caRegs.I2CFFTX.all = 0x6000;   // Enable FIFO mode and TXFIFO

    I2caRegs.I2CFFRX.all = 0x2040;   // Enable RXFIFO, clear RXFFINT

}

 

Function:

int16 write_I2c_data ( unsigned int slave_addr, unsigned int length, unsigned char I2CRegister, unsigned char Value )

{

    int16 retval = 1;

    retval = check_BB_bit (I2C_TIMEOUT);

    if (retval < 0)

    {

        I2caRegs.I2CMDR.bit.IRS = 0;   // Timed out. Reset module.

        I2C_ Errorhandling ();

        return retval; // Abbrechen

    }

 

    /***************Write******************/

    I2caRegs.I2CSAR = slave_addr; // Setup slave address

    I2caRegs.I2CCNT = length; // Setup number of bytes to send MsgBuffer + Address

    I2caRegs.I2CDXR = I2CRegister; 

    I2caRegs.I2CDXR = Value;       

 

    // Send start as master transmitter

    I2caRegs.I2CMDR.all = 0x6E20; //gesetzt werden FREE, STT, STP, MST, TRX, IRS

 

    // -->> -- I2CMaster_Wait

    retval |= check_STP_and_BB_bit ( I2C_TIMEOUT);

    if (retval < 0)

    {

        I2caRegs.I2CMDR.bit.IRS = 0;   // Timed out. Reset module.

        I2C_Errorhandling();

        return retval; // Abbrechen

    }

    //--<<---

    return retval;

}

Call:

write_I2c_data ( I2C_SLAVE_ADDR, 2, MCP23008_GPIO, GPIO_exp.all );

This function is called very quickly.

 

 

Are overflows of the Send FIFO known?

How can I debug this exactly?

Thank you.

Markus

  • Hello Markus,

    I am not aware of any overflow issues on I2C. Just to double-check, can you use a print statement either before or after the write_I2c_data function to make sure the correct parameters are sent? If you add a delay between writes, does anything change? Can you share a screenshot of those two cases where 0x09 was not sent first?

    Best regards,

    Omer Amir

  • Hi Omer,

    thank you for the quick feedback. In the screenshot above you can see this (yellow line). There you can see that 0x0C is sent first, thats wrong.

    The call in the code of the first databyte is a define, so no other value like 0x09 can actually be sent first..

    #define I2C_SLAVE_ADDR      0x20
    #define MCP23008_GPIO       0x09
    
    write_I2c_data ( I2C_SLAVE_ADDR, 2, MCP23008_GPIO, GPIO_exp.all );


    With a delay I could never see the error. Therefore the assumption that Fifo overflows.

    Best regards,

    Markus

  • Hello Markus,

    I looked at some examples we have which are intended for I2C with EEPROM, and it looks like we do have a delay when transmitting via the FIFO; there is a while loop that waits 10 microseconds at the very longest (it checks if there is a NACK received or a timeout occurs and breaks out of the loop if this is the case). Are you using polling to determine when to write or an interrupt, or are you just writing as soon as possible?

    Best regards,

    Omer Amir

  • Hello Omar,

    we writing as soon as possible. I check the Stopbit and the Busybit, and then the next Cycle will start.

    Best regards,

    Markus

  • Hi Markus,

    I will check to see if polling the stop bit and busy bit is sufficient for waiting to write with I2C, I'll try to get back to you by tomorrow.

    Best regards,

    Omer Amir

  • Hello Markus,

    It seems like there should not be a problem with your method, can you provide the function code for the function on line 73 of your initial post? (retval |= check_STP_and_BB_bit ( I2C_TIMEOUT);). Also, since you're using FIFO mode can you try polling the I2caRegs.I2CFFTX.bit.TXFFST bit to see when the FIFO is empty?

    Best regards,

    Omer Amir

  • Hello Omer,

    thank you. Here is the code of line 73.

    int16 check_STP_and_BB_bit( Uint16 timeout )
    {
        int16 retval = 1;
    
        retval = check_STP_bit (timeout);
        retval |= check_BB_bit (timeout);
    
        return retval;
    }
    
    int16 check_BB_bit( Uint16 timeout )
    {
        int16 retval = 1;
        while (  I2caRegs.I2CSTR.bit.BB == 1 )
        {
            DELAY_US( 1 );
            timeout--;
            if ( timeout < 1 )
            {
                retval = -1; // I2C is locked up - fatal Error!
                break;
            }
        }
        return retval;
    }
    
    int16 check_STP_bit( Uint16 timeout )
    {
        int16 retval = 1;
        while ( I2caRegs.I2CMDR.bit.STP == 1 )
        {
            DELAY_US( 1 );
            timeout--;
            if ( timeout < 1 )
            {
                retval = -1; // I2C is locked up - fatal Error!
                break;
            }
        }
        return retval;
    }


    The timeout is meant as an "emergency exit". So that the main can not hang up.

    Good Idea. Could I also use I2caRegs.I2CFFTX.bit.TXFFINT for this?

    Which is the better solution, poling bits TXFFST or bit TXFFINT?

    Best regards,

    Markus

  • Hello Markus,

    Since you are using polling for your code, it would probably be best to keep with the polling bit, so I recommend trying TXFFST since it's a status. TXFFINT should work the same, given you also enable the TXFFIENA bit.

    Best regards,

    Omer Amir

  • Hello Omer,

    Thank you for your reply. About the TXFFINT: I read this as that I only need to set the TXFFIENA if I also want to generate an interrupt.  But according to my interpretation I can use the bit TXFFINT also without using a interrupt.

    The TXFFST consists of 5 bits. I would have to query for less than 1. With the TXFFINT I can query for equality. This should be a bit faster and more efficient, right?

    Best regards,

    Markus

  • Hello Markus,

    The TXFFST consists of 5 bits. I would have to query for less than 1. With the TXFFINT I can query for equality. This should be a bit faster and more efficient, right?

    This is not exactly correct, the logical check would be equivalent. This would be the same as saying 0xF & 0x0 is slower than 0b1 & 0b0; just because there are more bits doesn't necessarily mean it will take longer (it might take longer if you were comparing a number of bits larger than the assembly operation-equivalent). I've created some basic pseudo-code below:

    while(I2caRegs.I2CFFTX.TXFFST & 0xF);

    This is an easy check similar to how you checked other status bits before. You simple need to check when the transmit FIFO is empty, there is not a significant overhead to doing a bitwise AND operation.

    Best regards,

    Omer Amir

  • Hello Omer,

    I modified my Code. The test has not shown any error so far. However, it also came only sporadically before.

    int16 check_TXFFST_FIFO_status( Uint16 timeout )
    {
        int16 retval = 1;
        while ( I2caRegs.I2CFFTX.bit.TXFFST == 0 )
        {
            DELAY_US( 1 );
            timeout--;
            if ( timeout < 1 )
            {
                i2c_timeout_counter++;
                retval = -1;
                break;
            }
        }
        return retval;
    }

        /***************Write******************/
        I2caRegs.I2CSAR = slave_addr; 
        I2caRegs.I2CCNT = length; 
        I2caRegs.I2CDXR = I2CRegister;  
        I2caRegs.I2CDXR = Value;       
        retval |= check_TXFFST_FIFO_status ( I2C_TIMEOUT);
        if (retval < 0)
        {
            I2caRegs.I2CMDR.bit.IRS = 0;   // Timed out. Reset module.
            I2C_Errorrhandling();
            return retval;
        }
    
        // Send start as master transmitter
        I2caRegs.I2CMDR.all = 0x6E20; 
    

    ----

    Instead of using int16 check_TXFFST_FIFO_status( Uint16 timeout ) I also tested it with int16 check_TXFFINT_bit( Uint16 timeout ). Here also no error came so far.

    int16 check_TXFFINT_bit( Uint16 timeout )
    {
        int16 retval = 1;
        while ( I2caRegs.I2CFFTX.bit.TXFFINT == 0 )
        {
            DELAY_US( 1 );
            timeout--;
                break;
            }
        }
        I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;
        return retval;
    

    Do you see an advantage of one or the other function?

  • Hello Markus,

    They appear equivalent to me performance-wise. If you are really cautious about this, you can use the CCS cycle counter to see if there is any difference in how fast the functions can operate.

    Best regards,

    Omer Amir

  • Hello Omer,

    thank you for your assessment. I think the error is fixed with this. Thank you for your support.

    Best regards,

    Markus