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.

TMS320F28379D: How to send only control byte on I2C and detect ACK (have STOP)?

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Hi,

I develop a driver for eeprom 24LC01B. The end of writing data is detected by polling. For this purpose only control byte should be sent without data. The result of test is depending on ACK presence.

There are two cases:
1) when internal write to eeprom is unfinished - this case I can handle, I detect NACK properly and force to generate STOP on i2c,

2) when the write operation is completed - this is the problem:

     a. i2c does not generate STOP despite of ACK and empty data buffer,

     b. no ARDY is signalled, so I cannot detect it and force STOP

Due to software requirements I cannot use interrupts, so I check I2CSTR register periodically.
In this region of interest I have read following sequence of the register values:

  0:      start of i2c transmission,
~0:      0x410 (XSMT = transmit shift register empty, XRDY = transmit data ready)
39us:  end of ttransmission
44us:  ack 

no further activity on i2c lines

68us:   0x1010 ( BB = bus busy, XRDY)
101us: 0x0410 ( XSMT, XRDY)
164us: 0x1010
202us: 0x0410
...

I2c configuration

I use fifo for i2c transmission:
i2cregs->I2CFFTX.bit.I2CFFEN = 1;
i2cregs->I2CFFTX.bit.TXFFRST = 1;

Start of transmission:

i2cregs->I2CCNT = 0
no writes to fifo for this message
i2cregs->I2CMDR.all = I2CMDR_MST_MASK
    | I2CMDR_IRS_MASK
    | I2CMDR_TRX_MASK
    | I2CMDR_STT_MASK
    | I2CMDR_STP_MASK;

Why STOP condition nor ARDY are generated?

Regards,
Piotr Romaniuk

  • Hello Piotr,

    I tried comparing your code to one of the I2C examples we provide in C2000Ware and I noticed you set your count to 0, but I cannot tell if you are using repeat mode. If you're using the FIFO for I2C transmission without repeat mode, I believe your count mode should be set to the number of bytes that you want to transfer. You can follow along with this example to verify your configuration is correct, it should provide all the set up needed to run an I2C polling program with an EEPROM:

    C2000Ware_4_XX_XX_XX\driverlib\f2837xd\examples\cpu1\i2c (the example is called i2c_ex4_eeprom_polling)

    This example does use driverlib functions, but this should not impact the performance of your program. If you need help translating some of the functions to bitfields, let me know.

    Best regards,

    Omer Amir

  • Hi,

    I noticed you set your count to 0, but I cannot tell if you are using repeat mode

    No I am not using repeat mode. 

    If you're using the FIFO for I2C transmission without repeat mode, I believe your count mode should be set to the number of bytes that you want to transfer

    Can you confirm that using zero count is prohibitted by TI implementation of I2C? I need to be sure.
    For polling I don't want to send any data byte, only the status byte.

    You can follow along with this example to verify your configuration is correct, it should provide all the set up needed to run an I2C polling program with an EEPROM:

    C2000Ware_4_XX_XX_XX\driverlib\f2837xd\examples\cpu1\i2c (the example is called i2c_ex4_eeprom_polling)

    The example is to simple and is not usefull for me, not going into details I use tasks and multiple devices on the i2c bus. I need the information about the hardware behavior for correct implementation of its support. 

    I need to know:
    1) how to detect that i2c status word has been transmitted and ACK has been received,
    2) how to make STOP being generated on i2c

    Regards,
    Piotr Romaniuk

  • Hello Piotr,

    Can you confirm that using zero count is prohibitted by TI implementation of I2C? I need to be sure.
    For polling I don't want to send any data byte, only the status byte.

    I don't think I'm clear on what you mean, how does the status byte differ from a byte of data? Unless I'm mistaken, a byte you transmit using I2C is a byte of data. If you are transmitting some byte, you need to set the count value to however many bytes you're sending.

    how to detect that i2c status word has been transmitted and ACK has been received

    As you stated in your initial post, you can use NACK to do this. There are a few factors to keep in mind with this status bit, in that the NACK bit is cleared (an acknowledgement is received) whenever one of the following occurs:

    • An acknowledge bit (ACK) has been sent by the receiver
    • NACK is manually cleared. To clear this bit, write a 1 to it
    • The CPU reads the interrupt source register (I2CISRC) and the register contains the code for a NACK interrupt. Emulator reads of the I2CISRC do not affect this bit
    • The I2C module is reset

    However, the NACK bit is not cleared in the case where the I2C module performs a general call transfer; NACK remains 1, even if one or more slaves send acknowledgment. I'm not sure if this applies to your case or not.

    how to make STOP being generated on i2c

    The device manual states the following regarding the STOP bit in the I2CMDR register: "When in nonrepeat mode, at least one byte must be transferred before a stop condition can be generated." I will have to do some research to see if the count value is used to determine the stop condition in the architecture, but it might be quicker to just test whether setting the count value clears this bit; it might also be helpful to read the details on this register, as it contains more details on how it is used.

    Please let me know if you have more questions, or if something in the manual is not explained well.

    Best regards,

    Omer Amir

  • Hello,

    I don't think I'm clear on what you mean, how does the status byte differ from a byte of data?

    I used incorrect name of the byte. The first byte that is sent after START condition is called the control byte.
    It differs from data bytes:

    1. contains address of i2c device,
    2. contains direction of i2c transfer (read or write)
    3. is not passed by the fifo in microcontroller
    4. its value is built from registers that contains [1] and [2]
    "When in nonrepeat mode, at least one byte must be transferred before a stop condition can be generated."

    Please confirm that the bytes in this requirement exclude control byte.

    As you stated in your initial post, you can use NACK to do this

    I wish I could. When slave device sends ACK, NACK bit is in fact cleared, but I see no ARDY. 

    Let me rephrase the question:

    How to send ONLY the control byte on I2C and detect presence of ACK? (please see the eeprom documentation that I quoted at the begining)

    I need a reliable solution but I observe weird I2C module behavior.
    The software that I write is a part of an industrial energetic device that is sold in 1K/month. No issues are accepted. 

    Regards,
    Piotr Romaniuk

  • Hello Piotr,

    Please confirm that the bytes in this requirement exclude control byte

    I have confirmed this with another expert, you do need to make sure the I2CCNT is set to 1 to send the control byte, and it is possible to just send the control byte by itself in doing this. Let me know if this still does not work for you.

    Best regards,

    Omer Amir

  • Hi,

    I have confirmed this with another expert, you do need to make sure the I2CCNT is set to 1 to send the control byte, and it is possible to just send the control byte by itself in doing this.

    When I wrote I2CCNT=1 and something to tx fifo, that value is transmitted after the control byte (the case when eeprom sends ACK). 

    This is not the solution. 

    Regards,
    Piotr Romaniuk

  • Hello Piotr,

    Just to confirm, you are setting I2CCNT to 1, setting the target address, and populating the FIFO with your control byte, and then after this setting the START and STOP bit in I2CMDR (can be set simultaneously), correct? If you do this in non repeat mode, it should just be sending just this, including the R/W bit.

    Best regards,

    Omer Amir

  • Just to confirm, you are setting I2CCNT to 1, setting the target address, and populating the FIFO with your control byte, and then after this setting the START and STOP bit in I2CMDR (can be set simultaneously), correct?

    Not exactly. I never write control byte to fifo - it is built by hardware from the target address and direction bit.

    Regards,

    Piotr Romnaiuk

  • Piotr,

    Is your control byte = target address + direction bit?

    Regards,

    Manoj

  • Piotr,

    If you wish to get START condition + Transmit target (slave) address + R / W bit (control byte) + STOP condition, then you cannot use non-repeat mode. You have to use repeat mode. Here is the pseudo code:

    1) Configure I2C is send mode + repeat mode

    2) Configure I2C target (slave) address

    3) Generate START condition

    4) Wait for Register Access Ready bit to be set

    5) Generate STOP condition

    Regards,

    Manoj

  • Hi Manoj,

    I would like to avoid repeat mode, I am afraid that I don't have control how frequently the control bytes are transmitted.
    This is a limitation of the i2c module hardware implementation.

    Thank you anyway for clarification.

    Regards,
    Piotr Romaniuk