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.family.c7x;
38
39 import xdc.rov.ViewInfo;
40
41 import xdc.runtime.Assert;
42 import xdc.runtime.Diags;
43 import xdc.runtime.Error;
44 import xdc.runtime.Log;
45
46 /*!
47 * ======== Hwi ========
48 * C7x Hardware Interrupt Support Module.
49 *
50 * This Hwi module provides C7x family-specific implementations of the
51 * APIs defined in {@link ti.sysbios.interfaces.IHwi IHwi}.
52 *
53 * Additional C7x device-specific APIs are also provided.
54 *
55 * An example of creating a Hwi instance:
56 *
57 * @p(code)
58 *
59 * Int intNum;
60 * Hwi_Params params;
61 * Error_Block eb;
62 *
63 * // Initialize the error block
64 * Error_init(&eb);
65 *
66 * // Initialize the Hwi parameters
67 * Hwi_Params_init(¶ms);
68 *
69 * // Set the event id in the params
70 * params.eventId = 78
71 *
72 * // Specify the interrupt vector number
73 * intNum = 8;
74 *
75 * // create the Hwi for the specified interrupt number and params
76 * Hwi_create(intNum, myIsr, ¶ms, &eb);
77 *
78 * @p
79 *
80 * @a(NOTE)
81 * In this Hwi module implementation, the instance config parameter value
82 * {@link #MaskingOption_LOWER} is equivalent to {@link #MaskingOption_SELF}.
83 * Statically configuring a Hwi object's {@link #Params.maskSetting} to
84 * {@link #MaskingOption_LOWER} will result in the generation of a benign
85 * build warning. Dynamic usages of {@link #MaskingOption_LOWER} will be
86 * silently converted to {@link #MaskingOption_SELF}.
87 *
88 * @p(html)
89 * <h3> Calling Context </h3>
90 * <table border="1" cellpadding="3">
91 * <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
92 *
93 * <tr><th> Function </th><th> Hwi </th><th> Swi </th><th> Task </th><th> Main </th><th> Startup </th></tr>
94 * <!-- -->
95 * <tr><td> {@link #clearInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
96 * <tr><td> {@link #create} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
97 * <tr><td> {@link #disable} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
98 * <tr><td> {@link #disableIER} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
99 * <tr><td> {@link #disableInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
100 * <tr><td> {@link #enable} </td><td> Y </td><td> Y </td><td> Y </td><td> N </td><td> N </td></tr>
101 * <tr><td> {@link #enableIER} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
102 * <tr><td> {@link #enableInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
103 * <tr><td> {@link #eventMap} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
104 * <tr><td> {@link #getEventId} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
105 * <tr><td> {@link #getHandle} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
106 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
107 * <tr><td> {@link #restore} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
108 * <tr><td> {@link #restoreIER} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
109 * <tr><td> {@link #restoreInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
110 * <tr><td> {@link #construct} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
111 * <tr><td> {@link #delete} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
112 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
113 * <tr><td> {@link #getHookContext} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
114 * <tr><td> {@link #reconfig} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
115 * <tr><td> {@link #setFunc} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
116 * <tr><td> {@link #setHookContext} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
117 * <tr><td colspan="6"> Definitions: <br />
118 * <ul>
119 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
120 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
121 * <li> <b>Task</b>: API is callable from a Task thread. </li>
122 * <li> <b>Main</b>: API is callable during any of these phases: </li>
123 * <ul>
124 * <li> In your module startup after this module is started (e.g. Hwi_Module_startupDone() returns TRUE). </li>
125 * <li> During xdc.runtime.Startup.lastFxns. </li>
126 * <li> During main().</li>
127 * <li> During BIOS.startupFxns.</li>
128 * </ul>
129 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
130 * <ul>
131 * <li> During xdc.runtime.Startup.firstFxns.</li>
132 * <li> In your module startup before this module is started (e.g. Hwi_Module_startupDone() returns FALSE).</li>
133 * </ul>
134 * </ul>
135 * </td></tr>
136 *
137 * </table>
138 * @p
139 */
140
141 @Template("./Hwi.xdt")
142 @ModuleStartup
143 @InstanceInitStatic
144
145 module Hwi inherits ti.sysbios.interfaces.IHwi
146 {
147
148
149 config UInt DEFAULT_INT_PRIORITY = 6;
150
151 /*! C7x+ supports 64 "interrupt" events. */
152 const Int NUM_INTERRUPTS = 64;
153
154
155
156 /*! @_nodoc Hwi plug function type definition. */
157 typedef Void (*PlugFuncPtr)(void);
158
159 enum TSR_CXM {
160 TSR_CXM_GuestUser,
161 TSR_CXM_GuestSupervisor,
162 TSR_CXM_RootUser,
163 TSR_CXM_RootSupervisor,
164 TSR_CXM_SecureUser,
165 TSR_CXM_SecureSupervisor
166 };
167
168 /*!
169 * Flag to control Secure vs. Nonsecure boot. Default is true, which
170 * causes SYS/BIOS to boot the C7x into Nonsecure mode.
171 *
172 * Set to true to boot C7x into Nonsecure mode, set to false to boot
173 * C7x into Secure mode.
174 *
175 * When booting to Secure mode, the standard entry point _c_int00 is
176 * reached in Secure Supervisor mode, and this mode is never changed.
177 *
178 * When booting to Nonsecure mode, a special entry point named
179 * _c_int00_secure is reached in Secure Supervisor mode, at which point
180 * both the Secure and Nonsecure environments are set up (MMU tables,
181 * control registers, etc.). Once both environments are ready, a
182 * special transition function named Hwi_switchToNS() is called, which
183 * performs a mode transition by jumping to the normal entry point
184 * _c_int00 in Nonsecure Supervisor mode. The program then boots in the
185 * normal fashion (autoinit processing followed by a call to main()).
186 */
187 config Bool bootToNonSecure = true;
188
189 /*!
190 * ======== BasicView ========
191 * @_nodoc
192 */
193 metaonly struct BasicView {
194 Ptr halHwiHandle;
195 String label;
196 UInt intNum;
197 String fxn;
198 UArg arg;
199 Ptr irp;
200 UInt eventId;
201 String disableMask;
202 String restoreMask;
203 };
204
205 /*!
206 * ======== ModuleView ========
207 * @_nodoc
208 */
209 metaonly struct ModuleView {
210 String options[4];
211 String hwiStackPeak;
212 SizeT hwiStackSize;
213 Ptr hwiStackBase;
214 };
215
216 /*!
217 * ======== rovViewInfo ========
218 * @_nodoc
219 */
220 @Facet
221 metaonly config ViewInfo.Instance rovViewInfo =
222 ViewInfo.create({
223 viewMap: [
224 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
225 ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}]
226 ]
227 });
228
229
230
231 /*!
232 * non-dispatched interrupt object.
233 * provided so that XGCONF users can easily plug non-dispatched interrupts
234 */
235 metaonly struct NonDispatchedInterrupt {
236 Int intNum;
237 PlugFuncPtr fxn; /*! "Hwi_plug'd" ISR function. */
238 Bool enableInt;
239 Int eventId;
240 };
241
242 /*!
243 * non-dispatched interrupt array.
244 * provided so that XGCONF users can easily plug non-dispatched interrupts
245 */
246 metaonly config NonDispatchedInterrupt nonDispatchedInterrupts[string];
247
248 /*!
249 * Alternate reset vector address. Default is undefined.
250 *
251 * if initialized by the user then an additional reset vector
252 * is created and placed in the ".resetVector" section.
253 * To place the .resetVector section into a specific memory section,
254 * add the following command to your config script:
255 * @p(code)
256 * Program.sectMap[".resetVector"] = YourMemorySection;
257 * @p
258 */
259 metaonly config Ptr resetVectorAddress;
260
261 /*!
262 * ======== A_invalidPriority ========
263 * Assert raised when priority is out of range
264 */
265 config xdc.runtime.Assert.Id A_invalidPriority = {
266 msg: "A_invalidPriority: proiority out of range (1-7)"
267 };
268
269 /*!
270 * Error raised when Hwi is already defined
271 */
272 config Error.Id E_alreadyDefined = {
273 msg: "E_alreadyDefined: Hwi already defined: intr# %d"
274 };
275
276 /*!
277 * Error raised when Hwi handle referenced in Hwi_delete()
278 * is not found in the Hwi dispatch table
279 */
280 config Error.Id E_handleNotFound = {
281 msg: "E_handleNotFound: Hwi handle not found: 0x%x"
282 };
283
284 /*!
285 * Error raised when a secure context failed to be allocated
286 */
287 config Error.Id E_allocSCFailed = {
288 msg: "E_allocSCFailed: Alloc secure context failed"
289 };
290
291 /*!
292 * Error raised when a secure context failed to be registered
293 */
294 config Error.Id E_registerSCFailed = {
295 msg: "E_registerSCFailed: Register secure context failed"
296 };
297
298 /*!
299 * Error raised when an invalid interrupt number is passed in
300 */
301 config Error.Id E_invalidIntNum = {
302 msg: "E_invalidIntNum: Invalid interrupt number: intr# %d"
303 };
304
305 /*!
306 * Error raised when an invalid priority is passed in
307 */
308 config Error.Id E_invalidPriority = {
309 msg: "E_invalidPriority: Invalid priority: %d (should be 1-7)"
310 };
311
312 /*!
313 * Issued just prior to Hwi function invocation (with interrupts disabled)
314 */
315 config Log.Event LM_begin = {
316 mask: Diags.USER1 | Diags.USER2,
317 msg: "LM_begin: hwi: 0x%x, func: 0x%x, preThread: %d, intNum: %d, irp: 0x%x"
318 };
319
320 /*!
321 * Issued just after return from Hwi function (with interrupts disabled)
322 */
323 config Log.Event LD_end = {
324 mask: Diags.USER2,
325 msg: "LD_end: hwi: 0x%x"
326 };
327
328 /*!
329 * enable Exception module for exception processing.
330 */
331 config Bool enableException = true;
332
333
334
335 /*!
336 * ======== disable ========
337 * Globally disable interrupts.
338 *
339 * Hwi_disable globally disables hardware interrupts and returns an
340 * opaque key indicating whether interrupts were globally enabled or
341 * disabled on entry to Hwi_disable().
342 * The actual value of the key is target/device specific and is meant
343 * to be passed to Hwi_restore().
344 *
345 * Call Hwi_disable before a portion of a function that needs
346 * to run without interruption. When critical processing is complete, call
347 * Hwi_restore or Hwi_enable to reenable hardware interrupts.
348 *
349 * Servicing of interrupts that occur while interrupts are disabled is
350 * postponed until interrupts are reenabled. However, if the same type
351 * of interrupt occurs several times while interrupts are disabled,
352 * the interrupt's function is executed only once when interrupts are
353 * reenabled.
354 *
355 * A context switch can occur when calling Hwi_enable or Hwi_restore if
356 * an enabled interrupt occurred while interrupts are disabled.
357 *
358 * Hwi_disable may be called from main(). However, since Hwi interrupts
359 * are already disabled in main(), such a call has no effect.
360 *
361 * @a(constraints)
362 * If a Task switching API such as
363 * {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()},
364 * {@link ti.sysbios.knl.Semaphore#post Semaphore_post()},
365 * {@link ti.sysbios.knl.Task#sleep Task_sleep()}, or
366 * {@link ti.sysbios.knl.Task#yield Task_yield()}
367 * is invoked which results in a context switch while
368 * interrupts are disabled, an embedded call to
369 * {@link #enable Hwi_enable} occurs
370 * on the way to the new thread context which unconditionally re-enables
371 * interrupts. Interrupts will remain enabled until a subsequent
372 * {@link #disable Hwi_disable}
373 * invocation.
374 *
375 * Swis always run with interrupts enabled.
376 * See {@link ti.sysbios.knl.Swi#post Swi_post()} for a discussion Swis and
377 * interrupts.
378 *
379 * @b(returns) opaque key for use by Hwi_restore()
380 */
381 @Macro
382 override UInt disable();
383
384 /*!
385 * ======== enable ========
386 */
387 @Macro
388 override UInt enable();
389
390 /*!
391 * ======== restore ========
392 */
393 @Macro
394 override Void restore(UInt key);
395
396 /*!
397 * ======== inUseMeta ========
398 * @_nodoc
399 * Check for Hwi already in use.
400 * For internal SYS/BIOS use only.
401 * Should be called prior to any internal Hwi.create().
402 *
403 * @param(intNum) interrupt number
404 */
405 metaonly Bool inUseMeta(UInt intNum);
406
407 /*!
408 * ======== eventMap ========
409 * Maps a event to interrupt number
410 *
411 * Function maps a event to an interrupt number so that the
412 * event is the interrupt source of the vector.
413 *
414 * @p(code)
415 * // Maps event #65 as the interrupt source of int vector #7
416 * Hwi_eventMap(7, 65);
417 * @p
418 *
419 * @param(intNum) interrupt number
420 * @param(eventId) event ID
421 */
422 Void eventMap(Int intNum, Int eventId);
423
424 /*!
425 * ======== eventMapMeta ========
426 * Maps Event to interrupt number statically
427 *
428 * Function maps a event to an interrupt number so that the
429 * event is the interrupt source of the vector.
430 *
431 * @p(code)
432 * // Maps event #65 as the interrupt source of int vector #7
433 * Hwi.eventMapMeta(7, 65);
434 * @p
435 *
436 * @param(intNum) interrupt number
437 * @param(eventId) event Id
438 */
439 metaonly Void eventMapMeta(Int intNum, Int eventId);
440
441 /*!
442 * ======== plug ========
443 * Plug an interrupt vector with an ISR address.
444 *
445 * Hwi_plug writes an Interrupt Service Fetch Packet (ISFP) into the
446 * Interrupt Service Table (IST), at the address corresponding to intNum
447 * The op-codes written in the ISFP create a branch to the function
448 * entry point specified by fxn:
449 *
450 * @p(code)
451 * stw b0, *SP--[1]
452 * mvk fxn, b0
453 * mvkh fxn, b0
454 * b b0
455 * ldw *++SP[1],b0
456 * nop 4
457 * @p
458 *
459 * Hwi_plug hooks up the specified function as the branch target of a
460 * hardware interrupt (fielded by the CPU) at the vector address
461 * specified in intNum. Hwi_plug does not enable the interrupt.
462 * Use Hwi_enableIER to enable specific interrupts.
463 *
464 * AN ISR PLUGGED WITH THIS API IS NOT SERVICED BY THE INTERRUPT
465 * DISPATCHER. CONSEQUENTLY, IT SHOULD NOT INVOKE ANY SYS/BIOS APIs
466 * (ie Semaphore_post())!!!
467 *
468 * @a(constraints)
469 * o interrupt function MUST NOT INTERACT WITH SYS/BIOS.
470 * (ie do not call Semaphore_post())
471 *
472 * o vecid must be a valid interrupt ID in the range of 0-15.
473 *
474 * @param(intNum) interrupt number
475 * @param(fxn) pointer to ISR function
476 */
477 Void plug(UInt intNum, PlugFuncPtr fxn);
478
479 /*!
480 * ======== plugMeta ========
481 * Statically plug an interrupt vector with an ISR address.
482 *
483 * @param(intNum) interrupt number
484 * @param(fxn) pointer to ISR function
485 */
486 metaonly Void plugMeta(UInt intNum, PlugFuncPtr fxn);
487
488 /*!
489 * ======== getEventId ========
490 * Returns event id associated with interrupt number
491 *
492 * If a bad interrupt number is passed in, it will return -1.
493 *
494 * @param(intNum) interrupt number
495 * @b(returns) event id associated with intNum
496 */
497 Int getEventId(UInt intNum);
498
499 /*!
500 * ======== getHandle ========
501 * Returns Hwi_handle associated with interrupt number
502 *
503 * @param(intNum) interrupt number
504 * @b(returns) handle associated with intNum
505 */
506 Handle getHandle(UInt intNum);
507
508 /*!
509 * ======== disableIER ========
510 * Disable certain maskable interrupts.
511 *
512 * Atomically disables specific interrupts by clearing the bits
513 * specified by mask in the Interrupt Enable Register (IER).
514 *
515 * The IER bits to be cleared should be set to 1 in the mask.
516 *
517 * @param(mask) bitmask of interrupts to disable
518 * @b(returns) previous IER settings bitmask
519 */
520 ULong disableIER(ULong mask);
521
522 /*!
523 * ======== enableIER ========
524 * Enable certain maskable interrupts.
525 *
526 * Atomically enables specific interrupts by setting the bits
527 * specified by mask in the Interrupt Enable Register (IER).
528 *
529 * The IER bits to be set should be set to 1 in the mask.
530 *
531 * @param(mask) bitmask of interrupts to enable
532 * @b(returns) previous IER settings bitmask
533 */
534 ULong enableIER(ULong mask);
535
536 /*!
537 * ======== restoreIER ========
538 * Restore maskable interrupts to the state they were in
539 * when either disableIER() or enableIER() was called.
540 *
541 * Atomically writes the given mask to the IER register. Typically used
542 * to restore the IER register to the state returned from a call to
543 * either {@link #disableIER()} or {@link #enableIER()}.
544 *
545 * @param(mask) bitmask of interrupts to restore
546 * @b(returns) previous IER settings bitmask
547 */
548 ULong restoreIER(ULong mask);
549
550 /*!
551 * ======== setPriority ========
552 * Set an interrupt's priority.
553 *
554 * Not an instance function so that it can be used
555 * with non-dispatched interrupts.
556 *
557 * @param(intNum) ID of interrupt
558 * @param(priority) priority
559 */
560 Void setPriority(UInt intNum, UInt priority);
561
562 /*!
563 * ======== getCXM ========
564 *
565 * Return the current context mode (TSR.CXM field)
566 */
567 TSR_CXM getCXM();
568
569 Void setCOP(Int cop);
570
571 Void secureStart();
572
573 instance:
574
575 /*!
576 * Dispatcher auto-nesting interrupt disable mask.
577 *
578 * When the dispatcher's auto interrupt nesting support feature
579 * is enabled (see {@link #dispatcherAutoNestingSupport}),
580 * this mask defines which IER bits are disabled prior to invoking
581 * the user's ISR function with GIE = 1.
582 *
583 * disableMask bits set to 1 correspond to IER bits that will be cleared
584 * prior to invoking the ISR.
585 *
586 * The value of this mask is normally auto-calculated based on the
587 * value of the maskSetting. However, manual setting of this
588 * mask is enabled by setting the maskSetting to
589 * {@link #MaskingOption MaskingOption_BITMASK}.
590 *
591 * The default value is derived from the
592 * {@link #MaskingOption MaskingOption_SELF}
593 * maskSetting.
594 */
595 config ULong disableMask = 0;
596
597 /*!
598 * Dispatcher auto-nesting interrupt restore mask.
599 *
600 * When the dispatcher's auto interrupt nesting support feature
601 * is enabled (see {@link #dispatcherAutoNestingSupport}),
602 * this mask defines which IER bits are restored to their previous
603 * setting upon return from the user's ISR function.
604 *
605 * restoreMask bits set to 1 correspond to IER bits that will be restored.
606 *
607 * The value of this mask is normally auto-calculated based on the
608 * value of the maskSetting. However, manual setting of this
609 * mask is enabled by setting the maskSetting to
610 * {@link #MaskingOption MaskingOption_BITMASK}.
611 *
612 * The default value is derived from the
613 * {@link #MaskingOption MaskingOption_SELF}
614 * maskSetting.
615 */
616 config ULong restoreMask = 0;
617
618 /*!
619 * Interrupt priority. Valid values on C7x are 0-6 (7 means disabled)
620 */
621 override config Int priority = -1;
622
623 /*!
624 * ======== reconfig ========
625 * Reconfigures a dispatched interrupt.
626 *
627 * This function reconfigures the dispatched interrupt so the
628 * specified function is called with the specified parameters.
629 *
630 * @param(fxn) pointer to ISR function
631 * @param(params) pointer to Hwi parameter structure
632 */
633 Void reconfig(FuncPtr fxn, const Params *params);
634
635 internal:
636
637 config Ptr vectorTableBase;
638 config Ptr vectorTableBase_SS;
639
640 641 642 643 644 645
646 config UInt (*swiDisable)();
647 config Void (*swiRestoreHwi)(UInt);
648 config UInt (*taskDisable)();
649 config Void (*taskRestoreHwi)(UInt);
650
651 652 653 654 655 656 657 658
659 Char *getIsrStackAddress();
660
661
662 Void dispatchC(Int intNum);
663
664
665 Void dispatchCore(Int intNum);
666
667
668 Void unPluggedInterrupt();
669
670
671 Void switchAndDispatch(Int intNum);
672
673 674 675
676 Int postInit(Object *hwi, Error.Block *eb);
677
678 /*!
679 * const array to hold all HookSet objects.
680 */
681 config HookSet hooks[length] = [];
682
683 /*! Meta World Only Hwi Configuration Object. */
684 metaonly struct InterruptObj {
685 String name;
686 Bool used;
687 Bool useDispatcher;
688 FuncPtr fxn;
689 PlugFuncPtr pfxn;
690 };
691
692 /*!
693 * Meta-only array of interrupt objects.
694 * This meta-only array of Hwi config objects is initialized
695 * in Hwi.xs:module$meta$init().
696 */
697 metaonly config InterruptObj interrupt[NUM_INTERRUPTS];
698
699 struct Instance_State {
700 ULong disableMask;
701 ULong restoreMask;
702 UArg arg;
703 FuncPtr fxn;
704 Int intNum;
705 Int priority;
706 Irp irp;
707 Ptr hookEnv[];
708 };
709
710 struct Module_State {
711 Char intEvents[NUM_INTERRUPTS];
712 ULong ierMask;
713 volatile Int intNum;
714 Char *taskSP;
715
716
717 Char *isrStack;
718 Int scw;
719
720 Handle dispatchTable[NUM_INTERRUPTS];
721 };
722 }