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