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.

Can't get L138 I2C repeated starts to work

Hi all

I need to perform a read from a slave device where I first send the device address and subaddress as a write then a repeated start to read in the data.

The write works OK and the clock line stays low because set_stop is not set, but the repeated start doesn't happen. There is no activity on the clock or data line.

I'm calling I2C_write followed by I2C_read:

Both work fine individually. For this case, both set_stop and chk_busy are set to 0.

 

Any ideas??

Thanks,

Clive

 

uint32_t I2C_write(i2c_regs_t *i2c, uint16_t in_addr, uint8_t *src_buffer, uint16_t in_length, uint8_t set_stop)
{
uint32_t rtn
= ERR_INVALID_PARAMETER;

if ((i2c != NULL) && (src_buffer != NULL))
{
uint16_t i;

// wait for bus to be clear.
WAIT_WITH_TIMEOUT(CHKBIT(i2c->ICSTR, BB), I2C_TIMEOUT_COUNT);

// set byte count and slave address.
i2c->ICCNT = in_length;
i2c
->ICSAR = in_addr;

// configure i2c for master transmit mode and release from reset.
i2c->ICMDR = STT | MST | ICMDR_FREE | TRX | IRS;

// transmit data one byte at a time.
for (i = 0; i < in_length; i++)
{
i2c
->ICDXR = src_buffer[i];

// wait for data to be copied to shift register.
WAIT_WITH_TIMEOUT(!CHKBIT(i2c->ICSTR, ICXRDY), I2C_TIMEOUT_COUNT);
}

// send stop condition...we may want to skip this depending on which
// device we are talking to. see device datasheets for more info.
if (set_stop)
SETBIT(i2c
->ICMDR, STP);

rtn
= ERR_NO_ERROR;
}

return (rtn);

}

 

uint32_t I2C_read(i2c_regs_t *i2c, uint16_t in_addr, uint8_t *dest_buffer, uint16_t in_length, uint8_t chk_busy)

 

{
uint32_t rtn
= ERR_INVALID_PARAMETER;

if ((i2c != NULL) && (dest_buffer != NULL))
{
uint16_t i;

// wait for bus to be clear...we may want to skip this depending on which
// device we are talking to. see device datasheets for more info.
if (chk_busy)
WAIT_WITH_TIMEOUT(CHKBIT(i2c
->ICSTR, BB), I2C_TIMEOUT_COUNT);

// set byte count and slave address.
i2c->ICCNT = in_length;
i2c
->ICSAR = in_addr;

// configure i2c for master receive mode and release from reset.
i2c->ICMDR = STT | MST CMDR_FREE | IRS;
// receive data one byte at a time.
for (i = 0; i < in_length; i++)
{
// do not want to send an ack on last byte.
if (i == (in_length - 1))
{
SETBIT(i2c
->ICMDR, NACKMOD);
}

// wait for data to be received.
WAIT_WITH_TIMEOUT(!CHKBIT(i2c->ICSTR, ICRRDY), I2C_TIMEOUT_COUNT);

dest_buffer[i]
= i2c->ICDRR;
}

// send stop condition.
SETBIT(i2c->ICMDR, STP);

rtn
= ERR_NO_ERROR;
}

return (rtn);
}

 

 

  • After you finish the write portion you must first poll for ARDY before you issue the repeat start for the read.  You can find this info and some other tips here:

    http://processors.wiki.ti.com/index.php/I2C_Tips#Repeated_Start

  • Thanks for that Brad.

    Some useful information in there.

    Unfortunately waiting for ARDY didn't help. I also remember previously I had tried a 1mS delay between write and read and that hadn't make a difference.

    I am somewhat confused reading  SPRUFL9D where on page 26 if the BB bus busy bit is set then a start generates a restart, but on page 28, the AL arbitration lost bit is set if the I2C sends a start and the bus is busy, and this causes the I2C to go to slave receiver...

    Regards

    Clive

     

     

     

     

  • Clive Nicoll said:

    I am somewhat confused reading  SPRUFL9D where on page 26 if the BB bus busy bit is set then a start generates a restart, but on page 28, the AL arbitration lost bit is set if the I2C sends a start and the bus is busy, and this causes the I2C to go to slave receiver...

    BB is when activity is already present on the bus before we even try doing a transfer. AL is when everything is clean to begin but in the midst of sending a slave address we suddenly realize that someone else was also sending a slave address.

     

    Clive Nicoll said:

    Unfortunately waiting for ARDY didn't help. I also remember previously I had tried a 1mS delay between write and read and that hadn't make a difference.

    Hmm, maybe dump some registers at various points in the transfer to see if we can spot something wrong.  I assume you are NOT checking for bus busy when calling the read routine.  It will still be "busy" since you never terminated the write.

    On a related note, it's not necessary to change NACKMOD for the master receiver case.  It will automatically NACK the last byte.

     

  • hi clive

    are you fixed up on this now?