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