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