I2C nrfx_twim driver becomes stuck after SCL being held causes transfer timeout

Hi,

I am encountering an issue with the TWIM driver when attempting to communicate with the nPM1300 PMIC via I2C.

This problem seems to be related to the behavior of the NRFX driver, so I want to ask here if there is anything that can be done to recover it besides a powercycle of the nRF54.

Here is the timeline of the issue:

1. The nRF54 TWIM driver sends a successful i2c_nrfx_twim_transfer of 3 bytes to the nPM1300 (normal state)

2. Due to a power issue, SCL gets held low

3. Another write is attempted, but because SCL is low, it times out after 500ms and i2c_nrfx_twim_recover_bus is attempted (but has no effect - SDA is fine)

4. SCL is released, so the bus should now operate normally - but now it times out for 500ms waiting for completion_sync every time

Please let me know if there is any other information I need to provide to help describe the issue, or what I can try to restore operation of the TWIM driver after SCL gets held low during an attempted transfer.

Parents
  • Hello,

    Could you please try to fully disable, uninitialize, and then reinitialize the TWIM instance in your code after the error?

  •     const struct device *twim_dev = DEVICE_DT_GET(DT_NODELABEL(i2c21));
        nrfx_twim_t twim_inst = NRFX_TWIM_INSTANCE(21);
        int ret;
    
        if (!device_is_ready(twim_dev)) {
            shell_error(sh, "TWIM device not ready");
            return 1;
        }
    
    
        shell_print(sh, "Uninitializing...");
        k_sleep(K_MSEC(100));
        nrfx_twim_uninit(&twim_inst);
        shell_print(sh, "Initializing...");
        k_sleep(K_MSEC(100));
        i2c_nrfx_twim_common_init(twim_dev);

    Hi,

    I have done so using this code for my I2C device on i2c21 (nrf-twim), it compiles and runs without any assertions, but the bus behavior is unchanged. The transactions still all time out for 500ms even with the SCL released to be controlled by the nRF54L15.

    Let me know if there's any other information I should provide, or if I need to be re-initializing it differently. Thank you.

Reply
  •     const struct device *twim_dev = DEVICE_DT_GET(DT_NODELABEL(i2c21));
        nrfx_twim_t twim_inst = NRFX_TWIM_INSTANCE(21);
        int ret;
    
        if (!device_is_ready(twim_dev)) {
            shell_error(sh, "TWIM device not ready");
            return 1;
        }
    
    
        shell_print(sh, "Uninitializing...");
        k_sleep(K_MSEC(100));
        nrfx_twim_uninit(&twim_inst);
        shell_print(sh, "Initializing...");
        k_sleep(K_MSEC(100));
        i2c_nrfx_twim_common_init(twim_dev);

    Hi,

    I have done so using this code for my I2C device on i2c21 (nrf-twim), it compiles and runs without any assertions, but the bus behavior is unchanged. The transactions still all time out for 500ms even with the SCL released to be controlled by the nRF54L15.

    Let me know if there's any other information I should provide, or if I need to be re-initializing it differently. Thank you.

Children
  • Hello,

    I can see in your code snippet you have called nrfx_twim_uninit() directly and later you reinitialize with the function i2c_nrfx_twim_common_init(); this is not correct approach. You need to call these through APIs as Zephyr expects to control the initialization and uninitialization through it's own API.

    For example:

    // 1. Uninitialize the TWIM instance
    nrfx_twim_uninit(&twim_inst); // [nrfx_twim_uninit()](https://docs.nordicsemi.com/bundle/nrf5_SDK_v17.1.1/page/group_nrfx_twim.html#ga5046a4d075ac9fa4294b506d1f77603e)
    
    // 2. Recover the I2C bus
    nrfx_err_t err = nrfx_twim_bus_recover(scl_pin, sda_pin); // [nrfx_twim_bus_recover()](https://docs.nordicsemi.com/bundle/nrf5_SDK_v17.1.1/page/group_nrfx_twim.html#ga41fa3d184a4ed85bf5c073016708b561)
    if (err != NRFX_SUCCESS) {
        // Handle recovery failure
    }
    
    // 3. Reinitialize the TWIM instance
    err = nrfx_twim_init(&twim_inst, &config, event_handler, p_context); // [nrfx_twim_init()](https://docs.nordicsemi.com/bundle/nrf5_SDK_v17.1.1/page/group_nrfx_twim.html#ga7d37936f8b5a85bad6a4526e90e73287)
    if (err != NRFX_SUCCESS) {
        // Handle initialization failure
    }

Related