[nRF54L15 DK][Zephyr] How to implement deep sleep + interrupt-driven wakeup?

Hello,

I am exploring power management on the nRF54L15 DK with nRF Connect SDK v2.8.0 (Zephyr v3.7.99).

My goal is to:

  • Enter deep sleep / system off mode.

  • Wake up on an external GPIO interrupt ( Interrupt from LSM6DSL IMU Sensor).

What I tried so far

  • Tested with LSM6DSL IMU interrupt connected to the DK.

    • When the system is running normally (no sleep), the LSM6DSL interrupt is firing correctly.

    • But when entering system off / sleep, the interrupt does not wake the device.

    • Tried with k_sleep(K_FOREVER) and sys_poweroff(). for both interrupt is not waking up the device

  • Tested the system off demo sample (as-is from the SDK).

    • It enters system off successfully.

    • However, wakeup from Button0 (sw0) did not work on the nRF54L15 DK.

  • Tried adding wakeup-source; property in a device tree overlay:

    / {
    button0 {
    wakeup-source;
    };
    };

     Still no wakeup on button press.

    Environment

    • Board: nRF54L15 DK
    • NCS: v2.8.0
    • Toolchain: VS Code + west build

    Questions

    • What is the recommended way to implement deep sleep with interrupt-driven wakeup on nRF54L15?
    • Are there additional device tree settings or GPIOTE configurations required beyond wakeup-source;?
    • Does GPIO wakeup from sleep / system off currently work on nRF54L15 DK, or is this feature still pending support?
    • Are there reference examples or low power samples for nRF54l15 showing interrupt-driven wakeup?

    • lsm6dsl interrupt configure code snippet

    int configure_lsm6dsl_interrupt(void)
    {
        int rc;
        LOG_INF("Configuring LSM6DSL GPIO interrupt...");

        if (!device_is_ready(int_gpio.port)) {
            LOG_ERR("GPIO device not ready");
            return -ENODEV;
        }

        LOG_INF("GPIO device ready, configuring pin gpio %s, %d as input", int_gpio.port->name, int_gpio.pin);
        rc = gpio_pin_configure_dt(&int_gpio, GPIO_INPUT); // GPIO_PULL_DOWN
        if (rc) {
            LOG_ERR("Failed to configure GPIO pin %d: %d", int_gpio.pin, rc);
            return rc;
        }

        LOG_INF("Initializing GPIO callback structure...");
        //gpio_init_callback(&lsm_int_cb, lsm6dsl_no_motion_isr, 1U << int_gpio.pin);
        gpio_init_callback(&lsm_int_cb, lsm6dsl_no_motion_isr, BIT(int_gpio.pin));

        LOG_INF("Adding GPIO callback to port...");
        rc = gpio_add_callback(int_gpio.port, &lsm_int_cb);
        if (rc) {
            LOG_ERR("Failed to add GPIO callback: %d", rc);
            return rc;
        }

        LOG_INF("Enabling edge interrupt on GPIO pin...");
        rc = gpio_pin_interrupt_configure_dt(&int_gpio, GPIO_INT_LEVEL_HIGH | GPIO_INT_WAKEUP); //GPIO_INT_EDGE_TO_ACTIVE //GPIO_INT_LEVEL_ACTIVE //GPIO_INT_LEVEL_HIGH
        if (rc) {
            LOG_ERR("Failed to configure GPIO interrupt: %d", rc);
            return rc;
        }

        LOG_INF("LSM6DSL GPIO interrupt configured successfully on pin %d", int_gpio.pin);

        uint32_t abs_pin = NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(lsm6dsl), irq_gpios);
        uint32_t sense = nrf_gpio_pin_sense_get(abs_pin);
        printk("Pin %d sense setting: %d\n", abs_pin, sense);
        printk("  NRF_GPIO_PIN_NOSENSE   = %d\n", NRF_GPIO_PIN_NOSENSE);
        printk("  NRF_GPIO_PIN_SENSE_LOW = %d\n", NRF_GPIO_PIN_SENSE_LOW);
        printk("  NRF_GPIO_PIN_SENSE_HIGH= %d\n", NRF_GPIO_PIN_SENSE_HIGH);

        return 0;
    }
  • Hi Vishnu,

    When it comes to power off, I believe that might be a bit different on the 54L15. We have a bit about that here, and here for instance, though this quick sample mentioned by a colleague of mine might be more helpful. 

    And regarding having a pin wake-up, have a look at this other quick example I made for a customer earlier, that I think should also work for the nRF54L15 as well. You might have to add target_include_directories(app PRIVATE hal) to cmakelists to run it.

    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    
    
    #include <hal/nrf_gpio.h>
    #include <hal/nrf_power.h>
    #include <hal/nrf_regulators.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   1000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    
    /* The devicetree node identifier for the "sw0" alias (button0). */
    #define SW0_NODE DT_ALIAS(sw0)
    
    /*
     * A build error on this line means your board is unsupported.
     * See the sample documentation for information on how to fix this.
     */
    static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
    
    int main(void)
    {
    	int ret;
    	int iterate=0;
    	int naptime = 6;
    	bool led_state = true;
    	printk("Count down to System OFF mode: T-%d blinks\n", naptime/2);
    
    	if (!gpio_is_ready_dt(&led)) {
    		return 0;
    	}
    
    	if (!gpio_is_ready_dt(&button)) {
    		printk("Error: button device %s is not ready\n", button.port->name);
    		return 0;
    	}
    
    	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    	if (ret < 0) {
    		return 0;
    	}
    
    	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 0;
    	}
    
    	/* Configure the button pin for wake-up on low signal (button press) */
    	nrf_gpio_cfg_sense_set(button.pin, NRF_GPIO_PIN_SENSE_LOW);
    
    	while (iterate < naptime) {
    		ret = gpio_pin_toggle_dt(&led);
    		if (ret < 0) {
    			return 0;
    		}
    		iterate++;
    
    		led_state = !led_state;
    		printf("LED state: %s\n", led_state ? "ON" : "OFF");
    		k_msleep(SLEEP_TIME_MS);
    	}
    
    	printk("Entering sleep mode...\n");
    	/* Enter sleep mode */
    	nrf_regulators_system_off(NRF_REGULATORS);
    
    	return 0;
    }

    wakeup-source

    I am not that familiar with the wakeup-source property, but I do not think it does much by itself.

    Regards,

    Elfving

Related