The current is about 500uA when nrf52840 in idle mode

Hi,

SDK version : NCS 2.1.0

Hardware : nRF52840 DK (External supply)

I am trying to put the nrf52840 to idle mode based on the system_off example. 

D:\NCS_2.1.0\v2.1.0\zephyr\samples\boards\nrf\system_off

prj,config setting

CONFIG_PM=y
# 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_THREAD_NAME=y

# enable DC.DC
CONFIG_BOARD_ENABLE_DCDC=y

I use pm_state_force(0u, &(struct pm_state_info){PM_STATE_STANDBY, 0, 0}); to put system to idle mode and find the idle current is stuck at 500uA .

void main(void)
{
    int rc;
    const struct device *cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));

    if (!device_is_ready(cons)) {
        printk("%s: device not ready.\n", cons->name);
        return;
    }

    printk("\n%s system off demo\n", CONFIG_BOARD);

    if (IS_ENABLED(CONFIG_APP_RETENTION)) {
        bool retained_ok = retained_validate();

        /* Increment for this boot attempt and update. */
        retained.boots += 1;
        retained_update();

        printk("Retained data: %s\n", retained_ok ? "valid" : "INVALID");
        printk("Boot count: %u\n", retained.boots);
        printk("Off count: %u\n", retained.off_count);
        printk("Active Ticks: %" PRIu64 "\n", retained.uptime_sum);
    } else {
        printk("Retained data not supported\n");
    }

    /* Configure to generate PORT event (wakeup) on button 1 press. */
    nrf_gpio_cfg_input(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios),
               NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_sense_set(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios),
                   NRF_GPIO_PIN_SENSE_LOW);

    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; press BUTTON1 to restart\n");

    if (IS_ENABLED(CONFIG_APP_RETENTION)) {
        /* Update the retained state */
        retained.off_count += 1;
        retained_update();
    }

    /* Above we disabled entry to deep sleep based on duration of
     * controlled delay.  Here we need to override that, then
     * force entry to deep sleep on any delay.
     */
    pm_state_force(0u, &(struct pm_state_info){PM_STATE_STANDBY, 0, 0});


    /* Now we need to go sleep. This will let the idle thread runs and
     * the pm subsystem will use the forced state. To confirm that the
     * forced state is used, lets set the same timeout used previously.
     */
    k_sleep(K_SECONDS(SLEEP_S));

    printk("ERROR: System off failed\n");
    while (true) {
        return;
    }
}

As my understanding, once there is no other thread running, system will enter the idle thread. 

I also use thread analyzer to make sure there is no any other thread alive.

About the high current condition, do you have any advice on it?

Parents
  • 1- Are you sure you don't have any other peripherals attached to the board?

    2- Did you follow the guide provided by Nordic about making modifications to the board to measure the current using PPK

    3- Are you using the config file from the example? Or have you changed it in any way?

  • Hi

    1. I'm sure there are no other peripherals attached to the board. Below is the board I used.

    2. I use OTII to power the dk board and measure the current. Do I need to do other settings on dk board?

    3. Yes, I used the config file from the example and didn't do any changes to them. I only modify the main.c at 2 places.

    (1) change  pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0}) to pm_state_force(0u, &(struct pm_state_info){PM_STATE_STANDBY, 0, 0})

    (2) Add a return in main function to let main thread be suspended. (Make sure system enters idle thread)

    #Note : I also try the pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0}) on dk board and the current can successfully drop to 5uA as picture shown. But the system_off state didn't meet our need. We just need the system enter idle mode. (system sleep ON mode)

  • Hi, if you attach the Otii to the external supply header you will measure the current to the whole DK, including the debugger chip. Please have a look at this blog post on how to measure current on the DK (the blog is for nRF91 DK but it should be similar for the nRF52840 DK):

    Getting started with current measurements on the nRF9160 

    Since the Otii is an source measurement unit (SMU), you will have to use the SMU setup described in the blog. You also need to cut the SB22 solder bridge on the nRF52840 DK. And set the output voltage on the Otii to match the VDD voltage on the DK (3V), in order to avoid leakage current through the SWD lines.

  • Hi

    Thank you for your reply. I tried the SMU setup on nrf52840dk based on the blog step.

    But the current seems still as high as I used external power measuring. (about 500uA)

    Below was my setup.

    I also cut off the SB22 but it didn't improve the power consumption

    Do I need to do anything on SW when the system enters idle mode? 

  • Hi, I was wrong with SB22, it is for another DK version. You need to cut SB40. I'm very sorry. This is where it is located:

    This must be cut in order to disconnect VDD_nRF (which you are powering with the yellow cable), from VDD (which is powered from USB).

    I also see that the "nRF power switch" on your board is put to the Lo-Po position. This must be set to the default VDD position.

    About the CONFIG_SERIAL=y, and 600 uA, in order to both use the UART and get low power consumption, you either need to implement the "low power UART" driver, or you need to dynamically turn on and off the UART in the application using the device power management API.

    There is a blog post about power management in Zephyr here:  Optimizing Power on nRF5340 SoC Designs

    Best regards,
    Stian

Reply Children
No Data
Related