38 #include "contiki-conf.h"
44 #include "rtimer-arch.h"
52 #if LPM_CONF_ENABLE != 0
55 static unsigned long irq_energest = 0;
57 #define ENERGEST_IRQ_SAVE(a) do { \
58 a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0)
59 #define ENERGEST_IRQ_RESTORE(a) do { \
60 energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0)
62 #define ENERGEST_IRQ_SAVE(a) do {} while(0)
63 #define ENERGEST_IRQ_RESTORE(a) do {} while(0)
73 #define DEEP_SLEEP_PM1_THRESHOLD 10
74 #define DEEP_SLEEP_PM2_THRESHOLD 100
76 #define assert_wfi() do { asm("wfi"::); } while(0)
79 rtimer_clock_t lpm_stats[3];
81 #define LPM_STATS_INIT() do { memset(lpm_stats, 0, sizeof(lpm_stats)); \
83 #define LPM_STATS_ADD(pm, val) do { lpm_stats[pm] += val; } while(0)
85 #define LPM_STATS_INIT()
86 #define LPM_STATS_ADD(stat, val)
94 static rtimer_clock_t sleep_enter_time;
96 #define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND)
101 static uint8_t max_pm;
104 #ifdef LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX
105 #define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX
107 #define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 2
110 static lpm_periph_permit_pm1_func_t
111 periph_permit_pm1_funcs[LPM_PERIPH_PERMIT_PM1_FUNCS_MAX];
114 periph_permit_pm1(
void)
118 for(i = 0; i < LPM_PERIPH_PERMIT_PM1_FUNCS_MAX &&
119 periph_permit_pm1_funcs[i] !=
NULL; i++) {
120 if(!periph_permit_pm1_funcs[i]()) {
134 ENERGEST_OFF(ENERGEST_TYPE_CPU);
135 ENERGEST_ON(ENERGEST_TYPE_LPM);
138 ENERGEST_IRQ_RESTORE(irq_energest);
151 LPM_STATS_ADD(0,
RTIMER_NOW() - sleep_enter_time);
154 ENERGEST_IRQ_SAVE(irq_energest);
156 ENERGEST_ON(ENERGEST_TYPE_CPU);
157 ENERGEST_OFF(ENERGEST_TYPE_LPM);
161 select_32_mhz_xosc(
void)
177 select_16_mhz_rcosc(
void)
221 ((
RTIMER_NOW() - sleep_enter_time) / RTIMER_CLOCK_TICK_RATIO));
224 select_32_mhz_xosc();
230 ENERGEST_IRQ_SAVE(irq_energest);
232 ENERGEST_ON(ENERGEST_TYPE_CPU);
233 ENERGEST_OFF(ENERGEST_TYPE_LPM);
239 rtimer_clock_t lpm_exit_time;
240 rtimer_clock_t duration;
248 || !periph_permit_pm1() || max_pm == 0) {
264 if(duration < DEEP_SLEEP_PM1_THRESHOLD || lpm_exit_time == 0) {
275 select_16_mhz_rcosc();
283 if(duration < DEEP_SLEEP_PM1_THRESHOLD) {
290 select_32_mhz_xosc();
293 }
else if(duration >= DEEP_SLEEP_PM2_THRESHOLD && max_pm == 2) {
305 ENERGEST_IRQ_RESTORE(irq_energest);
306 ENERGEST_OFF(ENERGEST_TYPE_CPU);
307 ENERGEST_ON(ENERGEST_TYPE_LPM);
325 select_32_mhz_xosc();
330 ENERGEST_IRQ_SAVE(irq_energest);
331 ENERGEST_ON(ENERGEST_TYPE_CPU);
332 ENERGEST_OFF(ENERGEST_TYPE_LPM);
358 for(i = 0; i < LPM_PERIPH_PERMIT_PM1_FUNCS_MAX; i++) {
359 if(periph_permit_pm1_funcs[i] == permit_pm1_func) {
361 }
else if(periph_permit_pm1_funcs[i] ==
NULL) {
362 periph_permit_pm1_funcs[i] = permit_pm1_func;