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.

TIVA TM4C1294XL I2C question reading a 2 byte register.

Other Parts Discussed in Thread: TMP006

I am working with a Tiva eval board TM4C1294XL using TIRTOS version 2.14.0.10 and CCS 6.1.1. I am evaluating the Tiva CPU as a replacement for the Stallaris CPU I have used in the past so I have got this temperature device to work in the past. I ran into a question regarding I2C. I have an I2C temperature sensor MCP9808 hooked up to the eval board on the Tiva I2C0 interface. As a test, I am reading the manufacture ID from the temperature sensor and the ID is a 2 byte register. The data sheet on the temp sensor is:

http://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf

The problem is I have not been able to read the 2 byte data from the temp sensor reliably and I think it has to do with how the function I2CMasterControl() is used when I read 2 bytes from the temperature sensor.

If I use I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); then read the first byte and then do I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); and then read the second byte, a scope with a I2C module shows that sometimes the temp sensor will send two bytes but mostly the scope will only show 1 byte. When 2 bytes are sent the data is read correctly but the two bytes are not always sent so it’s unreliable.

If I use I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); and read the first byte and then use I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); and read the second byte then do the I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); the scope with the I2C always shows the temperature sensor sending 2 bytes data I read is inconstant.

In general if I want to read a 2 byte register shouldn’t I use I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); and read the first byte and then the I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); and then read the last byte? I assume the burst is used for more than one byte but that assumption may not be correct.

Note, in each case after the is I2CMasterControl() done, I poll the busy and also check for errors using the following:

 

 

       i2ctmo = 0;

       while(I2CMasterBusy(I2C0_BASE))

       {

              i2ctmo++;

              if(i2ctmo > I2CTIMEOUT)

              {

                     return 1;

              }

       }

 

       errorStatus = I2CMasterErr(I2C0_BASE);

       if (errorStatus != I2C_MASTER_ERR_NONE)

       {

              return 1;

       }

//now read the data

dataRead = (unsigned char) ROM_I2CMasterDataGet( I2C0_BASE );

  • Hello Doug,

    Have you tried increasing your I2C timeout counter? Or, better yet, try disabling this for now. Also I would recommend you simplify and not worrying too much about the error checking and timeout until you have robust communications between the master and slave. However, the methods you describe should be fine. You can have a look at this post to see a coding example where they are reading 4 bytes which should be applicable to what you are doing with 2 bytes.

    e2e.ti.com/.../389348

    Note the issue they found with the call to I2CMasterBusy instead of I2CMasterBusBusy in their original code posted.
  • I am using I2CMasterBusy() and not I2CMasterBusBusy() as noted in the link to the other post.  

    I am thinking the problem is the caused by the errata on the CPU we have. 

    Doug

  • Hi Doug,

    Sorry didn't mean to imply that you were using the wrong function call. Was intending to point out that the code in the other post was using the wrong function call.

    Which errata are you referring to?

    Also note that the I2C on the prior Stellaris devices is very similar to the current device so your code may port if you have any.
  • Hi Doug,

    I see that you are using TI-RTOS, have you looked at any of the I2C examples in Resource Explorer-> TI-RTOS for TivaC-><your device>->Driver Examples->I2C? We have an example that show communication with a TMP006 temperature sensor.

    Todd

  • I have used the I2C on two different projects with Stellaris without problems.  I looked at what I did on the other projects and also the new Tiva examples that are polled and as far as I can tell the code I have looks right.  I think the problem is the errata on the Tiva part.

    See page 44:

    http://www.ti.com/lit/er/spmz850d/spmz850d.pdf

    The answer looks like based on the errata and talking to a local TI support that I need to use the interrupts and not use the poll method. 

    Doug

  • Hi Doug,

    Reviewing the errata, I agree that this could be the cause of the intermittent fails on the second byte. Hopefully, using an interrupt based approach will not cause an issue for you.

  • A workaround that seems to be working is replace the following lines typically done in polling:

    ROM_I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);

    while (ROM_I2CMasterBusy( I2C0_MASTER_BASE ))

    with a call to a new function that wraps those two line and actually will wait till the transfer is complete. 

    The function masterControll() will return 0 if there was no timeout and non zero if there was a timeout.   Also, the function masterControll() takes the same arguments as I2CMasterControl() so it makes it easy to change to this and when/if the errata is ever fixed, the code change can be done in one spot inside I2CMasterControl().  

    Based on the errata, is this a sold fix if we want to use polling for a CPU with the I2C problem?  Testing seems to indicate it's solid.

    Doug

    #define    I2CTIMEOUT    (0xFFFFF)

    unsigned long masterControll(unsigned int ui32Base, unsigned long controllValue)
    {
        long i2ctmo;

        I2CMasterIntClearEx(ui32Base, I2C_MASTER_INT_NACK|I2C_MASTER_INT_DATA); // always clear the IRQ here !!!
        ROM_I2CMasterControl(ui32Base, controllValue);

        i2ctmo=0;
        while ( !(I2CMasterIntStatusEx(I2C0_BASE, false) & I2C_MASTER_INT_DATA) )
        {
            i2ctmo++;
            if(i2ctmo > I2CTIMEOUT)
            {
                return 1;
            }
        }

        i2ctmo=0;
        while (ROM_I2CMasterBusy( I2C0_BASE ))
        {
            i2ctmo++;
            if(i2ctmo > I2CTIMEOUT)
            {
                return 1;
            }
        }
        return 0;
    } // end unsigned long masterControll(unsigned int *ui32Base, unsigned long controllValue)

  • Doug,

    The errata states that if the I2CMCS is read on the same system clock as the setting of the ADR and DATA NAK error bits, then the read will return an ACK and no error flags will be set. This has nothing to do with the busy bit and the transmission completion. The only validated work around is to use the interrupt method instead of polling. Your solution moves the polling and therefore changes the timing which may have impacted the occurrence factor but does not solve the basic issue of the errata. If the timing changes with the slave such that there is some clock stretching or slight differences in the setup and hold timing of the silicon (master or slave), the issue may pop back up. This is why the recommendation remains to use the interrupt method.

    However, if you are comfortable with your testing and certain that the issue will not become an issue, then feel free to implement how you want. If you choose to do it this way, TI cannot not endorse the methodology you are using based on the errata. The choice is completely up to you.