This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

nRF51822 and Zephyr: GPIO interrupt on multiple GPIOs

Hello, guys!

I am using nRF51822 SoC with Zephyr. There is a need to configure multiple GPIOs as inputs, with the possibility to fire an interrupt on rising/falling/both edges.
The following piece of code is used to configure one single GPIO:

#define GPIO_PORT DT_LABEL(DT_NODELABEL(gpio0))
const struct device *gpio0;
struct gpio_callback callback;
void Touch1IrqCallback(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins);
    
gpio0 = device_get_binding(GPIO_PORT);

gpio_pin_configure(gpio0, Pin1, GPIO_INPUT | GPIO_PULL_UP);
gpio_pin_interrupt_configure(gpio0, Pin1, GPIO_INT_EDGE_BOTH);
gpio_init_callback(&callback, Touch1IrqCallback, BIT(Pin1));    
gpio_add_callback(gpio0, &callback);



Everything works well until the point when I want to configure 3rd GPIO the same way. At that moment, gpio_pin_interrupt_configure() function returns -19 which is the code for ENODEV.

Is there anything I am missing or I am not aware of? Can we configure multiple nRF51822 GPIOs to fire an interrupt?

Parents
  • Hi,

     

    I highly suspect that it's this call that returns ENODEV:

    https://github.com/nrfconnect/sdk-zephyr/blob/v2.7.0-ncs1/drivers/gpio/gpio_nrfx.c#L60

     

    The nRF51 devices has 4 GPIOTE channels available, are you using any of them in other parts of your application?

     

    Kind regards,

    Håkon

  • Hello, Hakon.

    Thanks for the clarifications. I don't use GPIOTE channels in other parts of the code.

    Perhaps the error occurs because I have 2xGPIOs sensitive to BOTH edges?

    Regards,

    Bojan

  • Hi Bojan,

     

    I just quickly added more inputs to the zephyr/samples/basic/button sample in ncs v1.8.0 (zephyr v2.7.0):

    /*
     * Copyright (c) 2016 Open-RnD Sp. z o.o.
     * Copyright (c) 2020 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <device.h>
    #include <drivers/gpio.h>
    #include <sys/util.h>
    #include <sys/printk.h>
    #include <inttypes.h>
    
    #define SLEEP_TIME_MS	1
    
    /*
     * Get button configuration from the devicetree sw0 alias. This is mandatory.
     */
    #define SW0_NODE	DT_ALIAS(sw0)
    #if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
    #error "Unsupported board: sw0 devicetree alias is not defined"
    #endif
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios,
    							      {0});
    static struct gpio_callback button0_cb_data;
    static struct gpio_callback button1_cb_data;
    static struct gpio_callback button2_cb_data;
    static struct gpio_callback button3_cb_data;
    
    #define PIN1 18
    #define PIN2 19
    #define PIN3 20
    
    /*
     * The led0 devicetree alias is optional. If present, we'll use it
     * to turn on the LED whenever the button is pressed.
     */
    static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios,
    						     {0});
    
    void button_pressed(const struct device *dev, struct gpio_callback *cb,
    		    uint32_t pins)
    {
    	uint32_t bit_to_pin = 0;
    	for (int i = 0; i < 32; i++) {
    		if ((pins >> i) == 1) {
    			bit_to_pin = i;
    			break;
    		}
    	}
    
    	printk("Button %d pressed at %" PRIu32 "\n", bit_to_pin, k_cycle_get_32());
    	static bool val;
    	val = !val;
    	gpio_pin_set_dt(&led, val);	
    }
    
    void main(void)
    {
    	int ret;
    
    	if (!device_is_ready(button.port)) {
    		printk("Error: button device %s is not ready\n",
    		       button.port->name);
    		return;
    	}
    
    	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
    	if (ret != 0) {
    		printk("Error %d: failed to configure %s pin %d\n",
    		       ret, button.port->name, button.pin);
    		return;
    	}
    
    	ret = gpio_pin_interrupt_configure_dt(&button,
    					      GPIO_INT_EDGE_TO_ACTIVE);
    	if (ret != 0) {
    		printk("Error %d: failed to configure interrupt on %s pin %d\n",
    			ret, button.port->name, button.pin);
    		return;
    	}
    
    	ret = gpio_pin_configure(button.port, PIN1, GPIO_INPUT | GPIO_PULL_UP);
    	printk("ret %d\n", ret);
    	ret = gpio_pin_configure(button.port, PIN2, GPIO_INPUT | GPIO_PULL_UP);
    	printk("ret %d\n", ret);
    	ret = gpio_pin_configure(button.port, PIN3, GPIO_INPUT | GPIO_PULL_UP);
    	printk("ret %d\n", ret);
    	ret = gpio_pin_interrupt_configure(button.port, PIN1, GPIO_INT_EDGE_BOTH);
    	printk("ret %d\n", ret);
    	ret = gpio_pin_interrupt_configure(button.port, PIN2, GPIO_INT_EDGE_BOTH);
    	printk("ret %d\n", ret);
    	ret = gpio_pin_interrupt_configure(button.port, PIN3, GPIO_INT_EDGE_BOTH);
    	printk("ret %d\n", ret);
    	gpio_init_callback(&button1_cb_data, button_pressed, BIT(PIN1));
    	ret = gpio_add_callback(button.port, &button1_cb_data);
    	printk("ret %d\n", ret);
    	gpio_init_callback(&button2_cb_data, button_pressed, BIT(PIN2));	
    	ret = gpio_add_callback(button.port, &button2_cb_data);
    	printk("ret %d\n", ret);
    	gpio_init_callback(&button3_cb_data, button_pressed, BIT(PIN3));	
    	ret = gpio_add_callback(button.port, &button3_cb_data);		
    	printk("ret %d\n", ret);
    	
    
    	gpio_init_callback(&button0_cb_data, button_pressed, BIT(button.pin));
    	gpio_add_callback(button.port, &button0_cb_data);
    	printk("Set up button at %s pin %d\n", button.port->name, button.pin);
    
    	if (led.port && !device_is_ready(led.port)) {
    		printk("Error %d: LED device %s is not ready; ignoring it\n",
    		       ret, led.port->name);
    		led.port = NULL;
    	}
    	if (led.port) {
    		ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
    		if (ret != 0) {
    			printk("Error %d: failed to configure LED device %s pin %d\n",
    			       ret, led.port->name, led.pin);
    			led.port = NULL;
    		} else {
    			printk("Set up LED at %s pin %d\n", led.port->name, led.pin);
    		}
    	}
    
    	printk("Press the button\n");
    }
    

     

    And it works as expected on my end (on my nrf51dk):

    *** Booting Zephyr OS build v2.7.0-ncs1  ***
    ...
    Set up button at GPIO_0 pin 17
    Set up LED at GPIO_0 pin 21
    Press the button
    Button 17 pressed at 234164
    Button 18 pressed at 253241
    Button 18 pressed at 256734
    Button 18 pressed at 256835
    Button 19 pressed at 272220
    Button 19 pressed at 276119
    Button 20 pressed at 288819
    Button 20 pressed at 292737
    

     

    Kind regards,

    Håkon

  • Thanks, Hakon. Let me dive deeper and figure out what I am missing.

    Thanks for the great support!

Reply Children
Related