Skip to main content
Associate
March 9, 2026
Question

STM32F767 I2C burst errors with Multiple slaves

  • March 9, 2026
  • 1 reply
  • 247 views

I've developed a board using an STM32F767ZI to manage a set of power supplies via PMBUS. I've connected 4 I2C buses, each with 5 slave devices (power supplies), managing a total of 20 slave devices.

My application continuously polls the slave devices to get their status. When I use a single I2C peripheral, I never get any read errors. However, when multiple I2C peripherals are running simultaneously, I get bursts of read errors on all 4 buses (though not all at the same time) approximately every 30 seconds to 1 minute.

Each I2C polling routine runs in a separate FreeRTOS task.

I've tried using the HAL drivers I2C in Polling, IRQ, and DMA modes. I've also tried using the I2C peripherals in PMBus mode (CubeMX Setup). The bus speed is 100KHz. I tested enabling one peripheral at a time and noticed that the frequency of errors increases as the number of enabled peripherals increases (no errors with only one I2C enabled, errors every 30s/1m with 4 I2C enabled).

Can anyone suggest what I should investigate?

Thanks

 

1 reply

TDK
Super User
March 9, 2026

> noticed that the frequency of errors increases as the number of enabled peripherals increases

If the HAL_I2C functions return HAL_OK, the problem is likely elsewhere in your code. Look at the data flow between this function and where you observe it. Use blocking functions while debugging.

"If you feel a post has answered your question, please click ""Accept as Solution""."
giucanMTAuthor
Associate
March 10, 2026
/**
 * @brief PMBus Command Read
 * Addr: PMBus target address
 * ComIdx: PMBus command index
 * ReadData: Buffer to store read data
 * @return 0: OK, >1: Error
 */
uint8_t PMBusCommRead(uint8_t BusIdx, uint8_t Addr, uint8_t ComIdx, uint8_t *ReadData)
{

 HAL_StatusTypeDef HAL_Res;
 BaseType_t SemaphoreFlag;
 uint8_t DataI2C[PMBUS_MAX_BYTE];
 uint8_t Comm;
 uint8_t NumBytes;
 uint8_t i;
 I2C_HandleTypeDef * I2C_Bus;

 switch(BusIdx)
 {
 	case PMBUS1:
 		I2C_Bus = &hi2c4;
		break;
 	case PMBUS2:
 		I2C_Bus = &hi2c3;
		break;
 	case PMBUS3:
 		I2C_Bus = &hi2c2;
		break;
 	case PMBUS4:
 		I2C_Bus = &hi2c1;
		break;
 }


 // Set I2C Semaphore
 if (I2C_Semaphore[BusIdx] != NULL)
 {
 SemaphoreFlag = xSemaphoreTake(I2C_Semaphore[BusIdx], 0);
 while (SemaphoreFlag != pdTRUE)
 {
 SemaphoreFlag = xSemaphoreTake(I2C_Semaphore[BusIdx], 0);
 }
 }

 Comm = RCP1600Commands[ComIdx].Cmd;
 NumBytes = RCP1600Commands[ComIdx].Len;

 // Send SMBUS message
 HAL_Res=HAL_I2C_Master_Transmit(I2C_Bus, (uint16_t)(Addr), &Comm, 1,I2C_TO);

 if (HAL_Res != HAL_OK)
 {
	 //Release I2C Semaphore
	 if (I2C_Semaphore[BusIdx] != NULL)
	 {
	 xSemaphoreGive(I2C_Semaphore[BusIdx]);
	 }
	 return 1;
 }

 // Wait for SMBUS transfer end
 while (HAL_I2C_GetState(I2C_Bus) != HAL_I2C_STATE_READY)
 {

 }
 HAL_Res=HAL_I2C_Master_Receive(I2C_Bus, (uint16_t) Addr, DataI2C, (uint16_t) NumBytes,I2C_TO);

 if (HAL_Res != HAL_OK)
 {
	 //Release I2C Semaphore
	 if (I2C_Semaphore[BusIdx] != NULL)
	 {
	 xSemaphoreGive(I2C_Semaphore[BusIdx]);
	 }
	 return 1;
 }

 while (HAL_I2C_GetState(I2C_Bus) != HAL_I2C_STATE_READY)
 {
 }

 //Release I2C Semaphore
 if (I2C_Semaphore[BusIdx] != NULL)
 {
 xSemaphoreGive(I2C_Semaphore[BusIdx]);
 }

 for (i = 0; i < NumBytes; i++)
 {
 	ReadData[i] = DataI2C[i];
 }
 return 0;

}

 this is my code. I never get return different from HAL_OK. But sometimes the ReadDat a contains 0xFF or wrong value. Observing the I2C bus on oscilloscope sometimes the transmitted message is not correct but sometimes is right. I have no idea about the errors happen only when multiple tasks run the "PMBusCommRead" function.

TDK
Super User
March 10, 2026

> Observing the I2C bus on oscilloscope sometimes the transmitted message is not correct but sometimes is right.

In what way is it not correct? The chip can only read the data on the bus. Only one thread can use the I2C bus at a time. If multiple call it at the same, time, it won't work.

To me, it looks like your semaphore check is not sufficient. If the semaphore is already taken, it just ignores it.

"If you feel a post has answered your question, please click ""Accept as Solution""."