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 package ti.sysbios.family.msp430;
38
39 import xdc.rov.ViewInfo;
40
41 import xdc.runtime.Types;
42 import xdc.runtime.Error;
43
44 import ti.sysbios.interfaces.ITimer;
45
46 /*!
47 * ======== Timer ========
48 * MSP430 Timer Peripherals Manager
49 *
50 * This module manages the timer peripherals available on MSP430 devices
51 * (see {@link ./doc-files/TimerTables.html Timer Mapping Tables} for
52 * supported device information).
53 *
54 * The Timer module supports the timer in 'one shot', 'continuous', and
55 * 'dynamic' modes.
56 *
57 * In 'one shot' mode, a timer function will "fire" (run) when the timer
58 * period expires. In 'one shot' mode this will only happen once.
59 *
60 * In 'continuous' mode, the specified timer function will "fire" every
61 * time the period expires, throughout the lifetime of the program.
62 *
63 * In 'dynamic' mode, the specified timer function will "fire" every
64 * time the period expires. But the period of the timer can be changed
65 * dynamically, to correspond to the next tick interrupt needed from the
66 * timer. This mode is used by the SYS/BIOS
67 * {@link ti.sysbios.knl.Clock Clock} module for implementing
68 * dynamic tick suppression, to reduce the number of interrupts from the
69 * timer to the minimum required for currently scheduled timeouts.
70 *
71 * NOTE: In the current implementation on MSP430 Timers cannot be
72 * created dynamically at runtime by the application. Timers must be
73 * created statically in the application configuration.
74 *
75 * @p(html)
76 * <h3> Calling Context </h3>
77 * <table border="1" cellpadding="3">
78 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
79 * </colgroup>
80 *
81 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
82 * <th> Task </th><th> Main </th><th> Startup </th></tr>
83 * <!-- -->
84 * <tr><td> {@link #getAvailMask} </td><td> Y </td>
85 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
86 * <tr><td> {@link #getNumTimers} </td><td> Y </td>
87 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
88 * <tr><td> {@link #getStatus} </td><td> Y </td>
89 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
90 * <tr><td> {@link #Params_init} </td><td> N </td>
91 * <td> N </td><td> N </td><td> N </td><td> N </td></tr>
92 * <tr><td> {@link #construct} </td><td> N </td>
93 * <td> N </td><td> N </td><td> N </td><td> N </td></tr>
94 * <tr><td> {@link #create} </td><td> N </td>
95 * <td> N </td><td> N </td><td> N </td><td> N </td></tr>
96 * <tr><td> {@link #delete} </td><td> N </td>
97 * <td> N </td><td> N </td><td> N </td><td> N </td></tr>
98 * <tr><td> {@link #destruct} </td><td> N </td>
99 * <td> N </td><td> N </td><td> N </td><td> N </td></tr>
100 * <tr><td> {@link #getCount} </td><td> Y </td>
101 * <td> Y </td><td> Y </td><td> N </td><td> N </td></tr>
102 * <tr><td> {@link #getFreq} </td><td> Y </td>
103 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
104 * <tr><td> {@link #getFunc} </td><td> Y </td>
105 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
106 * <tr><td> {@link #getPeriod} </td><td> Y </td>
107 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
108 * <tr><td> {@link #reconfig} </td><td> Y </td>
109 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
110 * <tr><td> {@link #setFunc} </td><td> Y </td>
111 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
112 * <tr><td> {@link #setPeriod} </td><td> Y </td>
113 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
114 * <tr><td> {@link #setPeriodMicroSecs} </td><td> Y </td>
115 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
116 * <tr><td> {@link #start} </td><td> Y </td>
117 * <td> Y </td><td> Y </td><td> N </td><td> N </td></tr>
118 * <tr><td> {@link #stop} </td><td> Y </td>
119 * <td> Y </td><td> Y </td><td> N </td><td> N </td></tr>
120 * <tr><td colspan="6"> Definitions: <br />
121 * <ul>
122 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
123 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
124 * <li> <b>Task</b>: API is callable from a Task thread. </li>
125 * <li> <b>Main</b>: API is callable during any of these phases: </li>
126 * <ul>
127 * <li> In your module startup after this module is started
128 * (e.g. Timer_Module_startupDone() returns TRUE). </li>
129 * <li> During xdc.runtime.Startup.lastFxns. </li>
130 * <li> During main().</li>
131 * <li> During BIOS.startupFxns.</li>
132 * </ul>
133 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
134 * <ul>
135 * <li> During xdc.runtime.Startup.firstFxns.</li>
136 * <li> In your module startup before this module is started
137 * (e.g. Timer_Module_startupDone() returns FALSE).</li>
138 * </ul>
139 * </ul>
140 * </td></tr>
141 *
142 * </table>
143 * @p
144 *
145 * @p(html)
146 * <h3> Timer Mapping Tables </h3>
147 * <p>
148 * The Timer module allows the user to use and configure the various timers
149 * that exist on a particular device. This is achieved by specifying a timer
150 * ID when statically creating the Timer instance.
151 * A convention is used to assign logical IDs to physical timers. ID '0'
152 * corresponds to the first Timer_A peripheral (TA0). ID '1' is assigned to
153 * the next Timer_A (TA1), until there are no more Timer_A peripherals. Then
154 * the next ID is assigned to the first Timer_B peripheral (if present), and
155 * so on.
156 * These tables are provided to show which timers map to which timer IDs.
157 * </p>
158 * {@link ./doc-files/TimerTables.html Timer Mapping Tables}
159 * @p
160 */
161 @ModuleStartup
162 @InstanceInitStatic
163
164 module Timer inherits ti.sysbios.interfaces.ITimer
165 {
166 /*! override supportsDynamic - this Timer does support RunMode_DYNAMIC */
167 override metaonly config Bool supportsDynamic = true;
168
169 /*! override defaultMode - use RunMode_PERIODIC by default */
170 override metaonly config Bool defaultDynamic = false;
171
172
173
174 /*! Lists of input clock sources for timers */
175 enum Source {
176 Source_ACLK = 0x100, /*! ACLK */
177 Source_SMCLK = 0x200, /*! SMCLK */
178 Source_EXTERNAL = 0x000, /*! External clock */
179 Source_EXTERNAL_INVERTED = 0x300 /*! Inverted external clock */
180 };
181
182 /*! Input divider (ID) bit field values */
183 enum ID {
184 ID_1 = 0x0, /*! /1 */
185 ID_2 = 0x40, /*! /2 */
186 ID_4 = 0x80, /*! /4 */
187 ID_8 = 0xC0 /*! /8 */
188 };
189
190 /*! Input Divider Expansion (IDEX) bit field values */
191 enum IDEX {
192 IDEX_1 = 0x0, /*! /1 */
193 IDEX_2 = 0x1, /*! /2 */
194 IDEX_3 = 0x2, /*! /3 */
195 IDEX_4 = 0x3, /*! /4 */
196 IDEX_5 = 0x4, /*! /5 */
197 IDEX_6 = 0x5, /*! /6 */
198 IDEX_7 = 0x6, /*! /7 */
199 IDEX_8 = 0x7 /*! /8 */
200 };
201
202 /*! Max value of Timer period for PeriodType_COUNTS */
203 const UInt MAX_PERIOD = 0x0000ffff;
204
205 /*! @_nodoc
206 * Min instructions to use in trigger().
207 */
208 const Int MIN_SWEEP_PERIOD = 1;
209
210 /*! Timer Configuration struct.
211 *
212 * @field(source) Timer clock source.
213 */
214 struct Control {
215 UInt source; /*! 0x100=ACLK, 0x200=SMCLK, 0=EXT, 0x300=EXT_INVERT */
216 };
217
218 /*! @_nodoc */
219 @XmlDtd
220 metaonly struct BasicView {
221 Ptr halTimerHandle;
222 String label;
223 UInt id;
224 Control configuration;
225 String startMode;
226 String runMode;
227 UInt period;
228 String periodType;
229 Bool synchronous;
230 UInt intNum;
231 String tickFxn[];
232 UArg arg;
233 UInt frequency;
234 String hwiHandle;
235 };
236
237 /*! @_nodoc */
238 metaonly struct DeviceView {
239 UInt id;
240 String device;
241 String devAddr;
242 UInt intNum;
243 String runMode;
244 UInt period;
245 UInt currCount;
246 UInt remainingCount;
247 UInt prevThreshold;
248 String state;
249 };
250
251 /*! @_nodoc */
252 metaonly struct ModuleView {
253 String availMask;
254 }
255
256 /*! @_nodoc */
257 @Facet
258 metaonly config ViewInfo.Instance rovViewInfo =
259 ViewInfo.create({
260 viewMap: [
261 [
262 'Basic',
263 {
264 type: ViewInfo.INSTANCE,
265 viewInitFxn: 'viewInitBasic',
266 structName: 'BasicView'
267 }
268 ],
269 [
270 'Device',
271 {
272 type: ViewInfo.INSTANCE,
273 viewInitFxn: 'viewInitDevice',
274 structName: 'DeviceView'
275 }
276 ],
277 [
278 'Module',
279 {
280 type: ViewInfo.MODULE,
281 viewInitFxn: 'viewInitModule',
282 structName: 'ModuleView'
283 }
284 ],
285 ]
286 });
287
288 /*!
289 * ======== E_invalidTimer ========
290 * Error raised when specified timer id is not supported
291 */
292 config Error.Id E_invalidTimer = {
293 msg: "E_invalidTimer: Invalid Timer Id %d"
294 };
295
296 /*!
297 * ======== E_notAvailable ========
298 * Error raised when requested timer is in use
299 */
300 config Error.Id E_notAvailable = {
301 msg: "E_notAvailable: Timer not available %d"
302 };
303
304 /*!
305 * ======== E_cannotSupport ========
306 * Error raised when requested period is not supported
307 */
308 config Error.Id E_cannotSupport = {
309 msg: "E_cannotSupport: Timer cannot support requested period %d"
310 };
311
312 /*!
313 * ======== E_runtimeCreate ========
314 * Error raised when dynamic Timer create is attempted
315 */
316 config Error.Id E_runtimeCreate = {
317 msg: "E_runtimeCreate: Runtime Timer create is not supported %d"
318 };
319
320 /*!
321 * ======== anyMask ========
322 * Mask of available timers
323 *
324 * This mask is used to identify the timers that can be used when
325 * Timer_create() is called with an id equal to
326 * {@link Timer#ANY Timer_ANY}.
327 */
328 config UInt anyMask = 0x7;
329
330 /*!
331 * ======== keepAwake ========
332 * Wakeup (enable) CPU when Timer ISR returns
333 *
334 * If set to `true`, all Timer instances keep the CPU awake upon
335 * return from interrupt.
336 */
337 config Bool keepAwake = false;
338
339 /*!
340 * ======== oneShotStub ========
341 * @_nodoc
342 *
343 * @param(arg) Unused.
344 */
345 Void oneShotStub(UArg arg);
346
347 /*!
348 * ======== oneShotNestStub ========
349 * @_nodoc
350 *
351 * @param(arg) Unused.
352 */
353 Void oneShotNestStub(UArg arg);
354
355 /*!
356 * ======== periodicStub ========
357 * @_nodoc
358 *
359 * @param(arg) Unused.
360 */
361 Void periodicStub(UArg arg);
362
363 /*!
364 * ======== periodicNestStub ========
365 * @_nodoc
366 *
367 * @param(arg) Unused.
368 */
369 Void periodicNestStub(UArg arg);
370
371 /*!
372 * ======== getHandle ========
373 * @_nodoc
374 * Used by TimestampProvider module to get hold of timer handle used by
375 * Clock.
376 *
377 * @param(id) timer Id.
378 */
379 Handle getHandle(UInt id);
380
381 /*!
382 * ======== getAvailMask ========
383 * Returns the availMask.
384 *
385 * @b(returns) Mask of available timers
386 */
387 UInt getAvailMask();
388
389 instance:
390
391 /*! Hwi Params for Hwi Object. Default is null. */
392 config Hwi.Params *hwiParams = null;
393
394 /*! Clock source input select. Default is ACLK. */
395 config Source clockSource = Source_ACLK;
396
397 /*! Selected clock source is synchronous to CPU clock? Default is false. */
398 config Bool synchronous = false;
399
400 /*! Clock Input Divider (ID) select. Default is /1. */
401 config ID inputDivider = ID_1;
402
403 /*! Clock Input Divider Expansion (IDEX) select. Default is /1. */
404 config IDEX inputDividerExp = IDEX_1;
405
406 /*! Enable nesting of other interrupts on top of this Timer's ISR? */
407 config Bool nesting = false;
408
409 /*! Previous threshold count value. */
410 config UInt prevThreshold = 0;
411
412 /*! Control register configuration. Default source = ACLK. */
413 config UInt controlRegInit = Source_ACLK;
414
415 /*!
416 * ======== reconfig ========
417 * Modify timer instances at runtime
418 *
419 * @param(timerParams) timer Params
420 * @param(tickFxn) function that runs when timer expires.
421 */
422 Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
423
424
425 internal:
426
427 /*!
428 * ======== noStartupNeeded ========
429 * Flag used to prevent misc code from being brought in
430 * un-necessarily
431 */
432 config UInt startupNeeded = false;
433
434 435 436 437
438 Void initDevice(Object *timer);
439
440 441 442 443
444 Int postInit(Object *timer, Error.Block *eb);
445
446 447 448
449 Bool checkOverflow(UInt32 a, UInt32 b);
450
451 /*! Information about timer */
452 struct TimerDevice {
453 UInt intNum;
454 Ptr baseAddr;
455 };
456
457 /*!
458 * ======== numTimerDevices ========
459 * The number of physical timers on the device
460 */
461 config Int numTimerDevices;
462
463 struct Instance_State {
464 Bool staticInst;
465 Int id;
466 UInt controlRegInit;
467 ITimer.RunMode runMode;
468 ITimer.StartMode startMode;
469 UInt period;
470 ITimer.PeriodType periodType;
471 UInt intNum;
472 UArg arg;
473 Hwi.FuncPtr tickFxn;
474 Types.FreqHz frequency;
475 Hwi.Handle hwi;
476 UInt prevThreshold;
477 UInt savedCurrCount;
478 UInt32 rollovers;
479 Bool synchronous;
480 UInt inputDivider;
481 UInt inputDividerExp;
482 }
483
484 struct Module_State {
485 UInt availMask;
486 TimerDevice device[];
487 Handle handles[];
488 }
489 }