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

nRF9160 wake up from button interrupt not working.

I am trying to use a button to put the nRF9160 to sleep and to wake it back up. 

I configure my button as follows:

gpio_pin_configure(dev, PIN, GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL);

gpio_init_callback(&button_cb, button_pressed, BIT(PIN));

gpio_add_callback(dev, &button_cb);

gpio_pin_enable_callback(dev, PIN);

and the callback button_pressed looks like this:

void button_pressed(struct device *dev, struct gpio_callback *cb, u32_t pin)
{
  sleep = !sleep;
  if ( sleep )
  {
    __WFI();
  }

  else
  {
    printk("Waking\n");
  }

}

When the system is awake and the button is pressed it goes to sleep properly, but when I press the button again it doesn't wake up.

It will wake up on its own after a few seconds, from some other interrupt.

The button callback will also be run when it does wake up, as "Waking" is printed immediately after it wakes, but the button isn't whats waking it up.

Any idea why it's not working?

  • Hi,

     

    Try to use 

    k_cpu_idle();
    instead of 
    __WFI();
    .

     

    I tested this with the following code:

     

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
     */
    
    #include <gpio.h>
    #include <net/socket.h>
    #include <nrf9160.h>
    #include <stdio.h>
    #include <string.h>
    #include <uart.h>
    #include <zephyr.h>
    
    struct device *gpio_dev;
    static const u8_t led_pins[] = { LED0_GPIO_PIN, LED1_GPIO_PIN, LED2_GPIO_PIN,
    				 LED3_GPIO_PIN };
    
    #define PIN SW0_GPIO_PIN
    
    static struct gpio_callback button_cb;
    
    void button_pressed(struct device *dev, struct gpio_callback *cb, u32_t pin)
    {
    	static bool sleep;
    	sleep = !sleep;
    	if (sleep) {
    		gpio_pin_write(gpio_dev, led_pins[0], 1);
    		printk("sleep!\n");
    		k_cpu_idle();
    	} else {
    		gpio_pin_write(gpio_dev, led_pins[0], 0);
    		printk("wakeup!\n");
    	}
    }
    
    int dk_leds_init(void)
    {
    	int err = 0;
    
    	gpio_dev = device_get_binding(DT_GPIO_P0_DEV_NAME);
    	if (!gpio_dev) {
    		printk("Cannot bind gpio device");
    		return -ENODEV;
    	}
    
    	for (size_t i = 0; i < ARRAY_SIZE(led_pins); i++) {
    		err = gpio_pin_configure(gpio_dev, led_pins[i], GPIO_DIR_OUT);
    
    		if (err) {
    			printk("Cannot configure LED gpio");
    			return err;
    		}
    	}
    	gpio_pin_configure(gpio_dev, PIN, GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW | GPIO_PUD_PULL_UP);
    
    	gpio_init_callback(&button_cb, button_pressed, BIT(PIN));
    	gpio_add_callback(gpio_dev, &button_cb);
    
    	gpio_pin_enable_callback(gpio_dev, PIN);	
    
    	return err;
    }
    
    int main(void)
    {
    	printk("GPIO demo!\n");
    	int err = dk_leds_init();
    	if (err) {
    		printk("Error gpio config: %d", err);
    	}
    	while (1) {
    		/* Using native gpio library adds delay */
    		k_sleep(500);
    		gpio_pin_write(gpio_dev, led_pins[1], 0);
    		k_sleep(500);
    		gpio_pin_write(gpio_dev, led_pins[1], 1);		
    	}
    }
    

    And do note the flags I put into the gpio configure: 

    gpio_pin_configure(gpio_dev, PIN, GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW | GPIO_PUD_PULL_UP);

    Unless you have external pull resistor, you need to apply either pull up or pull down (depending on your active level).

     

    Kind regards,

    Håkon

  • I tried this but there was no difference. In my main function I have a simple while loop that increments a counter and prints the counter, and then does k_busy_wait(100000); If i switch out k_busy_wait for k_sleep(500), it won't go to sleep at all. "Sleeping" and "Waking" get printed but the counter just keeps incrementing and printing regardless of which state its in.

Related