Contiki-NG
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
61extern 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/*---------------------------------------------------------------------------*/
82typedef bool (*lpm_periph_permit_pm1_func_t)(void);
83
84#if LPM_CONF_ENABLE
85/**
86 * \brief Initialise the LPM module
87 */
88void 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 */
140void 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 */
164void 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 */
190void 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 */
208void 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()
215static inline void
216lpm_set_max_pm(uint8_t pm)
217{
218}
219static inline void
220lpm_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 */
Header file for the real-time timer module.