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