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.knl;
39
40 import xdc.rov.ViewInfo;
41
42 import xdc.runtime.Assert;
43 import xdc.runtime.Diags;
44 import xdc.runtime.Log;
45
46 import ti.sysbios.hal.Timer;
47
48 /*!
49 * ======== Clock ========
50 * System Clock Manager.
51 *
52 * The System Clock manager is responsible for all timing services in
53 * SYS/BIOS.
54 * It generates the periodic system tick. The tick period is configurable.
55 * The timeout and period for all Clock Instances and timeout values in
56 * other SYS/BIOS modules are specified in terms of Clock ticks.
57 *
58 * Clock Instances are functions that can be scheduled to run after a
59 * certain number of Clock ticks.
60 * Clock instances are either one-shot or periodic. Instances are started
61 * when created or they are started later using the Clock_start()function.
62 * Instances can be stopped using the Clock_stop() function. All Clock
63 * Instances are executed when they expire in the context of a software
64 * interrupt.
65 *
66 * Clock objects are placed in the Clock object service list when
67 * created/constructed and remain there until deleted/destructed.
68 * To minimize processing overhead, unused or expired Clock objects
69 * should be deleted or destructed.
70 *
71 * The getTicks() function returns number of clock ticks since startup.
72 *
73 * By default, the Clock module statically configures a
74 * {@link ti.sysbios.hal.Timer}
75 * timer instance to provide the periodic 1 ms tick interrupt. If you
76 * want to use a custom configured timer for the Clock module's tick source,
77 * use the following example configuration as a guide:
78 *
79 * @p(code)
80 * var Clock = xdc.useModule('ti.sysbios.knl.Clock');
81 *
82 * // Tell the Clock module that YOU are providing the periodic interrupt
83 * Clock.tickSource = Clock.TickSource_USER;
84 *
85 * // this example uses the ti.sysbios.timers.dmtimer.Timer module
86 * var Timer = xdc.useModule('ti.sysbios.timers.dmtimer.Timer');
87 *
88 * // create a dmtimer config parameter object
89 * var timerParams = new Timer.Params();
90 *
91 * // make sure you set the period to 1000 us (1ms)
92 * timerParams.period = 1000;
93 *
94 * // custom dmtimer config parameters here...
95 * timerParams.twer.ovf_wup_ena = 1;
96 *
97 * // Create the timer.
98 * // This example uses timer id 3.
99 * // The timer interrupt handler must be set to 'Clock.tick'.
100 * Timer.create(3, Clock.tick, timerParams);
101 * @p
102 *
103 * @p(html)
104 * <h3> Calling Context </h3>
105 * <table border="1" cellpadding="3">
106 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
107 * </colgroup>
108 *
109 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
110 * <th> Task </th><th> Main </th><th> Startup </th></tr>
111 * <!-- -->
112 * <tr><td> {@link #getTicks} </td><td> Y </td><td> Y </td>
113 * <td> Y </td><td> N </td><td> N </td></tr>
114 * <tr><td> {@link #getTimerHandle} </td><td> Y </td><td> Y </td>
115 * <td> Y </td><td> Y </td><td> Y </td></tr>
116 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
117 * <td> Y </td><td> Y </td><td> Y </td></tr>
118 * <tr><td> {@link #tick} </td><td> Y </td><td> Y </td>
119 * <td> Y </td><td> N </td><td> N </td></tr>
120 * <tr><td> {@link #tickReconfig} </td><td> Y </td><td> Y </td>
121 * <td> Y </td><td> N </td><td> N </td></tr>
122 * <tr><td> {@link #tickStart} </td><td> Y </td><td> Y </td>
123 * <td> Y </td><td> N </td><td> N </td></tr>
124 * <tr><td> {@link #tickStop} </td><td> Y </td><td> Y </td>
125 * <td> Y </td><td> N </td><td> N </td></tr>
126 * <tr><td> {@link #construct} </td><td> N </td><td> N </td>
127 * <td> Y </td><td> Y </td><td> N </td></tr>
128 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
129 * <td> Y </td><td> Y </td><td> N </td></tr>
130 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
131 * <td> Y </td><td> Y </td><td> N </td></tr>
132 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td>
133 * <td> Y </td><td> Y </td><td> N </td></tr>
134 * <tr><td> {@link #getTimeout} </td><td> Y </td><td> Y </td>
135 * <td> Y </td><td> Y </td><td> N </td></tr>
136 * <tr><td> {@link #setFunc} </td><td> Y </td><td> Y </td>
137 * <td> Y </td><td> Y </td><td> N </td></tr>
138 * <tr><td> {@link #setPeriod} </td><td> Y </td><td> Y </td>
139 * <td> Y </td><td> Y </td><td> N </td></tr>
140 * <tr><td> {@link #setTimeout} </td><td> Y </td><td> Y </td>
141 * <td> Y </td><td> Y </td><td> N </td></tr>
142 * <tr><td> {@link #start} </td><td> Y </td><td> Y </td>
143 * <td> Y </td><td> Y </td><td> N </td></tr>
144 * <tr><td> {@link #stop} </td><td> Y </td><td> Y </td>
145 * <td> Y </td><td> Y </td><td> N </td></tr>
146 * <tr><td colspan="6"> Definitions: <br />
147 * <ul>
148 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
149 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
150 * <li> <b>Task</b>: API is callable from a Task thread. </li>
151 * <li> <b>Main</b>: API is callable during any of these phases: </li>
152 * <ul>
153 * <li> In your module startup after this module is started
154 * (e.g. Clock_Module_startupDone() returns TRUE). </li>
155 * <li> During
156 * {@link xdc.runtime.Startup#lastFxns Startup.lastFxns}. </li>
157 * <li> During main().</li>
158 * <li> During
159 * {@link ti.sysbios.BIOS#startupFxns BIOS.startupFxns}.</li>
160 * </ul>
161 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
162 * <ul>
163 * <li> During
164 * {@link xdc.runtime.Startup#firstFxns Startup.firstFxns}.</li>
165 * <li> In your module startup before this module is started
166 * (e.g. Clock_Module_startupDone() returns FALSE).</li>
167 * </ul>
168 * </ul>
169 * </td></tr>
170 *
171 * </table>
172 * @p
173 */
174
175 @ModuleStartup
176 @InstanceFinalize
177 @Template("./Clock.xdt")
178
179 module Clock
180 {
181 /*! Clock Tick Source. */
182 enum TickSource {
183 TickSource_TIMER, /*! Timer Instance used to generate tick */
184 TickSource_USER, /*! Clock_tick() run in user's ISR */
185 TickSource_NULL /*! No clock tick */
186 };
187
188 metaonly struct BasicView {
189 String label;
190 UInt32 timeout;
191 UInt period;
192 String fxn[];
193 UArg arg;
194 Bool started;
195 UInt32 tRemaining;
196 Bool periodic;
197 }
198
199 metaonly struct ModuleView {
200 volatile UInt32 ticks;
201 String tickSource;
202 String timerHandle;
203 UInt timerId;
204 UInt swiPriority;
205 UInt32 tickPeriod;
206 }
207
208 /*! @_nodoc */
209 @Facet
210 metaonly config ViewInfo.Instance rovViewInfo =
211 ViewInfo.create({
212 viewMap: [
213 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
214 ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}],
215 ]
216 });
217
218 /*! Instance function prototype. */
219 typedef Void (*FuncPtr)(UArg);
220
221 /*! Logged if Clock Swi delayed by >= 1 tick */
222 config Log.Event LW_delayed = {
223 mask: Diags.USER3,
224 msg: "LW_delayed: delay: %d"
225 };
226
227 /*! Logged in every Clock tick interrupt */
228 config Log.Event LM_tick = {
229 mask: Diags.USER1 | Diags.USER2,
230 msg: "LM_tick: tick: %d"
231 };
232
233 /*! Logged just prior to calling each Clock function */
234 config Log.Event LM_begin = {
235 mask: Diags.USER1 | Diags.USER2,
236 msg: "LM_begin: clk: 0x%x, func: 0x%x"
237 };
238
239 /*! Asserted in Clock_create() */
240 config Assert.Id A_clockDisabled = {
241 msg: "A_clockDisabled: Cannot create a clock instance when BIOS.clockEnabled is false."
242 };
243
244 /*! Asserted in Clock_create and Clock_delete */
245 config Assert.Id A_badThreadType = {
246 msg: "A_badThreadType: Cannot create/delete a Clock from Hwi or Swi thread."
247 };
248
249 /*!
250 * ======== tickSource ========
251 * Default is TickSource_TIMER.
252 */
253 config TickSource tickSource = TickSource_TIMER;
254
255 /*!
256 * ======== timerId ========
257 * Timer Id for Timer Instance created by Clock.
258 *
259 * The default value is Timer.ANY (~0).
260 * The maximum timerId possible is family-specific.
261 */
262 config UInt timerId = ~0;
263
264 /*!
265 * ======== swiPriority ========
266 * Set the priority of Swi used by Clock module to process its instances.
267 *
268 * Default is Swi.numPriorities - 1;
269 */
270 metaonly config UInt swiPriority;
271
272 /*!
273 * ======== tickPeriod ========
274 * Tick period specified in microseconds.
275 *
276 * Default value is family dependent. For example, linux86 supports a
277 * minimum of 10000us and supports only multiples of 10000us. TI
278 * targets have a default of 1000 microseconds.
279 */
280 config UInt32 tickPeriod;
281
282 /*!
283 * ======== getTicks ========
284 * Time in Clock ticks
285 *
286 * The value returned will wrap back to zero after it reaches the max
287 * value that can be stored in 32 bits.
288 *
289 * @b(returns) time in clock ticks
290 */
291 @DirectCall
292 UInt32 getTicks();
293
294 /*!
295 * ======== getTimerHandle ========
296 * Get timer Handle.
297 *
298 * Used when is it necessary to change family
299 * specific options for the timer and its Hwi Object.
300 *
301 * @b(returns) Timer Handle
302 */
303 @DirectCall
304 ti.sysbios.hal.Timer.Handle getTimerHandle();
305
306 /*!
307 * ======== tickStop ========
308 * Stop clock for reconfiguration.
309 *
310 * This function is used to stop the timer used for generation of
311 * clock ticks. It is used along with Clock_tickStart() and
312 * Clock_tickReconfig() to allow reconfiguration of timer at runtime.
313 *
314 * @a(constraints)
315 * This function is non-reentrant and appropriate locks must be used to
316 * protect against re-entrancy.
317 */
318 @DirectCall
319 Void tickStop();
320
321 /*!
322 * ======== tickReconfig ========
323 * Reconfigure clock for new cpu frequency.
324 *
325 * This function uses the new cpu frequency to reconfigure the timer used
326 * for generation of clock ticks such that tick period is
327 * accurate. This function is used along with Clock_tickStop() and
328 * Clock_tickStart() to allow reconfiguration of timer at runtime.
329 *
330 * When calling Clock_tickReconfig outside of main(), you must also call
331 * Clock_tickStop and Clock_tickStart to stop and restart the timer.
332 * Use the following call sequence:
333 *
334 * @p(code)
335 * // disable interrupts if an interrupt could lead to
336 * // another call to Clock_tickReconfig or if interrupt
337 * // processing relies on having a running timer
338 * Hwi_disable() or Swi_disable();
339 * BIOS_setCpuFrequency(Types.FreqHz *freq);
340 * Clock_tickStop();
341 * Clock_tickReconfig();
342 * Clock_tickStart();
343 * Hwi_restore() or Swi_enable()
344 * @p
345 *
346 * When calling Clock_tickReconfig from main(), the timer has not yet
347 * been started because the timer is started as part of BIOS_start().
348 * As a result, you can use the following simplified call sequence
349 * in main():
350 *
351 * @p(code)
352 * BIOS_setCpuFrequency(Types.FreqHz *freq);
353 * Clock_tickReconfig(Void);
354 * @p
355 *
356 * The return value is false if the timer cannot support the new
357 * frequency
358 *
359 * @b(returns) true if successful
360 *
361 * @a(constraints)
362 * This function is non-reentrant and appropriate locks must be used to
363 * protect against re-entrancy.
364 */
365 @DirectCall
366 Bool tickReconfig();
367
368 /*!
369 * ======== tickStart ========
370 * Start clock after reconfiguration.
371 *
372 * This function starts the timer used for generation of clock ticks
373 * It is used along with Clock_tickStop() and Clock_tickReconfig() to allow
374 * reconfiguration of timer at runtime. The new timer configuration
375 * reflects changes caused by a call to reconfig().
376 *
377 * @a(constraints)
378 * This function is non-reentrant and appropriate locks must be used to
379 * protect against re-entrancy.
380 */
381 @DirectCall
382 Void tickStart();
383
384 /*!
385 * ======== tick ========
386 * Function called by the timer ISR when {@link #tickSource} is
387 * {@link #TickSource_TIMER}.
388 *
389 * When {@link #tickSource} is set to
390 * {@link #TickSource_USER}, Clock_tick() is called by a user isr,
391 * Swi or Task. Note that this function is not re-entrant and
392 * appropriate locks should be used.
393 *
394 * This function posts a Swi that processes the clock instances.
395 */
396 @DirectCall
397 Void tick();
398
399 /*! @_nodoc
400 * ======== workFunc ========
401 * Clock Q service routine
402 *
403 * @param(arg0) Unused. required to match Swi.FuncPtr
404 * @param(arg1) Unused. required to match Swi.FuncPtr
405 */
406 @DirectCall
407 Void workFunc(UArg arg0, UArg arg1);
408
409 /*!
410 * @_nodoc
411 * ======= logTock ========
412 * Log the LD_tick from within Clock module scope
413 */
414 @DirectCall
415 Void logTick();
416
417 instance:
418
419 /*!
420 * ======== create ========
421 * Creates a Clock Instance.
422 *
423 * The first parameter is the function that gets called when the timeout
424 * expires.
425 *
426 * The timeout parameter is used to specify the initial timeout
427 * for both one-shot and periodic Clock instances (in Clock ticks).
428 *
429 * The {@link #period} parameter is used to set the subsequent timeout
430 * interval (in Clock ticks) for periodic instances.
431 *
432 * For one-shot instances, the period parameter must be set to zero.
433 *
434 * @param(clockFxn) function that runs upon timeout
435 * @param(timeout) timeout in clock ticks
436 */
437 @DirectCall
438 create(FuncPtr clockFxn, UInt timeout);
439
440 /*!
441 * ======== startFlag ========
442 * Set if instance needs to be started.
443 *
444 * The default is false.
445 *
446 * When this flag is set to true, the instance created will be started
447 * and the instance function will get called after an interval
448 * equal to its timeout. When set to false, the user has to call
449 * Clock_start() to start the instance.
450 */
451 config Bool startFlag = false;
452
453 /*!
454 * ======== period ========
455 * Instance period.
456 *
457 * The default is 0.
458 *
459 * For periodic Clock instances, this parameter specifies the periodic
460 * timeout interval (in Clock ticks).
461 *
462 * For one-shot Clock instances, this parameter must be set to zero.
463 */
464 config UInt period = 0;
465
466 /*!
467 * ======== arg ========
468 * UArg for Clock Instance function.
469 *
470 * The default is null.
471 */
472 config UArg arg = null;
473
474 /*!
475 * ======== start ========
476 * Start instance.
477 *
478 * The {@link #timeout} and {@link #period} values set during create()
479 * or by calling Clock_setTimeout() and Clock_setPeriod() are used and
480 * the expiry is recomputed.
481 * Note that for periodic instances, the first expiry is
482 * computed using the timeout specified. All subsequent expiries use the
483 * period value.
484 *
485 * @a(constraints)
486 * Timeout of instance cannot be zero
487 */
488 @DirectCall
489 Void start();
490
491 /*!
492 * @_nodoc
493 * ======== startI ========
494 * Internal start function which assumes Hwis disabled.
495 */
496 @DirectCall
497 Void startI();
498
499 /*!
500 * ======== stop ========
501 * Stop instance.
502 */
503 @DirectCall
504 Void stop();
505
506 /*!
507 * ======== setPeriod ========
508 * Set periodic interval.
509 *
510 * @param(period) periodic interval in Clock ticks
511 *
512 * @a(constraints)
513 * Cannot change period of instance that has been started.
514 */
515 @DirectCall
516 Void setPeriod(UInt period);
517
518 /*!
519 * ======== setTimeout ========
520 * Set the initial timeout.
521 *
522 * @param(timeout) initial timeout in Clock ticks
523 *
524 * @a(constraints)
525 * Cannot change the initial timeout of instance that has been started.
526 */
527 @DirectCall
528 Void setTimeout(UInt timeout);
529
530 /*!
531 * ======== setFunc ========
532 * Overwrite Clock function and arg.
533 *
534 * Replaces a Clock object's clockFxn function originally
535 * provided in {@link #create}.
536 *
537 * @param(clockFxn) function of type FuncPtr
538 * @param(arg) argument to clockFxn
539 *
540 * @a(constraints)
541 * Cannot change function and arg of Clock object that has been started.
542 */
543 @DirectCall
544 Void setFunc(FuncPtr fxn, UArg arg);
545
546 /*!
547 * ======== getTimeout ========
548 * Get timeout of instance.
549 *
550 * Returns the remaining time if instance has been started.
551 *
552 * @b(returns) returns timeout in clock ticks
553 */
554 @DirectCall
555 UInt getTimeout();
556
557 internal:
558
559 /*!
560 * ======== doTick ========
561 * Function called by the timer interrupt handler.
562 *
563 * @param(arg) Unused. Required to match signature of Hwi.FuncPtr
564 */
565 Void doTick(UArg arg);
566
567 struct Instance_State {
568 Queue.Elem elem;
569 UInt32 timeout;
570 UInt32 currTimeout;
571 UInt32 period;
572 volatile Bool active;
573 FuncPtr fxn;
574 UArg arg;
575 };
576
577 struct Module_State {
578 volatile UInt32 ticks;
579 UInt swiCount;
580 Timer.Handle timer;
581 Void (*doTickFunc)(UArg);
582
583 Queue.Object clockQ;
584 Swi.Handle swi;
585 };
586 }
587 588 589 590
591