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