i2c bug in 3.0, works with older idf

ardiehl
Posts: 7
Joined: Fri Oct 27, 2017 10:44 pm

i2c bug in 3.0, works with older idf

Postby ardiehl » Sun Jun 24, 2018 12:46 pm

tried to update to the current idf from github yesterday (June 23, 2018). After that, i had sporadic timeout retuned by i2c_master_cmd_begin. This always happend after i updated the firmware on my esp and restarted (via reset button or software). If this happens, i2c is dead and the only way to get it up again is a power cycle. Reset button or soft reset: no effect.

Here is where this happens in i2c.c:

Code: Select all

        portBASE_TYPE evt_res = xQueueReceive(p_i2c->cmd_evt_queue, &evt, wait_time);
        if (evt_res == pdTRUE) {
            if (evt.type == I2C_CMD_EVT_DONE) {
                if (p_i2c->status == I2C_STATUS_TIMEOUT) {
                    // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example,
                    // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case.
                    ESP_LOGE(I2C_TAG,"Timeout after xQueueReceive");  // AD: this is the timeout i get
                    i2c_hw_fsm_reset(i2c_num);
                    clear_bus_cnt = 0;
                    ret = ESP_ERR_TIMEOUT;
I have reverted to an older version of idf (i2c.c / 53760 / Feb 3 17:07), updated the firware, done a software restart without cycling power and i2c works fine as it should.
For me this looks like idf 3.0 is not resetting the i2c ?

WiFive
Posts: 2103
Joined: Tue Dec 01, 2015 7:35 am

Re: i2c bug in 3.0, works with older idf

Postby WiFive » Sun Jun 24, 2018 6:30 pm

Current master is technically "3.2-dev". It does look like i2c_master_clear_bus code is not quite right. Previous version was slightly better, still not totally right.

This may be better

Code: Select all

static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
{
    I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
    int sda_in_sig = 0, scl_in_sig = 0;
    if (i2c_num == I2C_NUM_0) {
        sda_in_sig = I2CEXT0_SDA_IN_IDX;
        scl_in_sig = I2CEXT0_SCL_IN_IDX;
    } else if (i2c_num == I2C_NUM_1) {
        sda_in_sig = I2CEXT1_SDA_IN_IDX;
        scl_in_sig = I2CEXT1_SCL_IN_IDX;
    }
    int scl_io = GPIO.func_in_sel_cfg[scl_in_sig].func_sel;
    int sda_io = GPIO.func_in_sel_cfg[sda_in_sig].func_sel;
    I2C_CHECK((GPIO_IS_VALID_OUTPUT_GPIO(scl_io)), I2C_SCL_IO_ERR_STR, ESP_ERR_INVALID_ARG);
    I2C_CHECK((GPIO_IS_VALID_GPIO(sda_io)), I2C_SDA_IO_ERR_STR, ESP_ERR_INVALID_ARG);
    // We do not check whether the SDA line is low
    // because after some serious interference, the bus may keep high all the time and the i2c bus is out of service.
    gpio_set_direction(scl_io, GPIO_MODE_OUTPUT_OD);
    gpio_set_direction(sda_io, GPIO_MODE_OUTPUT_OD);
    gpio_set_level(scl_io, 0);
    gpio_set_level(sda_io, 1);
    gpio_set_level(scl_io, 1); //clock transition
    gpio_set_level(sda_io, 0); //start condition
    for (int i = 0; i < 9; i++) { //9 clocks
        gpio_set_level(scl_io, 0);
        gpio_set_level(scl_io, 1);
        gpio_set_level(scl_io, 1); //allow for rise time
    }
    gpio_set_level(scl_io, 0);
    gpio_set_level(sda_io, 1);
    gpio_set_level(scl_io, 1); //clock transition
    gpio_set_level(sda_io, 0); //another start condition
    gpio_set_level(scl_io, 0);
    gpio_set_level(scl_io, 1); //clock transition
    gpio_set_level(sda_io, 1); //stop condition
    
    i2c_set_pin(i2c_num, sda_io, scl_io, 1, 1, I2C_MODE_MASTER);
    return ESP_OK;
}

ardiehl
Posts: 7
Joined: Fri Oct 27, 2017 10:44 pm

Re: i2c bug in 3.0, works with older idf

Postby ardiehl » Wed Jun 27, 2018 10:53 am

Current master is technically "3.2-dev".
Sorry,
Tried as follows:
Recompiled and flashed using 3.2-dev, had to soft restart 2 times to freeze i2c. Recompiled 3.2-dev with your new "i2c_master_clear_bus", uploaded, did a soft restart and i2c works well. Thanks for the fix.

Will your fix be integrated into current 3.2-dev on github ?

vonnieda
Posts: 90
Joined: Tue Nov 07, 2017 3:42 pm

Re: i2c bug in 3.0, works with older idf

Postby vonnieda » Wed Oct 17, 2018 5:41 pm

ardiehl wrote:
Current master is technically "3.2-dev".
Sorry,
Tried as follows:
Recompiled and flashed using 3.2-dev, had to soft restart 2 times to freeze i2c. Recompiled 3.2-dev with your new "i2c_master_clear_bus", uploaded, did a soft restart and i2c works well. Thanks for the fix.

Will your fix be integrated into current 3.2-dev on github ?
+1

I am experiencing a similar issue, and WiFive's function above let me manually reset the bus when I detect the condition and have it work. So +1 to getting this merged.

User avatar
fly135
Posts: 480
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: i2c bug in 3.0, works with older idf

Postby fly135 » Thu Oct 18, 2018 3:17 pm

I use i2c quite a bit. I also do software resets of the esp32. I've never experienced a complete failure of the i2c. I do get the occasional timeout. But the next transaction then seems fine. What should I be on the lookout for?

John A

vonnieda
Posts: 90
Joined: Tue Nov 07, 2017 3:42 pm

Re: i2c bug in 3.0, works with older idf

Postby vonnieda » Thu Oct 18, 2018 6:56 pm

fly135 wrote:I use i2c quite a bit. I also do software resets of the esp32. I've never experienced a complete failure of the i2c. I do get the occasional timeout. But the next transaction then seems fine. What should I be on the lookout for?

John A
In my case, the bus would get in a state where SDA was being held either high or low, can't remember which, but nothing else would happen on it. Only way to get past was a full power cycle. Software restart, and even toggling the ESP's enable line would not fix it. The code above *does* seem to fix it.

I am not able to say for sure if the ESP was the cause of the problem, or if it was one of the other devices on the bus. In my case I have an LM75 and a MCP3422 on the bus. I didn't go so far as to take them off to see who was misbehaving.

I don't *think* it has ever happened during normal operations. I think it only happened either on initial boot or during development when I was flashing the chip.

Jason

meowsqueak
Posts: 98
Joined: Thu Jun 15, 2017 4:54 am
Location: New Zealand

Re: i2c bug in 3.0, works with older idf

Postby meowsqueak » Fri Oct 19, 2018 11:09 am

I thought we'd been through all of this with 2.x? I spent countless hours debugging the i2c driver, investigating with brushing wires together, debugging the interrupt handler, finally concluding with a workaround for a hardware bug. Are we now saying that the 3.x driver is broken again? I haven't updated my application to 3.x yet, and now I'm thinking I probably will not...

mrrosen
Posts: 12
Joined: Tue Sep 26, 2017 12:53 am

Re: i2c bug in 3.0, works with older idf

Postby mrrosen » Thu Jan 17, 2019 8:02 pm

May not be relevant to all of the I2C issues people are seeing, but with respect to occasional (or constant) timeout errors from i2c_master_cmd_begin, there is a change from IDF v2.x to v3.x that caused problems for me talking to a TI BQ27621 battery monitor. Changes in the I2C driver force the bit-timeout, the timeout the hardware uses to make sure it doesnt get locked up on each bit of the transaction (see ESP32 Technical Reference Manual Section 11.5; Register 11.4), to be much shorter (from about 2.5ms to about 20us fro 400Khz I2C SCL frequency!). This bit-timeout applies to the acknowledge bit as well, so from devices that use clock stretching before acknowledging a read/write to do some work, this timeout can be way too short and terminate the transaction prematurely. I noticed that the premature termination also leads to some strange behavior on the bus as its usually partway through a complete transaction when the transaction is cancelled. In my case, the BQ27621 would stall the acknowledge by ~90us after writing the register address to which you want to read/write; causing bit-timeouts in the new IDF with applications using older IDFs worked fine. Note that this timeout is completely independent from the one passed into i2c_master_cmd_begin, the former being a timeout on each bit of the transaction, the latter being a timeout on the entire transaction. Luckily, you can change this timeout to be more generous using i2c_set_timeout, making sure to note that this function takes in a count in APB cycles and is only 20-bits wide, so a maximum timeout of ~13ms is possible (but that should be plenty for even the slowest of I2C devices). So, if you are getting frustrated with weird I2C timeouts and bus behavior (like I was :(), just trying setting this timeout to something really generous as it probably wont impact your system much otherwise.

Return to “ESP32 IDF”

Who is online

Users browsing this forum: Baidu [Spider], go4retro and 13 guests