cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 FW_F7_V1.3.1 I2C HAL_I2C_Master_Receive() BUG

thomfischer
Senior
Posted on May 18, 2016 at 14:18

i tried to port software from F4 to F7 but got HAL_TIMEOUT and wrong reading of data

from functio

n

HAL_I2C_Master_Receive()

i changed the following code

--- stm32f7xx_hal_i2c.c Tue Dec 22 14:36:08 2015
 +++ my_stm32f7xx_hal_i2c.c Wed May 18 11:59:02 2016
 @@ -197,15 +197,17 @@
 * @{
*/
#define TIMING_CLEAR_MASK ((uint32_t)0xF0FFFFFF) /*<! I2C TIMING clear register Mask */
-#define I2C_TIMEOUT_ADDR ((uint32_t)10000) /* 10 s */
-#define I2C_TIMEOUT_BUSY ((uint32_t)25) /* 25 ms */
-#define I2C_TIMEOUT_DIR ((uint32_t)25) /* 25 ms */
-#define I2C_TIMEOUT_RXNE ((uint32_t)25) /* 25 ms */
-#define I2C_TIMEOUT_STOPF ((uint32_t)25) /* 25 ms */
-#define I2C_TIMEOUT_TC ((uint32_t)25) /* 25 ms */
-#define I2C_TIMEOUT_TCR ((uint32_t)25) /* 25 ms */
-#define I2C_TIMEOUT_TXIS ((uint32_t)25) /* 25 ms */
-#define I2C_TIMEOUT_FLAG ((uint32_t)25) /* 25 ms */
+
+#define I2C_TIMEOUT_ADDR ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_BUSY ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_DIR ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_RXNE ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_STOPF ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_TC ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_TCR ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_TXIS ((uint32_t)100) /* 100 ms */
+#define I2C_TIMEOUT_FLAG ((uint32_t)100) /* 100 ms */
+
/**
* @}
*/ 
@@ -613,6 +615,7 @@
 }
}
+
/**
* @brief Receives in master mode an amount of data in blocking mode. 
* @param hi2c : Pointer to a I2C_HandleTypeDef structure that contains
@@ -627,6 +630,7 @@
 {
uint32_t sizetmp = 0;
+
if(hi2c->State == HAL_I2C_STATE_READY)
{ 
if((pData == NULL ) || (Size == 0)) 
@@ -659,19 +663,15 @@
 sizetmp = Size;
}
+ /* Clear RXNE Flag */
+ uint8_t dummy=hi2c->Instance->RXDR;
+
do
{
/* Wait until RXNE flag is set */
- if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, I2C_FLAG_RXNE) != HAL_OK) 
+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout) != HAL_OK)
{
- if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
- {
- return HAL_ERROR;
- }
- else
- {
return HAL_TIMEOUT;
- }
 }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

/* Write data to RXDR */

problem was that function

I2C_WaitOnRXNEFlagUntilTimeout(hi2c, I2C_FLAG_RXNE) is called with a flag as timeout value and that it returned because a stop flag was detected ,

with

hi2c->

ErrorCode

= HAL_I2C_ERROR_NONE

and return= HAL_ERROR

so function

HAL_I2C_Master_Receive()

returned with HAL_TIMEOUT and leaving RXNE flag set.

next read returned wrong values because RXNE flag was still set.

best regards

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on January 09, 2017 at 14:45

Hi

Soans.Joel

‌,

The reported bug is already fixed in I2C driver available in the last

http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software/stm32cubef7.html

version.

-Amel-

PS: As general recommendation, please use English for your posts.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

8 REPLIES 8
Amel NASRI
ST Employee
Posted on May 19, 2016 at 11:25

Hi thomas.004,

Thanks for highlighting this issue.

It is reported internally to be fixed in a coming release.

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Joel Soans
Associate
Posted on January 05, 2017 at 15:57

Hallo Thomas,

Ich habe dieselbe Problem. Kannst du den ganzen Code (

my_stm32f7xx_hal_i2c.c

) hier posten.

Beste Grüße,

Joel

Posted on January 09, 2017 at 14:45

Hi

Soans.Joel

‌,

The reported bug is already fixed in I2C driver available in the last

http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software/stm32cubef7.html

version.

-Amel-

PS: As general recommendation, please use English for your posts.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Posted on October 17, 2017 at 17:44

Please note that this problem is definitely not fixed as of F7 v1.8.0.  There's a race in I2C_WaitOnRXNEFlagUntilTimeout() due to it attempting to do more than is needed in support of HAL_I2C_Master_Receive().  The behavior in HAL_I2C_Mem_Read() (which doesn't use the broken I2C_WaitOnRXNEFlagUntilTimeout()) is more correct.

Posted on October 30, 2017 at 08:26

I agree. I'm using F7 v1.8.0 as well, and the problem still exists.

It would be great if someone from ST could investigate this, and fix it in the next version.

Posted on January 02, 2018 at 17:35

Hi

‌ &

‌,

Initially reported issue is thatI2C_WaitOnRXNEFlagUntilTimeout is called with a wrong parameter (I2C_FLAG_RXNE) , which was fixed.

Do you confirm that you still facing issues even after this fix?

Do you confirm that replacing

if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)�?

by

if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout) != HAL_OK)�?

in the implementation ofHAL_I2C_Master_Receive fixes the issue for you?

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Posted on January 03, 2018 at 09:13

Hi Amel,

Yes, that is correct. This fixes the issue - at least for me.

/Peter

Ralf Ebeling
Associate
Posted on February 19, 2018 at 09:27

Hi,

I just run into the same issue with a STM32F030, F070, F091 as reported here - I get a STOPF error while waiting for the last byte of a polled master receive operation. The race condition mentioned here doesn't seem to be fixed within I2C_WaitOnRXNEFlagUntilTimeout() and boils down to multiple reads of the ISR register to check different flags:

  1. read ISR, check for RXNE set
  2. read ISR again, check for NACKF set (within I2C_IsAcknowledgeFailed())
  3. read ISR again, check for STOPF set
  4. start over with 1.

I guess it is obvious what happens, if the ISR register is updated (by hardware) e.g. between step 1 and step 3. RXNE and STOPF may become set at the same time, but STOPF is evaluated only. A possible solution:

  1. read ISR register into local variable
  2. checklocal variable for RXNE set
  3. checklocal variable for STOPF set
  4. start over with 1.

Replacing the call of I2C_WaitOnRXNEFlagUntilTimeout() with I2C_WaitOnFlagUntilTimeout() of course hides

this race condition, but also removes the check for NACKF and STOPF...

Regards

Ralf