I2C times out when queueing multiple transaction
Posted: Fri Aug 26, 2022 4:20 pm
Hi,
I'm trying to create a single object that's storing the transactions to happen on I2C bus by queueing all the operations and expecting the CPU to run them all correctly. Typically, I'm doing this (pseudo code):
This code works perfectly for one transaction (numTrans = 1) and I can queue 2x 1 transaction and it's working. However, if I set numTrans = 2 (meaning that I'm appending 2 reads (and 4 writes) in the command list) then it fails with an I2C timeout error.
When it fails, it fails directly from the first time I'm running the transaction (first call of i2c_master_cmd_begin). When its working (one transaction case), I can run the transaction as many time as I want, and it's working as expected.
Any idea what I'm doing wrong, or is it an issue with current code in esp-idf ?
I'm trying to create a single object that's storing the transactions to happen on I2C bus by queueing all the operations and expecting the CPU to run them all correctly. Typically, I'm doing this (pseudo code):
Code: Select all
#define FilterError(x) ((x) == ESP_OK)
uint8 buffer[I2C_LINK_RECOMMENDED_SIZE(4)]; // Because 2 read transaction as documented
i2c_cmd_handle_t cmd = i2c_cmd_link_create_static(buffer, I2C_LINK_RECOMMENDED_SIZE(4));
uint8 devAddr = 0x76; // For BMP210
uint8 regAddr[] = { 0xFA, 0xF7 };
uint8 dataBuffer[6] = {};
size_t numTrans = 2;
for (size_t index = 0; index < numTrans; i++) {
if (!FilterError(i2c_master_start(cmd))) return false;
if (!FilterError(i2c_master_write_byte(cmd, (uint8)((devAddr << 1) | I2C_MASTER_WRITE), true))) return false;
// Set the register we are writing to
if (!FilterError(i2c_master_write(cmd, (uint8*)®Addr[index], 1, true))) return false;
// Repeated start
if (!FilterError(i2c_master_start(cmd))) return false;
if (!FilterError(i2c_master_write_byte(cmd, (uint8)((devAddr << 1) | I2C_MASTER_READ), true))) return false;
if (!FilterError(i2c_master_read(cmd, &dataBuffer[i * 3], 3, I2C_MASTER_LAST_NACK))) return false;
// Tried with and without the following line (repeated start or not), but it doesn't work
if (!FilterError(i2c_master_stop(cmd))) return false;
}
// Later
if (!FilterError(i2c_master_cmd_begin(port, cmd, 1000 / portTICK_PERIOD_MS))) return false;
When it fails, it fails directly from the first time I'm running the transaction (first call of i2c_master_cmd_begin). When its working (one transaction case), I can run the transaction as many time as I want, and it's working as expected.
Any idea what I'm doing wrong, or is it an issue with current code in esp-idf ?