This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

I2C start continues to fail

Hi everyone,

First off I would like to thank those who have taken the time to read this post.

My environment
Windows XP
uVision 3
Keil MCB2300 with NXP LPC2386

Goal
Read a temperature sensor

Physical Setup
I have pins 24 and 25 exposed on my Dev board ( just some male headers ) which is I2C Bus 0. Also the appropriate pins are connected to a device with some I2C devices on it.

I am going to display code in the order in which it is executed for simplicity. There is also some defines which I will display too.

Even though documentation and startup code state that all registers are initialized to 0, I do it also.

There are other PINSEL and FIO0DIR registers set, but I believe it is irrelevant.

PINSEL0 &= 0x00000000;
PINSEL1 &= 0x00000000;

FIO0DIR |= 0x407E8B00; //pins [9:8], 11, 15, [22:17], 30 are ouputs

This function is used to setup I2C. I am showing it all just in case I have overlooked something.

uint8 I2CInit( )
{

    PCONP |= (1 << 7);            /*Enable PCI2C0 interface 0 power/clock control bit */
    PINSEL1 |= 0x01400000;      /* set P0.27 and P0.28 to I2C0 SDA and SCK */

    PCONP |= (1 << 19);           /*Enable PCI2C1 interface 1 power/clock control bit */
    PINSEL0 |= 0x0000000F;      /* set P0.00 and P0.01 to I2C1 SDA and SCK */

    PCONP |= (1 << 26);       /*Enable PCI2C2 interface 2 power/clock control bit */
    PINSEL0 &= ~0x00F00000;
    PINSEL0 |= 0x00A00000;      /* set P0.10 and P0.11 to I2C2 SDA and SCK */

    /*--- Clear flags ---*/
    I20CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
    I21CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
  //I22CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;

    /*--- Reset registers ---*/
    I20SCLL   = I2SCLL_SCLL;
    I20SCLH   = I2SCLH_SCLH;
    I21SCLL   = I2SCLL_SCLL;
    I21SCLH   = I2SCLH_SCLH;

    if ( install_irq( I2C0_INT, (void *)I2C0MasterHandler, HIGHEST_PRIORITY ) == FALSE )
    {
                return FAIL;
    }
    if ( install_irq( I2C1_INT, (void *)I2C1MasterHandler, HIGHEST_PRIORITY ) == FALSE )
    {
                return FAIL;
    }

        I20CONSET = I2CONSET_I2EN;
        I21CONSET = I2CONSET_I2EN;
        return SUCCESS;
}

At this point everything should be initiated and ready to go

The function below gets called when we want to read an I2C device that requires a write first.

addr = Address of I2C device sz = Size of response offset = The register inside of the device I want to read buff = The buffer that gets passed here contains storage for the response of the read bus = Specify which bus the I2C device is connected to

int write_readI2C(uint8 addr, uint8 sz, uint8 offset, uint8 *buff, uint8 bus)
{
  uint8 i;
  uint16 stat;

  /* shift address to bits 7-1; bit 0 is R/W */
  I2CMasterBuffer[0] = addr<<1;

  /* write 2 size: I2C address + offset to read */
  I2CWrLength = 2;
  I2CMasterBuffer[1] = offset;

  /* now load read command */
  I2CMasterBuffer[2] = addr<<1 | RD_BIT;
  I2CRdLength = sz;

  stat = I2CEngine(bus);
  if (stat)
    return stat;

  if (RdIndex == 0) //no data was read
        return FAIL; //(I2C_ERR_MASK | RD_ERR);
  for ( i = 0; i < sz; i++ )
    buff[i] = I2CMasterBuffer[i+3];

  return stat;
}

The line
stat = I2CEngine(bus);
above is the function stated below

uint8 I2CEngine( BYTE bus )
{
  DWORD timeout = 0;

  I2CMasterState = I2C_IDLE;
  RdIndex = 0;
  WrIndex = 0;

  I2CStop(bus);
  if (I2CStart(bus) != SUCCESS)
  {
    I2CStop(bus);
    return FAIL;
  }

  while ( 1 )
  {
    if ( I2CMasterState == I2C_STOP) //DATA_NACK
    {
          I2CStop(bus);
          break;
    }
    if ( timeout >= MAX_TIMEOUT )
          return FAIL;

    timeout++;
  }

  return SUCCESS;
}

The statement
if (I2CStart(bus) != SUCCESS)
above is where the error occurs

#define MAX_TIMEOUT             0x00008FFF

uint8 I2CStart( uint8 bus )
{
    uint32 timeout = 0;
    uint8 returnValue = FAIL;

        if (bus == 1)
      I21CONSET = I2CONSET_STA; /* Set Start flag */
        else if (bus == 0)
      I20CONSET = I2CONSET_STA; /* Set Start flag */

    /*--- Wait until START transmitted ---*/
    while( 1 )
    {
        if (I2CMasterState == I2C_STARTED)
        {
              returnValue = SUCCESS;
              break;
        }

        if ( timeout >= MAX_TIMEOUT ) 
        {
            returnValue = FAIL;
            break;
        }
          timeout++;
    }
    return( returnValue );
}

The statement
if ( timeout >= MAX_TIMEOUT )
above is where the program takes me if I set a breakpoint inside the IF statement.

I was going to post my I2C0MasterHandler IRQ but this post is getting long.

0