nRF54L15 I2C and GPIO sharing pin control

Hello,

I am running into an issue when trying to use both GPIO and I2C peripherals on the same set of pins on an nRF54L15 board. I have an I2C bus configured on two pins, and can see the I2C traffic on that bus working as expected. However, at times when I2C is not in use, our application needs to use basic GPIO functionality to set the value of those same pins, and seems to be unable to do so. Just as a proof of concept, I have our application configuring the pins as output using gpio_pin_configure_dt and then toggling the pins on and off twice prior to attempting the I2C transaction. The I2C operations still works, but the toggling does not seem to be occurring on the pins.

For the period when the signals are reconfigured as push-pull outputs, it seems like the signals are being driven high, but no toggling occurs. Once the bus is used for I2C again, it is configured open-drain and is no longer being driven high, which is expected.

When I change the I2C bus pin definitions to use different pins, the GPIO toggling occurs as expected, which confirms that the GPIO pin definitions and application logic are working by themselves. We are using NCS version 3.2.1.

Is there something specific we would need to do to 'disable' I2C control of these pins when we are expecting to use GPIO control instead?

Thank you,

Ben

Here is some examples of our GPIO and I2C device tree definitions and the application code that should be toggling the GPIO lines. Note that the names of the SDA and SCL signals are reversed for the GPIO and I2C definitions, but attempting to toggle either GPIO signal gives the same result, so it should not be relevant.

    probe_ins {
        compatible = "gpio-leds";
        probe_scl: probe_scl {
            gpios = <&gpio1 12 (GPIO_ACTIVE_HIGH)>;
            label = "Probe Interface SCL Signal";
        };
        probe_sda: probe_sda {
            gpios = <&gpio1 11 (GPIO_ACTIVE_HIGH)>;
            label = "Probe Interface SDA Signal";
        };
    };
    
    ...
    
    &pinctrl {
    /omit-if-no-ref/ i2c20_default: i2c20_default {
        group1 {
            psels = <NRF_PSEL(TWIM_SDA, 1, 12)>,
                <NRF_PSEL(TWIM_SCL, 1, 11)>;
        };
    };

    /omit-if-no-ref/ i2c20_sleep: i2c20_sleep {
        group1 {
            psels = <NRF_PSEL(TWIM_SDA, 1, 12)>,
                <NRF_PSEL(TWIM_SCL, 1, 11)>;
            low-power-enable;
        };
    };
};

...

&i2c20 {
    status = "okay";
    clock-frequency = <I2C_BITRATE_STANDARD>;

    pinctrl-0 = <&i2c20_default>;
    pinctrl-1 = <&i2c20_sleep>;
    pinctrl-names = "default", "sleep";

    hdc2010: hdc2010@40 {
        compatible = "ti,hdc2010";
        reg = < 0x40 >;
        status = "okay";
    };
};

           ret = gpio_pin_configure_dt(&probe_scl,
                                        GPIO_OUTPUT | GPIO_OUTPUT_LOW | GPIO_PUSH_PULL);

            gpio_pin_set_dt(&probe_scl, 1);
            k_busy_wait(1000);
            gpio_pin_set_dt(&probe_scl, 0);
            k_busy_wait(1000);
            gpio_pin_set_dt(&probe_scl, 1);
            k_busy_wait(1000);
            gpio_pin_set_dt(&probe_scl, 0);
            k_busy_wait(1000);
            gpio_pin_set_dt(&probe_scl, 1);
            k_busy_wait(1000);

            // Reconfigure SCL pin for I2C transmission
            ret = gpio_pin_configure_dt(&probe_scl,
                                        GPIO_INPUT | GPIO_OUTPUT_INACTIVE | GPIO_OPEN_DRAIN);

            // Continue with I2C operations

Regardless of whether the output configuration sets the GPIO_OUTPUT_LOW, OUTPUT_HIGH, or OUPUT_ACTIVE flags, the results on the scope is always just driving a HIGH voltage, and never LOW.

Here is what we're seeing on the scope when trying to toggle pin 12. There is the 5ms period in the beginning between the red markers when the pin has been reconfigured as push-pull output, but no toggling occurs. It is then reconfigured to open-drain and the I2C operation occurs as expected (no device is connected on the bus). The bus pull-up voltage is only 2V due to weak external pullups. That should not impact the GPIO toggling behavior, but it does allow us to see the difference between push-pull and pull-up logic HIGHs.

Related