cancel
Showing results for 
Search instead for 
Did you mean: 

I2C TCR flag

andy_long
Associate III

hi,

The datasheet says "In this mode, the TCR flag is set when the number of bytes programmed in NBYTES is transferred"

Does this mean that the flag will be set when the data is transferred from TXDR to shift register, Or, the flag will be only set if there is an ack from the slave after the data in the TXDR is sent ? 

 

    /* Send Memory Address */
    hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);

 

I get a timeout randomly here in function I2C_RequestMemoryWrite(). Please note that no ErrorCode is set other than HAL_I2C_ERROR_TIMEOUT.

 

  /* Wait until TCR flag is set */
  if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK)
  {

 

Why does it take more than 25ms (default timeout) for a single byte to be transferred ? 
 
PS It does work if increase the timeout.
1 ACCEPTED SOLUTION

Accepted Solutions

Hi @waclawek.jan 

I identified that the problem is due to the context switching happening before the I2C_WaitOnFlagUntilTimeout() . I was using an old version of HAL and it did not have an additional check for the flag after the timeout.

Thank you for your support.

View solution in original post

6 REPLIES 6

Show waveforms; perhaps with added track where a GPIO pin would be toggled around critical points of the code.

JW

> This is only reproducible if it is run continuously for an hour.

I presume this does not run in an isolated environment. Can't there be some interrupt or similar process holding up execution for 25ms?

For sake of debugging, you can try e.g. to drastically increase number of I2C transactions, if possible, to decrease the time waiting for the error to occur.

> Meanwhile, could you please answer the first part of the question ?

Sure; unfortunately the answer is "I don't know" (that's why I avoided answering it before...).

There may be other scenarios, too: TCR may be set even before any of those events, at the moment when the last byte is written into TXDR.

JW

Thank you for your reply @waclawek.jan 

>>Can't there be some interrupt or similar process holding up execution for 25ms?

Good question. See the below snapshots: 

I am recording 3 timestamps startTime1, startTime2, & startTime3 (Line 4, 12, and 35), and this is being printed out in line 40 when there is an error. From the output, it can be seen that you have 23 ms after copying the MemAddress to the TXDR. So, does it really matter if an interrupt happens after line 35 as we have already loaded TXDR and have 23 ms remaining ? Does not the I2C activity beyond this point happen independent of the interrupts ?

static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
                                                uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)
{
  u32 startTime1 = HAL_GetTick();
  I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);

  /* Wait until TXIS flag is set */
  if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
  {
    return HAL_ERROR;
  }
  u32 startTime2 = HAL_GetTick();

  /* If Memory address size is 8Bit */
  if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
  {
    /* Send Memory Address */
    hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
  }
  /* If Memory address size is 16Bit */
  else
  {
    /* Send MSB of Memory Address */
    hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);

    /* Wait until TXIS flag is set */
    if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
    {
      return HAL_ERROR;
    }

    /* Send LSB of Memory Address */
    hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
  }
  u32 startTime3 = HAL_GetTick();

  /* Wait until TCR flag is set */
  if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK)
  {
    printf("I2C_WaitOnFlagUntil- timeout: %d, tickstart: %d", Timeout, Tickstart);
    printf("startTime1: %d, startTime2: %d, startTime3: %d ", startTime1, startTime2, startTime3);

andy_long_0-1712829970337.png

I will look into the other points you mentioned and I will get back to you.

 

I looked at I2C_WaitOnFlagUntilTimeout() and  indeed I can't quite see why would return with the timeout error code - except for the transmission genuinely lasting too long (slave stretching clock?)

Looking forward to the waveforms.

JW

Hi @waclawek.jan 

I identified that the problem is due to the context switching happening before the I2C_WaitOnFlagUntilTimeout() . I was using an old version of HAL and it did not have an additional check for the flag after the timeout.

Thank you for your support.

Thanks for coming back with the solution. Please click on "Accept as solution" in that post so that the thread is marked as solved.

JW