AnsweredAssumed Answered

adsp-21469 I2C c code example and problem?

Question asked by misterdsp on Nov 17, 2011
Latest reply on Dec 13, 2011 by Mitesh

See anything wrong with this test code? It gets stuck in state TWI_TXWHILE1 on the first write attempt. I only have one board to test the code on and one I2C device on the board to address. I can't tell if the c code is bad or if there is a problem with the slave I2C device. The test code tries to write data 0x43 to register address 0x00 at device address 0x24. The I2C handler is written as a state machine and is non blocking. I can set the TWISDAOVR and TWISCLOVR bits and the I2C lines do go low.

 

 


// TWI clock = 10MHz / 100 = 100KHz
#define TWICLKHI 50
#define TWICLKLO 50

enum TWISTATE
{
  TWI_IDLE           = 0,  /**< TWI is idle. */
  TWI_TXWHILE1       = 1,  /**< TWI address sent, wait for Ack. */
  TWI_TXDATA         = 2,  /**< TWI sending data byte. */
  TWI_TXWHILE2       = 3,  /**< TWI data sent, wait for Ack. */
  TWI_TXEXIT         = 4,  /**< TWI all data sent, wait for completion. */
  TWI_RXWHILE1       = 5,  /**< TWI address sent, wait for Ack. */
  TWI_RXDATA         = 6   /**< TWI data received, wait for Ack. */
};
typedef enum TWISTATE TWISTATE;

unsigned char    TWI_Buffer[256];
unsigned char *  TWI_Data;
TWISTATE         TWI_State;
int              TWI_bytes;

void TWI_Init(void);
void TWI_Xx(unsigned char ** data, int * nbytes);

void main()
{
  TWI_State = TWI_IDLE;
  TWI_Init();

  while(1)
  {
    if(TWI_State == TWI_IDLE)
    {
      /* Load I2C tx command */
      TWI_Data    = TWI_Buffer;
      TWI_Data[0] = 0x24;
      TWI_Data[1] = 0x00;
      TWI_Data[2] = 0x43;
      TWI_bytes   = 2;
    }
    /* Service the TWI I2C port. */
    TWI_Xx(&TWI_Data, &TWI_bytes);
  }
}

void TWI_Init(void)
{
    *pTWIDIV = (TWICLKHI << 8) | TWICLKLO;
    // Pclk = 225MHz clock -> 10MHz reference
    *pTWIMITR = TWIEN | 0x17;
}

void TWI_Xx(unsigned char ** data, int * nbytes)
{
  switch(TWI_State)
  {
    default:
    case TWI_IDLE:
    {
      /* Wait for a non zero I2C address. */
      if(**data != 0)
      {
        twi_count++;

        *pTWIFIFOCTL = 0;
        // write address
        *pTWIMADDR = (**data)>>1;

        /* Tx or Rx? */
        if((**data)&1)
        {
          /**********/
          /*** RX ***/
          /**********/
          (*data)++;
          // data must be available when turning TWI on
          *pTXTWI8 = **data;
          (*data)++;
          // enable tx transfer, 1 byte, repeated start
          *pTWIMCTL = TWIMEN | (1<<6) | TWIRSTART;
          TWI_State = TWI_RXWHILE1;
        }
        else
        {
          /**********/
          /*** TX ***/
          /**********/
          (*data)++;
          // data must be available when turning TWI on
          *pTXTWI8 = **data;
          (*data)++;
          // enable tx transfer
          *pTWIMCTL = TWIMEN | ((*nbytes)<<6);
          TWI_State = TWI_TXWHILE1;
        }
      }
      break;
    }
    case TWI_TXWHILE1:
    {
      if(!(*pTWIFIFOSTAT & TWITXS)) TWI_State = TWI_TXDATA;
      break;
    }
    case TWI_TXDATA:
    {
      if(*nbytes>0)
      {
        *pTXTWI8 = **data;
        (*data)++;
        (*nbytes)--;
        TWI_State = TWI_TXWHILE2;
      }
      else
      {
        TWI_State = TWI_TXEXIT;
      }
      break;
    }
    case TWI_TXWHILE2:
    {
      if(!(*pTWIFIFOSTAT & TWITXS)) TWI_State = TWI_TXDATA;
      break;
    }
    case TWI_TXEXIT:
    {
      if(!(*pTWIMSTAT & TWIMPROG)) TWI_State = TWI_IDLE;
      break;
    }
    case TWI_RXWHILE1:
    {
      if(!(*pTWIFIFOSTAT & TWITXS))
      {
        // enable rx transfer
        *pTWIMCTL = TWIMEN | (*nbytes<<6) | TWIMDIR;
        TWI_State = TWI_RXDATA;
      }
      break;
    }
    case TWI_RXDATA:
    {
     if(*nbytes>0)
      {
        if(!(*pTWIFIFOSTAT & TWIRXS))
        {
          **data = *pRXTWI8;
          (*data)++;
          (*nbytes)--;
        }
      }
     else
      {
        TWI_State = TWI_IDLE;
      }
      break;
    }
  }
}

 

Outcomes