1 /*
2 * Copyright (c) 2014, Texas Instruments Incorporated
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 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== Power.xdc ========
34 *
35 *
36 */
37
38 package ti.sysbios.family.msp430;
39
40 import xdc.runtime.Error;
41
42 /*!
43 * ======== Power ========
44 * Power Manager Module
45 *
46 * This module provides functions that can be called to reduce MSP430 power
47 * consumption.
48 *
49 * @p(html) 50 * <h3> Calling Context </h3>
51 * <table border="1" cellpadding="3">
52 * <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
53 *
54 * <tr><th> Function </th><th> Hwi </th><th> Swi </th><th> Task </th><th> Main </th><th> Startup </th></tr>
55 * <!-- -->
56 * <tr><td> {@link #idleCPU} </td><td> N </td><td> N </td><td> N </td><td> N </td><td> N </td></tr>
57 * <tr><td> {@link #changeIdleMode} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
58 * <tr><td> {@link #sleepCPU} </td><td> N </td><td> N </td><td> Y </td><td> N </td><td> N </td></tr>
59 * <tr><td> {@link #wakeCPU} </td><td> Y </td><td> N </td><td> N </td><td> N </td><td> N </td></tr>
60 * <tr><td colspan="6"> Definitions: <br />
61 * <ul>
62 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
63 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
64 * <li> <b>Task</b>: API is callable from a Task thread. </li>
65 * <li> <b>Main</b>: API is callable from main(). </li>
66 * <li> <b>Startup</b>: API is callable during any module startup. </li>
67 * </ul>
68 * </td></tr>
69 *
70 * </table>
71 * @p 72 */
73
74 @Template("./Power.xdt")
75 module Power inherits ti.sysbios.interfaces.IPower
76 {
77 /*!
78 * ======== SleepPrepFuncPtr ========
79 * Sleep mode preparation function type definition
80 */
81 typedef Void (*SleepPrepFuncPtr)();
82
83 /*!
84 * ======== IdleMode ========
85 * Available idle modes
86 */
87 enum IdleMode {
88 LPM0 = 0x10, /* CPUOFF */
89 LPM1 = 0x50, /* CPUOFF + SCG0 */
90 LPM2 = 0x90, /* CPUOFF + SCG1 */
91 LPM3 = 0xD0, /* CPUOFF + SCG0 + SCG1 */
92 LPM4 = 0xF0 /* CPUOFF + SCG0 + SCG1 + OSCOFF */
93 };
94
95 /*!
96 * ======== SleepMode ========
97 * Available sleep modes.
98 */
99 enum SleepMode {
100 Sleep_LPM4_5 /*! Shutdown (LPM4.5) */
101 };
102
103 /*!
104 * ======== E_dynamicModeNotAllowed ========
105 * Dynamic mode not allowed error
106 *
107 * This Error is raised if there is an attempt to change idleMode at
108 * runtime, or trigger a dynamic CPU wakeup, and
109 * `{@link #allowDynamicMode}` is set to "false".
110 */
111 config Error.Id E_dynamicModeNotAllowed = {
112 msg: "E_dynamicModeNotAllowed: Dynamic mode is not enabled (allowDynamicMode=false)"
113 };
114
115 /*!
116 * ======== idle ========
117 * Idle CPU when threads blocked waiting for an interrupt?
118 */
119 overrideconfig Bool idle = true;
120
121 /*!
122 * ======== idleMode ========
123 * Idle mode for CPU to enter while waiting for an interrupt
124 */
125 config IdleMode idleMode = LPM0;
126
127 /*!
128 * ======== allowDynamicMode ========
129 * Allow dynamic changes to idleMode (`{@link #changeIdleMode}`), or
130 * dynamically waking the CPU upon return from interrupt
131 * (`{@link #wakeCPU}`), at runtime?
132 */
133 config Bool allowDynamicMode = false;
134
135 /*!
136 * ======== sleepPrepFunction ========
137 * I/O preparation function to be called by Power_sleepCPU()
138 */
139 config SleepPrepFuncPtr sleepPrepFunction;
140
141 /*!
142 * ======== idleCPU ========
143 * Function to automatically idle the CPU during idle time
144 *
145 * When the `{@link #idle}` configuration parameter is set, this function
146 * will be added to the list of Idle loop functions. When called from the
147 * `Idle` loop, it will transition the CPU into the idle mode specified
148 * by the `{@link #idleMode}` configuration parameter. The CPU will stay
149 * in the corresponding low power mode until the next interrupt occurs.
150 */
151 Void idleCPU();
152
153 /*!
154 * ======== changeIdleMode ========
155 * Change the idleMode used for idling the CPU
156 *
157 * This function does not immediately affect the state of the CPU, but
158 * defines the idleMode that will be invoked at subsequent opportunities
159 * SYS/BIOS has to idle the CPU.
160 *
161 * Changing the `idleMode` at runtime requires that `{@link #idle}` be
162 * enabled, the initial `{@link #idleMode}` is defined, and
163 * `{@link #allowDynamicMode}` is specified in the application
164 * configuration. For example:
165 *
166 * @p(code) 167 * var Power = xdc.useModule('ti.sysbios.family.msp430.Power');
168 * Power.idle = true;
169 * Power.idleMode = Power.LPM3;
170 * Power.allowDynamicMode = true;
171 * @p 172 */
173 Void changeIdleMode(Power.IdleMode mode);
174
175 /*!
176 * ======== sleepCPU ========
177 * Function called by the application to sleep the CPU
178 *
179 * This function currently supports the `LPM4.5` sleep mode only, and
180 * only on MSP430 devices that support this mode. To be effective, the
181 * device I/Os MUST be properly configured before `LPM4.5` is activated,
182 * otherwise there may be excessive current draw, which could be higher
183 * than before this function is called. The proper configuration of I/Os
184 * is device, application, and board specific. The caller of this
185 * function has two options:
186 *
187 * 1) Prepare the device I/Os, and any (non-reset) wakeup interrupts
188 * prior to calling this function, or
189 * 2) Write a function for this purpose, and configure it as the
190 * optional `{@link #sleepPrepFunction}`, that `Power_sleepCPU()`
191 * should call before transitioning to `LPM4.5`.
192 */
193 Void sleepCPU(SleepMode sleepMode);
194
195 /*!
196 * ======== wakeCPU ========
197 * Function called to trigger a dynamic CPU wakeup upon return from
198 * interrupt
199 *
200 * An interrupt can be configured statically (at build time) to let the
201 * CPU naturally resume an LPM mode upon return from interrupt (see
202 * `{@link ti.sysbios.family.msp430 Hwi}`).
203 *
204 * This function (Power_wakeCPU()) can be called from within an ISR
205 * function to override the static configuration (where the CPU would
206 * resume an LPM mode), and force the CPU to stay awake upon return from
207 * interrupt.
208 *
209 * For the case of nested interrupts, the effect of this API is for the
210 * bottom-most (or first-preempting) interrupt, meaning that if this
211 * function is called from an ISR that has nested upon another, the CPU
212 * will be kept awake after the interrupt that first awoke the CPU.
213 *
214 * To call this function, it is required that
215 * `{@link #allowDynamicMode}` is specified as 'true' in the application
216 * configuration. For example:
217 *
218 * @p(code) 219 * var Power = xdc.useModule('ti.sysbios.family.msp430.Power');
220 * Power.allowDynamicMode = true;
221 * @p 222 *
223 */
224 Void wakeCPU();
225
226 /*! @_nodoc 227 * ======== getModeChangeFlag ========
228 * Retrieve flag indicating whether the application changed the idleMode
229 */
230 UInt getModeChangeFlag();
231
232 internal:
233
234 /*
235 * ======== defaultSleepPrepFunction ========
236 * Default (NOP) function to be called to prepare device I/Os for sleep
237 */
238 Void defaultSleepPrepFunction();
239
240 /*
241 * ======== blockedTaskFunction ========
242 * Function to call when Idle not used, and plugging Task.allBlockedFunc
243 */
244 Void blockedTaskFunction();
245
246 /*
247 * ======== Module_State ========
248 */
249 struct Module_State {
250 UInt idleMode; /* idle depth to invoke in Power_idle() */
251 Bool newMode; /* flag indicating idleMode has just changed */
252 }
253 }