Contiki-NG
Toggle main menu visibility
Loading...
Searching...
No Matches
lpm.h
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2013, Texas Instruments Incorporated - http://www.ti.com/
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* 3. Neither the name of the copyright holder nor the names of its
15
* contributors may be used to endorse or promote products derived
16
* from this software without specific prior written permission.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29
* OF THE POSSIBILITY OF SUCH DAMAGE.
30
*/
31
/**
32
* \addtogroup cc2538
33
* @{
34
*
35
* \defgroup cc2538-lpm cc2538 Low Power Modes
36
*
37
* Driver for the cc2538 power modes
38
* @{
39
*
40
* \file
41
* Header file with register, macro and function declarations for the cc2538
42
* low power module
43
*/
44
#ifndef LPM_H_
45
#define LPM_H_
46
47
#include "contiki.h"
48
#include "
rtimer.h
"
49
50
#include <stdbool.h>
51
#include <stdint.h>
52
/*---------------------------------------------------------------------------*/
53
/**
54
* \name LPM stats
55
*
56
* Maintains a record of how many rtimer ticks spent in each Power Mode.
57
* Mainly used for debugging the module
58
* @{
59
*/
60
#if LPM_CONF_STATS
61
extern
rtimer_clock_t lpm_stats[3];
62
63
/**
64
* \brief Read the time spent in a PM in rtimer ticks
65
* \param pm The pm as a value in [0,2]
66
*/
67
#define LPM_STATS_GET(pm) lpm_stats[pm]
68
#else
69
#define LPM_STATS_GET(pm)
70
#endif
71
/** @} */
72
/*---------------------------------------------------------------------------*/
73
/**
74
* \name Constants to be used as arguments to lpm_set_max_pm()
75
* @{
76
*/
77
#define LPM_PM0 0
78
#define LPM_PM1 1
79
#define LPM_PM2 2
80
/** @} */
81
/*---------------------------------------------------------------------------*/
82
typedef
bool (*lpm_periph_permit_pm1_func_t)(void);
83
84
#if LPM_CONF_ENABLE
85
/**
86
* \brief Initialise the LPM module
87
*/
88
void
lpm_init
(
void
);
89
90
/**
91
* \brief Drop to Deep Sleep
92
*
93
* This function triggers a sequence to enter Deep Sleep. The sequence involves
94
* determining the most suitable PM and switching the system clock source to
95
* the 16MHz if required. If the energest module is enabled, the sequence also
96
* performs some simple energest calculations.
97
*
98
* Broadly speaking, this function will be called from the main loop when all
99
* events have been serviced. This functions aims to be clever enough in order
100
* to be able to choose between PMs 0/1/2 depending on chip status and
101
* anticipated sleep duration. This choice is made subject to configuration
102
* restrictions and subject to restrictions imposed by calls to
103
* lpm_set_max_pm().
104
*
105
* This PM selection heuristic has the following primary criteria:
106
* - Is the RF off?
107
* - Are all registered peripherals permitting PM1+?
108
* - Is the Sleep Timer scheduled to fire an interrupt?
109
*
110
* If the answer to any of those questions is no, we will drop to PM0 and
111
* will wake up to any interrupt. Best case scenario (if nothing else happens),
112
* we will idle until the next SysTick in no more than 1000/CLOCK_SECOND ms
113
* (7.8125ms).
114
*
115
* If all can be answered with 'yes', we can drop to PM1/2 knowing that the
116
* Sleep Timer will wake us up. Depending on the estimated deep sleep duration
117
* and the max PM allowed by user configuration, we select the most efficient
118
* Power Mode to drop to. If the duration is too short, we simply IDLE in PM0.
119
*
120
* Dropping to PM1/2 requires a switch to the 16MHz OSC. We have the option of
121
* letting the SoC do this for us automatically. However, if an interrupt fires
122
* during this automatic switch, we will need to re-assert WFI. To avoid this
123
* complexity, we perform the switch to the 16MHz OSC manually in software and
124
* we assert WFI after the transition has been completed. This gives us a
125
* chance to bail out if an interrupt fires or an event is raised during the
126
* transition. If nothing happens, dropping to PM1+ is un-interruptible and
127
* with a deterministic duration. When we wake up, we switch back to the 32MHz
128
* OSC manually before handing control back to main. This is implemented in
129
* lpm_exit(), which will always be called from within the Sleep Timer ISR
130
* context.
131
*
132
* \note Dropping to PM2 means that data in the SRAM non-retention area will
133
* be lost. It is recommended to disable PM2 if the total RAM footprint is
134
* larger than what will fit in the retention area.
135
* .nrdata* sections can be used to place uninitialized data in the SRAM
136
* non-retention area.
137
*
138
* \sa main(), rtimer_arch_next_trigger(), lpm_exit(), lpm_set_max_pm()
139
*/
140
void
lpm_enter(
void
);
141
142
/**
143
* \brief Perform an 'Exit Deep Sleep' sequence
144
*
145
* This routine is called from within the context of the ISR that caused us to
146
* come out of PM1/2. It performs a wake up sequence to make sure the 32MHz OSC
147
* is back on and the system clock is sourced on it.
148
*
149
* While in PMs 1 and 2, the system clock stops ticking. This functions adjusts
150
* it when we wake up.
151
*
152
* We always exit PM1/2 as a result of a scheduled rtimer task or a GPIO
153
* interrupt. This may lead to other parts of the code trying to use the RF,
154
* so we need to switch the clock source \e before said code gets executed.
155
*
156
* This function also makes sure that the sleep timer value is up-to-date
157
* following wake-up from PM1/2 so that RTIMER_NOW() works.
158
*
159
* \note This function should be called at the very beginning of ISRs waking up
160
* the SoC in order to restore all clocks and timers.
161
*
162
* \sa lpm_enter(), rtimer_isr()
163
*/
164
void
lpm_exit(
void
);
165
166
/**
167
* \brief Prevent the SoC from dropping to a PM higher than \e max_pm
168
* \param pm The highest PM we are allowed to enter, specified as a
169
* number in [0, 2]
170
*
171
* Defines for the \e pm argument are LPM_PMx.
172
*
173
* This function can be used by software in situations where some power
174
* modes are undesirable. If, for example, an application needs to avoid PM2,
175
* it would call lpm_set_max_pm(LPM_PM1).
176
* If an application wants to avoid PM1 as well, it would call
177
* lpm_set_max_pm(LPM_PM0)
178
*
179
* PM0 can not be disabled at runtime. Use LPM_CONF_ENABLE to disable LPM
180
* support altogether
181
*
182
* \note If the value of argument \e pm is greater than the value of the
183
* LPM_CONF_MAX_PM configuration directive, LPM_CONF_MAX_PM is used. Thus
184
* if LPM_CONF_MAX_PM==1, calling lpm_set_max_pm(LPM_PM2) would
185
* result in a maximum PM set to 1 and all subsequent Deep Sleeps would
186
* be limited to either PM0 or PM1.
187
*
188
* \sa lpm_enter()
189
*/
190
void
lpm_set_max_pm(uint8_t pm);
191
192
/**
193
* \brief Register a peripheral function which will get called by the LPM
194
* module to get 'permission' to drop to PM1+
195
* \param permit_pm1_func Pointer to the function
196
*
197
* Some peripherals are sensitive to PM changes. For instance, we don't want to
198
* drop to PM1+ if the USB PLL is active or if the UART TX FIFO is not clear.
199
*
200
* When changing power modes, the LPM driver will call all FPs registered with
201
* this function. The peripheral's function will return true or false to permit
202
* / prohibit PM1+ respectively. If at least one peripheral returns false, the
203
* SoC will drop to PM0 Deep Sleep instead.
204
*
205
* Registering several times the same function makes the LPM module behave as if
206
* the function had been registered once.
207
*/
208
void
lpm_register_peripheral(lpm_periph_permit_pm1_func_t permit_pm1_func);
209
/*---------------------------------------------------------------------------*/
210
/* Disable the entire module if required */
211
#else
212
#define lpm_init()
213
#define lpm_enter()
214
#define lpm_exit()
215
static
inline
void
216
lpm_set_max_pm(uint8_t pm)
217
{
218
}
219
static
inline
void
220
lpm_register_peripheral(lpm_periph_permit_pm1_func_t permit_pm1_func)
221
{
222
}
223
#endif
224
225
#endif
/* LPM_H_ */
226
227
/**
228
* @}
229
* @}
230
*/
lpm_init
void lpm_init()
Initialise the low-power mode management module.
Definition
lpm.c:557
rtimer.h
Header file for the real-time timer module.
arch
cpu
cc2538
lpm.h
Generated on
for Contiki-NG by
1.17.0