cpu/kinetis: implement power modes for pm_layered
This commit is contained in:
parent
00b14cce27
commit
ae7ec96731
@ -18,5 +18,6 @@ else ifneq (,$(filter periph_mcg,$(FEATURES_USED)))
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
USEMODULE += periph_wdog
|
USEMODULE += periph_wdog
|
||||||
|
USEMODULE += pm_layered
|
||||||
|
|
||||||
include $(RIOTCPU)/cortexm_common/Makefile.dep
|
include $(RIOTCPU)/cortexm_common/Makefile.dep
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
FEATURES_PROVIDED += periph_cpuid
|
FEATURES_PROVIDED += periph_cpuid
|
||||||
|
FEATURES_PROVIDED += periph_pm
|
||||||
|
|
||||||
# TRNG driver is not implemented for mkw41z models
|
# TRNG driver is not implemented for mkw41z models
|
||||||
_KINETIS_CPU_MODELS_WITHOUT_HWRNG += mkw41z256vht4 mkw41z512vht4
|
_KINETIS_CPU_MODELS_WITHOUT_HWRNG += mkw41z256vht4 mkw41z512vht4
|
||||||
|
|||||||
@ -130,9 +130,32 @@ typedef uint16_t gpio_t;
|
|||||||
#define PERIPH_TIMER_PROVIDES_SET
|
#define PERIPH_TIMER_PROVIDES_SET
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief number of usable power modes
|
* @name Kinetis power mode configuration
|
||||||
|
* @{
|
||||||
*/
|
*/
|
||||||
#define PM_NUM_MODES (1U)
|
#define PM_NUM_MODES (3U)
|
||||||
|
enum {
|
||||||
|
KINETIS_PM_LLS = 0,
|
||||||
|
KINETIS_PM_VLPS = 1,
|
||||||
|
KINETIS_PM_STOP = 2,
|
||||||
|
KINETIS_PM_WAIT = 3,
|
||||||
|
};
|
||||||
|
#if MODULE_PM_LAYERED
|
||||||
|
#include "pm_layered.h"
|
||||||
|
/**
|
||||||
|
* @brief pm_block iff pm_layered is used
|
||||||
|
*/
|
||||||
|
#define PM_BLOCK(x) pm_block(x)
|
||||||
|
/**
|
||||||
|
* @brief pm_unblock iff pm_layered is used
|
||||||
|
*/
|
||||||
|
#define PM_UNBLOCK(x) pm_unblock(x)
|
||||||
|
#else
|
||||||
|
/* ignore these calls when not using pm_layered */
|
||||||
|
#define PM_BLOCK(x)
|
||||||
|
#define PM_UNBLOCK(x)
|
||||||
|
#endif
|
||||||
|
/** @} */
|
||||||
|
|
||||||
#ifdef RTC
|
#ifdef RTC
|
||||||
/* All Kinetis CPUs have exactly one RTC hardware module, except for the KL02
|
/* All Kinetis CPUs have exactly one RTC hardware module, except for the KL02
|
||||||
|
|||||||
@ -26,17 +26,92 @@
|
|||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
/**
|
/* Set to 1 to use the LEDx macros to show which sleep mode is entered */
|
||||||
* @note The current PM implementation is very much simplified down to only
|
#define ENABLE_LEDS (0)
|
||||||
* using the 'WAIT' mode. This implementation must be further expanded
|
|
||||||
* to make use of the available and more efficient (deep) sleep modes
|
#if ENABLE_LEDS
|
||||||
* of the Kinetis CPUs.
|
#include "board.h"
|
||||||
*/
|
#define PM_LED(x, state) LED ## x ## _ ## state
|
||||||
|
#else
|
||||||
|
#define PM_LED(x, state)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* SMC_PMCTRL_STOPM masks */
|
||||||
|
enum {
|
||||||
|
SMC_PMCTRL_STOPM_STOP = 0,
|
||||||
|
/* 1 is reserved */
|
||||||
|
SMC_PMCTRL_STOPM_VLPS = 2,
|
||||||
|
SMC_PMCTRL_STOPM_LLS = 3,
|
||||||
|
/* VLLS is not supported */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Configure which stop mode will be entered when cortexm_sleep(1) is called */
|
||||||
|
static inline void pm_stopm(uint8_t stopm)
|
||||||
|
{
|
||||||
|
SMC->PMCTRL = (SMC->PMCTRL & ~(SMC_PMCTRL_STOPM_MASK)) | SMC_PMCTRL_STOPM(stopm);
|
||||||
|
}
|
||||||
|
|
||||||
void pm_set(unsigned mode)
|
void pm_set(unsigned mode)
|
||||||
{
|
{
|
||||||
|
unsigned deep = 1;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0:
|
/* Only the CPU stops in this mode. No clocks or peripherals are powered
|
||||||
cortexm_sleep(0);
|
* off. This state should always be safe to use, as any interrupt will
|
||||||
|
* wake it. Power consumption in this state is reduced by about 50%. */
|
||||||
|
case KINETIS_PM_WAIT: /* 3 - ARM Sleep */
|
||||||
|
/* WAIT */
|
||||||
|
deep = 0;
|
||||||
|
PM_LED(0, ON);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Some system clocks are stopped in this mode. Usage, means of waking,
|
||||||
|
* and power consumption depend heavily on board-level clock and
|
||||||
|
* peripheral configuration.*/
|
||||||
|
/* If the debug hardware has been used since the last POR, the debug
|
||||||
|
* hardware as well as the clock needed to support it will stay on in
|
||||||
|
* this mode. Thus, after flashing, issue a POR before testing it. */
|
||||||
|
case KINETIS_PM_STOP: /* 2 - ARM Deep Sleep */
|
||||||
|
/* STOP */
|
||||||
|
pm_stopm(SMC_PMCTRL_STOPM_STOP);
|
||||||
|
PM_LED(1, ON);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Some system clocks are stopped in this mode. Usage, means of waking,
|
||||||
|
* and power consumption depend heavily on board-level clock and
|
||||||
|
* peripheral configuration.*/
|
||||||
|
/* If the debug hardware has been used since the last POR, the debug
|
||||||
|
* hardware as well as the clock needed to support it will stay on in
|
||||||
|
* this mode. Thus, after flashing, issue a POR before testing it. */
|
||||||
|
case KINETIS_PM_VLPS: /* 1 - ARM Deep Sleep */
|
||||||
|
/* VLPS */
|
||||||
|
pm_stopm(SMC_PMCTRL_STOPM_VLPS);
|
||||||
|
PM_LED(2, ON);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* All clocks except 32kHz are stopped. Wakeup can occur from
|
||||||
|
* interrupts, several (LLWU-enabled) GPIOs, RTC, or (if the board
|
||||||
|
* configuration uses the 32kHz clock for xtimer) xtimer. Debug hardware
|
||||||
|
* is powered off. Power consumption in this state should be on the
|
||||||
|
* order of 5 uA for the MCU alone, with most boards having additional
|
||||||
|
* parts that will raise this amount. */
|
||||||
|
case KINETIS_PM_LLS: /* 0 - ARM Deep Sleep */
|
||||||
|
/* LLSx */
|
||||||
|
pm_stopm(SMC_PMCTRL_STOPM_LLS);
|
||||||
|
PM_LED(0, ON);
|
||||||
|
PM_LED(2, ON);
|
||||||
|
/* Enable LLWU interrupt, or else we can never resume from LLS */
|
||||||
|
/* Clear pending flag first, the LLWU has no purpose in RUN mode, so
|
||||||
|
* if the flag is set then it must be a remainder from handling the
|
||||||
|
* previous wakeup. */
|
||||||
|
LLWU->F1 = 0xffu;
|
||||||
|
LLWU->F2 = 0xffu;
|
||||||
|
NVIC_ClearPendingIRQ(LLWU_IRQn);
|
||||||
|
NVIC_EnableIRQ(LLWU_IRQn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
DEBUG("pm_set(%u)\n", mode);
|
||||||
|
cortexm_sleep(deep);
|
||||||
|
PM_LED(0, OFF);
|
||||||
|
PM_LED(1, OFF);
|
||||||
|
PM_LED(2, OFF);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user