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) 67 rtimer_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() 74 #define LPM_STATS_ADD(stat, val) 81 static rtimer_clock_t sleep_enter_time;
86 static uint8_t max_pm;
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 95 static lpm_periph_permit_pm1_func_t
96 periph_permit_pm1_funcs[LPM_PERIPH_PERMIT_PM1_FUNCS_MAX];
99 periph_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);
135 select_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;
158 select_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);
335 lpm_set_max_pm(uint8_t pm)
341 lpm_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;
Header file for the cc2538 System Control driver.
#define RFCORE_XREG_FSMSTAT0
Radio status register.
#define LPM_CONF_STATS
Set to 1 to enable LPM-related stats.
#define SCB_SCR_SLEEPDEEP_Msk
Header file for the energy estimation mechanism
#define SYS_CTRL_PMCTL_PM0
PM0.
Header file with register, macro and function declarations for the cc2538 low power module...
CMSIS Cortex-M3 core peripheral access layer header file for CC2538.
#define SYS_CTRL_PMCTL_PM1
PM1.
Header file with register manipulation macro definitions.
#define SYS_CTRL_PMCTL_PM3
PM3.
#define RTIMER_NOW()
Get the current clock time.
#define RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE
FIFO and FFCTRL status.
Header file for the cc2538 rtimer driver.
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_CLOCK_STA
Clock status register.
Header file for the Contiki process interface.
#define SYS_CTRL_PMCTL
Power Mode Control.
int process_nevents(void)
Number of events waiting to be processed.
void clock_adjust(void)
Adjust the clock following missed SysTick ISRs.
void lpm_init()
Initialise the low-power mode management module.
#define SYS_CTRL_CLOCK_CTRL
Clock control register.
Header with declarations of the RF Core XREGs.
#define LPM_CONF_MAX_PM
Maximum PM.