soc: arm: nrf52: Update power management code for nRF52

This commit updates the power management code for nRF52 SoC
series after recent changes in Zephyr power management subsystem.

Changes:
- Removed LPS modes, as they are not supported by HW.
  (previous implemntation used CONSTLAT and LOWPWR settings
  in NRF_POWER to implement low power modes, however these
  knobs should be used only when application needs ultra low
  CPU wake-up time).

- Reworked code in order to allow adding custom power levels
  on the application level and provide better integration
  with power management subsystem.

Signed-off-by: Piotr Zięcik <piotr.ziecik@nordicsemi.no>
This commit is contained in:
Piotr Zięcik 2019-01-02 13:28:13 +01:00 committed by Carles Cufí
commit 4ce523094f
4 changed files with 72 additions and 83 deletions

View file

@ -14,9 +14,6 @@ config SOC_SERIES_NRF52X
select NRF_RTC_TIMER
select CLOCK_CONTROL
select CLOCK_CONTROL_NRF
select SYS_POWER_LOW_POWER_STATE_SUPPORTED
select SYS_POWER_STATE_CPU_LPS_SUPPORTED
select SYS_POWER_STATE_CPU_LPS_1_SUPPORTED
select SYS_POWER_DEEP_SLEEP_SUPPORTED
select SYS_POWER_STATE_DEEP_SLEEP_SUPPORTED
select XIP

View file

@ -7,73 +7,22 @@
#include <soc_power.h>
#include <nrf_power.h>
#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_DECLARE(soc);
#if defined(CONFIG_SYS_POWER_DEEP_SLEEP)
/* System_OFF is deepest Power state available, On exiting from this
* state CPU including all peripherals reset
*/
static void _system_off(void)
{
nrf_power_system_off();
}
#endif
static void _issue_low_power_command(void)
{
__WFE();
__SEV();
__WFE();
}
/* Name: _low_power_mode
* Parameter : Low Power Task ID
*
* Set Notdic SOC specific Low Power Task and invoke
* _WFE event to put the nordic SOC into Low Power State.
*/
static void _low_power_mode(enum power_states state)
{
switch (state) {
/* CONSTANT LATENCY TASK */
case SYS_POWER_STATE_CPU_LPS:
nrf_power_task_trigger(NRF_POWER_TASK_CONSTLAT);
break;
/* LOW POWER TASK */
case SYS_POWER_STATE_CPU_LPS_1:
nrf_power_task_trigger(NRF_POWER_TASK_LOWPWR);
break;
default:
/* Unsupported State */
LOG_ERR("Unsupported State");
break;
}
/* Issue __WFE*/
_issue_low_power_command();
}
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
/* Invoke Low Power/System Off specific Tasks */
void sys_set_power_state(enum power_states state)
{
switch (state) {
case SYS_POWER_STATE_CPU_LPS:
_low_power_mode(SYS_POWER_STATE_CPU_LPS);
break;
case SYS_POWER_STATE_CPU_LPS_1:
_low_power_mode(SYS_POWER_STATE_CPU_LPS_1);
break;
#if defined(CONFIG_SYS_POWER_DEEP_SLEEP)
#ifdef CONFIG_SYS_POWER_DEEP_SLEEP
#ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_SUPPORTED
case SYS_POWER_STATE_DEEP_SLEEP:
_system_off();
nrf_power_system_off();
break;
#endif
#endif
default:
/* Unsupported State */
LOG_ERR("Unsupported State");
LOG_ERR("Unsupported power state %u", state);
break;
}
}
@ -82,38 +31,63 @@ void sys_set_power_state(enum power_states state)
void sys_power_state_post_ops(enum power_states state)
{
switch (state) {
case SYS_POWER_STATE_CPU_LPS:
case SYS_POWER_STATE_CPU_LPS_1:
/* Enable interrupts */
__set_BASEPRI(0);
break;
#if defined(CONFIG_SYS_POWER_DEEP_SLEEP)
#ifdef CONFIG_SYS_POWER_DEEP_SLEEP
#ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_SUPPORTED
case SYS_POWER_STATE_DEEP_SLEEP:
/* Nothing to do. */
break;
#endif
#endif
default:
/* Unsupported State */
LOG_ERR("Unsupported State");
LOG_ERR("Unsupported power state %u", state);
break;
}
/*
* System is now in active mode. Reenable interrupts which were disabled
* when OS started idling code.
*/
irq_unlock(0);
}
bool sys_is_valid_power_state(enum power_states state)
{
switch (state) {
#ifdef CONFIG_SYS_POWER_LOW_POWER_STATE
#ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_SUPPORTED
case SYS_POWER_STATE_CPU_LPS:
case SYS_POWER_STATE_CPU_LPS_1:
#if defined(CONFIG_SYS_POWER_DEEP_SLEEP)
case SYS_POWER_STATE_DEEP_SLEEP:
#endif
return true;
break;
#endif
#ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_1_SUPPORTED
case SYS_POWER_STATE_CPU_LPS_1:
return true;
#endif
#ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_2_SUPPORTED
case SYS_POWER_STATE_CPU_LPS_2:
return true;
#endif
#endif /* CONFIG_SYS_POWER_LOW_POWER_STATE */
#ifdef CONFIG_SYS_POWER_DEEP_SLEEP
#ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_SUPPORTED
case SYS_POWER_STATE_DEEP_SLEEP:
return true;
#endif
#ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_1_SUPPORTED
case SYS_POWER_STATE_DEEP_SLEEP_1:
return true;
#endif
#ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_2_SUPPORTED
case SYS_POWER_STATE_DEEP_SLEEP_2:
return true;
#endif
#endif /* CONFIG_SYS_POWER_DEEP_SLEEP */
default:
LOG_DBG("Unsupported State");
break;
return false;
}
return false;
/* Not reached */
}
/* Overrides the weak ARM implementation:

View file

@ -16,6 +16,8 @@
#include <nrf_common.h>
#include <nrf.h>
#include <soc_power.h>
/* Add include for DTS generated information */
#include <generated_dts_board.h>

View file

@ -14,13 +14,29 @@ extern "C" {
#endif
enum power_states {
SYS_POWER_STATE_CPU_LPS, /* CONSTLAT Task Activited */
SYS_POWER_STATE_CPU_LPS_1, /* LOWPWR Task Activated */
SYS_POWER_STATE_CPU_LPS_2, /* Not supported*/
SYS_POWER_STATE_DEEP_SLEEP, /* System Off */
SYS_POWER_STATE_DEEP_SLEEP_1, /* Not Supported */
SYS_POWER_STATE_DEEP_SLEEP_2, /* Not Supported */
#ifdef CONFIG_SYS_POWER_LOW_POWER_STATE
# ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_SUPPORTED
SYS_POWER_STATE_CPU_LPS, /* Not used */
# endif
# ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_1_SUPPORTED
SYS_POWER_STATE_CPU_LPS_1, /* Not used */
# endif
# ifdef CONFIG_SYS_POWER_STATE_CPU_LPS_2_SUPPORTED
SYS_POWER_STATE_CPU_LPS_2, /* Not used */
# endif
#endif /* CONFIG_SYS_POWER_LOW_POWER_STATE */
#ifdef CONFIG_SYS_POWER_DEEP_SLEEP
# ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_SUPPORTED
SYS_POWER_STATE_DEEP_SLEEP, /* System OFF */
# endif
# ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_1_SUPPORTED
SYS_POWER_STATE_DEEP_SLEEP_1, /* Not used */
# endif
# ifdef CONFIG_SYS_POWER_STATE_DEEP_SLEEP_2_SUPPORTED
SYS_POWER_STATE_DEEP_SLEEP_2, /* Not used */
# endif
#endif /* CONFIG_SYS_POWER_DEEP_SLEEP */
SYS_POWER_STATE_MAX /* Do nothing */
};
@ -30,7 +46,7 @@ enum power_states {
void sys_set_power_state(enum power_states state);
/**
* @brief Check a low power state is supported by SoC
* @brief Check the low power state is supported by SoC
*/
bool sys_is_valid_power_state(enum power_states state);