Hi! I have a problem with waking up from system on using gpio interrupts. Originally I was using SYSTEM OFF and that was working fine but i also wanted to wake the system up with the RTC. Now this works on SYSTEM ON. I can specify a time and the system wakes up by an interrupt from an RTC. But now I want it to work with gpios too but for some reason it does not wake up. This is my code so far:
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/pm/device.h>
#include <zephyr/sys/poweroff.h>
#include <soc.h>
#include <hal/nrf_gpio.h>
#include <hal/nrf_regulators.h>
#include <zephyr/drivers/gpio.h>
#include <modem/lte_lc.h>
#include <modem/nrf_modem_lib.h>
#include <nrfx_rtc.h>
#include <nrfx_clock.h>
#define BUSY_WAIT_S 2U
#define SLEEP_S 2U
#define NODE_SWITCH DT_ALIAS(sw0)
#define SW0_PIN 6
#define LED0_NODE DT_ALIAS(led0)
#define INPUT_PIN_NODE DT_NODELABEL(input_pin)
#define INPUT_PIN_NODE2 DT_NODELABEL(input_pin2)
#define OUTPUT_PIN_NODE DT_NODELABEL(output_pin)
// static const struct device *switch_dev = DEVICE_DT_GET(NODE_SWITCH);
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec input_pin = GPIO_DT_SPEC_GET(INPUT_PIN_NODE, gpios);
static const struct gpio_dt_spec input2_pin = GPIO_DT_SPEC_GET(INPUT_PIN_NODE2, gpios);
// static const struct gpio_dt_spec output_pin = GPIO_DT_SPEC_GET(OUTPUT_PIN_NODE, gpios);
static const struct gpio_dt_spec output_pin = GPIO_DT_SPEC_GET(OUTPUT_PIN_NODE, gpios);
static const nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(0);
static void rtc_handler(nrfx_rtc_int_type_t int_type)
{
if (int_type == NRFX_RTC_INT_COMPARE0)
{
printk("RTC compare event\n");
}
else if (int_type == NRFX_RTC_INT_TICK)
{
printk("RTC tick event\n");
}
}
static void rtc_config(void)
{
nrfx_err_t err_code;
//Initialize RTC instance
printf("RTC instance\n");
nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
err_code = nrfx_rtc_init(&rtc, &config, rtc_handler);
if (err_code != NRFX_SUCCESS)
{
printk("Error initializing RTC\n");
k_msleep(1000);
}
printf("RTC initialized\n");
//Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
err_code = nrfx_rtc_cc_set(&rtc,0, 32768*35, true);
if (err_code != NRFX_SUCCESS)
{
printk("Error setting compare channel\n");
}
printf("RTC compare channel set\n");
//Power on RTC instance
nrfx_rtc_enable(&rtc);
printf("RTC enabled\n");
}
int main(void)
{
uint32_t input_pin_nr = DT_GPIO_PIN(INPUT_PIN_NODE, gpios);
uint32_t input2_pin_nr = DT_GPIO_PIN(INPUT_PIN_NODE2, gpios);
printf("latch input pin 16 %d\n", nrf_gpio_pin_latch_get(input_pin_nr));
printf("latch input pin 13 %d\n", nrf_gpio_pin_latch_get(input2_pin_nr));
// Toggle LED0 ON
int ret;
// Output pin
if (!gpio_is_ready_dt(&output_pin)) {
printf("Output pin is not ready\n");
return 0;
}
ret = gpio_pin_configure_dt(&output_pin, GPIO_OUTPUT_ACTIVE);
if (ret != 0) {
printf("Configuring GPIO pin failed: %d\n", ret);
return 0;
}
gpio_pin_set_dt(&output_pin, 1);
if (!gpio_is_ready_dt(&led)) {
return 0;
}
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
int rc;
const struct device *const cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
if (!device_is_ready(cons)) {
printk("%s: device not ready.\n", cons->name);
return 0;
}
printk("\n%s system off demo\n", CONFIG_BOARD);
/* Configure to generate PORT event (wakeup) on input pin interrupt. */
nrf_gpio_cfg_input(NRF_DT_GPIOS_TO_PSEL(INPUT_PIN_NODE, gpios),
NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(NRF_DT_GPIOS_TO_PSEL(INPUT_PIN_NODE, gpios),
NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_input(NRF_DT_GPIOS_TO_PSEL(INPUT_PIN_NODE2, gpios),
NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(NRF_DT_GPIOS_TO_PSEL(INPUT_PIN_NODE2, gpios),
NRF_GPIO_PIN_SENSE_LOW);
//configure GPIOTE interrupt
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
NVIC_EnableIRQ(GPIOTE0_IRQn);
printk("Busy-wait %u s\n", BUSY_WAIT_S);
k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
printk("Busy-wait %u s with UART off\n", BUSY_WAIT_S);
rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);
rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);
printk("Sleep %u s\n", SLEEP_S);
k_sleep(K_SECONDS(SLEEP_S));
printk("Sleep %u s with UART off\n", SLEEP_S);
rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
k_sleep(K_SECONDS(SLEEP_S));
rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME);
printk("Entering system off; Waiting to be awaken from input_pin\n");
// Turn off output pin before entering system off
ret = gpio_pin_set_dt(&output_pin, 0);
if (ret) {
printf("Error setting output pin: %d\n", ret);
return 0;
}
// Toggle LED0 OFF before entering system off
ret = gpio_pin_toggle_dt(&led);
if (ret < 0) {
return 0;
}
// turn off the LTE modem to allow the system to enter full system off.
printf("resetting latch\n");
nrf_gpio_pin_latch_clear(input_pin_nr);
nrf_gpio_pin_latch_clear(input2_pin_nr);
rtc_config();
nrf_modem_lib_init();
lte_lc_power_off();
rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);
k_msleep(1000);
__SEV();
__WFE();
__WFE();
// NRF_REGULATORS->SYSTEMOFF = 1;
return 0;
}
void GPIOTE_IRQHandler(void)
{
// This handler will be run after wakeup from system ON (GPIO wakeup)
if(NRF_GPIOTE->EVENTS_PORT)
{
NRF_GPIOTE->EVENTS_PORT = 0;
}
}And this is my prj.conf:
# Required to disable default behavior of deep sleep on timeout CONFIG_PM_DEVICE=y CONFIG_GPIO=y # Optional select RAM retention (nRF52 only) #CONFIG_APP_RETENTION=y CONFIG_CRC=y CONFIG_POWEROFF=y CONFIG_NRFX_RTC0=y #Below forces us to build the nonsecure image for the nRF9160dk i.e.: "west build -p -b nrf9160dk_nrf9160ns". CONFIG_LTE_LINK_CONTROL=y #Below means that the modem will not automatically connect to the network on boot, you need to manually enable it of you want to connect to the network. #Putting this to "y" will mess with the system off mode current consumption. #If auto connect is enabled, the MCU will restart itself straight after it has entered system off mode. CONFIG_LTE_AUTO_INIT_AND_CONNECT=n CONFIG_NRF_MODEM_LIB=y #Below is not crucial to be disabled to allow the system off mode to work. CONFIG_DEBUG=n CONFIG_PM_DEVICE=y
Thanks in advance!
Best,
Ray