This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to configure multiple GPIOs in nRF9160 DK?

I want to use several GPIOs for different purposes.

for example,
- motion detection interrupt by accelerometer 
- low battery alert interrupt by battery gauge.

However, it doesn't work. Any help?

This is my code below. When I configure second GPIO in the line of gpio_fake_interrupt = device_get_binding("GPIO_1"), it causes error. Why?

#include <zephyr.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <gpio.h>
#include <i2c.h>
#include <device.h>

/* for accelerometer */
#define I2C_ACCEL_ADDR (0x32 >> 1)
#define GPIO_IN_ACCEL_INT GPIO_OUT_PIN11_Pos

#define DEV "dev"

struct device *i2c_accel;
struct device *gpio_accel_interrupt;
struct gpio_callback gpio_cb;
bool is_move = false;

void accel_interrupt(struct device *gpio, struct gpio_callback *cb, u32_t pins) {
    is_move = true;
}

u8_t init_accelerometer() {
    i2c_accel = device_get_binding("I2C_1");
    if (!i2c_accel) {
        return -1;
    }

    /* Configure accelerometer */
    .
    .
    /* end */

    return 0;
}

u8_t init_accel_interrupt_gpio() {
    int8_t ret;

    gpio_accel_interrupt = device_get_binding("GPIO_0");
    if (!gpio_accel_interrupt) {
        printk("gpio_accel_interrupt init error\r\n");
        return -1;
    }

    ret = gpio_pin_configure(gpio_accel_interrupt, GPIO_IN_ACCEL_INT, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH));
    if (ret) {
        printk("Error configuring %lu!\n", GPIO_IN_ACCEL_INT);
        return -1;
    }

    gpio_init_callback(&gpio_cb, accel_interrupt, BIT(GPIO_IN_ACCEL_INT));

    ret = gpio_add_callback(gpio_accel_interrupt, &gpio_cb);
    if (ret){
        printk("Cannot setup callback!\n");
        return -1;
    }

    ret =  gpio_pin_enable_callback(gpio_accel_interrupt, GPIO_IN_ACCEL_INT);
    if (ret){
        printk("Error enabling callback!\n");
        return -1;
    }

    return 0;
}

#if defined(DEV)
#define GPIO_IN_FAKE_INT GPIO_OUT_PIN18_Pos
struct device *gpio_fake_interrupt;
struct gpio_callback gpio_fake_cb;

void fake_interrupt(struct device *gpio, struct gpio_callback *cb, u32_t pins) {
    printk("fake_interrupt\r\n");
}

u8_t init_fake_interrupt_gpio() {
    int8_t ret;

    gpio_fake_interrupt = device_get_binding("GPIO_1");
    if (!gpio_fake_interrupt) {
        printk("gpio_fake_interrupt init error\r\n"); // ERROR  OCCURS HERE !!!
        return -1;
    }

    ret = gpio_pin_configure(gpio_fake_interrupt, GPIO_IN_FAKE_INT, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH));
    if (ret) {
        printk("Error configuring %lu! gpio_fake_interrupt\n", GPIO_IN_FAKE_INT);
        return -1;
    }

    gpio_init_callback(&gpio_fake_cb, fake_interrupt, BIT(GPIO_IN_FAKE_INT));

    ret = gpio_add_callback(gpio_fake_interrupt, &gpio_fake_cb);
    if (ret){
        printk("Cannot setup callback! gpio_fake_interrupt\n");
        return -1;
    }

    ret =  gpio_pin_enable_callback(gpio_fake_interrupt, GPIO_IN_FAKE_INT);
    if (ret){
        printk("Error enabling callback! gpio_fake_interrupt\n");
        return -1;
    }

    return 0;
}
#endif

void main(void)
{
    if(init_accelerometer() != 0) {
        sys_reboot();
    }

    if (init_accel_interrupt_gpio() != 0) {
        sys_reboot();
    }

#if defined(DEV)
    if (init_fake_interrupt_gpio() != 0) {
        printk("init_fake_interrupt_gpio fails!);
    }
#endif

    while (1) {
        k_cpu_idle();
        printk("is_move = %u\n", is_move);    
    }            
}

Parents Reply Children
  • Thank you for your reply!

    I got it. What about gpio_callback? Should it be only one object in main.c?

    Could you show me an example code which configures two different GPIO interrupt?

  • There shouldn't be any issue with using gpio_callback again in main.c or in other source files. gpio_callback simply sets up a struct of type gpio_callback.

    You then link that structure to the struct device you set-up to hold the device_get_binding and gpio_pin_configure, using the callback functions. The APIs should allow you to set-up multiple callbacks this way.

  • Hi, MJD093.

    I improved the program using two GPIO interrupt. Is this correct?

    In the function of init_accel_interrupt_gpio, the two GPIO interrupt is configured.

    #include <zephyr.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <gpio.h>
    #include <i2c.h>
    #include <device.h>
    
    /* for accelerometer */
    #define I2C_ACCEL_ADDR (0x32 >> 1)
    #define GPIO_IN_ACCEL_INT GPIO_OUT_PIN11_Pos
    #define GPIO_IN_FAKE_INT GPIO_OUT_PIN18_Pos
    #define DEV "dev"
    
    struct device *i2c_accel;
    struct device *gpio_accel_interrupt;
    struct gpio_callback gpio_cb;
    bool is_move = false;
    
    struct device *gpio_fake_interrupt;
    struct gpio_callback gpio_fake_cb;
    
    void accel_interrupt(struct device *gpio, struct gpio_callback *cb, u32_t pins) {
        is_move = true;
    }
    
    void fake_interrupt(struct device *gpio, struct gpio_callback *cb, u32_t pins) {
        printk("fake_interrupt\r\n");
    }
    
    u8_t init_accelerometer() {
        i2c_accel = device_get_binding("I2C_1");
        if (!i2c_accel) {
            return -1;
        }
    
        /* Configure accelerometer */
        .
        .
        /* end */
    
        return 0;
    }
    
    u8_t init_accel_interrupt_gpio() {
        int8_t ret;
    
        gpio_cntrler = device_get_binding("GPIO_0");
        if (!gpio_cntrler) {
            printk("gpio_cntrler init error\r\n");
            return -1;
        }
        
        /* accel_interrupt set up */
        
        ret = gpio_pin_configure(gpio_cntrler, GPIO_IN_ACCEL_INT, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH));
        if (ret) {
            printk("Error configuring %lu!\n", GPIO_IN_ACCEL_INT);
            return -1;
        }
        
        gpio_init_callback(&gpio_cb, accel_interrupt, BIT(GPIO_IN_ACCEL_INT));
    
        ret = gpio_add_callback(gpio_cntrler, &gpio_cb);
        if (ret){
            printk("Cannot setup callback!\n");
            return -1;
        }
    
        ret =  gpio_pin_enable_callback(gpio_cntrler, GPIO_IN_ACCEL_INT);
        if (ret){
            printk("Error enabling callback!\n");
            return -1;
        }
        
        /* gpio_fake_interrupt */
    
        ret = gpio_pin_configure(gpio_cntrler, GPIO_IN_FAKE_INT, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH));
        if (ret) {
            printk("Error configuring %lu!\n", GPIO_IN_FAKE_INT);
            return -1;
        }
    
        gpio_init_callback(&gpio_fake_cb, fake_interrupt, BIT(GPIO_IN_FAKE_INT));
    
        ret = gpio_add_callback(gpio_cntrler, &gpio_fake_cb);
        if (ret){
            printk("Cannot setup callback!\n");
            return -1;
        }
    
        ret =  gpio_pin_enable_callback(gpio_cntrler, GPIO_IN_FAKE_INT);
        if (ret){
            printk("Error enabling callback!\n");
            return -1;
        }
    
        return 0;
    }
    
    void main(void)
    {
        if(init_accelerometer() != 0) {
            sys_reboot();
        }
    
        if (init_accel_interrupt_gpio() != 0) {
            sys_reboot();
        }
    
        while (1) {
            k_cpu_idle();
            printk("is_move = %u\n", is_move);    
        }            
    }
    

  • seems ok, just tested two interrupt callbacks and they work

Related