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