AnsweredAssumed Answered

STM32F746N - HAL_I2C_Master_Receive() ends before all bytes read

Question asked by Rennecke.S_ren on Mar 13, 2017
Latest reply on Apr 24, 2017 by Lucas C

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

Outcomes