This can be an important normal task, for instance when retrying an eeprom waiting for its last write burn cycle to complete before it will respond again.
Example code
void WaitForLastWriteToComplete ()
{
uint16_t TriesCount = 5000;
i2c_cmd_handle_t OurI2cCmdHandle = i2c_cmd_link_create();
while (1)
{
//----- DUMMY WRITE OPERATION -----
i2c_master_start(OurI2cCmdHandle);
i2c_master_write_byte(OurI2cCmdHandle, EXAMPLE_I2C_ADDR | EXAMPLE_I2C_WRITE_BIT, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_stop(OurI2cCmdHandle);
//Send queued commands
i2c_ret = i2c_master_cmd_begin(EXAMPLE_I2C_PORT_NUMBER, OurI2cCmdHandle, (1 / portTICK_PERIOD_MS)); //ticks_to_wait small value as we're not expecting the device to clock stretch
if (i2c_ret != ESP_FAIL) //ESP_FAIL returned for Sending command error, slave hasn't ACK the transfer
break;
TriesCount--;
if (TriesCount == 0)
break;
} //while (1)
i2c_cmd_link_delete(OurI2cCmdHandle);
}
Things discovered when getting this to work on an ESP32 S3
Do not use i2c_cmd_link_delete() and i2c_cmd_link_create() between back-to-back retrying. In tests it causes a 1 second delay after the first NACK generating i2c_ret == 0x107 which is Operation timed out. Very odd as it should have just generated a new short attempt and i2c_ret == -1 ESP_FAIL like the first attempt. But it doesn’t, removing the use of i2c_cmd_link_delete() and i2c_cmd_link_create() between tries solved it.
i2c_master_write_byte() ack_en (Enable ACK signal) value must be 1, not 0. If you use 0 then the NACK is ignored and you get a ESP_OK back on the first try.