Electrical – STM32 HAL I2C always sends 0xFF as first byte when responding to master using HAL_I2C_Slave_Transmit

hal-libraryi2cstm32

I have an STM32G4 using the HAL function HAL_I2C_Slave_Transmit to respond with some data when requested by a master on the I2C bus. In the image below you can see the device sends 0xFF followed by the actual data it was meant to send (the data I am expecting is 0x11 0x01 0x00).

Wave

I have tried this with the minimal test program below so I don't believe it's anything to do with my full program having a delay:

/* USER CODE BEGIN 2 */
  typedef struct {
      char id;
      char payload[2];
  } I2C_RSP_TO_MASTER;
  I2C_RSP_TO_MASTER  I2C_response;
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    I2C_response.id = 0x11;
    I2C_response.payload[0] = 0x01;
    I2C_response.payload[1] = 0x00;
 
    HAL_I2C_Slave_Transmit(&hi2c2, (uint8_t*) &I2C_response, 3, 10);
 
    while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY) {
      }
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

For my current testing the master is an Arduino Nano using the Arduino function:

Wire.requestFrom(ADDR, 4);

I am requesting 4 bytes because the initial byte is garbage (0xFF). The STM32 is clocked at 128MHz so I don't believe it is possible that it is running too slowly to respond to the first byte – I think it may be a problem with the HAL! Is there a way to fix this problem?

Best Answer

If you have enabled "No Clock Stretch" mode, you can't expect the thing to react to it's address and send the first byte correctly, because it does not stretch the clock to make the master wait until the slave code has loaded the first byte into its I2C engine.

If you want to do it without clock stretching, be prepared to write your own I2C routines. The HAL functions can be used as a good starting point, but many times they just are not the best for special needs.