This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

I2C (TWI driver) Bus recovery

Hi I'm wondering if anyone has any tips on implementing a I2C recovery sequence with NRFX 2.3.0 (as included with Zephyr 2.4.99). I've seen this discussed https://devzone.nordicsemi.com/f/nordic-q-a/33466/twi-clearing-bus-with-nrfx_twi-driver but I can't find any of the clearing functions in the SDK (such as the mentioned twi_clear_bus() ).

Also note, that although I'm using Zephyr, I'm not against talking directly to the HAL SDK, as I'd like my application working ASAP.

  • I took a look at nRF5_SDK_17.0.2_d674dde\integration\nrfx\legacy\nrf_drv_twi.c-->twi_clear_bus() and it did the following:

    static void twi_clear_bus(nrf_drv_twi_config_t const * p_config)
    {
        NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_INIT_CONF;
        NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_INIT_CONF;
    
        nrf_gpio_pin_set(p_config->scl);
        nrf_gpio_pin_set(p_config->sda);
    
        NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_INIT_CONF_CLR;
        NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_INIT_CONF_CLR;
    
        nrf_delay_us(4);
    
        for (int i = 0; i < 9; i++)
        {
            if (nrf_gpio_pin_read(p_config->sda))
            {
                if (i == 0)
                {
                    return;
                }
                else
                {
                    break;
                }
            }
            nrf_gpio_pin_clear(p_config->scl);
            nrf_delay_us(4);
            nrf_gpio_pin_set(p_config->scl);
            nrf_delay_us(4);
        }
        nrf_gpio_pin_clear(p_config->sda);
        nrf_delay_us(4);
        nrf_gpio_pin_set(p_config->sda);
    }

    I could not find any similar functions in NCS/Zephyr, so if you want to use twi_clear_bus(), use the code above as a reference. 

    In the thread TWI Stuck Bus Recovery it was recommended to reinitialize the I2C driver, however I'm not quite sure how to go about this if you're using the Zephyr drivers, since you're not running the init function yourself. It happens automatically before main. However, f you use the nrfx drivers directly, you will be able to reinitialize the driver, since you run the init function yourself.

    Another solutions could be to reset the chip, which will reinitialize the I2C. If the device you're communicating with has a reset pin, you could solve it by triggering a reset on that chip as well.

    Best regards,

    Simon

Related