cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F746N - HAL_I2C_Master_Receive() ends before all bytes read

S�ren Rennecke
Associate
Posted on March 13, 2017 at 10:00

Hi,

I'm calling the function HAL_I2C_Master_Receive() within an FreeRTOS task. The RTOS task scheduling is triggered by the SYS tick hardware. There are two slaves at the same I2C bus.

Reading data from slaves works fine for a while (minutes or hours), but at any time an error will occur. 

HAL_I2C_Master_Receive always returns with HAL_OK but the RXNE flag is still set in ISR register. Calling

HAL_I2C_Master_Receive() the next time 

first delivered byte is exactly the same byte which was send by the slave with last read

transfer

. And so on ....

The bus communication is monitored with logic analyzer and it looks perfect.

I think that there is a HW bug In I2C. I assume that in some cases the 

RXNE flag is not cleared immediately by HW by reading the RXDR register as it should. 

(*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; 

So during the next round in while loop the RXDR will be re-read and the counter hi2c->XferSize counts down.

HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

{

I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);

..

while(hi2c->XferSize > 0)

{

/* Wait until RXNE flag is set */

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

...

/* Read data from RXDR */

(*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;

hi2c->XferSize--;

hi2c->XferCount--;

...

}

..

}

This problem only happens when interrupts occur during I2C read function is executed (actually I only recognized the SYSTICK Interrupt).

To avoid this problem I added a critical section around. But this has the disadvantage that it blocks all Interrupts for a 'long' time. 

portENTER_CRITICAL();

HAL_I2C_Master_Receive()

portEXIT_CRITICAL(); around calling 

I hope anybody can help.

In beteween I' try to use HAL_I2C_Master_Receive_IT() instead.

Best regards.

S�ren

#i2c
4 REPLIES 4
Lucas C
Associate II
Posted on April 19, 2017 at 22:00

Hi Soren,

I'm having a very similar issue. I'm trying to look into it now. I'll run some test to see if I can determine how to trigger this issue consistently.

You mentioned that it happened every time you had an interrupt happening during the I2C read? Do you know which interrupt caused it? And do you know if it matters at which point of the 

HAL_I2C_Master_Receive() the interrupt happens?

Meanwhile, I'll try to run some tests here.

In case you have already got an answer to this problem, please, share it with me.

Cheers,

Lucas

S�ren Rennecke
Associate
Posted on April 20, 2017 at 11:00

Hi Lucas,

Sorry but I'm not longer working on this project. So I can't analyse the error in more in detail.

At the end I used the routine 

HAL_I2C_Master_Receive_IT() without any problems.

But in general I think this problem should be Analyzed by a STM FAE. 

I guess it was the interrupt of the sys tick timer each 1 ms triggering FreeRTOS.

Regards,

Sören

Posted on April 20, 2017 at 15:59

Hi

lccavalheiro

,

You did not precise the version of the driver/Cube you are using . Is-it the last version ?

Try to debug your project and identify where is it sticking and when it occurs.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Posted on April 24, 2017 at 17:14

Hi Imen,

Unfortunately, I don't know the version of the HAL library I'm using because it has been added by another engineer and I couldn't find in the documents what is the date or version.

I tried to find out what exactly triggers the problem, but to be honest, it is very hard to find a 'scientific' method to reproduce it. I could only make it happen a few times, but on thing is true for all the times it happened: it took a while with the program running until it happened. By 'a while' I mean anywhere between 10 min to 1 hour. Another thing that seems to make it more likely to happen is to continuously keep sending and receiving data through I2C for a long period of time.

Another fact is that it only happened when I pressed a button that triggered an external interrupt in an IO pin.  That leads me to think that it does have something to do with interrupts happening during the I2C communication, but certainly that is not the only necessary action to cause the issue.

I have tried causing a timer interrupt while receiving many times and the issue did not show up. I also tried causing the external IO interrupt during the I2C communication and once again, that did not cause the issue.

As I cannot spend much more time trying to solve this issue, I will try a workaround by not utilizing the external IO interrupt, and by using the I2C IT instead of the blocking I2C.

In any case, if you find something out, or have some ideas, please let me know and I'll try to look into it.

Thanks!

Lucas