Multiple GPIO interrupts

Hello

I have 2 peripherals on my custom nRF52840 board: accelerometer and a touch button

I configured the gpio callbacks for both parts but see strange behavior: On a button press both  button and accelerometer GPIO callbacks trigger. But on the accelerometer event the accelerometer GPIO callback DOES NOT  trigger. I am 100% certain that the accelerometer is configured correctly and generates interrupt events.

Details below

Any ideas what is wrong??
Thank you

DTS

custom_pins {
        compatible = "gpio-keys";
button1: button_1 {
            gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
            label = "Touch button";
        };
// accelerometer int1
        acc_int1: acc_int1 {
            gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
        };
};
proj.conf
CONFIG_GPIO=y
---------------------------------
// buttton init code
static const struct gpio_dt_spec _btn_map[] = {
    GPIO_DT_SPEC_GET_OR(DT_ALIAS(sw1), gpios, {0}),
};

      
int btn_init(btn_cb_t cb)
{
    int ret;
    uint32_t btn_mask = 0;

    // Setup common callback. Note the callback struct must not be a local var.
    static struct gpio_callback gpio_cb;
   
    for (unsigned i=0; i<NUM_BTNS; ++i) {
        ret = gpio_pin_configure_dt(&_btn_map[i], GPIO_INPUT);
        if (ret != 0) {
            LOG_ERR("Error %d: failed to configure %s pin %d", ret, _btn_map[i].port->name, _btn_map[i].pin);
            return -1;
        }
        btn_mask |= BIT(_btn_map[i].pin);
        gpio_init_callback(&gpio_cb, btn_gpio_evt_cb, btn_mask);
        gpio_add_callback(_btn_map[i].port, &gpio_cb);
        ret = gpio_pin_interrupt_configure_dt(&_btn_map[i], GPIO_INT_EDGE_BOTH);
        if (ret != 0) {
            LOG_ERR("Error %d: failed to configure interrupt on %s pin %d", ret, _btn_map[i].port->name, _btn_map[i].pin);
            return -2;
        }
    }

    LOG_DBG("button config done.");

    return 0;
}
//------------------------
Accelerometer INT1 init  code
static const struct gpio_dt_spec _int1_dt_spec = GPIO_DT_SPEC_GET_OR(DT_ALIAS(accint1), gpios, {0});
gpio_pin_configure_dt(&_int1_dt_spec, GPIO_INPUT);
gpio_init_callback(&_gpio_int1_cb,gpio_int1_callback, BIT(_int1_dt_spec.pin));
gpio_add_callback(_int1_dt_spec.port, &_gpio_int1_cb);
gpio_pin_interrupt_configure_dt(&_int1_dt_spec,GPIO_INT_LEVEL_ACTIVE);

Parents
  • Question, Is it OK for the accelerometer int1 pin to be under "gpio-keys"  binding? The documentation says this is for buttons

    If no - what binding should be under ?

    Thanks

  • Hi,

    Just to be clear, are you saying that _gpio_int1_cb() is called when you press the GPIO button, but it's not called when accint1 is toggled by the accelerometer? 

    AndyM said:
    Question, Is it OK for the accelerometer int1 pin to be under "gpio-keys"  binding? The documentation says this is for buttons

    Yes, this should be fine,

    regards

    Jared 

  • Jared, just to clarify, I made the following changes  but it did not make a difference

    acc_int1: acc_int1 {
                gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
            };
    gpio_pin_configure_dt(&_int1_dt_spec, GPIO_INPUT|GPIO_ACTIVE_LOW);
    gpio_pin_interrupt_configure_dt(&_int1_dt_spec,GPIO_INT_LEVEL_INACTIVE);

    I also tried  GPIO_INT_EDGE_TO_ACTIVE when configuring the interrupt - no luck

    Did I miss anything?

    Thank you

     
  • Hi,

    AndyM said:
    Did I miss anything?

    That looks correct, were you able to verify if the interrupt line is toggled by the slave and if so in what direction?

    Another suggestion, can you try to move the gpio_pin_interrupt_configure_dt() call before gpio_init_callback() and see if that changes anything? Also try using 

    GPIO_INT_EDGE_TO_ACTIVE instead of GPIO_INT_LEVEL_ACTIVE as well. 
    regards
    Jared
  • Yes, in the code gpio_pin_interrupt_configure_dt is called before gpio_init_callback

    Unfortunately did not work

    Waiting on the results of the hardware analysis, will keep you posted

    Anything else worth trying in the meantime?

    Thank you

  • Jared

    I checked the spec - by default the INT1 pin polarity is active-high

    Also my gpio nodes are configured with sense-edge-mask i.e

    &gpio0 {
        status = "okay";
        sense-edge-mask = <0xffffffff>;
    };
    I believe this is done to avoid the limitation of 8 gpiote channels in the NRF52
    Not sure it matters, it does not work without that property either. Thought I'd bring it up just in case 
    Thank you
  • AndyM said:
    I believe this is done to avoid the limitation of 8 gpiote channels in the NRF52

    You might be into something here, what happens if you disable the other button interrupts completely by removing all code related to it. Both in the dts and main.c file. Only include the interrupt for the accelerometer. 

    This whole issue is a bit strange as setting up an interrupt for a button or an external slave should be exactly the same, effectively you should be able to replace the connection of one of the buttons to the pin with the accelerometer and see that it triggers the same interrupt. 

    regards

    Jared 

Reply
  • AndyM said:
    I believe this is done to avoid the limitation of 8 gpiote channels in the NRF52

    You might be into something here, what happens if you disable the other button interrupts completely by removing all code related to it. Both in the dts and main.c file. Only include the interrupt for the accelerometer. 

    This whole issue is a bit strange as setting up an interrupt for a button or an external slave should be exactly the same, effectively you should be able to replace the connection of one of the buttons to the pin with the accelerometer and see that it triggers the same interrupt. 

    regards

    Jared 

Children
Related