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