Can't reach low power with zephyr's GPIO API

Hi,

using nrf connect sdk 3.11, nrf54L15-PDK

I am testing low power with development board, I am trying to reach low power 2.9uA as bench marked.

When GPIO (button) set with interrupt on evaluation boards ,P1.13 i reach 23uA.

uart is disabled.

without this GPIO configuration i do reach low power benchmark target.

see code snippets to reproduce.

Steps:

1. I start with a shell example using the uart over USB on eval board.

2. call in main

const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart20));
    pm_device_runtime_enable(uart);
    pm_device_runtime_get(uart);

2. configure gpio button as seen in code below

3. Turn of UART using a shell command - pm_device_runtime_put(uart)

observe that current has reached 20uA.

-- when not configuring GPIO as below, eval board reach 2.9uA.

static const struct gpio_dt_spec pad_input_gpio = GPIO_DT_SPEC_GET(DT_NODELABEL(pad_state_in), gpios);

static void button_pressed(const struct device *gpio_dev, struct gpio_callback *cb,
		    uint32_t pins)
{
    // blink led
    LOG_INF("GPIOTE event:");
}

void setup_gpio(void)
{
    int ret;
    if (!device_is_ready((pad_input_gpio.port))) 
    {
        LOG_ERR("GPIO controller not ready");
        return -1;
    }

    ret = gpio_pin_configure_dt(&pad_input_gpio, GPIO_INPUT | GPIO_PULL_UP);
    if (ret != 0) 
    {
        LOG_ERR("Failed to configure pin (err %d)", ret);
        return -1;
    }
    
    uint32_t pin_mask = 0;
    pin_mask |= BIT(pad_input_gpio.pin);
    gpio_init_callback(&gpio_cb, button_pressed, pin_mask);
    int err = gpio_add_callback(pad_input_gpio.port, &gpio_cb);
    if (err) {
        LOG_ERR("Cannot add callback");
        return err;
    }

    gpio_pin_interrupt_configure_dt(&pad_input_gpio, GPIO_INT_EDGE_TO_ACTIVE);
}

CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000

CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y
#CONFIG_NRFX_UARTE20=y
#CONFIG_PINCTRL=y
#CONFIG_PINCTRL_NRF=y
#CONFIG_PINCTRL_DYNAMIC=y

# Shell
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_UART_CONSOLE=y

# Logging
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=2
CONFIG_LOG_MODE_MINIMAL=n
#CONFIG_LOG_BACKEND_UART=n
CONFIG_LOG_RUNTIME_FILTERING=y              # adds ability to change log levels at runtime
#CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_LOG_CMDS=y                           # shell commands
CONFIG_LOG_PRINTK=y

# Bluetooth
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="BLE_Advertiser"
CONFIG_BT_DEVICE_APPEARANCE=0
CONFIG_BT_PRIVACY=n
CONFIG_BT_HCI=y


#float support
CONFIG_CBPRINTF_FP_SUPPORT=y                # enables float support in printf functions

# external flash
CONFIG_FLASH=y
CONFIG_SPI_NOR_SFDP_RUNTIME=y               # enable SFDP support for SPI NOR flash
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_FLASH_PAGE_LAYOUT=y                  # enable flash page layout API    
CONFIG_FLASH_SHELL=y
CONFIG_FLASH_MAP=y

# NVS Filesystem
CONFIG_NVS=y
CONFIG_NVS_LOG_LEVEL_DBG=y
CONFIG_MPU_ALLOW_FLASH_WRITE=y

# Input sub system
CONFIG_INPUT=y
CONFIG_INPUT_EVENT_DUMP=y
CONFIG_INPUT_GPIO_KEYS=n
CONFIG_GPIO=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
#CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS MAX is 12
#CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS=12  
#CONFIG_NRFX_GPIOTE_LOG=y



# NFC
CONFIG_NFC_T4T_NRFXLIB=y
CONFIG_NFC_NDEF=y
CONFIG_NFC_NDEF_MSG=y
CONFIG_NFC_NDEF_RECORD=y
CONFIG_NFC_NDEF_LE_OOB_REC=y
CONFIG_NFC_NDEF_PARSER=y


# HEAP

# CONFIG_PM_PARTITION_SIZE_NVS_STORAGE=0x00

# MAIN TASK MODULE
CONFIG_APP_MAIN_TASK_ENABLED=y
CONFIG_APP_MAIN_TASK_SHORT_QUEUE_LEN=10
CONFIG_APP_MAIN_TASK_MAX_SHORT_MESSAGE_LEN=4
CONFIG_APP_MAIN_TASK_LONG_QUEUE_LEN=4
CONFIG_APP_MAIN_TASK_MAX_LONG_MESSAGE_LEN=128
CONFIG_APP_MAIN_TASK_MAX_NUM_OF_EVENTS=15 

I to tried all GPIO_INT_  defined configuration.  all do not help.

GPIO_INT_EDGE_TO_ACTIVE
GPIO_INT_LEVEL_INACTIVE
GPIO_INT_LEVEL_ACTIVE
GPIO_INT_EDGE_BOTH
GPIO_INT_LEVEL_INACTIVE
gpio_pin_interrupt_configure_dt(&pad_input_gpio, GPIO_INT_EDGE_TO_INACTIVE);

thanks.

Dan

Parents
  • overlay:

    #define PAD_IN_GPIO_SPEC        <&gpio1 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
        pad_input:pad_input {
            compatible = "gpio-keys";
            debounce-interval-ms = <150>;                      /* Debouncing time */
            pad_state_in: pad_state_in {
                gpios = PAD_IN_GPIO_SPEC;
                label = "pad_signal_in";
                zephyr,code = <INPUT_KEY_0>;
            };
  • Pretty sure this is intended behaviour, but it may not be properly documented.

    GPIOTE "in" events are more expensive than "port" events. But "port" events only support level detection - your code sets up edge detect which requires "in" event.

    I can't find documentation on how much current this is supposed to cost extra.

    Workaround is to use the "sense" mechanism (I believe you can set this up in DT overlay) and "level" triggered GPIO interrupt. 

    Note: Just setting up level triggers for the GPIO int is not enough, the pin must also be set up correctly (sense-edge-mask).

  • Added this into the device tree sense-edge-mask.
    It did the job. Thanks.
    Documentations is very poor.
    Expected this basic option to be enabled and supplied with nrf connect SDK.
    wasted hours on this, on contrary using nrfx gpiote API -
    worked immediately out of the box and it took 15 minutes.
    #define PAD_BTN_GPIO_SPEC       <&gpio1 8  (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
    &gpio1 {
        sense-edge-mask = <0x00002100>; /* P1.08 and P1.13 */
    };
        button_in:button_in {
            compatible = "gpio-keys";
            debounce-interval-ms = <150>;                      /* Debouncing time */
            button: button {
                gpios = PAD_BTN_GPIO_SPEC;
                label = "pad_btn";
                zephyr,code = <INPUT_KEY_2>;
            };
        };
Reply
  • Added this into the device tree sense-edge-mask.
    It did the job. Thanks.
    Documentations is very poor.
    Expected this basic option to be enabled and supplied with nrf connect SDK.
    wasted hours on this, on contrary using nrfx gpiote API -
    worked immediately out of the box and it took 15 minutes.
    #define PAD_BTN_GPIO_SPEC       <&gpio1 8  (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
    &gpio1 {
        sense-edge-mask = <0x00002100>; /* P1.08 and P1.13 */
    };
        button_in:button_in {
            compatible = "gpio-keys";
            debounce-interval-ms = <150>;                      /* Debouncing time */
            button: button {
                gpios = PAD_BTN_GPIO_SPEC;
                label = "pad_btn";
                zephyr,code = <INPUT_KEY_2>;
            };
        };
Children
No Data
Related