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 * {@link #disable} also disables the Task scheduler.
118 * Therefore, Task pre-emption and blocking is disabled while
119 * the Swi scheduler is disabled.
120 * {@link #restore} will re-enable and invoke the Task
121 * scheduler if the Task scheduler was not disabled prior
122 * to invoking {@link #disable}.
123 * The currently ready highest priority task will be immediately
124 * switched to or continue to run when the lowest order {@link #restore}
125 * invocation re-enables the Swi scheduler.
126 *
127 * In the following example, the newly created task is not switched to
128 * until after the Swi_restore() call since Task scheduling is disabled
129 * while Swi scheduling is disabled:
130 *
131 * @p(code)
132 * key = Swi_disable();
133 * // create a task of higher priority than the current task thread
134 * myTaskParams.priority = Task_getPri(Task_self()) + 1;
135 * myTask = Task_create(myTaskFunc, &myTaskParams, NULL);
136 * Swi_restore(key);
137 * @p
138 *
139 * @p(html)
140 * <a name="hookfunc"></a>
141 * @p
142 *
143 * @a(Hook Functions)
144 *
145 * Sets of hook functions can be specified for the Swi module. Each set
146 * contains these hook functions:
147 * @p(blist)
148 * -Register: A function called before all statically-created Swis
149 * are initialized at runtime.
150 * -Create: A function that is called when a Swi is created.
151 * This includes Swis that are created statically and those
152 * created dynamically using {@link #create}.
153 * -Ready: A function that is called when any Swi becomes ready
154 * to run.
155 * -Begin: A function that is called just prior to running a Swi.
156 * -End: A function that is called just after a Swi finishes.
157 * -Delete: A function that is called when a Swi is deleted at
158 * run-time with {@link #delete}.
159 * @p
160 * Hook functions can only be configured statically.
161 *
162 * If you define more than one set of hook functions, all the functions
163 * of a particular type will be run when a Swi triggers that type of
164 * hook.
165 *
166 * @p(html)
167 * <B>Register Function</B>
168 * @p
169 *
170 * The Register function is provided to allow a hook set to store its
171 * hookset ID. This id can be passed to {@link #setHookContext} and
172 * {@link #getHookContext} to set or get hookset-specific context. The
173 * Register function must be specified if the hook implementation
174 * needs to use {@link #setHookContext} or {@link #getHookContext}.
175 * The registerFxn hook function is called during system initialization
176 * before interrupts have been enabled.
177 *
178 * @p(code)
179 * Void myRegisterFxn(Int id);
180 * @p
181 *
182 * @p(html)
183 * <B>Create and Delete Functions</B>
184 * @p
185 *
186 * The create and delete functions are called whenever a Swi is created
187 * or deleted. They are called with interrupts enabled (unless called
188 * at boot time or from main()).
189 *
190 * @p(code)
191 * Void myCreateFxn(Swi_Handle swi, Error_Block *eb);
192 * @p
193 *
194 * @p(code)
195 * Void myDeleteFxn(Swi_Handle swi);
196 * @p
197 *
198 * @p(html)
199 * <B>Ready, Begin, and End Functions</B>
200 * @p
201 *
202 * The ready, begin and end functions are all called with interrupts
203 * enabled. The ready function is called when a Swi is posted and made
204 * ready to run. The begin function is called right before the function
205 * associated with the given Swi is run. The end function is called
206 * right after this function returns.
207 *
208 * @p(code)
209 * Void myReady(Swi_Handle swi);
210 * @p
211 *
212 * @p(code)
213 * Void myBegin(Swi_Handle swi);
214 * @p
215 *
216 * @p(code)
217 * Void myEnd(Swi_Handle swi);
218 * @p
219 *
220 * @p(html)
221 * <h3> Calling Context </h3>
222 * <table border="1" cellpadding="3">
223 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
224 * </colgroup>
225 *
226 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
227 * <th> Task </th><th> Main </th><th> Startup </th></tr>
228 * <!-- -->
229 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
230 * <td> Y </td><td> Y </td><td> N </td></tr>
231 * <tr><td> {@link #disable} </td><td> Y </td><td> Y </td>
232 * <td> Y </td><td> Y </td><td> N </td></tr>
233 * <tr><td> {@link #getTrigger} </td><td> Y </td><td> Y </td>
234 * <td> N </td><td> N </td><td> N </td></tr>
235 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
236 * <td> Y </td><td> Y </td><td> Y </td></tr>
237 * <tr><td> {@link #restore} </td><td> Y </td><td> Y </td>
238 * <td> Y </td><td> Y </td><td> N </td></tr>
239 * <tr><td> {@link #self} </td><td> Y </td><td> Y </td>
240 * <td> N </td><td> N </td><td> N </td></tr>
241 *
242 * <tr><td> {@link #andn} </td><td> Y </td><td> Y </td>
243 * <td> Y </td><td> Y </td><td> N </td></tr>
244 * <tr><td> {@link #construct} </td><td> N </td><td> N </td>
245 * <td> Y </td><td> Y </td><td> N </td></tr>
246 * <tr><td> {@link #dec} </td><td> Y </td><td> Y </td>
247 * <td> Y </td><td> Y </td><td> N </td></tr>
248 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
249 * <td> Y </td><td> Y </td><td> N </td></tr>
250 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td>
251 * <td> Y </td><td> Y </td><td> N </td></tr>
252 * <tr><td> {@link #getHookContext} </td><td> Y </td><td> Y </td>
253 * <td> Y </td><td> Y </td><td> N </td></tr>
254 * <tr><td> {@link #getPri} </td><td> Y </td><td> Y </td>
255 * <td> Y </td><td> Y </td><td> N </td></tr>
256 * <tr><td> {@link #getFunc} </td><td> Y </td><td> Y </td>
257 * <td> Y </td><td> Y </td><td> N </td></tr>
258 * <tr><td> {@link #inc} </td><td> Y </td><td> Y </td>
259 * <td> Y </td><td> Y </td><td> N </td></tr>
260 * <tr><td> {@link #or} </td><td> Y </td><td> Y </td>
261 * <td> Y </td><td> Y </td><td> N </td></tr>
262 * <tr><td> {@link #post} </td><td> Y </td><td> Y </td>
263 * <td> Y </td><td> Y </td><td> N </td></tr>
264 * <tr><td> {@link #setHookContext} </td><td> Y </td><td> Y </td>
265 * <td> Y </td><td> Y </td><td> N </td></tr>
266 * <tr><td colspan="6"> Definitions: <br />
267 * <ul>
268 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
269 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
270 * <li> <b>Task</b>: API is callable from a Task thread. </li>
271 * <li> <b>Main</b>: API is callable during any of these phases: </li>
272 * <ul>
273 * <li> In your module startup after this module is started
274 * (e.g. Swi_Module_startupDone() returns TRUE). </li>
275 * <li> During xdc.runtime.Startup.lastFxns. </li>
276 * <li> During main().</li>
277 * <li> During BIOS.startupFxns.</li>
278 * </ul>
279 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
280 * <ul>
281 * <li> During xdc.runtime.Startup.firstFxns.</li>
282 * <li> In your module startup before this module is started
283 * (e.g. Swi_Module_startupDone() returns FALSE).</li>
284 * </ul>
285 * </ul>
286 * </td></tr>
287 *
288 * </table>
289 * @p
290 */
291
292 @ModuleStartup
293
294 @InstanceFinalize
295
296 @InstanceInitError
297
298 module Swi
299 {
300
301
302
303
304 /*!
305 * ======== FuncPtr ========
306 * Swi function type definition
307 *
308 * All Swi functions are passed two uninterpreted arguments of type
309 * UArg and have no return value.
310 */
311 typedef Void (*FuncPtr)(UArg, UArg);
312
313 /*!
314 * ======== HookSet ========
315 * Swi hook set type definition
316 *
317 * This structure defines the set of hook functions that can be
318 * specified for the Swi module.
319 *
320 * See {@link #hookfunc Hook Functions} for details.
321 */
322 struct HookSet {
323 Void (*registerFxn)(Int);
324 Void (*createFxn)(Handle, Error.Block *);
325 Void (*readyFxn)(Handle);
326 Void (*beginFxn)(Handle);
327 Void (*endFxn)(Handle);
328 Void (*deleteFxn)(Handle);
329 };
330
331 /*!
332 * ======== BasicView ========
333 * @_nodoc
334 */
335 metaonly struct BasicView {
336 String label;
337 String state;
338 UInt priority;
339 String fxn[];
340 UArg arg0;
341 UArg arg1;
342 UInt initTrigger;
343 UInt curTrigger;
344
345 };
346
347 /*!
348 * ======== ModuleView ========
349 * @_nodoc
350 */
351 metaonly struct ModuleView {
352 String schedulerState;
353 String readyQMask;
354 Ptr currentSwi;
355 String currentFxn[];
356 };
357
358 /*!
359 * ======== rovViewInfo ========
360 * @_nodoc
361 */
362 @Facet
363 metaonly config ViewInfo.Instance rovViewInfo =
364 xdc.rov.ViewInfo.create({
365 viewMap: [
366 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
367 ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}]
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 @DirectCall
503 Void startup();
504
505 /*!
506 * ======== Swi_enabled ========
507 * Returns TRUE if the Swi scheduler is enabled
508 *
509 * @_nodoc
510 */
511 @DirectCall
512 Bool enabled();
513
514 /*!
515 * ======== disable ========
516 * Disable Swi Scheduling
517 *
518 * {@link #disable} and {@link #restore} control Swi scheduling.
519 * {@link #disable} disables all other Swi functions from running until
520 * {@link #restore} is called. Hardware interrupts can still run.
521 *
522 * {@link #disable} and {@link #restore} allow you to ensure that
523 * statements that must be performed together during critical
524 * processing are not preempted by other Swis or Tasks.
525 *
526 * The value of the key returned is opaque to applications and is meant
527 * to be passed to Swi_restore().
528 *
529 * In the following example, the critical section cannot be preempted
530 * by any Swis.
531 *
532 * @p(code)
533 * key = Swi_disable();
534 * `critical section`
535 * Swi_restore(key);
536 * @p
537 *
538 * @a(constraints)
539 * Swi_disable also disables the Task scheduler.
540 * Swi_restore will re-enable and invoke the Task
541 * scheduler if the Task scheduler was not disabled prior
542 * to invoking Swi_disable().
543 *
544 * @b(returns) opaque key for use with Swi_restore()
545 */
546 @DirectCall
547 UInt disable();
548
549 /*!
550 * ======== enable ========
551 * Enable Swi Scheduling
552 *
553 * @_nodoc
554 * Swi_enable unconditionally enables Swis and invokes the Swi scheduler
555 * if any Swis are pending.
556 *
557 * @a(constraints)
558 * Swi_enable will also invoke the Task scheduler if the
559 * Task scheduler is not currently disabled.
560 *
561 * The {@link #post} discussion regarding global interrupts also applies
562 * to this API.
563 *
564 */
565 @DirectCall
566 Void enable();
567
568 /*!
569 * ======== restore ========
570 * Restore Swi Scheduling state
571 *
572 * Swi_restore restores the Swi scheduler to the locked/unlocked state
573 * it was in when Swi_disable was called. If the scheduler becomes
574 * unlocked and Swis of sufficient priority have been made ready to
575 * run by any of the posting APIs, then they are run at this time.
576 *
577 * Swi_disable and Swi_restore control software interrupt processing.
578 * Swi_disable disables all other Swi functions from running until
579 * Swi_restore is called. Hardware interrupts can still run.
580 *
581 * Swi_disable and Swi_restore allow you to ensure that statements that
582 * must be performed together during critical processing are not
583 * pre-empted by other Swis.
584 *
585 * In the following example, the critical section cannot be preempted
586 * by any Swis:
587 *
588 * @p(code)
589 * key = Swi_disable();
590 * `critical section`
591 * Swi_restore(key);
592 * @p
593 *
594 * @a(constraints)
595 * Swi_restore will also re-enable and invoke the Task
596 * scheduler if the Task scheduler was not disabled prior to
597 * invoking Swi_disable().
598 *
599 * The {@link #post} discussion regarding global interrupts applies
600 * to this API.
601 *
602 * @param(key) key to restore previous Swi scheduler state
603 */
604 @DirectCall
605 Void restore(UInt key);
606
607 /*!
608 * ======== restoreHwi ========
609 * Restore Swi Scheduling state
610 *
611 * @_nodoc
612 * Optimized version used by Hwi dispatcher.
613 */
614 @DirectCall
615 Void restoreHwi(UInt key);
616
617 /*!
618 * ======== self ========
619 * Return address of currently executing Swi object
620 *
621 * Swi_self returns the handle of the currently executing Swi.
622 *
623 * For example, you can call Swi_self as follows if you want
624 * a Swi to repost itself:
625 *
626 * @p(code)
627 * Swi_post( Swi_self() );
628 * @p
629 *
630 * @b(returns) handle of currently running Swi
631 */
632 @DirectCall
633 Handle self();
634
635 /*!
636 * ======== getTrigger ========
637 * Return the trigger value of the currently executing Swi
638 *
639 * Swi_getTrigger returns the value that Swi's trigger had when the Swi
640 * started running. SYS/BIOS saves the trigger value internally, so that
641 * Swi_getTrigger can access it at any point within a Swi object's
642 * function, and then automatically resets the trigger to its initial
643 * value.
644 *
645 * Swi_getTrigger should only be called within a function run by a Swi
646 * object.
647 *
648 * When called from within the context of a Swi, the value returned by
649 * Swi_getTrigger is zero if the Swi was posted by a call to Swi_andn,
650 * or Swi_dec. Therefore, Swi_getTrigger provides relevant information
651 * only if the Swi was posted by a call to Swi_inc, Swi_or, Swi_orHook,
652 * or Swi_post.
653 *
654 * This API is called within a Swi object's function to use the trigger
655 * value that caused the function to run. For example, if you use
656 * Swi_or or Swi_inc to post a Swi, different trigger values can require
657 * different processing.
658 *
659 * @p(code)
660 * swicount = Swi_getTrigger();
661 * @p
662 *
663 * @b(returns) trigger value
664 */
665 @DirectCall
666 UInt getTrigger();
667
668 /*!
669 * ======== raisePri ========
670 * Raise a Swi's priority
671 *
672 * @_nodoc
673 * This function is provided for legacy compatibility.
674 *
675 * Swi_raisePri is used to raise the priority of the currently running
676 * Swi to the priority passed in as the argument. Swi_raisePri can be
677 * used in conjunction with Swi_restorePri to provide a mutual exclusion
678 * mechanism without disabling Swis.
679 *
680 * Swi_raisePri should be called before a shared resource is accessed,
681 * and Swi_restorePri should be called after the access to the shared
682 * resource.
683 *
684 * A call to Swi_raisePri not followed by a Swi_restorePri keeps the
685 * Swi's priority for the rest of the processing at the raised level. A
686 * Swi_post of the Swi posts the Swi at its original priority level.
687 *
688 * A Swi object's execution priority must range from 0 to
689 * Swi_numPriorities - 1
690 *
691 * Swi_raisePri never lowers the current Swi priority.
692 *
693 * Constraints and Calling Context
694 * @p(blist)
695 * - Swi_raisePri must only be called from a Swi context.
696 * @p
697 *
698 * @b(returns) key for use with restorePri()
699 */
700 @DirectCall
701 UInt raisePri(UInt priority);
702
703 /*!
704 * ======== restorePri ========
705 * Restore a Swi's priority
706 *
707 * @_nodoc
708 * This function is provided for legacy compatibility.
709 *
710 * Swi_restorePri restores the priority to the Swi's priority prior to the
711 * Swi_raisePri call. Swi_restorePri can be used in
712 * conjunction with Swi_raisePri to provide a mutual exclusion mechanism
713 * without disabling all Swis.
714 *
715 * Swi_raisePri should be called right before the shared resource is
716 * referenced, and Swi_restorePri should be called after the reference to
717 * the shared resource.
718 *
719 * Constraints and Calling Context
720 *
721 * @p(blist)
722 * - Swi_restorePri must only be called from a Swi context.
723 * @p
724 *
725 * @param(key) key returned from Swi_raisePri
726 */
727 @DirectCall
728 Void restorePri(UInt key);
729
730 instance:
731
732 /*!
733 * ======== create ========
734 * Create a software interrupt
735 *
736 * Swi_create creates a new Swi object.
737 *
738 * The following C code sets Swi parameters and
739 * creates two Swi objects:
740 *
741 * @p(code)
742 * Void main()
743 * {
744 * Swi_Params swiParams;
745 *
746 * Swi_Params_init(&swiParams);
747 * swiParams.arg0 = 1;
748 * swiParams.arg1 = 0;
749 * swiParams.priority = 2;
750 * swiParams.trigger = 0;
751 *
752 * swi0 = Swi_create(swi0Fxn, &swiParams, NULL);
753 *
754 * swiParams.arg0 = 2;
755 * swiParams.arg1 = 0;
756 * swiParams.priority = 1;
757 * swiParams.trigger = 3;
758 *
759 * swi1 = Swi_create(swi1Fxn, &swiParams, NULL);
760 *
761 * BIOS_start();
762 * }
763 * @p
764 *
765 * The following XDCscript statements set Swi parameters and
766 * create two Swi objects:
767 *
768 * @p(code)
769 * var Swi = xdc.useModule('ti.sysbios.knl.Swi');
770 *
771 * var swiParams = new Swi.Params();
772 * swiParams.arg0 = 1;
773 * swiParams.arg1 = 0;
774 * swiParams.priority = 2;
775 * swiParams.trigger = 0;
776 * Program.global.swi0 = Swi.create('&swi0Fxn', swiParams);
777 *
778 * swiParams.arg0 = 2;
779 * swiParams.priority = 1;
780 * swiParams.trigger = 3;
781 * Program.global.swi1 = Swi.create('&swi1Fxn', swiParams);
782 * @p
783 *
784 * @param(fxn) Swi Function
785 */
786 @DirectCall
787 create(FuncPtr fxn);
788
789
790
791 /*!
792 * ======== arg0 ========
793 * Swi function argument 0
794 *
795 * The default value of this optional parameter is 0.
796 *
797 * @see #FuncPtr
798 */
799 config UArg arg0 = 0;
800
801 /*!
802 * ======== arg1 ========
803 * Swi function argument 1
804 *
805 * The default value of this optional parameter is 0.
806 *
807 * @see #FuncPtr
808 */
809 config UArg arg1 = 0;
810
811 /*!
812 * ======== priority ========
813 * Swi priority
814 *
815 * Each software interrupt has a priority level, 0 to
816 * ({@link #numPriorities} - 1). A software interrupt
817 * preempts any lower-priority software interrupt currently executing.
818 * When multiple Swis of the same priority level have been posted,
819 * their respective Swi functions are executed in the order the Swis
820 * were posted.
821 *
822 * The default value of this optional parameter is ~0, which yields a
823 * Swi with the highest priority: ({@link #numPriorities} - 1).
824 */
825 config UInt priority = ~0;
826
827 /*!
828 * ======== trigger ========
829 * Initial Swi trigger value
830 *
831 * The default value of this optional parameter is 0.
832 *
833 * Each Swi object has a "trigger" used either to determine whether to
834 * post the Swi or as a value that can be evaluated within the Swi's
835 * function.
836 *
837 * The {@link #andn} and {@link #dec} functions post the Swi
838 * if the trigger value transitions to 0. The {@link #or} and
839 * {@link #inc} functions also modify the trigger value. ({@link #or}
840 * sets bits, and {@link #andn} clears bits.)
841 */
842 config UInt trigger = 0;
843
844
845
846 /*!
847 * ======== andn ========
848 * Clear bits in Swi's trigger; post if trigger becomes 0
849 *
850 * Swi_andn is used to conditionally post a software interrupt.
851 * Swi_andn clears the bits specified by a mask from Swi's internal
852 * trigger. If the Swi's trigger becomes 0, Swi_andn posts the Swi.
853 * The bitwise logical operation performed is:
854 *
855 * @p(code)
856 * trigger = trigger AND (NOT MASK)
857 * @p
858 *
859 * If multiple conditions that all be met before a
860 * Swi can run, you should use a different bit in the trigger for
861 * each condition. When a condition is met, clear the bit for that
862 * condition.
863 *
864 * For example, if two events must happen before a Swi is to be
865 * triggered, the initial trigger value of the Swi can be 3 (binary 0011).
866 * One call to Swi_andn can have a mask value of 2 (binary 0010), and
867 * another call to Swi_andn can have a mask value of 1 (binary 0001).
868 * After both calls have been made, the trigger value will be 0.
869 *
870 * @p(code)
871 * Swi_andn(swi0, 2); // clear bit 1
872 * Swi_andn(swi0, 1); // clear bit 0
873 * @p
874 *
875 * Swi_andn results in a context switch if the Swi's trigger becomes
876 * zero and the Swi has higher priority than the currently executing
877 * thread.
878 *
879 * You specify a Swi's initial trigger value at Swi creation time.
880 * The trigger value is automatically reset when the Swi executes.
881 *
882 * @a(constraints)
883 * The {@link #post} discussion regarding global interrupts applies
884 * to this API.
885 *
886 * @param(mask) inverse value to be ANDed
887 */
888 @DirectCall
889 Void andn(UInt mask);
890
891 /*!
892 * ======== dec ========
893 * Decrement Swi's trigger value; post if trigger becomes 0
894 *
895 * Swi_dec is used to conditionally post a software interrupt. Swi_dec
896 * decrements the value in Swi's trigger by 1. If Swi's trigger value
897 * becomes 0, Swi_dec posts the Swi. You can increment a trigger value
898 * by using Swi_inc, which always posts the Swi.
899 *
900 * For example, you would use Swi_dec if you wanted to post a Swi after
901 * a number of occurrences of an event.
902 *
903 * @p(code)
904 * // swi0's trigger is configured to start at 3
905 * Swi_dec(swi0); // trigger = 2
906 * Swi_dec(swi0); // trigger = 1
907 * Swi_dec(swi0); // trigger = 0
908 * @p
909 *
910 * You specify a Swi's initial trigger value at Swi creation time. The
911 * trigger value is automatically reset when the Swi executes.
912 *
913 * Swi_dec results in a context switch if the Swi's trigger becomes
914 * zero and the Swi has higher priority than the currently executing
915 * thread.
916 *
917 * @a(constraints)
918 * The {@link #post} discussion regarding global interrupts applies
919 * to this API.
920 */
921 @DirectCall
922 Void dec();
923
924 /*!
925 * ======== getHookContext ========
926 * Get hook instance's context pointer for a Swi
927 *
928 * For example, this C code gets the HookContext, prints it,
929 * and sets a new value for the HookContext.
930 *
931 * @p(code)
932 * Ptr pEnv;
933 * Swi_Handle mySwi;
934 * Int myHookSetId1;
935 *
936 * pEnv = Swi_getHookContext(swi, myHookSetId1);
937 *
938 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
939 * (ULong)pEnv, (ULong)Timestamp_get32());
940 *
941 * Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1);
942 * @p
943 *
944 * See {@link #hookfunc Hook Functions} for more details.
945 *
946 * @b(returns) hook instance's context pointer for Swi
947 */
948 @DirectCall
949 Ptr getHookContext(Int id);
950
951 /*!
952 * ======== setHookContext ========
953 * Set hook instance's context for a swi
954 *
955 * For example, this C code gets the HookContext, prints it,
956 * and sets a new value for the HookContext.
957 *
958 * @p(code)
959 * Ptr pEnv;
960 * Swi_Handle mySwi;
961 * Int myHookSetId1;
962 *
963 * pEnv = Swi_getHookContext(swi, myHookSetId1);
964 *
965 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
966 * (ULong)pEnv, (ULong)Timestamp_get32());
967 *
968 * Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1);
969 * @p
970 *
971 * See {@link #hookfunc Hook Functions} for more details.
972 *
973 * @param(id) hook instance's ID
974 * @param(hookContext) value to write to context
975 */
976 @DirectCall
977 Void setHookContext(Int id, Ptr hookContext);
978
979 /*!
980 * ======== getPri ========
981 * Return a Swi's priority
982 *
983 * Swi_getPri returns the priority of the Swi passed in as the
984 * argument.
985 *
986 * @b(returns) Priority of Swi
987 */
988 @DirectCall
989 UInt getPri();
990
991 /*!
992 * ======== getFunc ========
993 * Get Swi function and arguments
994 *
995 * If either arg0 or arg1 is NULL, then the corresponding argument is not
996 * returned.
997 *
998 * @param(arg0) pointer for returning Swi's first function argument
999 * @param(arg1) pointer for returning Swi's second function argument
1000 *
1001 * @b(returns) Swi function
1002 */
1003 @DirectCall
1004 FuncPtr getFunc(UArg *arg0, UArg *arg1);
1005
1006 /*!
1007 * ======== inc ========
1008 * Increment Swi's trigger value and post the Swi
1009 *
1010 * Swi_inc increments the value in Swi's trigger by 1 and posts the Swi
1011 * regardless of the resulting trigger value. You can decrement a
1012 * trigger value using Swi_dec, which only posts the Swi if the
1013 * trigger value is 0.
1014 *
1015 * If a Swi is posted several times before it has a chance to begin
1016 * executing (i.e. when Hwis or higher priority Swis are running) the Swi
1017 * only runs one time. If this situation occurs, you can use Swi_inc to
1018 * post the Swi. Within the Swi's function, you could then use
1019 * Swi_getTrigger to find out how many times this Swi has been posted
1020 * since the last time it was executed.
1021 *
1022 * You specify a Swi's initial trigger value at Swi creation time.
1023 * The trigger value is automatically reset when the Swi executes.
1024 * To get the trigger value, use Swi_getTrigger.
1025 *
1026 * Swi_inc results in a context switch if the Swi is higher priority
1027 * than the currently executing thread.
1028 *
1029 * @a(constraints)
1030 * The {@link #post} discussion regarding global interrupts applies
1031 * to this API.
1032 */
1033 @DirectCall
1034 Void inc();
1035
1036 /*!
1037 * ======== or ========
1038 * Or mask with value contained in Swi's trigger and post the
1039 * Swi.
1040 *
1041 * Swi_or is used to post a software interrupt. Swi_or sets the bits
1042 * specified by a mask in Swi's trigger. Swi_or posts the Swi
1043 * regardless of the resulting trigger value. The bitwise logical
1044 * operation performed on the trigger value is:
1045 *
1046 * @p(code)
1047 * trigger = trigger OR mask
1048 * @p
1049 *
1050 * You specify a Swi's initial trigger value at Swi creation time.
1051 * The trigger value is automatically reset when the Swi executes.
1052 * To get the trigger value, use Swi_getTrigger.
1053 *
1054 * For example, you might use Swi_or to post a Swi if any of three
1055 * events should cause a Swi to be executed, but you want the Swi's
1056 * function to be able to tell which event occurred. Each event
1057 * would correspond to a different bit in the trigger.
1058 *
1059 * Swi_or results in a context switch if the Swi is higher priority
1060 * than the currently executing thread.
1061 *
1062 * @a(constraints)
1063 * The {@link #post} discussion regarding global interrupts applies
1064 * to this API.
1065 *
1066 * @param(mask) value to be ORed
1067 */
1068 @DirectCall
1069 Void or(UInt mask);
1070
1071 /*!
1072 * ======== post ========
1073 * Unconditionally post a software interrupt
1074 *
1075 * Swi_post is used to post a software interrupt regardless of the
1076 * trigger value. No change is made to the Swi object's trigger value.
1077 *
1078 * Swi_post results in a context switch if the Swi is higher priority
1079 * than the currently executing thread.
1080 *
1081 * @a(constraints)
1082 * Swis are ALWAYS run with interrupts enabled.
1083 * If a Swi is made ready to run as a consequence of this
1084 * API, interrupts will be globally enabled while the Swi function
1085 * executes, regardless of the prior globally enabled/disabled
1086 * state of interrupts.
1087 * Upon return from this API, the global interrupt enabled/disabled state
1088 * is restored to its previous value.
1089 */
1090 @DirectCall
1091 Void post();
1092
1093 internal:
1094
1095 1096 1097 1098 1099 1100 1101
1102 config UInt (*taskDisable)();
1103 config Void (*taskRestore)(UInt);
1104
1105 1106 1107 1108 1109 1110 1111 1112 1113
1114 Void schedule();
1115
1116 1117 1118 1119 1120 1121 1122
1123 Void run(Object *swi);
1124
1125 1126 1127 1128
1129 Int postInit(Object *swi, Error.Block *eb);
1130
1131 /*!
1132 * ======== numConstructedSwis ========
1133 * Number of statically constructed Swi objects
1134 *
1135 * @_nodoc
1136 * Shouldn't be set directly by the user's
1137 * config (it gets set by instance$static$init).
1138 */
1139 config UInt numConstructedSwis = 0;
1140
1141 /*!
1142 * ======== Instance_State ========
1143 * @_nodoc
1144 */
1145 struct Instance_State {
1146 Queue.Elem qElem;
1147 FuncPtr fxn;
1148 UArg arg0;
1149 UArg arg1;
1150 UInt priority;
1151 UInt mask;
1152 Bool posted;
1153 UInt initTrigger;
1154 UInt trigger;
1155 Queue.Handle readyQ;
1156 Ptr hookEnv[];
1157 };
1158
1159 /*!
1160 * ======== Module_State ========
1161 * @_nodoc
1162 */
1163 struct Module_State {
1164 Bool locked;
1165 UInt curSet;
1166 UInt curTrigger;
1167 Handle curSwi;
1168 Queue.Handle curQ;
1169
1170 Queue.Object readyQ[];
1171 Handle constructedSwis[];
1172
1173 };
1174 }
1175 1176 1177 1178
1179