43#include "rtimer-arch.h"
52#if LPM_CONF_ENABLE != 0
61#define DEEP_SLEEP_PM1_THRESHOLD 10
62#define DEEP_SLEEP_PM2_THRESHOLD 100
64#define assert_wfi() do { __asm("wfi"::); } while(0)
67rtimer_clock_t lpm_stats[3];
69#define LPM_STATS_INIT() \
70 do { memset(lpm_stats, 0, sizeof(lpm_stats)); } while(0)
71#define LPM_STATS_ADD(pm, val) do { lpm_stats[pm] += val; } while(0)
73#define LPM_STATS_INIT() do {} while (0)
74#define LPM_STATS_ADD(stat, val) do {} while (0)
81static rtimer_clock_t sleep_enter_time;
89#ifdef LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX
90#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX
92#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 5
95static lpm_periph_permit_pm1_func_t
96periph_permit_pm1_funcs[LPM_PERIPH_PERMIT_PM1_FUNCS_MAX];
99periph_permit_pm1(
void)
103 for(i = 0; i < LPM_PERIPH_PERMIT_PM1_FUNCS_MAX &&
104 periph_permit_pm1_funcs[i] != NULL; i++) {
105 if(!periph_permit_pm1_funcs[i]()) {
119 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
129 LPM_STATS_ADD(0,
RTIMER_NOW() - sleep_enter_time);
131 ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
135select_32_mhz_xosc(
void)
148#if SYS_CTRL_SYS_DIV == SYS_CTRL_CLOCK_CTRL_SYS_DIV_32MHZ
149 & ~SYS_CTRL_CLOCK_CTRL_SYS_DIV
151#if SYS_CTRL_IO_DIV == SYS_CTRL_CLOCK_CTRL_IO_DIV_32MHZ
152 & ~SYS_CTRL_CLOCK_CTRL_IO_DIV
154 ) | SYS_CTRL_CLOCK_CTRL_OSC_PD;
158select_16_mhz_rcosc(
void)
168#if SYS_CTRL_SYS_DIV == SYS_CTRL_CLOCK_CTRL_SYS_DIV_32MHZ
169 | SYS_CTRL_CLOCK_CTRL_SYS_DIV_16MHZ
171#if SYS_CTRL_IO_DIV == SYS_CTRL_CLOCK_CTRL_IO_DIV_32MHZ
172 | SYS_CTRL_CLOCK_CTRL_IO_DIV_16MHZ
174 ) & ~SYS_CTRL_CLOCK_CTRL_OSC_PD;
213 select_32_mhz_xosc();
216 ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
218 ENERGEST_SWITCH(ENERGEST_TYPE_DEEP_LPM, ENERGEST_TYPE_CPU);
228 rtimer_clock_t lpm_exit_time;
229 rtimer_clock_t duration;
237 || !periph_permit_pm1() || max_pm == 0) {
253 if(duration < DEEP_SLEEP_PM1_THRESHOLD || lpm_exit_time == 0) {
264 select_16_mhz_rcosc();
272 if(duration < DEEP_SLEEP_PM1_THRESHOLD) {
279 select_32_mhz_xosc();
282 }
else if(duration >= DEEP_SLEEP_PM2_THRESHOLD && max_pm == 2) {
311 select_32_mhz_xosc();
318 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
320 ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_DEEP_LPM);
335lpm_set_max_pm(uint8_t pm)
341lpm_register_peripheral(lpm_periph_permit_pm1_func_t permit_pm1_func)
345 for(i = 0; i < LPM_PERIPH_PERMIT_PM1_FUNCS_MAX; i++) {
346 if(periph_permit_pm1_funcs[i] == permit_pm1_func) {
348 }
else if(periph_permit_pm1_funcs[i] == NULL) {
349 periph_permit_pm1_funcs[i] = permit_pm1_func;
363 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
CMSIS Cortex-M3 core peripheral access layer header file for CC2538.
Header file for the energy estimation mechanism.
void clock_adjust(void)
Adjust the clock following missed SysTick ISRs.
#define RFCORE_XREG_FSMSTAT0
Radio status register.
#define RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE
FIFO and FFCTRL status.
rtimer_clock_t rtimer_arch_next_trigger()
Get the time of the next scheduled rtimer trigger.
#define SYS_CTRL_PMCTL_PM2
PM2.
#define SYS_CTRL_PMCTL_PM3
PM3.
#define SYS_CTRL_PMCTL_PM1
PM1.
#define SYS_CTRL_PMCTL_PM0
PM0.
#define SYS_CTRL_CLOCK_STA
Clock status register.
#define SYS_CTRL_PMCTL
Power Mode Control.
#define SYS_CTRL_CLOCK_CTRL
Clock control register.
#define LPM_CONF_MAX_PM
Maximum PM.
#define LPM_CONF_STATS
Set to 1 to enable LPM-related stats.
void lpm_init()
Initialise the low-power mode management module.
int process_nevents(void)
Number of events waiting to be processed.
#define RTIMER_NOW()
Get the current clock time.
Header file for the Contiki process interface.
Header file with register manipulation macro definitions.
Header with declarations of the RF Core XREGs.
Header file for the cc2538 System Control driver.