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 

  • AndyM said:
    Your hunch was correct. I was including a header which redefined the BIT macro so the pin used for the button was added to the pin mask for the accelerometer interrupt and that' caused the accelerometer gpio callback to be called  on a button press. I fixed that and now the button press works fine and does not trigger the accelerometer gpio callback. .Thank you!

    Good,

    AndyM said:
    However the accelerometer interrup callback still is not called on a movement event, as expected. I'm certain that the part generates the interrupt - if I poll the control register of the accelerometer in a loop I see the interrupt bit set when the event occurs. I tried using  GPIO_INT_EDGE_TO_ACTIVE  and GPIO_INT_LEVEL_ACTIVE flags in gpio_pin_interrupt_configure_dt() function - makes no difference

    Can you double check it by probing the interrupt line either with an oscilloscope or logic analyzer and confirm that the pin is asserted by the accelerometer? 

    regards

    Jared 

  • Can you double check it by probing the interrupt line either with an oscilloscope or logic analyzer and confirm that the pin is asserted by the accelerometer? 

    I put in a request but it's out of my hands,l hopefully later this week.

    One peculiar thing is that  gpio_pin_get_dt() always returns 0  but the pin is configured as 

    GPIO_INPUT|GPIO_ACTIVE_HIGH so I expected to see a 1
    Is my expectation correct? And if it is wouldn't this point to hardware?
    Thanks
  • AndyM said:
    I put in a request but it's out of my hands,l hopefully later this week.

    Got it,

    AndyM said:
    GPIO_INPUT|GPIO_ACTIVE_HIGH so I expected to see a 1
    Is my expectation correct?

    If by this you mean that you configure the pin as GPIO_ACTIVE_HIGH in the dts and as an INPUT in the application with for example gpio_pin_configure_dt() then that is OK. But you still need to configure what interrupt that should trigger the callback handler which you have already done in gpio_pin_interrupt_configure_dt().

    I therefore wonder, does the accelerometer pull the signal to a logical 1 or a logical 0 when it enables the interrupt? Have you tried switching it to a GPIO_ACTIVE_LOW and see if that fixes the issue?

    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
Reply
  • 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
Children
Related