Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

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.

OMAP-L138 I2C controller problem ??

Other Parts Discussed in Thread: OMAP-L138

OMAP-L138 I2C controller problem ??

We optimized software for the OMAP-L138:
 - Speed 456Mhz,
 - Code and Data Cache enable.
 - Compiler optimized -O2

We have a I2C problem since we speed up the hardware over 300Mhz.
It seems that we are too fast for the controller.
A STOP interrupt doesn't correspond to it's internal idle state.

The starterware functions say:
I2CMasterIsBusy = idle
I2CMasterBusBusy = idle
But that seems to be wrong.

Internally the controller still seems to be busy (probably with the stop sequence).
An immediate next transfer will fail.

We found a solution which helps !
We can poll I2C_CON for Bits 10 and 11.
Only if these two bits are zero, the controller is really ready for a new transfer.

I posted the function below.
The maximum loop i saw till now was 10 hardware register reads.

What we do is undocumented !
Can somebody explain me what happens !!!!!!



 
//============================================================================
// Function   : I2cDelay
// Description: In case of 456MHz we seen to have a i2c hardware problem.
//              We have to poll until controller has finished something.
//============================================================================
static void I2cDelay(unsigned int instanceNum)
{
  int loops;
  Boolean b1,b2;

  #define I2C_CON       (0xA4)     /* */
  #define I2C_CON_STB    (1 << 11)  /* Start byte mode (master mode only) */
  #define I2C_CON_MST    (1 << 10)  /* Master/slave mode */

  b1 = I2CMasterIsBusy(i2c[instanceNum].regBaseAddr);
  b2 = I2CMasterBusBusy(i2c[instanceNum].regBaseAddr);
  for (loops=0; loops<100; loops++) {
    if ( (HWREG(i2c[instanceNum].regBaseAddr + I2C_CON) & (I2C_CON_STB|I2C_CON_MST)) == 0)
        break;
  }
  if (loops > 0) {
      LogPrintf(LOG_ERROR, "I2c needed loops = %d, (%d,%d)", loops, b1, b2);
  }
}


Output of log function:
I2c needed loops = 4, (0,0)
I2c needed loops = 2, (0,0)
I2c needed loops = 7, (0,0)
I2c needed loops = 2, (0,0)
I2c needed loops = 2, (0,0)
I2c needed loops = 1, (0,0)
I2c needed loops = 2, (0,0)
I2c needed loops = 3, (0,0)
I2c needed loops = 3, (0,0)
I2c needed loops = 1, (0,0)
I2c needed loops = 1, (0,0)
I2c needed loops = 6, (0,0)
I2c needed loops = 1, (0,0)
I2c needed loops = 7, (0,0)
I2c needed loops = 5, (0,0)
I2c needed loops = 4, (0,0)
I2c needed loops = 3, (0,0)
I2c needed loops = 3, (0,0)
I2c needed loops = 2, (0,0)
I2c needed loops = 1, (0,0)
I2c needed loops = 1, (0,0)
I2c needed loops = 4, (0,0)
I2c needed loops = 4, (0,0)