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, or Swi_post.
728 *
729 * This API is called within a Swi object's function to use the trigger
730 * value that caused the function to run. For example, if you use
731 * Swi_or or Swi_inc to post a Swi, different trigger values can require
732 * different processing.
733 *
734 * @p(code)
735 * swicount = Swi_getTrigger();
736 * @p
737 *
738 * @b(returns) trigger value
739 */
740 UInt getTrigger();
741
742 /*!
743 * ======== raisePri ========
744 * Raise a Swi's priority
745 *
746 * @_nodoc
747 * This function is provided for legacy compatibility.
748 *
749 * Swi_raisePri is used to raise the priority of the currently running
750 * Swi to the priority passed in as the argument. Swi_raisePri can be
751 * used in conjunction with Swi_restorePri to provide a mutual exclusion
752 * mechanism without disabling Swis.
753 *
754 * Swi_raisePri should be called before a shared resource is accessed,
755 * and Swi_restorePri should be called after the access to the shared
756 * resource.
757 *
758 * A call to Swi_raisePri not followed by a Swi_restorePri keeps the
759 * Swi's priority for the rest of the processing at the raised level. A
760 * Swi_post of the Swi posts the Swi at its original priority level.
761 *
762 * A Swi object's execution priority must range from 0 to
763 * Swi_numPriorities - 1
764 *
765 * Swi_raisePri never lowers the current Swi priority.
766 *
767 * Constraints and Calling Context
768 * @p(blist)
769 * - Swi_raisePri must only be called from a Swi context.
770 * @p
771 *
772 * @b(returns) key for use with restorePri()
773 */
774 UInt raisePri(UInt priority);
775
776 /*!
777 * ======== restorePri ========
778 * Restore a Swi's priority
779 *
780 * @_nodoc
781 * This function is provided for legacy compatibility.
782 *
783 * Swi_restorePri restores the priority to the Swi's priority prior to the
784 * Swi_raisePri call. Swi_restorePri can be used in
785 * conjunction with Swi_raisePri to provide a mutual exclusion mechanism
786 * without disabling all Swis.
787 *
788 * Swi_raisePri should be called right before the shared resource is
789 * referenced, and Swi_restorePri should be called after the reference to
790 * the shared resource.
791 *
792 * Constraints and Calling Context
793 *
794 * @p(blist)
795 * - Swi_restorePri must only be called from a Swi context.
796 * @p
797 *
798 * @param(key) key returned from Swi_raisePri
799 */
800 Void restorePri(UInt key);
801
802 instance:
803
804 /*!
805 * ======== create ========
806 * Create a software interrupt
807 *
808 * Swi_create creates a new Swi object.
809 *
810 * The following C code sets Swi parameters and
811 * creates two Swi objects:
812 *
813 * @p(code)
814 * Void main()
815 * {
816 * Swi_Params swiParams;
817 *
818 * Swi_Params_init(&swiParams);
819 * swiParams.arg0 = 1;
820 * swiParams.arg1 = 0;
821 * swiParams.priority = 2;
822 * swiParams.trigger = 0;
823 *
824 * swi0 = Swi_create(swi0Fxn, &swiParams, NULL);
825 *
826 * swiParams.arg0 = 2;
827 * swiParams.arg1 = 0;
828 * swiParams.priority = 1;
829 * swiParams.trigger = 3;
830 *
831 * swi1 = Swi_create(swi1Fxn, &swiParams, NULL);
832 *
833 * BIOS_start();
834 * }
835 * @p
836 *
837 * The following XDCscript statements set Swi parameters and
838 * create two Swi objects:
839 *
840 * @p(code)
841 * var Swi = xdc.useModule('ti.sysbios.knl.Swi');
842 *
843 * var swiParams = new Swi.Params();
844 * swiParams.arg0 = 1;
845 * swiParams.arg1 = 0;
846 * swiParams.priority = 2;
847 * swiParams.trigger = 0;
848 * Program.global.swi0 = Swi.create('&swi0Fxn', swiParams);
849 *
850 * swiParams.arg0 = 2;
851 * swiParams.priority = 1;
852 * swiParams.trigger = 3;
853 * Program.global.swi1 = Swi.create('&swi1Fxn', swiParams);
854 * @p
855 *
856 * @param(swiFxn) Swi Function
857 */
858 create(FuncPtr swiFxn);
859
860
861
862 /*!
863 * ======== arg0 ========
864 * Swi function argument 0
865 *
866 * The default value of this optional parameter is 0.
867 *
868 * @see #FuncPtr
869 */
870 config UArg arg0 = 0;
871
872 /*!
873 * ======== arg1 ========
874 * Swi function argument 1
875 *
876 * The default value of this optional parameter is 0.
877 *
878 * @see #FuncPtr
879 */
880 config UArg arg1 = 0;
881
882 /*!
883 * ======== priority ========
884 * Swi priority
885 *
886 * Each software interrupt has a priority level, 0 to
887 * ({@link #numPriorities} - 1). A software interrupt
888 * preempts any lower-priority software interrupt currently executing.
889 * When multiple Swis of the same priority level have been posted,
890 * their respective Swi functions are executed in the order the Swis
891 * were posted.
892 *
893 * The default value of this optional parameter is ~0, which yields a
894 * Swi with the highest priority: ({@link #numPriorities} - 1).
895 */
896 config UInt priority = ~0;
897
898 /*!
899 * ======== trigger ========
900 * Initial Swi trigger value
901 *
902 * The default value of this optional parameter is 0.
903 *
904 * Each Swi object has a "trigger" used either to determine whether to
905 * post the Swi or as a value that can be evaluated within the Swi's
906 * function.
907 *
908 * The {@link #andn} and {@link #dec} functions post the Swi
909 * if the trigger value transitions to 0. The {@link #or} and
910 * {@link #inc} functions also modify the trigger value. ({@link #or}
911 * sets bits, and {@link #andn} clears bits.)
912 */
913 config UInt trigger = 0;
914
915
916
917 /*!
918 * ======== andn ========
919 * Clear bits in Swi's trigger; post if trigger becomes 0
920 *
921 * Swi_andn is used to conditionally post a software interrupt.
922 * Swi_andn clears the bits specified by a mask from Swi's internal
923 * trigger. If the Swi's trigger becomes 0, Swi_andn posts the Swi.
924 * The bitwise logical operation performed is:
925 *
926 * @p(code)
927 * trigger = trigger AND (NOT MASK)
928 * @p
929 *
930 * If multiple conditions that all be met before a
931 * Swi can run, you should use a different bit in the trigger for
932 * each condition. When a condition is met, clear the bit for that
933 * condition.
934 *
935 * For example, if two events must happen before a Swi is to be
936 * triggered, the initial trigger value of the Swi can be 3 (binary 0011).
937 * One call to Swi_andn can have a mask value of 2 (binary 0010), and
938 * another call to Swi_andn can have a mask value of 1 (binary 0001).
939 * After both calls have been made, the trigger value will be 0.
940 *
941 * @p(code)
942 * Swi_andn(swi0, 2); // clear bit 1
943 * Swi_andn(swi0, 1); // clear bit 0
944 * @p
945 *
946 * Swi_andn results in a context switch if the Swi's trigger becomes
947 * zero and the Swi has higher priority than the currently executing
948 * thread.
949 *
950 * You specify a Swi's initial trigger value at Swi creation time.
951 * The trigger value is automatically reset when the Swi executes.
952 *
953 * @a(constraints)
954 * The {@link #post} discussion regarding global interrupts applies
955 * to this API.
956 *
957 * @param(mask) inverse value to be ANDed
958 */
959 Void andn(UInt mask);
960
961 /*!
962 * ======== dec ========
963 * Decrement Swi's trigger value; post if trigger becomes 0
964 *
965 * Swi_dec is used to conditionally post a software interrupt. Swi_dec
966 * decrements the value in Swi's trigger by 1. If Swi's trigger value
967 * becomes 0, Swi_dec posts the Swi. You can increment a trigger value
968 * by using Swi_inc, which always posts the Swi.
969 *
970 * For example, you would use Swi_dec if you wanted to post a Swi after
971 * a number of occurrences of an event.
972 *
973 * @p(code)
974 * // swi0's trigger is configured to start at 3
975 * Swi_dec(swi0); // trigger = 2
976 * Swi_dec(swi0); // trigger = 1
977 * Swi_dec(swi0); // trigger = 0
978 * @p
979 *
980 * You specify a Swi's initial trigger value at Swi creation time. The
981 * trigger value is automatically reset when the Swi executes.
982 *
983 * Swi_dec results in a context switch if the Swi's trigger becomes
984 * zero and the Swi has higher priority than the currently executing
985 * thread.
986 *
987 * @a(constraints)
988 * The {@link #post} discussion regarding global interrupts applies
989 * to this API.
990 */
991 Void dec();
992
993 /*!
994 * ======== getHookContext ========
995 * Get hook instance's context pointer for a Swi
996 *
997 * For example, this C code gets the HookContext, prints it,
998 * and sets a new value for the HookContext.
999 *
1000 * @p(code)
1001 * Ptr pEnv;
1002 * Swi_Handle mySwi;
1003 * Int myHookSetId1;
1004 *
1005 * pEnv = Swi_getHookContext(swi, myHookSetId1);
1006 *
1007 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
1008 * (ULong)pEnv, (ULong)Timestamp_get32());
1009 *
1010 * Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1);
1011 * @p
1012 *
1013 * See {@link #hookfunc Hook Functions} for more details.
1014 *
1015 * @b(returns) hook instance's context pointer for Swi
1016 */
1017 Ptr getHookContext(Int id);
1018
1019 /*!
1020 * ======== setHookContext ========
1021 * Set hook instance's context for a swi
1022 *
1023 * For example, this C code gets the HookContext, prints it,
1024 * and sets a new value for the HookContext.
1025 *
1026 * @p(code)
1027 * Ptr pEnv;
1028 * Swi_Handle mySwi;
1029 * Int myHookSetId1;
1030 *
1031 * pEnv = Swi_getHookContext(swi, myHookSetId1);
1032 *
1033 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
1034 * (ULong)pEnv, (ULong)Timestamp_get32());
1035 *
1036 * Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1);
1037 * @p
1038 *
1039 * See {@link #hookfunc Hook Functions} for more details.
1040 *
1041 * @param(id) hook instance's ID
1042 * @param(hookContext) value to write to context
1043 */
1044 Void setHookContext(Int id, Ptr hookContext);
1045
1046 /*!
1047 * ======== getPri ========
1048 * Return a Swi's priority
1049 *
1050 * Swi_getPri returns the priority of the Swi passed in as the
1051 * argument.
1052 *
1053 * @b(returns) Priority of Swi
1054 */
1055 UInt getPri();
1056
1057 /*!
1058 * ======== getFunc ========
1059 * Get Swi function and arguments
1060 *
1061 * If either arg0 or arg1 is NULL, then the corresponding argument is not
1062 * returned.
1063 *
1064 * @related {@link #getAttrs Swi_getAttrs()}
1065 *
1066 * @param(arg0) pointer for returning Swi's first function argument
1067 * @param(arg1) pointer for returning Swi's second function argument
1068 *
1069 * @b(returns) Swi function
1070 */
1071 FuncPtr getFunc(UArg *arg0, UArg *arg1);
1072
1073 /*!
1074 * ======== getAttrs ========
1075 * Retrieve attributes of an existing Swi object.
1076 *
1077 * The 'handle' argument specifies the address of the Swi object whose
1078 * attributes are to be retrieved.
1079 *
1080 * The 'swiFxn' argument is the address of a function pointer where the
1081 * the Swi function address is to be written to. If NULL is passed for
1082 * 'swiFxn', no attempt is made to return the Swi function.
1083 *
1084 * The 'params' argument is a pointer to a Swi_Params structure that will
1085 * contain the retrieved Swi attributes.
1086 *
1087 * @related {@link #setAttrs Swi_setAttrs()}
1088 *
1089 * @param(swiFxn) pointer to a Swi_FuncPtr
1090 * @param(params) pointer for returning Swi's Params
1091 */
1092 Void getAttrs(FuncPtr *swiFxn, Params *params);
1093
1094 /*!
1095 * ======== setAttrs ========
1096 * Set the attributes of an existing Swi object.
1097 *
1098 * The 'handle' argument specifies the address of the Swi object whose
1099 * attributes are to be set.
1100 *
1101 * The 'swiFxn' argument is the address of the function to be invoked
1102 * when the Swi runs. If 'swiFxn' is NULL, no change is made to the Swi
1103 * function.
1104 *
1105 * The 'params' argument, which can be either NULL or a pointer to
1106 * a Swi_Params structure that contains attributes for the
1107 * Swi object, facilitates setting the attributes of the Swi object.
1108 *
1109 * If 'params' is NULL, the Swi object is assigned a default set of
1110 * attributes.
1111 * Otherwise, the Swi object's attributes are set according the values
1112 * passed within 'params'.
1113 *
1114 * @Constraints
1115 * Swi_setAttrs() must not be used on a Swi that is preempted
1116 * or is ready to run.
1117 *
1118 * @related {@link #getAttrs Swi_getAttrs()}
1119 *
1120 * @param(swiFxn) address of the Swi function
1121 * @param(params) pointer for returning Swi's Params
1122 */
1123 Void setAttrs(FuncPtr swiFxn, Params *params);
1124
1125 /*!
1126 * ======== inc ========
1127 * Increment Swi's trigger value and post the Swi
1128 *
1129 * Swi_inc increments the value in Swi's trigger by 1 and posts the Swi
1130 * regardless of the resulting trigger value. You can decrement a
1131 * trigger value using Swi_dec, which only posts the Swi if the
1132 * trigger value is 0.
1133 *
1134 * If a Swi is posted several times before it has a chance to begin
1135 * executing (i.e. when Hwis or higher priority Swis are running) the Swi
1136 * only runs one time. If this situation occurs, you can use Swi_inc to
1137 * post the Swi. Within the Swi's function, you could then use
1138 * Swi_getTrigger to find out how many times this Swi has been posted
1139 * since the last time it was executed.
1140 *
1141 * You specify a Swi's initial trigger value at Swi creation time.
1142 * The trigger value is automatically reset when the Swi executes.
1143 * To get the trigger value, use Swi_getTrigger.
1144 *
1145 * Swi_inc results in a context switch if the Swi is higher priority
1146 * than the currently executing thread.
1147 *
1148 * @a(constraints)
1149 * The {@link #post} discussion regarding global interrupts applies
1150 * to this API.
1151 */
1152 Void inc();
1153
1154 /*!
1155 * ======== or ========
1156 * Or mask with value contained in Swi's trigger and post the
1157 * Swi.
1158 *
1159 * Swi_or is used to post a software interrupt. Swi_or sets the bits
1160 * specified by a mask in Swi's trigger. Swi_or posts the Swi
1161 * regardless of the resulting trigger value. The bitwise logical
1162 * operation performed on the trigger value is:
1163 *
1164 * @p(code)
1165 * trigger = trigger OR mask
1166 * @p
1167 *
1168 * You specify a Swi's initial trigger value at Swi creation time.
1169 * The trigger value is automatically reset when the Swi executes.
1170 * To get the trigger value, use Swi_getTrigger.
1171 *
1172 * For example, you might use Swi_or to post a Swi if any of three
1173 * events should cause a Swi to be executed, but you want the Swi's
1174 * function to be able to tell which event occurred. Each event
1175 * would correspond to a different bit in the trigger.
1176 *
1177 * Swi_or results in a context switch if the Swi is higher priority
1178 * than the currently executing thread.
1179 *
1180 * @a(constraints)
1181 * The {@link #post} discussion regarding global interrupts applies
1182 * to this API.
1183 *
1184 * @param(mask) value to be ORed
1185 */
1186 Void or(UInt mask);
1187
1188 /*!
1189 * ======== post ========
1190 * Unconditionally post a software interrupt
1191 *
1192 * Swi_post is used to post a software interrupt regardless of the
1193 * trigger value. No change is made to the Swi object's trigger value.
1194 *
1195 * Swi_post results in a context switch if the Swi is higher priority
1196 * than the currently executing thread.
1197 *
1198 * @a(constraints)
1199 * Swis are ALWAYS run with interrupts enabled.
1200 * If a Swi is made ready to run as a consequence of this
1201 * API, interrupts will be globally enabled while the Swi function
1202 * executes, regardless of the prior globally enabled/disabled
1203 * state of interrupts.
1204 * Upon return from this API, the global interrupt enabled/disabled state
1205 * is restored to its previous value.
1206 */
1207 Void post();
1208
1209 internal:
1210
1211 1212 1213 1214 1215 1216 1217
1218 config UInt (*taskDisable)();
1219 config Void (*taskRestore)(UInt);
1220
1221 1222 1223 1224 1225 1226 1227 1228 1229
1230 Void schedule();
1231
1232 1233 1234 1235 1236 1237
1238 Void runLoop();
1239
1240 1241 1242 1243 1244 1245 1246
1247 Void run(Object *swi);
1248
1249 1250 1251 1252
1253 Int postInit(Object *swi, Error.Block *eb);
1254
1255 1256 1257 1258
1259 Void restoreSMP();
1260
1261 /*!
1262 * ======== numConstructedSwis ========
1263 * Number of statically constructed Swi objects
1264 *
1265 * @_nodoc
1266 * Shouldn't be set directly by the user's
1267 * config (it gets set by instance$static$init).
1268 */
1269 config UInt numConstructedSwis = 0;
1270
1271 /*!
1272 * ======== Instance_State ========
1273 * @_nodoc
1274 */
1275 struct Instance_State {
1276 Queue.Elem qElem;
1277 FuncPtr fxn;
1278 UArg arg0;
1279 UArg arg1;
1280 UInt priority;
1281 UInt mask;
1282 Bool posted;
1283 UInt initTrigger;
1284 UInt trigger;
1285 Queue.Handle readyQ;
1286 Ptr hookEnv[];
1287 };
1288
1289 /*!
1290 * ======== Module_State ========
1291 * @_nodoc
1292 */
1293 struct Module_State {
1294 volatile Bool locked;
1295 UInt curSet;
1296 UInt curTrigger;
1297 Handle curSwi;
1298 Queue.Handle curQ;
1299
1300 Queue.Object readyQ[];
1301 Handle constructedSwis[];
1302
1303 };
1304 }