Adding GPIO interrupt callback disables interrupts on another pin and port

Hello,

I spent a solid two hours debugging an interrupt pin that was not working, to discover that the problem appears when configuring a callback in another part of the program.
I add the callbacks with gpio_add_callback in this order: pin 1.10, pin 1.9 and pin 0.27. Somehow adding the last callback disables interrupts on pin 1.10. Even more confusing in my opinion the fact that the the last pin is on a different port than the first one.

Am I doing anything wrong?

I reproduced with a minimal example on NRF Connect 2.7.0, see attached code for the nrf5340dk west build -b  nrf5340dk/nrf5340/cpuapp --sysbuild

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/gpio.h>

LOG_MODULE_REGISTER(main);

static const struct gpio_dt_spec imu_int1 = GPIO_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), imu_int_gpios, 0);
static const struct gpio_dt_spec imu_int2 = GPIO_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), imu_int_gpios, 1);
static const struct gpio_dt_spec btn = GPIO_DT_SPEC_GET(DT_NODELABEL(btn), gpios);

static void btn_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins){
	if(pins & BIT(btn.pin)){
		if(gpio_pin_get_dt(&btn)){
			LOG_INF("Minus button pressed");
		}else{
			LOG_INF("Minus button released");
		}
	}
}

static void _fifo_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins){
    if(pins & BIT(imu_int1.pin)){
        LOG_INF("INT1");
    }else if(pins & BIT(imu_int2.pin)){
		LOG_INF("INT2");
    }else{
        LOG_ERR("unknown interrupt pin");
    }
}


int main(void){
	LOG_INF("Start");

	int err;
	// btn GPIO1.10
	err = gpio_pin_configure_dt(&btn, GPIO_INPUT);
	err |= gpio_pin_interrupt_configure_dt(&btn, GPIO_INT_EDGE_BOTH);
	gpio_port_pins_t pin_mask = BIT(btn.pin);
	static struct gpio_callback cb;
	gpio_init_callback(&cb, btn_callback, pin_mask);
	err |= gpio_add_callback(btn.port, &cb);

	// INT1 GPIO1.9 and INT2 GPIO0.27
	err = gpio_pin_configure_dt(&imu_int1, GPIO_INPUT | GPIO_ACTIVE_HIGH);
    err |= gpio_pin_interrupt_configure_dt(&imu_int1, GPIO_INT_EDGE_TO_ACTIVE);
    err |= gpio_pin_configure_dt(&imu_int2, GPIO_INPUT | GPIO_ACTIVE_HIGH);
    err |= gpio_pin_interrupt_configure_dt(&imu_int2, GPIO_INT_EDGE_TO_ACTIVE);
	static struct gpio_callback fifo_cb;
    gpio_init_callback(&fifo_cb, _fifo_callback, BIT(imu_int1.pin) | BIT(imu_int2.pin));
    err |= gpio_add_callback(imu_int1.port, &fifo_cb);
	// configuring this disables the callback on BTN
    // err |= gpio_add_callback(imu_int2.port, &fifo_cb);

	LOG_INF("Adios");

	return 0;
}

/ {
    zephyr,user {
    imu-int-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>, //INT1
                      <&gpio0 27 GPIO_ACTIVE_HIGH>; //INT2
    };

    buttons {
        compatible = "gpio-keys";
        debounce-interval-ms = <20>;
        btn: button_2 {
            gpios = <&gpio1 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
            label = "Btn";
        };
    };
};

Parents
  • Hello,

    I can't grasp what the problem is here, looks to be some sort of bug. I suggest as workaround to change:

         static struct gpio_callback fifo_cb;
         gpio_init_callback(&fifo_cb, _fifo_callback, BIT(imu_int1.pin) | BIT(imu_int2.pin));

    To

         static struct gpio_callback fifo_cb1;
         static struct gpio_callback fifo_cb2;
         gpio_init_callback(&fifo_cb1, _fifo_callback, BIT(imu_int1.pin));
         gpio_init_callback(&fifo_cb2, _fifo_callback, BIT(imu_int1.pin));

         err |= gpio_add_callback(imu_int1.port, &fifo_cb1);
         err |= gpio_add_callback(imu_int2.port, &fifo_cb2);

    The same _fifo_callback callback will be called, so should not be a problem. I can try to report it unless you find the cause.

    Kenneth

Reply Children
No Data
Related