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