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.knl;
38
39 import xdc.rov.ViewInfo;
40
41 import xdc.runtime.Error;
42 import xdc.runtime.Assert;
43 import xdc.runtime.Diags;
44 import xdc.runtime.Log;
45 import xdc.runtime.Types;
46
47 import ti.sysbios.knl.Queue;
48
49 /*!
50 * ======== Swi ========
51 * Software Interrupt Manager
52 *
53 * The Swi module manages software interrupt service routines, which are
54 * patterned after hardware interrupt service routines.
55
56 * SYS/BIOS manages four distinct levels of execution threads: hardware
57 * interrupt service routines, software interrupt routines, tasks, and
58 * background idle functions. A software interrupt is an object that
59 * encapsulates a function to be executed and a priority.
60 * Software interrupts are prioritized, preempt tasks, and are preempted
61 * by hardware interrupt service routines.
62 *
63 * Each software interrupt has a priority level. A software interrupt
64 * preempts any lower-priority software interrupt currently executing.
65 *
66 * A target program uses an API call to post a Swi object. This causes the
67 * Swi module to schedule execution of the software interrupt's function.
68 * When a Swi is posted by an API call, the Swi object's function is not
69 * executed immediately. Instead, the function is scheduled for execution.
70 * SYS/BIOS uses the Swi's priority to determine whether to preempt the
71 * thread currently running. Note that if a Swi is posted several times
72 * before it begins running, (because Hwis and higher priority interrupts
73 * are running,) when the Swi does eventually run, it will run only one time.
74 *
75 * Software interrupts can be posted for execution with a call to
76 * {@link #post} or a number of other Swi functions. Each Swi object has a
77 * "trigger" which is used either to determine whether to post the Swi or as
78 * a value that can be evaluated within the Swi's function. {@link #andn} and
79 * {@link #dec} post the Swi if the trigger value transitions to 0.
80 * {@link #or} and {@link #inc} also modify the trigger value. ({@link #or}
81 * sets bits, and {@link #andn} clears bits.)
82 *
83 * The {@link #disable} and {@link #restore} operations allow you to
84 * post several
85 * Swis and enable them all for execution at the same time. The Swi
86 * priorities then determine which Swi runs first.
87 *
88 * All Swis run to completion; you cannot suspend a Swi while it waits for
89 * something (for example, a device) to be ready. So, you can use the
90 * trigger to tell the Swi when all the devices and other conditions it
91 * relies on are ready. Within a Swi processing function, a call to
92 * Swi_getTrigger returns the value of the trigger when the Swi started
93 * running.
94 * Note that the trigger is automatically reset to its original value
95 * when a Swi runs; however, {@link #getTrigger} will return the saved
96 * trigger
97 * value from when the Swi started execution.
98 *
99 * All Swis run with interrupts globally enabled (ie GIE = 1).
100 * Therefore, any Swi module API that results in a
101 * Swi being made ready to run (ie {@link #post}, {@link #inc},
102 * {@link #andn}, {@link #or}, {@link #restore}, or {@link #enable})
103 * will subsequently also cause interrupts to be enabled while the
104 * Swi function executes. Upon return from the Swi function,
105 * global interrupts are restored to their previous enabled/disabled
106 * state.
107 *
108 * A Swi preempts any currently running Swi with a lower priority.
109 * When multiple Swis of the same priority level have been posted,
110 * their respective Swi functions are executed in the order the Swis
111 * were posted.
112 * Hwis in turn preempt any currently running Swi,
113 * allowing the target to respond quickly to hardware peripherals.
114 *
115 * Swi threads are executed using the ISR (or "Hwi") stack. Thus
116 * they share the ISR stack with Hwi threads.
117 *
118 * @p(html)
119 * <a name="hookfunc"></a>
120 * @p
121 *
122 * @a(Hook Functions)
123 *
124 * Sets of hook functions can be specified for the Swi module. Each set
125 * contains these hook functions:
126 * @p(blist)
127 * -Register: A function called before all statically-created Swis
128 * are initialized at runtime.
129 * -Create: A function that is called when a Swi is created.
130 * This includes Swis that are created statically and those
131 * created dynamically using {@link #create}.
132 * -Ready: A function that is called when any Swi becomes ready
133 * to run.
134 * -Begin: A function that is called just prior to running a Swi.
135 * -End: A function that is called just after a Swi finishes.
136 * -Delete: A function that is called when a Swi is deleted at
137 * run-time with {@link #delete}.
138 * @p
139 * Hook functions can only be configured statically.
140 *
141 * If you define more than one set of hook functions, all the functions
142 * of a particular type will be run when a Swi triggers that type of
143 * hook.
144 *
145 * @p(html)
146 * <B>Register Function</B>
147 * @p
148 *
149 * The Register function is provided to allow a hook set to store its
150 * hookset ID. This id can be passed to {@link #setHookContext} and
151 * {@link #getHookContext} to set or get hookset-specific context. The
152 * Register function must be specified if the hook implementation
153 * needs to use {@link #setHookContext} or {@link #getHookContext}.
154 * The registerFxn hook function is called during system initialization
155 * before interrupts have been enabled.
156 *
157 * @p(code)
158 * Void myRegisterFxn(Int id);
159 * @p
160 *
161 * @p(html)
162 * <B>Create and Delete Functions</B>
163 * @p
164 *
165 * The create and delete functions are called whenever a Swi is created
166 * or deleted. They are called with interrupts enabled (unless called
167 * at boot time or from main()).
168 *
169 * @p(code)
170 * Void myCreateFxn(Swi_Handle swi, Error_Block *eb);
171 * @p
172 *
173 * @p(code)
174 * Void myDeleteFxn(Swi_Handle swi);
175 * @p
176 *
177 * @p(html)
178 * <B>Ready, Begin, and End Functions</B>
179 * @p
180 *
181 * The ready, begin and end functions are all called with interrupts
182 * enabled. The ready function is called when a Swi is posted and made
183 * ready to run. The begin function is called right before the function
184 * associated with the given Swi is run. The end function is called
185 * right after this function returns.
186 *
187 * @p(code)
188 * Void myReady(Swi_Handle swi);
189 * @p
190 *
191 * @p(code)
192 * Void myBegin(Swi_Handle swi);
193 * @p
194 *
195 * @p(code)
196 * Void myEnd(Swi_Handle swi);
197 * @p
198 *
199 * @p(html)
200 * <h3> Calling Context </h3>
201 * <table border="1" cellpadding="3">
202 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
203 * </colgroup>
204 *
205 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
206 * <th> Task </th><th> Main </th><th> Startup </th></tr>
207 * <!-- -->
208 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
209 * <td> Y </td><td> Y </td><td> N </td></tr>
210 * <tr><td> {@link #disable} </td><td> Y </td><td> Y </td>
211 * <td> Y </td><td> Y </td><td> N </td></tr>
212 * <tr><td> {@link #getTrigger} </td><td> Y </td><td> Y </td>
213 * <td> N </td><td> N </td><td> N </td></tr>
214 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
215 * <td> Y </td><td> Y </td><td> Y </td></tr>
216 * <tr><td> {@link #restore} </td><td> Y </td><td> Y </td>
217 * <td> Y </td><td> Y </td><td> N </td></tr>
218 * <tr><td> {@link #self} </td><td> Y </td><td> Y </td>
219 * <td> N </td><td> N </td><td> N </td></tr>
220 *
221 * <tr><td> {@link #andn} </td><td> Y </td><td> Y </td>
222 * <td> Y </td><td> Y </td><td> N </td></tr>
223 * <tr><td> {@link #construct} </td><td> N </td><td> N </td>
224 * <td> Y </td><td> Y </td><td> N </td></tr>
225 * <tr><td> {@link #dec} </td><td> Y </td><td> Y </td>
226 * <td> Y </td><td> Y </td><td> N </td></tr>
227 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
228 * <td> Y </td><td> Y </td><td> N </td></tr>
229 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td>
230 * <td> Y </td><td> Y </td><td> N </td></tr>
231 * <tr><td> {@link #getAttrs} </td><td> Y </td><td> Y </td>
232 * <td> Y </td><td> Y </td><td> N </td></tr>
233 * <tr><td> {@link #getFunc} </td><td> Y </td><td> Y </td>
234 * <td> Y </td><td> Y </td><td> N </td></tr>
235 * <tr><td> {@link #getHookContext} </td><td> Y </td><td> Y </td>
236 * <td> Y </td><td> Y </td><td> N </td></tr>
237 * <tr><td> {@link #getPri} </td><td> Y </td><td> Y </td>
238 * <td> Y </td><td> Y </td><td> N </td></tr>
239 * <tr><td> {@link #inc} </td><td> Y </td><td> Y </td>
240 * <td> Y </td><td> Y </td><td> N </td></tr>
241 * <tr><td> {@link #or} </td><td> Y </td><td> Y </td>
242 * <td> Y </td><td> Y </td><td> N </td></tr>
243 * <tr><td> {@link #post} </td><td> Y </td><td> Y </td>
244 * <td> Y </td><td> Y </td><td> N </td></tr>
245 * <tr><td> {@link #setAttrs} </td><td> Y* </td><td> Y* </td>
246 * <td> Y </td><td> Y </td><td> N </td></tr>
247 * <tr><td> {@link #setHookContext} </td><td> Y </td><td> Y </td>
248 * <td> Y </td><td> Y </td><td> N </td></tr>
249 * <tr><td colspan="6"> Definitions: <br />
250 * <ul>
251 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
252 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
253 * <li> <b>Task</b>: API is callable from a Task thread. </li>
254 * <li> <b>Main</b>: API is callable during any of these phases: </li>
255 * <ul>
256 * <li> In your module startup after this module is started
257 * (e.g. Swi_Module_startupDone() returns TRUE). </li>
258 * <li> During xdc.runtime.Startup.lastFxns. </li>
259 * <li> During main().</li>
260 * <li> During BIOS.startupFxns.</li>
261 * </ul>
262 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
263 * <ul>
264 * <li> During xdc.runtime.Startup.firstFxns.</li>
265 * <li> In your module startup before this module is started
266 * (e.g. Swi_Module_startupDone() returns FALSE).</li>
267 * </ul>
268 * </ul>
269 * </td></tr>
270 *
271 * </table>
272 * @p
273 */
274
275 @DirectCall
276 @ModuleStartup
277
278 @InstanceFinalize
279 @InstanceInitError
280 @InstanceInitStatic
281
282 module Swi
283 {
284
285
286
287
288 /*!
289 * ======== FuncPtr ========
290 * Swi function type definition
291 *
292 * All Swi functions are passed two uninterpreted arguments of type
293 * UArg and have no return value.
294 */
295 typedef Void (*FuncPtr)(UArg, UArg);
296
297 /*!
298 * ======== HookSet ========
299 * Swi hook set type definition
300 *
301 * This structure defines the set of hook functions that can be
302 * specified for the Swi module.
303 *
304 * See {@link #hookfunc Hook Functions} for details.
305 */
306 struct HookSet {
307 Void (*registerFxn)(Int);
308 Void (*createFxn)(Handle, Error.Block *);
309 Void (*readyFxn)(Handle);
310 Void (*beginFxn)(Handle);
311 Void (*endFxn)(Handle);
312 Void (*deleteFxn)(Handle);
313 };
314
315 /*!
316 * ======== Struct2 ========
317 */
318 struct Struct2__ {
319 Queue.Elem qElem;
320 FuncPtr fxn;
321 UArg arg0;
322 UArg arg1;
323 UInt priority;
324 UInt mask;
325 Bool posted;
326 UInt initTrigger;
327 UInt trigger;
328 Queue.Handle readyQ;
329 Ptr hookEnv[];
330 Types.CordAddr name;
331 };
332
333 typedef Struct2__ Struct2;
334
335 /*!
336 * ======== BasicView ========
337 * @_nodoc
338 */
339 metaonly struct BasicView {
340 String label;
341 String state;
342 UInt priority;
343 String fxn[];
344 UArg arg0;
345 UArg arg1;
346 UInt initTrigger;
347 UInt curTrigger;
348
349 };
350
351 /*!
352 * ======== ModuleView ========
353 * @_nodoc
354 */
355 metaonly struct ModuleView {
356 String schedulerState;
357 String readyQMask;
358 Ptr currentSwi;
359 String currentFxn[];
360 };
361
362 /*!
363 * ======== ReadyQView ========
364 * @_nodoc
365 */
366 metaonly struct ReadyQView {
367 Ptr swi;
368 Ptr next;
369 Ptr prev;
370 Ptr readyQ;
371 String label;
372 String state;
373 Int priority;
374 String fxn[];
375 UArg arg0;
376 UArg arg1;
377 }
378
379 /*!
380 * ======== rovViewInfo ========
381 * @_nodoc
382 */
383 @Facet
384 metaonly config ViewInfo.Instance rovViewInfo =
385 xdc.rov.ViewInfo.create({
386 viewMap: [
387 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
388 ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}],
389 ['ReadyQs', {type: ViewInfo.TREE_TABLE, viewInitFxn: 'viewInitReadyQs', structName: 'ReadyQView'}],
390 ]
391 });
392
393
394
395
396
397 /*!
398 * ======== LM_begin ========
399 * The event logged just prior to invoking a Swi's function
400 */
401 config Log.Event LM_begin = {
402 mask: Diags.USER1 | Diags.USER2,
403 msg: "LM_begin: swi: 0x%x, func: 0x%x, preThread: %d"
404 };
405
406 /*!
407 * ======== LD_end ========
408 * The event logged just after returning from a Swi's function
409 */
410 config Log.Event LD_end = {
411 mask: Diags.USER2,
412 msg: "LD_end: swi: 0x%x"
413 };
414
415 /*!
416 * ======== LM_post ========
417 * The event logged when Swi_post() is called
418 */
419 config Log.Event LM_post = {
420 mask: Diags.USER1 | Diags.USER2,
421 msg: "LM_post: swi: 0x%x, func: 0x%x, pri: %d"
422 };
423
424 /*!
425 * ======== A_swiDisabled ========
426 * Assertion raised if Swi_create is called and runtime Swi creation is
427 * disabled
428 *
429 * see {@link ti.sysbios.BIOS#swiEnabled}
430 */
431 config Assert.Id A_swiDisabled = {
432 msg: "A_swiDisabled: Cannot create a Swi when Swi is disabled."
433 };
434
435 /*!
436 * ======== A_badPriority ========
437 * Assertion raised if a Swi's priority is out of range
438 *
439 * Swi priorities must be in the range of 0 and numPriorities-1.
440 */
441 config Assert.Id A_badPriority = {
442 msg: "A_badPriority: An invalid Swi priority was used."
443 };
444
445 /*!
446 * ======== A_badContextId ========
447 * Assert raised if bad context ID is used.
448 *
449 * Asserted in Swi_setHookContext()/Swi_getHookContext().
450 */
451 config Assert.Id A_badContextId = {
452 msg: "A_badContextId: Hook context id is out of range."
453 };
454
455 /*!
456 * ======== numPriorities ========
457 * Number of Swi priorities supported
458 *
459 * The maximum number of priorities supported is
460 * target-specific and depends on the number of
461 * bits in a UInt data type. For 6x and ARM devices
462 * the maximum number of priorities is therefore 32.
463 * For the C28x, the maximum number of
464 * priorities is 16.
465 */
466
467 config UInt numPriorities = 16;
468
469 /*!
470 * ======== hooks ========
471 * const array to hold all HookSet objects
472 * @_nodoc
473 */
474 config HookSet hooks[length] = [];
475
476
477
478
479 /*!
480 * ======== construct2 ========
481 * Construct a software interrupt
482 *
483 * Swi_construct2 constructs a Swi object. This function is identical
484 * to Swi_construct(), but does not take an Error_Block parameter, and
485 * returns a Swi_Handle.
486 *
487 * The following C code sets Swi parameters and
488 * constructs a Swi object:
489 *
490 * @p(code)
491 *
492 * Swi_Struct2 swiStruct2;
493 * Swi_Handle swi;
494 *
495 * Void main()
496 * {
497 * Swi_Params swiParams;
498 *
499 * Swi_Params_init(&swiParams);
500 * swiParams.arg0 = 1;
501 * swiParams.arg1 = 0;
502 * swiParams.priority = 2;
503 * swiParams.trigger = 0;
504 *
505 * swi = Swi_construct2(&swiStruct2, swiFxn, &swiParams);
506 * if (swi == NULL) {
507 * // Failure
508 * }
509 *
510 * BIOS_start();
511 * }
512 * @p
513 *
514 * @param(swi) Pointer to Swi_Struct2 object.
515 * @param(swiFxn) Swi Function
516 * @param(prms) Pointer to Swi_Params structure
517 *
518 * @b(returns) A Swi handle
519 */
520 Handle construct2(Struct2 *swi, FuncPtr swiFxn, const Params *prms);
521
522 /*!
523 * ======== addHookSet ========
524 * Add hook functions to be called by the Swi scheduler
525 *
526 * This function is used in a config file to add a set of functions
527 * that are called before or after significant points within the Swi
528 * scheduler.
529 *
530 * Configures a set of hook functions for the
531 * Swi module. Each set contains these hook functions:
532 *
533 * @p(blist)
534 * -Register: A function called before all statically-created Swis
535 * are initialized at runtime.
536 * -Create: A function that is called when a Swi is created.
537 * This includes Swis that are created statically and those
538 * created dynamically using {@link #create}.
539 * -Ready: A function that is called when any Swi becomes ready
540 * to run.
541 * -Begin: A function that is called just prior to running a Swi.
542 * -End: A function that is called just after a Swi finishes.
543 * -Delete: A function that is called when a Swi is deleted at
544 * run-time with {@link #delete}.
545 * @p
546 *
547 * See {@link #hookfunc Hook Functions} for more details.
548 *
549 * HookSet structure elements may be omitted, in which case those
550 * elements will not exist.
551 *
552 * For example, the following configuration code defines a
553 * HookSet:
554 *
555 * @p(code)
556 * // Hook Set 1
557 * Swi.addHookSet({
558 * registerFxn: '&myRegister1',
559 * createFxn: '&myCreate1',
560 * readyFxn: '&myReady1',
561 * beginFxn: '&myBegin1',
562 * endFxn: '&myEnd1',
563 * deleteFxn: '&myDelete1'
564 * });
565 * @p
566 *
567 * @param(hookSet) structure of type HookSet
568 */
569
570 metaonly Void addHookSet(HookSet hookSet);
571
572 /*!
573 * ======== Swi_startup ========
574 * Start the Swi scheduler
575 *
576 * @_nodoc
577 * This function is called in BIOS_start() after Hwi_enable().
578 */
579 Void startup();
580
581 /*!
582 * ======== Swi_enabled ========
583 * Returns TRUE if the Swi scheduler is enabled
584 *
585 * @_nodoc
586 */
587 Bool enabled();
588
589 /*!
590 * @_nodoc
591 * ======== unlockSched ========
592 * Force a Swi scheduler unlock. Used by Core_atExit() & Core_hwiFunc()
593 * to unlock Swi scheduler before exiting.
594 *
595 * This function should only be called after a Hwi_disable() has entered
596 * the Inter-core gate and disabled interrupts locally.
597 */
598 Void unlockSched();
599
600 /*!
601 * ======== disable ========
602 * Disable Swi Scheduling
603 *
604 * Swi_disable() and {@link #restore Swi_restore()} control Swi
605 * scheduling.
606 * Swi_disable() disables all Swi functions from running until
607 * Swi_restore() is called. Hardware interrupts can still run.
608 *
609 * Swi_disable() and Swi_restore() allow you to ensure that
610 * statements that must be performed together during critical
611 * processing are not preempted by other Swis or Tasks.
612 *
613 * The value of the key returned by Swi_disable() is opaque to
614 * applications and is meant to be passed to Swi_restore().
615 *
616 * In the following example, the critical section cannot be preempted
617 * by any Swis. Nor can it be pre-empted by other Tasks.
618 *
619 * @p(code)
620 * key = Swi_disable();
621 * `critical section`
622 * Swi_restore(key);
623 * @p
624 *
625 * @a(Side Effects of Disabling the Swi Scheduler)
626 *
627 * {@link #disable Swi_disable()}, in addition to disabling Swis from
628 * pre-empting the code which follows its invocation, has
629 * the side effect of also disabling the Task scheduler.
630 * Consequently, Task pre-emption and blocking is also disabled while
631 * the Swi scheduler is disabled.
632 * When {@link #restore Swi_restore()} is subsequently called, it will
633 * re-enable and invoke the Task scheduler if the Task scheduler was not
634 * already disabled prior to invoking Swi_disable().
635 *
636 * The following code snippet:
637 * @p(code)
638 * key = Swi_disable();
639 * ...
640 * Swi_post(swi); <-- 'swi' will not run
641 * ...
642 * Swi_restore(key); <-- 'swi' runs now
643 * @p
644 * Should be thought of as equivalent to this:
645 * @p(code)
646 * tasKey = Task_disable();
647 * swiKey = Swi_disable();
648 * ...
649 * Swi_post(swi); <-- 'swi' will not run
650 * ...
651 * Swi_restore(swiKey); <-- 'swi' runs now
652 * Task_restore(taskKey);
653 * @p
654 *
655 * In the following example, even though the Semaphore_post() call
656 * unblocks a task of higher priority, the local task is not pre-empted
657 * until after the Swi_restore() call is made:
658 *
659 * @p(code)
660 * key = Swi_disable();
661 * ...
662 * Swi_post(swi); <-- 'swi' will not run
663 * Semaphore_post(sem); <-- readys a task of higher priority than current task
664 * ...
665 * Swi_restore(key); <-- 'swi' runs now, then current task is pre-empted.
666 * @p
667 *
668 * @p(html)
669 * <B>
670 * A common mistake that users make is to invoke a blocking
671 * API such as Semaphore_pend() after calling Swi_disable().
672 * This results in unrecoverable damage to the Task scheduler's internal
673 * state and will lead to unpredictable and usually catastrophic behavior:
674 * </B>
675 * @p
676 *
677 * @p(code)
678 * key = Swi_disable();
679 * ...
680 * Semaphore_pend(sem, BIOS_WAIT_FOREVER); <-- !!! DO NOT DO THIS !!!
681 * ...
682 * Swi_restore(key); <-- !!! System failure guaranteed to follow !!!
683 * @p
684 *
685 * @p(html)
686 * <B>
687 * A more subtle variant of the above problem occurs when an API such
688 * as GateMutex_enter() is invoked directly or indirectly while the
689 * Swi scheduler
690 * is disabled. If the GateMutex has already been entered by another thread,
691 * the current thread should block until the other thread calls
692 * GateMutex_leave().
693 * But because the Task scheduler is disabled, the local thread returns
694 * immediately from GateMutex_enter(), just as though it successfully
695 * entered the GateMutex! This usually leads to catastrophic results.
696 * </B>
697 * @p
698 *
699 * @b(returns) opaque key for use with Swi_restore()
700 */
701
702 UInt disable();
703
704 /*!
705 * ======== enable ========
706 * Enable Swi Scheduling
707 *
708 * @_nodoc
709 * Swi_enable unconditionally enables Swis and invokes the Swi scheduler
710 * if any Swis are pending.
711 *
712 * @a(constraints)
713 * Swi_enable will also invoke the Task scheduler if the
714 * Task scheduler is not currently disabled.
715 *
716 * The {@link #post} discussion regarding global interrupts also applies
717 * to this API.
718 *
719 */
720
721 Void enable();
722
723 /*!
724 * ======== restore ========
725 * Restore Swi Scheduling state
726 *
727 * Swi_restore restores the Swi scheduler to the locked/unlocked state
728 * it was in when Swi_disable was called. If the scheduler becomes
729 * unlocked and Swis of sufficient priority have been made ready to
730 * run by any of the posting APIs, then they are run at this time.
731 *
732 * Swi_disable and Swi_restore control software interrupt processing.
733 * Swi_disable disables all other Swi functions from running until
734 * Swi_restore is called. Hardware interrupts can still run.
735 *
736 * Swi_disable and Swi_restore allow you to ensure that statements that
737 * must be performed together during critical processing are not
738 * pre-empted by other Swis.
739 *
740 * In the following example, the critical section cannot be preempted
741 * by any Swis. Nor can it be pre-empted by other Tasks.
742 *
743 * @p(code)
744 * key = Swi_disable();
745 * `critical section`
746 * Swi_restore(key);
747 * @p
748 *
749 * Read the discussion of the side effects of disabling the Swi
750 * scheduler {@link #disable here}.
751 *
752 * @a(constraints)
753 * Swi_restore will also re-enable and invoke the Task
754 * scheduler if the Task scheduler was not disabled prior to
755 * invoking Swi_disable().
756 *
757 * The {@link #post} discussion regarding global interrupts applies
758 * to this API.
759 *
760 * @param(key) key to restore previous Swi scheduler state
761 */
762
763 Void restore(UInt key);
764
765 /*!
766 * ======== restoreHwi ========
767 * Restore Swi Scheduling state
768 *
769 * @_nodoc
770 * Optimized version used by Hwi dispatcher.
771 */
772 Void restoreHwi(UInt key);
773
774 /*!
775 * ======== self ========
776 * Return address of currently executing Swi object
777 *
778 * Swi_self returns the handle of the currently executing Swi.
779 *
780 * For example, you can call Swi_self as follows if you want
781 * a Swi to repost itself:
782 *
783 * @p(code)
784 * Swi_post( Swi_self() );
785 * @p
786 *
787 * @b(returns) handle of currently running Swi
788 */
789
790 Handle self();
791
792 /*!
793 * ======== getTrigger ========
794 * Return the trigger value of the currently executing Swi
795 *
796 * Swi_getTrigger returns the value that Swi's trigger had when the Swi
797 * started running. SYS/BIOS saves the trigger value internally, so that
798 * Swi_getTrigger can access it at any point within a Swi object's
799 * function, and then automatically resets the trigger to its initial
800 * value.
801 *
802 * Swi_getTrigger should only be called within a function run by a Swi
803 * object.
804 *
805 * When called from within the context of a Swi, the value returned by
806 * Swi_getTrigger is zero if the Swi was posted by a call to Swi_andn,
807 * or Swi_dec. Therefore, Swi_getTrigger provides relevant information
808 * only if the Swi was posted by a call to Swi_inc, Swi_or, or Swi_post.
809 *
810 * This API is called within a Swi object's function to use the trigger
811 * value that caused the function to run. For example, if you use
812 * Swi_or or Swi_inc to post a Swi, different trigger values can require
813 * different processing.
814 *
815 * @p(code)
816 * swicount = Swi_getTrigger();
817 * @p
818 *
819 * @b(returns) trigger value
820 */
821
822 UInt getTrigger();
823
824 /*!
825 * ======== raisePri ========
826 * Raise a Swi's priority
827 *
828 * @_nodoc
829 * This function is provided for legacy compatibility.
830 *
831 * Swi_raisePri is used to raise the priority of the currently running
832 * Swi to the priority passed in as the argument. Swi_raisePri can be
833 * used in conjunction with Swi_restorePri to provide a mutual exclusion
834 * mechanism without disabling Swis.
835 *
836 * Swi_raisePri should be called before a shared resource is accessed,
837 * and Swi_restorePri should be called after the access to the shared
838 * resource.
839 *
840 * A call to Swi_raisePri not followed by a Swi_restorePri keeps the
841 * Swi's priority for the rest of the processing at the raised level. A
842 * Swi_post of the Swi posts the Swi at its original priority level.
843 *
844 * A Swi object's execution priority must range from 0 to
845 * Swi_numPriorities - 1
846 *
847 * Swi_raisePri never lowers the current Swi priority.
848 *
849 * Constraints and Calling Context
850 * @p(blist)
851 * - Swi_raisePri must only be called from a Swi context.
852 * @p
853 *
854 * @b(returns) key for use with restorePri()
855 */
856
857 UInt raisePri(UInt priority);
858
859 /*!
860 * ======== restorePri ========
861 * Restore a Swi's priority
862 *
863 * @_nodoc
864 * This function is provided for legacy compatibility.
865 *
866 * Swi_restorePri restores the priority to the Swi's priority prior to the
867 * Swi_raisePri call. Swi_restorePri can be used in
868 * conjunction with Swi_raisePri to provide a mutual exclusion mechanism
869 * without disabling all Swis.
870 *
871 * Swi_raisePri should be called right before the shared resource is
872 * referenced, and Swi_restorePri should be called after the reference to
873 * the shared resource.
874 *
875 * Constraints and Calling Context
876 *
877 * @p(blist)
878 * - Swi_restorePri must only be called from a Swi context.
879 * @p
880 *
881 * @param(key) key returned from Swi_raisePri
882 */
883 Void restorePri(UInt key);
884
885 instance:
886
887 /*!
888 * ======== create ========
889 * Create a software interrupt
890 *
891 * Swi_create creates a new Swi object.
892 *
893 * The following C code sets Swi parameters and
894 * creates two Swi objects:
895 *
896 * @p(code)
897 * Void main()
898 * {
899 * Swi_Params swiParams;
900 *
901 * Swi_Params_init(&swiParams);
902 * swiParams.arg0 = 1;
903 * swiParams.arg1 = 0;
904 * swiParams.priority = 2;
905 * swiParams.trigger = 0;
906 *
907 * swi0 = Swi_create(swi0Fxn, &swiParams, NULL);
908 *
909 * swiParams.arg0 = 2;
910 * swiParams.arg1 = 0;
911 * swiParams.priority = 1;
912 * swiParams.trigger = 3;
913 *
914 * swi1 = Swi_create(swi1Fxn, &swiParams, NULL);
915 *
916 * BIOS_start();
917 * }
918 * @p
919 *
920 * The following XDCscript statements set Swi parameters and
921 * create two Swi objects:
922 *
923 * @p(code)
924 * var Swi = xdc.useModule('ti.sysbios.knl.Swi');
925 *
926 * var swiParams = new Swi.Params();
927 * swiParams.arg0 = 1;
928 * swiParams.arg1 = 0;
929 * swiParams.priority = 2;
930 * swiParams.trigger = 0;
931 * Program.global.swi0 = Swi.create('&swi0Fxn', swiParams);
932 *
933 * swiParams.arg0 = 2;
934 * swiParams.priority = 1;
935 * swiParams.trigger = 3;
936 * Program.global.swi1 = Swi.create('&swi1Fxn', swiParams);
937 * @p
938 *
939 * @param(swiFxn) Swi Function
940 */
941 create(FuncPtr swiFxn);
942
943
944
945 /*!
946 * ======== arg0 ========
947 * Swi function argument 0
948 *
949 * The default value of this optional parameter is 0.
950 *
951 * @see #FuncPtr
952 */
953 config UArg arg0 = 0;
954
955 /*!
956 * ======== arg1 ========
957 * Swi function argument 1
958 *
959 * The default value of this optional parameter is 0.
960 *
961 * @see #FuncPtr
962 */
963 config UArg arg1 = 0;
964
965 /*!
966 * ======== priority ========
967 * Swi priority
968 *
969 * Each software interrupt has a priority level, 0 to
970 * ({@link #numPriorities} - 1). A software interrupt
971 * preempts any lower-priority software interrupt currently executing.
972 * When multiple Swis of the same priority level have been posted,
973 * their respective Swi functions are executed in the order the Swis
974 * were posted.
975 *
976 * The default value of this optional parameter is ~0, which yields a
977 * Swi with the highest priority: ({@link #numPriorities} - 1).
978 */
979 config UInt priority = ~0;
980
981 /*!
982 * ======== trigger ========
983 * Initial Swi trigger value
984 *
985 * The default value of this optional parameter is 0.
986 *
987 * Each Swi object has a "trigger" used either to determine whether to
988 * post the Swi or as a value that can be evaluated within the Swi's
989 * function.
990 *
991 * The {@link #andn} and {@link #dec} functions post the Swi
992 * if the trigger value transitions to 0. The {@link #or} and
993 * {@link #inc} functions also modify the trigger value. ({@link #or}
994 * sets bits, and {@link #andn} clears bits.)
995 */
996 config UInt trigger = 0;
997
998
999
1000 /*!
1001 * ======== andn ========
1002 * Clear bits in Swi's trigger; post if trigger becomes 0
1003 *
1004 * Swi_andn is used to conditionally post a software interrupt.
1005 * Swi_andn clears the bits specified by a mask from Swi's internal
1006 * trigger. If the Swi's trigger becomes 0, Swi_andn posts the Swi.
1007 * The bitwise logical operation performed is:
1008 *
1009 * @p(code)
1010 * trigger = trigger AND (NOT MASK)
1011 * @p
1012 *
1013 * If multiple conditions that all be met before a
1014 * Swi can run, you should use a different bit in the trigger for
1015 * each condition. When a condition is met, clear the bit for that
1016 * condition.
1017 *
1018 * For example, if two events must happen before a Swi is to be
1019 * triggered, the initial trigger value of the Swi can be 3 (binary 0011).
1020 * One call to Swi_andn can have a mask value of 2 (binary 0010), and
1021 * another call to Swi_andn can have a mask value of 1 (binary 0001).
1022 * After both calls have been made, the trigger value will be 0.
1023 *
1024 * @p(code)
1025 * Swi_andn(swi0, 2); // clear bit 1
1026 * Swi_andn(swi0, 1); // clear bit 0
1027 * @p
1028 *
1029 * Swi_andn results in a context switch if the Swi's trigger becomes
1030 * zero and the Swi has higher priority than the currently executing
1031 * thread.
1032 *
1033 * You specify a Swi's initial trigger value at Swi creation time.
1034 * The trigger value is automatically reset when the Swi executes.
1035 *
1036 * @a(constraints)
1037 * The {@link #post} discussion regarding global interrupts applies
1038 * to this API.
1039 *
1040 * @param(mask) inverse value to be ANDed
1041 */
1042
1043 Void andn(UInt mask);
1044
1045 /*!
1046 * ======== dec ========
1047 * Decrement Swi's trigger value; post if trigger becomes 0
1048 *
1049 * Swi_dec is used to conditionally post a software interrupt. Swi_dec
1050 * decrements the value in Swi's trigger by 1. If Swi's trigger value
1051 * becomes 0, Swi_dec posts the Swi. You can increment a trigger value
1052 * by using Swi_inc, which always posts the Swi.
1053 *
1054 * For example, you would use Swi_dec if you wanted to post a Swi after
1055 * a number of occurrences of an event.
1056 *
1057 * @p(code)
1058 * // swi0's trigger is configured to start at 3
1059 * Swi_dec(swi0); // trigger = 2
1060 * Swi_dec(swi0); // trigger = 1
1061 * Swi_dec(swi0); // trigger = 0
1062 * @p
1063 *
1064 * You specify a Swi's initial trigger value at Swi creation time. The
1065 * trigger value is automatically reset when the Swi executes.
1066 *
1067 * Swi_dec results in a context switch if the Swi's trigger becomes
1068 * zero and the Swi has higher priority than the currently executing
1069 * thread.
1070 *
1071 * @a(constraints)
1072 * The {@link #post} discussion regarding global interrupts applies
1073 * to this API.
1074 */
1075
1076 Void dec();
1077
1078 /*!
1079 * ======== getHookContext ========
1080 * Get hook instance's context pointer for a Swi
1081 *
1082 * For example, this C code gets the HookContext, prints it,
1083 * and sets a new value for the HookContext.
1084 *
1085 * @p(code)
1086 * Ptr pEnv;
1087 * Swi_Handle mySwi;
1088 * Int myHookSetId1;
1089 *
1090 * pEnv = Swi_getHookContext(swi, myHookSetId1);
1091 *
1092 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
1093 * (ULong)pEnv, (ULong)Timestamp_get32());
1094 *
1095 * Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1);
1096 * @p
1097 *
1098 * See {@link #hookfunc Hook Functions} for more details.
1099 *
1100 * @b(returns) hook instance's context pointer for Swi
1101 */
1102 Ptr getHookContext(Int id);
1103
1104 /*!
1105 * ======== setHookContext ========
1106 * Set hook instance's context for a swi
1107 *
1108 * For example, this C code gets the HookContext, prints it,
1109 * and sets a new value for the HookContext.
1110 *
1111 * @p(code)
1112 * Ptr pEnv;
1113 * Swi_Handle mySwi;
1114 * Int myHookSetId1;
1115 *
1116 * pEnv = Swi_getHookContext(swi, myHookSetId1);
1117 *
1118 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
1119 * (ULong)pEnv, (ULong)Timestamp_get32());
1120 *
1121 * Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1);
1122 * @p
1123 *
1124 * See {@link #hookfunc Hook Functions} for more details.
1125 *
1126 * @param(id) hook instance's ID
1127 * @param(hookContext) value to write to context
1128 */
1129 Void setHookContext(Int id, Ptr hookContext);
1130
1131 /*!
1132 * ======== getPri ========
1133 * Return a Swi's priority
1134 *
1135 * Swi_getPri returns the priority of the Swi passed in as the
1136 * argument.
1137 *
1138 * @b(returns) Priority of Swi
1139 */
1140
1141 UInt getPri();
1142
1143 /*!
1144 * ======== getFunc ========
1145 * Get Swi function and arguments
1146 *
1147 * If either arg0 or arg1 is NULL, then the corresponding argument is not
1148 * returned.
1149 *
1150 * @related {@link #getAttrs Swi_getAttrs()}
1151 *
1152 * @param(arg0) pointer for returning Swi's first function argument
1153 * @param(arg1) pointer for returning Swi's second function argument
1154 *
1155 * @b(returns) Swi function
1156 */
1157
1158 FuncPtr getFunc(UArg *arg0, UArg *arg1);
1159
1160 /*!
1161 * ======== getAttrs ========
1162 * Retrieve attributes of an existing Swi object.
1163 *
1164 * The 'handle' argument specifies the address of the Swi object whose
1165 * attributes are to be retrieved.
1166 *
1167 * The 'swiFxn' argument is the address of a function pointer where the
1168 * the Swi function address is to be written to. If NULL is passed for
1169 * 'swiFxn', no attempt is made to return the Swi function.
1170 *
1171 * The 'params' argument is a pointer to a Swi_Params structure that will
1172 * contain the retrieved Swi attributes. If 'params' is NULL, no attempt
1173 * is made to retrieve the Swi_Params.
1174 *
1175 * @related {@link #setAttrs Swi_setAttrs()}
1176 *
1177 * @param(swiFxn) pointer to a Swi_FuncPtr
1178 * @param(params) pointer for returning Swi's Params
1179 */
1180
1181 Void getAttrs(FuncPtr *swiFxn, Params *params);
1182
1183 /*!
1184 * ======== setAttrs ========
1185 * Set the attributes of an existing Swi object.
1186 *
1187 * The 'handle' argument specifies the address of the Swi object whose
1188 * attributes are to be set.
1189 *
1190 * The 'swiFxn' argument is the address of the function to be invoked
1191 * when the Swi runs. If 'swiFxn' is NULL, no change is made to the Swi
1192 * function.
1193 *
1194 * The 'params' argument, which can be either NULL or a pointer to
1195 * a Swi_Params structure that contains attributes for the
1196 * Swi object, facilitates setting the attributes of the Swi object.
1197 *
1198 * If 'params' is NULL, the Swi object is assigned a default set of
1199 * attributes.
1200 * Otherwise, the Swi object's attributes are set according the values
1201 * passed within 'params'.
1202 *
1203 * @Constraints
1204 * Swi_setAttrs() must not be used on a Swi that is preempted
1205 * or is ready to run.
1206 *
1207 * @related {@link #getAttrs Swi_getAttrs()}
1208 *
1209 * @param(swiFxn) address of the Swi function
1210 * @param(params) pointer to optional Swi_Params structure
1211 */
1212
1213 Void setAttrs(FuncPtr swiFxn, Params *params);
1214
1215 /*!
1216 * ======== setPri ========
1217 * Set a Swi's priority
1218 *
1219 * Swi_setPri sets the priority of the Swi passed in as the
1220 * argument.
1221 *
1222 * @a(constraints)
1223 * The priority must be in the range of 0 and numPriorities-1.
1224 *
1225 * @a(constraints)
1226 * Swi_setPri() must not be used on a Swi that is preempted
1227 * or is ready to run.
1228 *
1229 * @related {@link #getPri Swi_setAttrs()}
1230 *
1231 * @param(priority) priority of Swi
1232 */
1233
1234 Void setPri(UInt priority);
1235
1236 /*!
1237 * ======== inc ========
1238 * Increment Swi's trigger value and post the Swi
1239 *
1240 * Swi_inc increments the value in Swi's trigger by 1 and posts the Swi
1241 * regardless of the resulting trigger value. You can decrement a
1242 * trigger value using Swi_dec, which only posts the Swi if the
1243 * trigger value is 0.
1244 *
1245 * If a Swi is posted several times before it has a chance to begin
1246 * executing (i.e. when Hwis or higher priority Swis are running) the Swi
1247 * only runs one time. If this situation occurs, you can use Swi_inc to
1248 * post the Swi. Within the Swi's function, you could then use
1249 * Swi_getTrigger to find out how many times this Swi has been posted
1250 * since the last time it was executed.
1251 *
1252 * You specify a Swi's initial trigger value at Swi creation time.
1253 * The trigger value is automatically reset when the Swi executes.
1254 * To get the trigger value, use Swi_getTrigger.
1255 *
1256 * Swi_inc results in a context switch if the Swi is higher priority
1257 * than the currently executing thread.
1258 *
1259 * @a(constraints)
1260 * The {@link #post} discussion regarding global interrupts applies
1261 * to this API.
1262 */
1263
1264 Void inc();
1265
1266 /*!
1267 * ======== or ========
1268 * Or mask with value contained in Swi's trigger and post the
1269 * Swi.
1270 *
1271 * Swi_or is used to post a software interrupt. Swi_or sets the bits
1272 * specified by a mask in Swi's trigger. Swi_or posts the Swi
1273 * regardless of the resulting trigger value. The bitwise logical
1274 * operation performed on the trigger value is:
1275 *
1276 * @p(code)
1277 * trigger = trigger OR mask
1278 * @p
1279 *
1280 * You specify a Swi's initial trigger value at Swi creation time.
1281 * The trigger value is automatically reset when the Swi executes.
1282 * To get the trigger value, use Swi_getTrigger.
1283 *
1284 * For example, you might use Swi_or to post a Swi if any of three
1285 * events should cause a Swi to be executed, but you want the Swi's
1286 * function to be able to tell which event occurred. Each event
1287 * would correspond to a different bit in the trigger.
1288 *
1289 * Swi_or results in a context switch if the Swi is higher priority
1290 * than the currently executing thread.
1291 *
1292 * @a(constraints)
1293 * The {@link #post} discussion regarding global interrupts applies
1294 * to this API.
1295 *
1296 * @param(mask) value to be ORed
1297 */
1298
1299 Void or(UInt mask);
1300
1301 /*!
1302 * ======== post ========
1303 * Unconditionally post a software interrupt
1304 *
1305 * Swi_post is used to post a software interrupt regardless of the
1306 * trigger value. No change is made to the Swi object's trigger value.
1307 *
1308 * Swi_post results in a context switch if the Swi is higher priority
1309 * than the currently executing thread.
1310 *
1311 * @a(constraints)
1312 * Swis are ALWAYS run with interrupts enabled.
1313 * If a Swi is made ready to run as a consequence of this
1314 * API, interrupts will be globally enabled while the Swi function
1315 * executes, regardless of the prior globally enabled/disabled
1316 * state of interrupts.
1317 * Upon return from this API, the global interrupt enabled/disabled state
1318 * is restored to its previous value.
1319 */
1320
1321 Void post();
1322
1323 internal:
1324
1325 1326 1327 1328 1329 1330 1331
1332 config UInt (*taskDisable)();
1333 config Void (*taskRestore)(UInt);
1334
1335 1336 1337 1338 1339 1340 1341 1342 1343
1344 Void schedule();
1345
1346 1347 1348 1349 1350 1351
1352 Void runLoop();
1353
1354 1355 1356 1357 1358 1359 1360
1361 Void run(Object *swi);
1362
1363 1364 1365 1366
1367 Int postInit(Object *swi, Error.Block *eb);
1368
1369 1370 1371 1372
1373 Void restoreSMP();
1374
1375 /*!
1376 * ======== numConstructedSwis ========
1377 * Number of statically constructed Swi objects
1378 *
1379 * @_nodoc
1380 * Shouldn't be set directly by the user's
1381 * config (it gets set by instance$static$init).
1382 */
1383 config UInt numConstructedSwis = 0;
1384
1385 /*!
1386 * ======== Instance_State ========
1387 * @_nodoc
1388 */
1389 struct Instance_State {
1390 Queue.Elem qElem;
1391 FuncPtr fxn;
1392 UArg arg0;
1393 UArg arg1;
1394 UInt priority;
1395 UInt mask;
1396 Bool posted;
1397 UInt initTrigger;
1398 UInt trigger;
1399 Queue.Handle readyQ;
1400 Ptr hookEnv[];
1401 };
1402
1403 /*!
1404 * ======== Module_State ========
1405 * @_nodoc
1406 */
1407 struct Module_State {
1408 volatile Bool locked;
1409 UInt curSet;
1410 UInt curTrigger;
1411 Handle curSwi;
1412 Queue.Handle curQ;
1413
1414 Queue.Object readyQ[];
1415 Handle constructedSwis[];
1416
1417 };
1418 }