2017-01-10 12:30 PM
Hi,
I didn't find any report posted about this issue so here we are.
There is a stupid bug in the implementation of HAL_I2C_Mem_Read()@STM32Cube_FW_F4_V1.0/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c. The 'Size' parameter is supposed to be used only to initialize the transfer size, but it is also misused during the transfer to check the number of bytes left for reading (see the marked line in the code below). In result if in the last loop iteration there are 2 bytes left, code block expecting 3 bytes on the bus could be executed and the function hangs (till the timeout event, not shown here).
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size,
uint32_t Timeout)
{
/*....*/
/* Prepare transfer parameters */
hi2c->pBuffPtr = pData;
hi2c->XferCount = Size;
hi2c->XferOptions = I2C_NO_OPTION_FRAME;
hi2c->XferSize = hi2c->XferCount;
/*....*/
while(hi2c->XferSize > 0U)
{
if(hi2c->XferSize <= 3U)
{
/* One byte */
if(hi2c->XferSize== 1U)
{
/*....*/
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
/* Two bytes */
else if(Size == 2U) /* <----------- CHECK THIS LINE ----------------- */
{
/*....*/
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
/* 3 Last bytes */
else
{
/*....*/
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
/*....*/
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
}
else
{
/*....*/
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET)
{
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferSize--;
hi2c->XferCount--;
}
}
}
/*....*/
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
To fix the problem the marked line:
/* Two bytes */
else if(Size == 2U)�?�?
should be changed to:
/* Two bytes */
else if(hi2c->XferSize == 2U)�?�?
Cheers!
A
#f4 #cubemx #bug #hal #i2cSolved! Go to Solution.
2017-04-17 11:46 AM
Hi
Zotow.Adam
,This issue is fixed in the STM32CubeF4 v1.0
Imen
2017-01-11 04:03 AM
Dear
adam.zotow
,Thank you for posting this issue.Please note that the reported bug is tracked internally for checking and working onthis.
Sorry for any inconvenience this may cause.
All your feedback are welcome in order to improve our solutions.
Best Regards
Imen
2017-01-12 09:06 AM
Hi!
great, thank you.
One small note: this is a regression introduced in this release.
Cheers!
A
2017-04-17 11:46 AM
Hi
Zotow.Adam
,This issue is fixed in the STM32CubeF4 v1.0
Imen
2017-08-22 12:29 AM
The above fix using XferSize is WRONG and fails for transfers of 2 bytes.
At the changed line, when (XferSize == 2) is tested, Size is 2 but XferSize is 0 so the code to read 3 bytes runs.
This results in a timeout error.
Refer to the updated code for a proper fix.
2019-01-16 05:47 PM
Hi,
I'm using HAL_I2c_Mem_Read(), too.
And may I ask if STM32's I2C can generate wave like the following picture. I have tryed Mem_read() and any other function in i2c.c , but the bit following device addres is "0",which means "write" in I2c.
May you help me out, thanks.
2019-05-10 05:42 AM
I have a problem with the functions HAL_I2C_Mem_Read(...) / HAL_I2C_Mem_Write(...) too. I use a STM32F103C8T6 and an 24LC32. When trying to store 2 bytes in the memory, it actually stores only 1. When I give a size of 3 to the function it stores 2 bytes.
I only have to store 2 bytes, so i simplified the surrounding function.
static I2C_HandleTypeDef i2c2;
void EEPROM_Init (void)
{
__HAL_RCC_I2C2_CLK_ENABLE();
GPIO_Config(eeprom_pins, EEPROM_PIN_COUNT);
i2c2.Instance = I2C2;
i2c2.Init.ClockSpeed = 50000UL;
i2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
i2c2.Init.OwnAddress1 = 0;
i2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
i2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
i2c2.Init.OwnAddress2 = 0;
i2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
i2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
HAL_I2C_Init(&i2c2);
//__HAL_I2C_ENABLE(&i2c2);
}
//EEPROM_ADDRESS = 0xA0
void EEPROM_Store(uint8_t* data)
{
HAL_I2C_Mem_Write(&i2c2, EEPROM_ADDRESS, 0x0000, I2C_MEMADD_SIZE_16BIT, data, 0x03, 1000);
}
void EEPROM_Read(uint8_t* data)
{
HAL_I2C_Mem_Read(&i2c2, EEPROM_ADDRESS, 0x0000, I2C_MEMADD_SIZE_16BIT, data, 0x03, 1000);
}
//Store:
uint32_t dist = atol(cmd_str[1]);
EEPROM_Store((uint8_t*)&dist);
//Read:
uint8_t buff[4];
uint16_t dist;
EEPROM_Read(buff);
dist = (buff[1]<<8)|buff[0];
I don't know what wrong her. Do you have any ideas?
Thank You
Paul