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.

28335 I2C and NACK issues

Hi,

I'm having a bit of trouble with the I2C port on a 28335. The port is connected to a single EEPROM, so the 28335 is master, EEPROM is slave.  I'm currently running the code out of RAM using an XDS560v2 emulator, CCS5.2.1.00018.

I can successfully read and write to the EEPROM, and everything works fine until I try and use acknowledgement polling to check for the write completed.

As soon as the EEPROM doesn't reply, I receive a NACK (because it's busy writing, so I'd expect this), but the SCL line is driven low by the 28335.  This feature doesn't seem to be described in the reference guide (SPRUG03B), but I did find reference to it on the I2C Tips Wiki (http://processors.wiki.ti.com/index.php/I2C_Tips#User_Response_to_a_NACK), so I try and recover the situation by sending a stop bit, as suggested.

This is where the problem arises - it just doesn't seem to work, and the SCL line refuses to go high again.  The only way I seem to be able to get the SCL to go high again is to reset the I2C module, but then successive reads or writes don't work properly because the I2C module thinks that the bus is busy, or still waiting for a stop bit.  If I do a full device reset, I can then use the I2C again, but obviously this isn't a real solution!

Does anyone have any idea what's going on?

Thanks in advance,

Regards,

Simon

  • Hi Simon,

    Have a look at this post and see if Trey's solution is useful: http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/138541.aspx

  • Hi Vishal,

    Thanks for the info - unfortunately, this didn't directly relate to the problem I'm having, but it got me thinking and doing some more tests, and I think I've fixed it, so thanks for the memory jog...

    What I've found is that when I'm doing the acknowledgement polling, I need to only wait for ARDY to be set (rather than XRDY as well), and then I must reset the NACK bit (by writing a 1 to it).  The reference manual seems to indicate that the NACK bit will be automatically reset by the next ACK which comes along (so I wasn't resetting it), but I've found that this isn't the case, and if you don't manually reset then the I2C will never see the ACK when it appears.

    The other thing I think I've found relates to the setting of the ARDY bit - the reference manual indicates that, in repeat mode (RM=1), ARDY is set at the end of each byte transmitting from I2CDXR, but it seems as if it's actually set once the data has been shifted out of the I2CXSR.

    My reasoning for this is as follows - part of my code for the ACK POLL looks like this: 

    // Wait for ARDY bit to be set.
    while (I2CaRegs.I2CSTR.bit.ARDY == 0u)
    {
        ;
    }
    // If NACK bit is set then reset it by writing a '1' to it.
    if (I2CaRegs.I2CSTR.bit.NACK == 1u)
    {
        I2caRegs.I2CSTR.bit.NACK = 1u;
    } 

     So, if the ARDY bit was set once the data had left the I2CDXR register (but was still in the shift register), the NACK bit wouldn't have been clocked in yet, so it would never show up as being set, but the above seems to work, which suggests that ARDY is set once the data has been shifted into the slave device.

    Is my reasoning valid?  Can you confirm when the ARDY bit is actually set in the 28335, please?

    Best Regards,

    Simon

  • Hi Simon,

    Your reasoning is sound. ARDY should be set in the event that everything in I2CXSR is transmitted out on the line and either an ACK/NACK is received otherwise you run the risk of the user overwriting the data in the I2CDXR prior to receiving the acknowledgement for the previous data.

  • Simon,

    I am working on a project requiring the reading and writing to an eeprom using I2C without the use of interrupts.

    Does your code use ISR's ? Or do you simply check for busy bits on the I2C bus during reading and writing?

    -Chuck

  • Thanks, Vishal.  Good to know that I haven't gone completely mad over the last week or so! :-)

  • Chuck,

    I'm not using ISR's - 'just' checking for the ACK \ NACK bit, and using acknowledgement polling to check for the write completed.

    Simon

  • Simon,

    Could you post your code? I would appreciate to see how you write to eeprom without an ISR.

    Thank you,

    -Chuck

  • Chuck,

    I'm afraid I can't do that - the code police would take me away if I released any of our source code into the wild!

    When I'm writing to the eeprom, I transmit the data by setting up the slave address, number of bytes to transmit (remember to add 1 because you're sending the address as well) and the device address, then setting up the I2CMDR register with my required config (generate start and stop, module is master transmitter, non-repeat mode).  I then wait for the initial data to be transmitted (by polling for the XRDY and ARDY bits) and then loop round sending the rest of the data (writing to the I2CDXR register and then polling XRDY and ARDY).

    The gotcha which caught me out was the subject of this post - if the eeprom didn't ACK, the code got stuck, and I found I had to check for the NACK bit and then write a 1 into it to reset it and get correct operation.

    Hope this helps,

    Cheers,

    Simon