This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Minimizing the power draw using System OFF and RAM retention

Hi everyone,

I'm having an issue with the power draw of my application (SDK 15.0.0, SD 132 v6, Sparkfun nRF52832 Breakout). The application does roughly the following: it sleeps until it receives an GPIO interrupt (there are two different GPIOs which can wake up the application), does some (non connectable) advertising and resumes sleeping.

According to the data sheet of the nRF52832 0.7 µA are possible with full RAM retention and in system state System OFF. The power draw of my application exceeds this number (around ten times higher), however I'm not utilising the System OFF mode yet (currently using only the nrf_pwr_mgmt_run() function).

I did some research and discovered the sd_power_off() function. When I add the sd_power_off() function to my code, the system "freezes" / 'hangs" and draws about 10mA.

I did take a look at the example "ble_app_pwr_profiling" but it is rather complex - has anyone created / found a simpler solution (do some advertising, go to System OFF with RAM retention, wake up to an GPIO interrupt, repeat) yet?

How can I differentiate the two different GPIO interrupt sources when using them to wake up? (I want to count the times my application has woken up to sources 1 and 2)


Best,

lhochstetter

  • Hi,

     

    If you are using the nrf_pwr_mgmt library, you should call the appropriate API for entering system off mode:

    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    Are you debugging while trying to enter system off mode? Emulated systemoff (entering system off in debug mode) will not work as intended, as it will return immediately due to the debugger being attached.
    Kind regards,
    Håkon
  • Hi,

    sorry for the belated reply. I tried your suggestion (the board did go to some sort of power saving mode, drawing ~1mA but was unresponsive afterwards).

    I spent some time studying the ble_app_pwr_profiling example. In the example two functions are used to go to the System OFF mode:

    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF)

    and

    sd_power_system_off()

    Since sd_power_system_off() is used in the ble_evt_handler() I assume that this function is used when the Softdevice is / was active. nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF) is used otherwise.

    Right now I'm trying to gut the ble_app_pwr_profiling example to get a simple non-connectable beacon which reacts to button presses, advertising the button pressed and the count of button presses, and returning to System OFF afterwards.

    EDIT

    I'm not debugging / There is no debugger attached

    /EDIT

    Best,

    lhochstetter

  • Hi,

     

    1 mA is too high. it should be ~1 uA in system off, given that there's no LEDs or similar that is on in sleep. Your GPIOs are latched when entering sleep mode, so it is important that you set these to a defined level, or disconnect them in firmware (setting NRF_GPIO->PIN_CNF[] field "CONNECT" to 0).

     

    You could add system off to any example, after a given time/event has occurred (per your application requirement).

    Here's an example for a active low button:

    nrf_gpio_cfg_sense_input(MY_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
    err_code = sd_power_system_off();
    APP_ERROR_CHECK(err_code);

     

    Kind regards,

    Håkon

  • Hi,

    thanks for the input, going to System OFF and waking up to the GPIO interrupts works!

    The remaining issues are the RAM retention and the "GPIO detection" (i.e. which GPIO is responsible for the interrupt).

    ---

    I tried to adapt the approach taken in the ble_app_pwr_profiling example, namely bsp_board_button_state_get(...) but to no avail.

    I would like to also connect an ISR to the GPIO interrupt if it takes place while the system is active / not in System OFF (I guess that I'll have to do the (ISR) configuration each time the system wakes up again).  Therefore I've configured the GPIOs like so:


    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
    in_config.pull = NRF_GPIO_PIN_PULLUP;
    err_code = nrf_drv_gpiote_in_init(BSP_BUTTON_0, &in_config, button_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_event_enable(BSP_BUTTON_0, true);



    How do I determine which GPIO woke up the system?

    ---

    I tried to merge my current code with the peripheral / ram_retention example:

        NRF_POWER->RAMON |= (POWER_RAMON_OFFRAM0_RAM0On << POWER_RAMON_OFFRAM0_Pos) |
                            (POWER_RAMON_OFFRAM1_RAM1On << POWER_RAMON_OFFRAM1_Pos);

    When I use this snippet the system freezes up again and the voltage rises to a couple hundred mV (without I measure <20 mV when idling). Judging by the existance of the sd_power_ram_power_*() functions I assume that you have to use those to configure RAM retention but my attempts so far failed.

    From what I have gathered I may have to adapt the .ld file and add something like no_init memory sections.

    Am I on the right way / are there any "more elaborate" examples regarding RAM retention with the S132 softdevice present?

    Kind regards,

    lhochstetter

  • Hi,

     

    Systemoff will generate a reset when you wake up, so the simplest logic is to check your GPIOs upon init, or reading the NRF_GPIO->LATCH register:

    gpio_init();
    // Check the GPIO states to see which one is still active
    if (nrf_gpio_pin_read(my_pin) == ACTIVE_LEVEL) {
        do_something();
    }
    
    // Alternative is to read NRF_GPIO->LATCH register.
    // See http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/gpio.html#register.LATCH
    // Write '1' to bitfields in register to clear it.

     

    lhochstetter said:
    When I use this snippet the system freezes up again and the voltage rises to a couple hundred mV (without I measure <20 mV when idling). Judging by the existance of the sd_power_ram_power_*() functions I assume that you have to use those to configure RAM retention but my attempts so far failed.

     When the softdevice is enabled, you shall not write directly to the NRF_POWER register, as this will create a fault-condition. You should rather use the sd_ prefixed function call. You can write the exact same bit pattern into the sd_power_ram_power_* function as you would to the NRF_POWER->RAMON register.

      

    Kind regards,

    Håkon

Related