2022-12-21 06:23 AM
Hi,
I use the NUCLEO-F091RC, STM32CubeIDE with the MCU Package 1.11.3 and FreeRtos.
The I2C1 is used with an Eeprom. So I would like to use the function HAL_I2C_Mem_Read_DMA as it is shown for example STM32Cube_FW_F0_V1.11.3\Projects\STM32091C_EVAL\Examples\I2C\I2C_EEPROM\Src\main.c:
/*##-3- Start reading process ##############################################*/
if (HAL_I2C_Mem_Read_DMA(&I2cHandle, (uint16_t)EEPROM_ADDRESS, 0, I2C_MEMADD_SIZE_16BIT, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
{
/* Reading process Error */
Error_Handler();
}
/* Wait for the end of the transfer */
while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
{
}
But if I run the code it hangs in the HAL_I2C_GetState loop. The SDA/SCL lines look fine with the oscilloscope. And at the end the software does jump into the I2C_DMAMasterReceiveCplt function (file stm32f0xx_hal_i2c.c).
I would expect that in function I2C_DMAMasterReceiveCplt somewhere set hi2c->State = HAL_I2C_STATE_READY would be coded?
Where should be hi2c->State = HAL_I2C_STATE_READY happen?
My fix would be this:
static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma)
{
/* Derogation MISRAC2012-Rule-11.5 */
I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
/* Disable DMA Request */
hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
/* If last transfer, enable STOP interrupt */
if (hi2c->XferCount == 0U)
{
hi2c->State = HAL_I2C_STATE_READY; // <<<<<<< this is my fix <<<<
/* Enable STOP interrupt */
I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
}
/* else prepare a new DMA transfer and enable TCReload interrupt */
else
{
/* Update Buffer pointer */
hi2c->pBuffPtr += hi2c->XferSize;
/* Set the XferSize to transfer */
if (hi2c->XferCount > MAX_NBYTE_SIZE)
{
hi2c->XferSize = MAX_NBYTE_SIZE;
}
else
{
hi2c->XferSize = hi2c->XferCount;
}
/* Enable the DMA channel */
if (HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)hi2c->pBuffPtr,
hi2c->XferSize) != HAL_OK)
{
/* Call the corresponding callback to inform upper layer of End of Transfer */
I2C_ITError(hi2c, HAL_I2C_ERROR_DMA);
}
else
{
/* Enable TC interrupts */
I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT);
}
}
}