Page 1 of 1

I2C - Using both Ports - First Transaction fails

Posted: Sat Mar 21, 2020 4:15 pm
by kb3523
Dear ESP community,

If the i2c driver is 'installed twice', the first transaction of the first initialized port fails. Afterwards the communication happens without any error on both ports.
Am I initializing both ports correctly? Is there anything else I could consider?

My current ESP-IDF Version is: v4.0-dev-1443

Thank you all in advance


I can reproduce it with the following steps, its enough to have only one i2c device connected to the first initialized port to test it:

Code: Select all

#define I2C_DISTRIBUTED I2C_NUM_0
#define I2C_LOCAL       I2C_NUM_1
#define TEST_DEV_ADDR 0x20

esp_err_t i2c_master_init( i2c_port_t port );
int8_t bus_checkForACK(i2c_port_t port, uint8_t dev_addr);

void test_this_it_fails()
{
    i2c_master_init(I2C_LOCAL);
    i2c_master_init(I2C_DISTRIBUTED);

    while ( bus_checkForACK(I2C_LOCAL, 0x20 ) != ESP_OK )
    {
            printf("First Transaction on First initialized bus failed! \n ");
    }
}


//****************************************************************************
int8_t bus_checkForACK(i2c_port_t port, uint8_t dev_addr)
{
    i2c_cmd_handle_t cmd_link = i2c_cmd_link_create();

    i2c_master_start(cmd_link);
    i2c_master_write_byte(cmd_link, (dev_addr << 1) | I2C_MASTER_WRITE, true);
    esp_err_t ret = i2c_master_cmd_begin(port, cmd_link, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd_link);
    return (int8_t)ret;
}

esp_err_t i2c_master_init( i2c_port_t port )
{
    i2c_config_t conf;
    if ( I2C_DISTRIBUTED )
    {
        conf.mode = I2C_MODE_MASTER;
        conf.sda_io_num = GPIO_I2C_DIST_SDA;
        conf.scl_io_num = GPIO_I2C_DIST_SCL;
        conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
        conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
        conf.master.clk_speed = I2C_START_FREQ;
    }
    else if ( I2C_LOCAL )
    {
        conf.mode = I2C_MODE_MASTER;
        conf.sda_io_num = GPIO_I2C_LOCAL_SDA;
        conf.scl_io_num = GPIO_I2C_LOCAL_SCL;
        conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
        conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
        conf.master.clk_speed = 1000000;
    }
    else
    {
        printf("I2C Invalid Config! \n");
        return 0xFF;
    }
    if ( i2c_param_config(port, &conf) != ESP_OK )
    {
        printf("I2C Invalid Config! \n");
        return 0xFF;
    }

    return i2c_driver_install(port, conf.mode,
                              I2C_MASTER_RX_BUF_DISABLE,
                              I2C_MASTER_TX_BUF_DISABLE, ESP_INTR_FLAG_IRAM);

}


Re: I2C - Using both Ports - First Transaction fails

Posted: Sat Mar 21, 2020 7:00 pm
by vonnieda
kb3523 wrote:
Sat Mar 21, 2020 4:15 pm
Dear ESP community,

If the i2c driver is 'installed twice', the first transaction of the first initialized port fails. Afterwards the communication happens without any error on both ports.
Am I initializing both ports correctly? Is there anything else I could consider?

My current ESP-IDF Version is: v4.0-dev-1443

Thank you all in advance


I can reproduce it with the following steps, its enough to have only one i2c device connected to the first initialized port to test it:

Code: Select all

#define I2C_DISTRIBUTED I2C_NUM_0
#define I2C_LOCAL       I2C_NUM_1
#define TEST_DEV_ADDR 0x20

esp_err_t i2c_master_init( i2c_port_t port );
int8_t bus_checkForACK(i2c_port_t port, uint8_t dev_addr);

void test_this_it_fails()
{
    i2c_master_init(I2C_LOCAL);
    i2c_master_init(I2C_DISTRIBUTED);

    while ( bus_checkForACK(I2C_LOCAL, 0x20 ) != ESP_OK )
    {
            printf("First Transaction on First initialized bus failed! \n ");
    }
}


//****************************************************************************
int8_t bus_checkForACK(i2c_port_t port, uint8_t dev_addr)
{
    i2c_cmd_handle_t cmd_link = i2c_cmd_link_create();

    i2c_master_start(cmd_link);
    i2c_master_write_byte(cmd_link, (dev_addr << 1) | I2C_MASTER_WRITE, true);
    esp_err_t ret = i2c_master_cmd_begin(port, cmd_link, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd_link);
    return (int8_t)ret;
}

esp_err_t i2c_master_init( i2c_port_t port )
{
    i2c_config_t conf;
    if ( I2C_DISTRIBUTED )
    {
        conf.mode = I2C_MODE_MASTER;
        conf.sda_io_num = GPIO_I2C_DIST_SDA;
        conf.scl_io_num = GPIO_I2C_DIST_SCL;
        conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
        conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
        conf.master.clk_speed = I2C_START_FREQ;
    }
    else if ( I2C_LOCAL )
    {
        conf.mode = I2C_MODE_MASTER;
        conf.sda_io_num = GPIO_I2C_LOCAL_SDA;
        conf.scl_io_num = GPIO_I2C_LOCAL_SCL;
        conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
        conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
        conf.master.clk_speed = 1000000;
    }
    else
    {
        printf("I2C Invalid Config! \n");
        return 0xFF;
    }
    if ( i2c_param_config(port, &conf) != ESP_OK )
    {
        printf("I2C Invalid Config! \n");
        return 0xFF;
    }

    return i2c_driver_install(port, conf.mode,
                              I2C_MASTER_RX_BUF_DISABLE,
                              I2C_MASTER_TX_BUF_DISABLE, ESP_INTR_FLAG_IRAM);

}


You have an error in your code that is likely causing the issue.

Code: Select all

 if ( I2C_DISTRIBUTED )
Should be

Code: Select all

 if (port == I2C_DISTRIBUTED)
And likewise for the next conditional.

Jason

Re: I2C - Using both Ports - First Transaction fails

Posted: Sat Mar 21, 2020 9:06 pm
by kb3523
Lol. This is so obvious, I dont know how I could not notice this.. :D
Maybe I should stop working for today :) Thank you, please consider thes topic closed. Is there an option to close the topic with the resolution: "Used did not have eyes to read his own code, others had.." ;)