Hi,
First off, I'm very new to the nRF52 development so I'm suspecting to have done something wrong...
The datasheet of the nRF52832 states a current consumption of 0.7muA in SYSTEM OFF with full RAM retention, as per 18.10.1 Current consumption sleep. I'm using the aforementioned nRF52832 with the pca10040 development board and a slightly altered version of pwr_mgmt from the nRF5_SDK_17.0.2_d674dde examples, however the lowest current that I could measure was 2 muA with (what I assume to be) SYSTEM OFF with no RAM retention.
I am measuring with a Keysight 34465A 6.5 digit multimeter according to docs.
Is there something that I am missing?
Here is the code (please forgive the mess):
#include <stdbool.h>
#include <stdint.h>
#include "nrf_soc.h"
#include "boards.h"
#include "bsp.h"
#include "bsp_nfc.h"
#include "app_timer.h"
#include "nordic_common.h"
#include "app_error.h"
#include "nrf_drv_clock.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#if NRF_PWR_MGMT_CONFIG_USE_SCHEDULER
#include "app_scheduler.h"
#define APP_SCHED_MAX_EVENT_SIZE 0 /**< Maximum size of scheduler events. */
#define APP_SCHED_QUEUE_SIZE 4 /**< Maximum number of events in the scheduler queue. */
#endif // NRF_PWR_MGMT_CONFIG_USE_SCHEDULER
#define BTN_ID_READY 0 /**< ID of the button used to change the readiness to sleep. */
#define BTN_ID_SLEEP 1 /**< ID of the button used to put the application into sleep/system OFF mode. */
#define BTN_ID_WAKEUP 1 /**< ID of the button used to wake up the application. */
#define BTN_ID_RESET 2 /**< ID of the button used to reset the application. */
static volatile bool m_stay_in_sysoff; /**< True if the application should stay in system OFF mode. */
static volatile bool m_is_ready; /**< True if the application is ready to enter sleep/system OFF mode. */
static volatile bool m_sysoff_started; /**< True if the application started sleep preparation. */
#define NRF52_ONRAM1_OFFRAM1 POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos \
| POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos \
| POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos \
| POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos;
#define NRF52_ONRAM1_OFFRAM0 POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos \
| POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos \
| POWER_RAM_POWER_S0RETENTION_Off << POWER_RAM_POWER_S0RETENTION_Pos \
| POWER_RAM_POWER_S1RETENTION_Off << POWER_RAM_POWER_S1RETENTION_Pos;
#define NRF52_ONRAM0_OFFRAM0 POWER_RAM_POWER_S0POWER_Off << POWER_RAM_POWER_S0POWER_Pos \
| POWER_RAM_POWER_S1POWER_Off << POWER_RAM_POWER_S1POWER_Pos;
/**@brief Handler for shutdown preparation.
*/
bool shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
uint32_t err_code;
if (m_is_ready == false)
{
m_sysoff_started = true;
return false;
}
switch (event)
{
case NRF_PWR_MGMT_EVT_PREPARE_SYSOFF:
NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_SYSOFF");
err_code = bsp_buttons_disable();
APP_ERROR_CHECK(err_code);
break;
case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:
NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_WAKEUP");
err_code = bsp_buttons_disable();
// Suppress NRF_ERROR_NOT_SUPPORTED return code.
UNUSED_VARIABLE(err_code);
err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP);
// Suppress NRF_ERROR_NOT_SUPPORTED return code.
UNUSED_VARIABLE(err_code);
err_code = bsp_nfc_sleep_mode_prepare();
// Suppress NRF_ERROR_NOT_SUPPORTED return code.
UNUSED_VARIABLE(err_code);
break;
case NRF_PWR_MGMT_EVT_PREPARE_DFU:
NRF_LOG_ERROR("Entering DFU is not supported by this example.");
APP_ERROR_HANDLER(NRF_ERROR_API_NOT_IMPLEMENTED);
break;
case NRF_PWR_MGMT_EVT_PREPARE_RESET:
NRF_LOG_INFO("NRF_PWR_MGMT_EVT_PREPARE_RESET");
break;
}
err_code = app_timer_stop_all();
APP_ERROR_CHECK(err_code);
return true;
}
/**@brief Register application shutdown handler with priority 0. */
NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, 0);
/**@brief Function for handling BSP events.
*/
static void bsp_evt_handler(bsp_event_t evt)
{
#if NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
nrf_pwr_mgmt_feed();
NRF_LOG_INFO("Power management fed");
#endif // NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
switch (evt)
{
case BSP_EVENT_KEY_0:
if (m_is_ready)
{
m_is_ready = false;
NRF_LOG_INFO("System is not ready for shutdown");
}
else
{
m_is_ready = true;
NRF_LOG_INFO("System is ready for shutdown");
}
if (m_sysoff_started && m_is_ready)
{
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_CONTINUE);
}
break;
case BSP_EVENT_SYSOFF:
m_stay_in_sysoff = true;
break;
case BSP_EVENT_SLEEP:
if (m_stay_in_sysoff)
{
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_STAY_IN_SYSOFF);
}
else
{
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
}
break;
case BSP_EVENT_RESET:
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_RESET);
break;
default:
return; // no implementation needed
}
}
/**@brief Function for initializing low-frequency clock.
*/
static void lfclk_config(void)
{
ret_code_t err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);
nrf_drv_clock_lfclk_request(NULL);
}
/**@brief Function for initializing the BSP module.
*/
static void bsp_configuration()
{
uint32_t err_code;
err_code = bsp_init(BSP_INIT_BUTTONS, bsp_evt_handler);
APP_ERROR_CHECK(err_code);
err_code = bsp_event_to_button_action_assign(BTN_ID_SLEEP,
BSP_BUTTON_ACTION_LONG_PUSH,
BSP_EVENT_SYSOFF);
APP_ERROR_CHECK(err_code);
err_code = bsp_event_to_button_action_assign(BTN_ID_SLEEP,
BSP_BUTTON_ACTION_RELEASE,
BSP_EVENT_SLEEP);
APP_ERROR_CHECK(err_code);
err_code = bsp_event_to_button_action_assign(BTN_ID_READY,
BSP_BUTTON_ACTION_PUSH,
BSP_EVENT_NOTHING);
APP_ERROR_CHECK(err_code);
err_code = bsp_event_to_button_action_assign(BTN_ID_READY,
BSP_BUTTON_ACTION_RELEASE,
BSP_EVENT_KEY_0);
APP_ERROR_CHECK(err_code);
err_code = bsp_event_to_button_action_assign(BTN_ID_RESET,
BSP_BUTTON_ACTION_RELEASE,
BSP_EVENT_RESET);
APP_ERROR_CHECK(err_code);
}
void configure_ram_retention(void){
// Configure nRF52 RAM retention parameters. Set for System Off 0kB RAM retention
NRF_POWER->RAM[0].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[1].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[2].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[3].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[4].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[5].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[6].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[7].POWER = NRF52_ONRAM1_OFFRAM0;
}
/**
* @brief Function for application main entry.
*/
int main(void){
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
NRF_LOG_INFO("Power Management examplo");
lfclk_config();
//uint32_t err_code = app_timer_init();
//APP_ERROR_CHECK(err_code);
#if NRF_PWR_MGMT_CONFIG_USE_SCHEDULER
APP_SCHED_INIT(APP_SCHED_MAX_EVENT_SIZE, APP_SCHED_QUEUE_SIZE);
#endif // NRF_PWR_MGMT_CONFIG_USE_SCHEDULER
bsp_configuration();
//ret_code_t ret_code = nrf_pwr_mgmt_init();
//APP_ERROR_CHECK(ret_code);
//Configure RAM retention. More RAM retention means increased current consumption (see electrical specification in the Product Specification, power chapter)
configure_ram_retention();
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
while(true){
/**
#if NRF_PWR_MGMT_CONFIG_USE_SCHEDULER
app_sched_execute();
#endif // NRF_PWR_MGMT_CONFIG_USE_SCHEDULER
if (NRF_LOG_PROCESS() == false)
{
nrf_pwr_mgmt_run();
}
*/
}
}