cancel
Showing results for 
Search instead for 
Did you mean: 

Since STM32Cube_FW_F7_V1.17.0 the HAL I2C Functions do not work the same. For a huge project that used to work with no issues on STM32Cube_FW_F7_V1.16.2 the I2C Data line goes low and the Firmware reports an HAL_I2C_ERROR_SIZE. Is there a known bug?

AMarc.4.33
Associate II

We are using a STM32F76ZI for a consumer device.

The Firmware used to work fine with no errors.

Since STM32Cube_FW_F7_V1.17.0 the I2C communication does not work all the time reporting random I2C Errors. The most common error is HAL_I2C_ERROR_SIZE that never occurred when using STM32Cube_FW_F7_V1.16.2.

I am trying to find out what is triggering this error to then write a small example so that it can be fixed.

The CLK line remains high and the DATA line goes low when the I2C communication stops working. The errror reported by HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) is almost always HAL_I2C_ERROR_SIZE.

If u already know about the issue let me know so i don't waste time on it.

My solution, for now, is to keep the project on STM32Cube_FW_F7_V1.16.2.

6 REPLIES 6
Bob S
Principal

I haven't used F7 1.17.0 yet. You have the source for both versions. Run a compare and see what changed, specifically in the functions that you use. Typically that error means the transfer ended before the expected number of bytes were sent (in master mode). At a quick glance most of the changes seem related to master mode mem read/write IT and DMA functions, with smaller changes in the slave mode functions.

But yeah, stick with 1.16.2 if it works for you. Though I wonder what issue(s) the 1.17.0 changes are trying to address.

AMarc.4.33
Associate II

The problem seems to be in static HAL_StatusTypeDef I2C_Mem_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources)

....

 else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TCR) != RESET) && \

          (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))

 {

   if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))

   {

     if (hi2c->XferCount > MAX_NBYTE_SIZE)

     {

       hi2c->XferSize = MAX_NBYTE_SIZE;

       I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,

                          I2C_RELOAD_MODE, I2C_NO_STARTSTOP);

     }

     else

     {

       hi2c->XferSize = hi2c->XferCount;

       I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,

                          I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);

     }

   }

   else

   {

     /* Wrong size Status regarding TCR flag event */

     /* Call the corresponding callback to inform upper layer of End of Transfer */

     I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE); //!! < this is the trigger hi2c->XferSize = 2; hi2c->XferCount = 1

   }

 }

......

AMarc.4.33
Associate II

It seems that all transfers above #define MAX_NBYTE_SIZE  255U Bytes do not work anymore.

The transfer functions take uint16_t Size. So they sould function with longer buffers.

That explains the random errors. The transfer sizes are not constant at runtime.

AMarc.4.33
Associate II

Could be a lock and interrupt problem.

I found __HAL_UNLOCK(hi2c) with missing __HAL_LOCK(hi2c) in:

static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)

static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)

static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)

Hope it helps to narrow out the issue.

AMarc.4.33
Associate II

Found more locking problems:

The following Functions work on but do not do not lock hi2c:

  • HAL_StatusTypeDef HAL_I2C_RegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID, pI2C_CallbackTypeDef pCallback)
  • HAL_StatusTypeDef HAL_I2C_UnRegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID)
  • HAL_StatusTypeDef HAL_I2C_UnRegisterAddrCallback(I2C_HandleTypeDef *hi2c)

I suspect these omit the lock/unlock calls because those functions can be called before the I2C handle has been initialized (and therefore the "state" variable is PRESUMED to be zero = HAL_I2C_STATE_RESET). That is a change from 16.2 to 17.0.

As for the functions that call unlock without a corresponding lock, those are possibly/probably called from functions that have already called lock. But I have not done an exhaustive search.

17.0 added the separate I2C_Mem_ISR_IT() and I2C_Mem_ISR_DMA() instead of using the I2C_Master_ISR_IT() and DMA() for the memory read/write functions. ***IF*** you are inclined to try debugging the 17.0 code, set breakpoints in I2C_Mem_ISR_IT() or I2C_Mem_ISR_DMA(), which ever you use, on the lines where it sets HAL_I2C_ERROR_SIZE. See what the handle structure and interrupt flags say.