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 import xdc.runtime.Error;
38
39
40 /*!
41 * ======== Hwi ========
42 * Hardware Interrupt Support Module.
43 *
44 * The IHwi interface specifies APIs for globally enabling, disabling, and
45 * restoring interrupts.
46 *
47 * Additionally, management of individual, device-specific hardware
48 * interrupts is provided.
49 *
50 * The user can statically or dynamically assign routines that run when
51 * specific hardware interrupts occur.
52 *
53 * Dynamic assignment of Hwi routines to interrupts at run-time is done
54 * using the Hwi_create function.
55 *
56 * Interrupt routines can be written completely in C, completely in
57 * assembly, or in a mix of C and assembly. In order to support interrupt
58 * routines
59 * written completely in C, an interrupt dispatcher is provided that performs
60 * the requisite prolog and epilog for an interrupt routine.
61 *
62 * Some routines are assigned to interrupts by the other SYS/BIOS
63 * modules. For example, the Clock module configures its own timer interrupt
64 * handler. See the Clock Module for more details.
65 *
66 * @a(Runtime Hwi Creation)
67 *
68 * Below is an example of configuring an interrupt at runtime.
69 * Usually this code would be placed in main().
70 *
71 * @p(code)
72 * #include <xdc/runtime/Error.h>
73 * #include <ti/sysbios/hal/Hwi.h>
74 *
75 * Hwi_Handle myHwi;
76 *
77 * Int main(Int argc, char* argv[])
78 * {
79 * Hwi_Params hwiParams;
80 * Error_Block eb;
81 *
82 * Hwi_Params_init(&hwiParams);
83 * Error_init(&eb);
84 *
85 * // set the argument you want passed to your ISR function
86 * hwiParams.arg = 1;
87 *
88 * // set the event id of the peripheral assigned to this interrupt
89 * hwiParams.eventId = 10;
90 *
91 * // don't allow this interrupt to nest itself
92 * hwiParams.maskSetting = Hwi_MaskingOption_SELF;
93 *
94 * //
95 * // Configure interrupt 5 to invoke "myIsr".
96 * // Automatically enables interrupt 5 by default
97 * // set params.enableInt = FALSE if you want to control
98 * // when the interrupt is enabled using Hwi_enableInterrupt()
99 * //
100 *
101 * myHwi = Hwi_create(5, myIsr, &hwiParams, &eb);
102 *
103 * if (Error_check(&eb)) {
104 * // handle the error
105 * }
106 * }
107 *
108 * Void myIsr(UArg arg)
109 * {
110 * // here when interrupt #5 goes off
111 * }
112 * @p
113 *
114 * @a(Hook Functions)
115 *
116 * Sets of hook functions can be specified for the Hwi module
117 * using the configuration tool. Each set contains these hook
118 * functions:
119 * @p(blist)
120 * -Register: A function called before any statically-created Hwis
121 * are initialized at runtime. The register hook is called at boot time
122 * before main() and before interrupts are enabled.
123 * -Create: A function that is called when a Hwi is created.
124 * This includes hwis that are created statically and those
125 * created dynamically using {@link #create Hwi_create}.
126 * -Begin: A function that is called just prior to running a Hwi.
127 * -End: A function that is called just after a Hwi finishes.
128 * -Delete: A function that is called when a Hwi is deleted at
129 * run-time with {@link #delete Hwi_delete}.
130 * @p
131 *
132 * Register Function
133 *
134 * The Register function is provided to allow a hook set to store its
135 * hookset ID. This id can be passed to
136 * {@link #setHookContext Hwi_setHookContext} and
137 * {@link #getHookContext Hwi_getHookContext} to set or get
138 * hookset-specific context. The
139 * Register function must be specified if the hook implementation
140 * needs to use {@link #setHookContext Hwi_setHookContext} or
141 * {@link #getHookContext Hwi_getHookContext}.
142 * The registerFxn hook function is called during system initialization
143 * before interrupts have been enabled.
144 *
145 * @p(code)
146 * Void myRegisterFxn(Int id);
147 * @p
148 *
149 * Create and Delete Functions
150 *
151 * The create and delete functions are called whenever a Hwi is created
152 * or deleted. They are called with interrupts enabled (unless called
153 * at boot time or from main()).
154 *
155 * @p(code)
156 * Void myCreateFxn(Hwi_Handle hwi, Error_Block *eb);
157 * @p
158 *
159 * @p(code)
160 * Void myDeleteFxn(Hwi_Handle hwi);
161 * @p
162 *
163 * Begin and End Functions
164 *
165 * The beginFxn and endFxn function hooks are called with interrupts
166 * globally disabled, therefore any hook processing function will contribute
167 * to the overall system interrupt response latency. In order to minimize
168 * this impact, carefully consider the processing time spent in an Hwi
169 * beginFxn or endFxn function hook.
170 *
171 * @p(code)
172 * Void myBeginFxn(Hwi_Handle hwi);
173 * @p
174 *
175 * @p(code)
176 * Void myEndFxn(Hwi_Handle hwi);
177 * @p
178 *
179 * Hook functions can only be configured statically.
180 */
181
182 @DirectCall
183 @InstanceFinalize
184 @InstanceInitError
185
186 interface IHwi {
187
188
189
190 /*! Hwi create function type definition. */
191 typedef Void (*FuncPtr)(UArg);
192
193 /*!
194 * Interrupt Return Pointer.
195 *
196 * This is the address of the interrupted instruction.
197 */
198 typedef UArg Irp;
199
200 /*!
201 * Hwi hook set type definition.
202 *
203 * The functions that make up a hookSet have certain restrictions. They
204 * cannot call any Hwi instance functions other than Hwi_getHookContext()
205 * and Hwi_setHookContext(). For all practical purposes, they should treat
206 * the Hwi_Handle passed to these functions as an opaque handle.
207 */
208 struct HookSet {
209 Void (*registerFxn)(Int);
210 Void (*createFxn)(Handle, Error.Block *);
211 Void (*beginFxn)(Handle);
212 Void (*endFxn)(Handle);
213 Void (*deleteFxn)(Handle);
214 };
215
216 /*!
217 * ======== MaskingOption ========
218 * Shorthand interrupt masking options
219 *
220 * @value(MaskingOption_NONE) No interrupts are disabled
221 *
222 * @value(MaskingOption_ALL) All interrupts are disabled
223 *
224 * @value(MaskingOption_SELF) Only this interrupt is disabled
225 *
226 * @value(MaskingOption_BITMASK) User supplies interrupt enable masks
227 *
228 * @value(MaskingOption_LOWER) All current and lower priority
229 * interrupts are disabled.
230 *
231 * Only a few targets/devices truly
232 * support this masking option. For those
233 * that don't, this setting is treated
234 * the same as MaskingOption_SELF.
235 */
236 enum MaskingOption {
237 MaskingOption_NONE,
238 MaskingOption_ALL,
239 MaskingOption_SELF,
240 MaskingOption_BITMASK,
241 MaskingOption_LOWER
242 };
243
244 /*!
245 * ======== StackInfo ========
246 * Structure contains Hwi stack usage info
247 *
248 * Used by getStackInfo() and viewGetStackInfo() functions
249 */
250 struct StackInfo {
251 SizeT hwiStackPeak;
252 SizeT hwiStackSize;
253 Ptr hwiStackBase;
254 };
255
256
257
258 /*!
259 * Include interrupt nesting logic in interrupt dispatcher?
260 *
261 * Default is true.
262 *
263 * This option provides the user with the ability to optimize
264 * interrupt dispatcher performance when support for interrupt
265 * nesting is not required.
266 *
267 * Setting this parameter to false will disable the logic in
268 * the interrupt dispatcher that manipulates interrupt mask
269 * registers and enables and disables interrupts before and
270 * after invoking the user's Hwi function.
271 *
272 * Set this parameter to false if you don't need interrupts
273 * enabled during the execution of your Hwi functions.
274 */
275 config Bool dispatcherAutoNestingSupport = true;
276
277 /*!
278 * Include Swi scheduling logic in interrupt dispatcher?
279 *
280 * Default is inherited from {@link ti.sysbios.BIOS#swiEnabled
281 * BIOS.swiEnabled}, which is true by default.
282 *
283 * This option provides the user with the ability to optimize
284 * interrupt dispatcher performance when it is known that Swis
285 * will not be posted from any of their Hwi threads.
286 *
287 * @a(Warning)
288 * Setting this parameter to false will disable the logic in
289 * the interrupt dispatcher that invokes the Swi scheduler
290 * prior to returning from an interrupt.
291 * With this setting, Swis MUST NOT be posted from Hwi functions!
292 */
293 config Bool dispatcherSwiSupport;
294
295 /*!
296 * Include Task scheduling logic in interrupt dispatcher?
297 *
298 * Default is inherited from {@link ti.sysbios.BIOS#taskEnabled
299 * BIOS.taskEnabled}, which is true by default.
300 *
301 * This option provides the user with the ability to optimize
302 * interrupt dispatcher performance when it is known that no
303 * Task scheduling APIs (ie {@link ti.sysbios.knl.Semaphore#post
304 * Semaphore_post()}) will be executed from any of their Hwi threads.
305 *
306 * Setting this parameter to false will disable the logic in
307 * the interrupt dispatcher that invokes the Task scheduler
308 * prior to returning from an interrupt.
309 */
310 config Bool dispatcherTaskSupport;
311
312 /*!
313 * Controls whether the
314 * dispatcher retains the interrupted thread's return address.
315 *
316 * This option is enabled by default.
317 *
318 * Setting this parameter to false will disable the logic in
319 * the interrupt dispatcher that keeps track of the interrupt's
320 * return address and provide a small savings in interrupt latency.
321 *
322 * The application can get an interrupt's most recent return
323 * address using the {@link #getIrp} API.
324 */
325 config Bool dispatcherIrpTrackingSupport = true;
326
327
328
329 /*!
330 * ======== addHookSet ========
331 * addHookSet is used in a config file to add a hook set (defined
332 * by struct HookSet).
333 *
334 * HookSet structure elements may be omitted, in which case those
335 * elements will not exist.
336 *
337 * @param(hook) structure of type HookSet
338 */
339 metaonly Void addHookSet(HookSet hook);
340
341 /*!
342 * ======== viewGetStackInfo ========
343 * @_nodoc
344 * Returns the Hwi stack usage info. Used at ROV time.
345 *
346 * @b(returns) Hwi stack base, size, peak
347 */
348 metaonly StackInfo viewGetStackInfo();
349
350 /*!
351 * ======== getStackInfo ========
352 * Get Hwi stack usage Info.
353 *
354 * getStackInfo returns the Hwi stack usage info to its calling
355 * function by filling stack base address, stack size and stack
356 * peak fields in the {@link #StackInfo} structure.
357 *
358 * getStackInfo accepts two arguments, a pointer to a structure
359 * of type {@link #StackInfo} and a boolean. If the boolean is set
360 * to true, the function computes the stack depth and fills the
361 * stack peak field in the StackInfo structure. If a stack overflow
362 * is detected, the stack depth is not computed. If the boolean is
363 * set to false, the function only checks for a stack overflow.
364 *
365 * The isr stack is always checked for an overflow and a boolean
366 * is returned to indicate whether an overflow occured.
367 *
368 * Below is an example of calling getStackInfo() API:
369 *
370 * @p(code)
371 * #include <ti/sysbios/BIOS.h>
372 * #include <ti/sysbios/hal/Hwi.h>
373 * #include <ti/sysbios/knl/Swi.h>
374 * #include <ti/sysbios/knl/Task.h>
375 *
376 * Swi_Handle swi0;
377 * volatile Bool swiStackOverflow = FALSE;
378 *
379 * Void swi0Fxn(UArg arg1, UArg arg2)
380 * {
381 * Hwi_StackInfo stkInfo;
382 *
383 * // Request stack depth
384 * swiStackOverflow = Hwi_getStackInfo(&stkInfo, TRUE);
385 *
386 * // Alternately, we can omit the request for stack depth and
387 * // request only the stack base and stack size (the check for
388 * // stack overflow is always performed):
389 * //
390 * // swiStackOverflow = Hwi_getStackInfo(&stkInfo, FALSE);
391 *
392 * if (swiStackOverflow) {
393 * // isr Stack Overflow detected
394 * }
395 * }
396 *
397 * Void idleTask()
398 * {
399 * Swi_post(swi0);
400 * }
401 *
402 * Int main(Int argc, char* argv[])
403 * {
404 * swi0 = Swi_create(swi0Fxn, NULL, NULL);
405 *
406 * BIOS_start();
407 * return (0);
408 * }
409 * @p
410 *
411 * @param(stkInfo) pointer to structure of type {@link #StackInfo}
412 * @param(computeStackDepth) decides whether to compute stack depth
413 *
414 * @b(returns) boolean to indicate a stack overflow
415 */
416 Bool getStackInfo(StackInfo *stkInfo, Bool computeStackDepth);
417
418 /*!
419 * ======== getCoreStackInfo ========
420 * Get Hwi stack usage Info for the specified coreId.
421 *
422 * getCoreStackInfo returns the Hwi stack usage info for the specified
423 * coreId to its calling function by filling stack base address,
424 * stack size and stack peak fields in the {@link #StackInfo} structure.
425 *
426 * This function should be used only in applications built with
427 * {@link ti.sysbios.BIOS#smpEnabled} set to true.
428 *
429 * getCoreStackInfo accepts three arguments, a pointer to a structure
430 * of type {@link #StackInfo}, a boolean and a coreId. If the boolean
431 * is set to true, the function computes the stack depth and fills the
432 * stack peak field in the StackInfo structure. If a stack overflow
433 * is detected, the stack depth is not computed. If the boolean is
434 * set to false, the function only checks for a stack overflow.
435 *
436 * The isr stack is always checked for an overflow and a boolean
437 * is returned to indicate whether an overflow occured.
438 *
439 * Below is an example of calling getCoreStackInfo() API:
440 *
441 * @p(code)
442 * #include <ti/sysbios/BIOS.h>
443 * #include <ti/sysbios/hal/Hwi.h>
444 * #include <ti/sysbios/hal/Core.h>
445 * #include <ti/sysbios/knl/Task.h>
446 *
447 * ...
448 *
449 * Void idleTask()
450 * {
451 * UInt idx;
452 * Hwi_StackInfo stkInfo;
453 * Bool stackOverflow = FALSE;
454 *
455 * // Request stack depth for each core's Hwi stack and check for
456 * // overflow
457 * for (idx = 0; idx < Core_numCores; idx++) {
458 * stackOverflow = Hwi_getCoreStackInfo(&stkInfo, TRUE, idx);
459 *
460 * // Alternately, we can omit the request for stack depth and
461 * // request only the stack base and stack size (the check for
462 * // stack overflow is always performed):
463 * //
464 * // stackOverflow = Hwi_getCoreStackInfo(&stkInfo, FALSE, idx);
465 *
466 * if (stackOverflow) {
467 * // isr Stack Overflow detected
468 * }
469 * }
470 * }
471 *
472 * Int main(Int argc, char* argv[])
473 * {
474 * ...
475 * BIOS_start();
476 * return (0);
477 * }
478 * @p
479 *
480 * @param(stkInfo) pointer to structure of type {@link #StackInfo}
481 * @param(computeStackDepth) decides whether to compute stack depth
482 * @param(coreId) core whose stack info needs to be retrieved
483 *
484 * @b(returns) boolean to indicate a stack overflow
485 */
486 Bool getCoreStackInfo(StackInfo *stkInfo, Bool computeStackDepth,
487 UInt coreId);
488
489 /*!
490 * ======== startup ========
491 * Initially enable interrupts
492 *
493 * Called within BIOS_start
494 */
495 Void startup();
496
497 /*!
498 * ======== disable ========
499 */
500 UInt disable();
501
502 /*!
503 * ======== enable ========
504 * Globally enable interrupts.
505 *
506 * Hwi_enable globally enables hardware interrupts and returns an
507 * opaque key indicating whether interrupts were globally enabled or
508 * disabled on entry to Hwi_enable().
509 * The actual value of the key is target/device specific and is meant
510 * to be passed to Hwi_restore().
511 *
512 *
513 * This function is
514 * called as part of SYS/BIOS Startup_POST_APP_MAIN phase.
515 *
516 * Hardware interrupts are enabled unless a call to Hwi_disable disables
517 * them.
518 *
519 * Servicing of interrupts that occur while interrupts are disabled is
520 * postponed until interrupts are reenabled. However, if the same type
521 * of interrupt occurs several times while interrupts are disabled,
522 * the interrupt's function is executed only once when interrupts are
523 * reenabled.
524 *
525 * A context switch can occur when calling Hwi_enable or Hwi_restore if
526 * an enabled interrupt occurred while interrupts are disabled.
527 *
528 * Any call to Hwi_enable enables interrupts, even if Hwi_disable has
529 * been called several times.
530 *
531 * Hwi_enable must not be called from main().
532 *
533 * @b(returns) opaque key for use by Hwi_restore()
534 */
535 UInt enable();
536
537 /*!
538 * ======== restore ========
539 * Globally restore interrupts.
540 *
541 * Hwi_restore globally restores interrupts to the state determined
542 * by the key argument provided by a previous invocation of Hwi_disable.
543 *
544 * A context switch may occur when calling Hwi_restore if Hwi_restore
545 * reenables interrupts and another Hwi occurred while interrupts were
546 * disabled.
547 *
548 * Hwi_restore may be called from main(). However, since Hwi_enable
549 * cannot be called from main(), interrupts are always disabled in
550 * main(), and a call to Hwi_restore has no effect.
551 *
552 * @param(key) enable/disable state to restore
553 */
554 Void restore(UInt key);
555
556 /*!
557 * @_nodoc
558 * ======== switchFromBootStack ========
559 * Indicate that we are leaving the boot stack and
560 * are about to switch to a task stack.
561 * Used by Task_startup()
562 */
563 Void switchFromBootStack();
564
565 /*!
566 * ======== post ========
567 * Generate an interrupt for test purposes.
568 *
569 * @param(intNum) ID of interrupt to generate
570 */
571 Void post(UInt intNum);
572
573 /*!
574 * @_nodoc
575 * ======== getTaskSP ========
576 * retrieve interrupted task's SP
577 *
578 * Used for benchmarking the SYS/BIOS Hwi dispatcher's task
579 * stack utilization.
580 *
581 * @b(returns) interrupted task's SP
582 */
583 Char *getTaskSP();
584
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
603
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
619
620
621 622 623 624 625 626 627 628 629 630 631 632 633
634
635
636 637 638 639 640 641 642 643 644 645 646 647 648 649
650
651
652 /*!
653 * ======== disableInterrupt ========
654 * Disable a specific interrupt.
655 *
656 * Disable a specific interrupt identified by an interrupt number.
657 *
658 * @param(intNum) interrupt number to disable
659 * @b(returns) key to restore previous enable/disable state
660 */
661 UInt disableInterrupt(UInt intNum);
662
663 /*!
664 * ======== enableInterrupt ========
665 * Enable a specific interrupt.
666 *
667 * Enables a specific interrupt identified by an interrupt number.
668 *
669 * @param(intNum) interrupt number to enable
670 * @b(returns) key to restore previous enable/disable state
671 */
672 UInt enableInterrupt(UInt intNum);
673
674 /*!
675 * ======== restoreInterrupt ========
676 * Restore a specific interrupt's enabled/disabled state.
677 *
678 * Restores a specific interrupt identified by an interrupt number.
679 * restoreInterrupt is generally used to restore an interrupt to its state
680 * before {@link #disableInterrupt} or {@link #enableInterrupt} was
681 * invoked
682 *
683 * @param(intNum) interrupt number to restore
684 * @param(key) key returned from enableInt or disableInt
685 */
686 Void restoreInterrupt(UInt intNum, UInt key);
687
688 /*!
689 * ======== clearInterrupt ========
690 * Clear a specific interrupt.
691 *
692 * Clears a specific interrupt's pending status.
693 * The implementation is family-specific.
694 *
695 * @param(intNum) interrupt number to clear
696 */
697 Void clearInterrupt(UInt intNum);
698
699 instance:
700
701 /*!
702 * Create a dispatched interrupt.
703 *
704 * A Hwi dispatcher table entry is created and filled with the
705 * function specified by the fxn parameter and the attributes
706 * specified by the params parameter.
707 *
708 * If params is NULL, the Hwi's dispatcher properties are assigned a
709 * default set of values. Otherwise, the following properties
710 * are specified by a structure of type Hwi_Params.
711 *
712 * @p(blist)
713 * - The arg element is a generic argument that is passed to the plugged
714 * function as its only parameter. The default value is 0.
715 * - The enableInt element determines whether the interrupt should be
716 * enabled in the IER by create.
717 * - The maskSetting element defines the dispatcherAutoNestingSupport
718 * behavior of the interrupt.
719 * @p
720 *
721 * Hwi_create returns a pointer to the created Hwi object.
722 *
723 * @param(intNum) interrupt number
724 * @param(hwiFxn) pointer to ISR function
725 *
726 */
727 create(Int intNum, FuncPtr hwiFxn);
728
729 /*! maskSetting. Default is {@link #MaskingOption Hwi_MaskingOption_SELF} */
730 config MaskingOption maskSetting = MaskingOption_SELF;
731
732 /*! ISR function argument. Default is 0. */
733 config UArg arg = 0;
734
735 /*! Enable this interrupt when object is created? Default is true. */
736 config Bool enableInt = true;
737
738 /*!
739 * Interrupt event ID (Interrupt Selection Number)
740 *
741 * Default is -1.
742 * Not all targets/devices support this instance parameter.
743 * On those that don't, this parameter is ignored.
744 */
745 config Int eventId = -1;
746
747 /*!
748 * Interrupt priority.
749 *
750 * The default value of -1 is used as a flag to indicate
751 * the lowest (logical) device-specific priority value.
752 *
753 * Not all targets/devices support this instance parameter.
754 * On those that don't, this parameter is ignored.
755 */
756 config Int priority = -1;
757
758 /*!
759 * ======== getFunc ========
760 * Get Hwi function and arg
761 *
762 * @param(arg) pointer for returning hwi's ISR function argument
763 * @b(returns) hwi's ISR function
764 */
765 FuncPtr getFunc(UArg *arg);
766
767 /*!
768 * ======== setFunc ========
769 * Overwrite Hwi function and arg
770 *
771 * Replaces a Hwi object's hwiFxn function originally
772 * provided in {@link #create}.
773 *
774 * @param(fxn) pointer to ISR function
775 * @param(arg) argument to ISR function
776 */
777 Void setFunc(FuncPtr fxn, UArg arg);
778
779 /*!
780 * ======== getHookContext ========
781 * Get hook instance's context for a Hwi.
782 *
783 * @b(returns) hook instance's context for hwi
784 */
785 Ptr getHookContext(Int id);
786
787 /*!
788 * ======== setHookContext ========
789 * Set hook instance's context for a Hwi.
790 *
791 * @param(id) hook instance's ID
792 * @param(hookContext) value to write to context
793 */
794 Void setHookContext(Int id, Ptr hookContext);
795
796 /*!
797 * ======== getIrp ========
798 * Get address of interrupted instruction.
799 *
800 * @b(returns) most current IRP of a Hwi
801 */
802 Irp getIrp();
803 }