1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 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,
89 LPM1 = 0x50,
90 LPM2 = 0x90,
91 LPM3 = 0xD0,
92 LPM4 = 0xF0
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 override config 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 236 237
238 Void defaultSleepPrepFunction();
239
240 241 242 243
244 Void blockedTaskFunction();
245
246 247 248
249 struct Module_State {
250 UInt idleMode;
251 Bool newMode;
252 }
253 }