cancel
Showing results for 
Search instead for 
Did you mean: 

[BUG] STM32Cube_FW_F4_V1.14.0 HAL_I2C_Mem_Read: handling of last 2 bytes done incorrectly

Adam Zotow
Associate
Posted on January 10, 2017 at 21:30

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 #i2c
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on April 17, 2017 at 18:46

Hi

Zotow.Adam

,

This issue is fixed in the STM32CubeF4 v1.0

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

View solution in original post

6 REPLIES 6
Imen.D
ST Employee
Posted on January 11, 2017 at 13:03

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

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

Hi!

great, thank you.

One small note: this is a regression introduced in this release.

Cheers!

A

Posted on April 17, 2017 at 18:46

Hi

Zotow.Adam

,

This issue is fixed in the STM32CubeF4 v1.0

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
john noyb
Associate
Posted on August 22, 2017 at 09:29

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.

dbo
Associate II

0690X000006D8D0QAK.jpgHi,

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.

PPreu
Associate

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