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
38 package ti.sysbios.family.windows;
39
40 import xdc.runtime.Assert;
41 import xdc.runtime.Diags;
42 import xdc.runtime.Error;
43 import xdc.runtime.IHeap;
44 import xdc.runtime.Log;
45
46 /*!
47 * ======== Hwi ========
48 * Windows emulation Hardware Interrupt Support Module
49 *
50 * This Hwi module provides Windows emulation specific implementations of
51 * the APIs defined in {@link ti.sysbios.interfaces.IHwi IHwi}.
52 *
53 * Additional Windows emulation specific APIs are also provided.
54 *
55 * @a(NOTE)
56 * In this Hwi module implementation, the instance config parameter value
57 * {@link #MaskingOption_LOWER} is equivalent to {@link #MaskingOption_SELF}.
58 * Statically configuring a Hwi object's {@link #Params.maskSetting} to
59 * {@link #MaskingOption_LOWER} will result in the generation of a benign
60 * build warning. Dynamic usages of {@link #MaskingOption_LOWER} will be
61 * silently converted to {@link #MaskingOption_SELF}.
62 *
63 * @p(html)
64 * <h3> Calling Context </h3>
65 * <table border="1" cellpadding="3">
66 * <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
67 *
68 * <tr><th> Function </th><th> Hwi </th><th> Swi </th><th> Task </th><th> Main </th><th> Startup </th></tr>
69 * <!-- -->
70 * <tr><td> {@link #clearInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
71 * <tr><td> {@link #create} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
72 * <tr><td> {@link #disable} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
73 * <tr><td> {@link #disableIER} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
74 * <tr><td> {@link #disableInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
75 * <tr><td> {@link #enable} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
76 * <tr><td> {@link #enableIER} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
77 * <tr><td> {@link #enableInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
78 * <tr><td> {@link #getHandle} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
79 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
80 * <tr><td> {@link #plug} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
81 * <tr><td> {@link #restore} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
82 * <tr><td> {@link #restoreIER} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
83 * <tr><td> {@link #restoreInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
84 * <tr><td> {@link #construct} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
85 * <tr><td> {@link #delete} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
86 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
87 * <tr><td> {@link #getHookContext} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
88 * <tr><td> {@link #reconfig} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
89 * <tr><td> {@link #setFunc} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
90 * <tr><td> {@link #setHookContext} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
91 * <tr><td colspan="6"> Definitions: <br />
92 * <ul>
93 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
94 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
95 * <li> <b>Task</b>: API is callable from a Task thread. </li>
96 * <li> <b>Main</b>: API is callable during any of these phases: </li>
97 * <ul>
98 * <li> In your module startup after this module is started (e.g. Hwi_Module_startupDone() returns TRUE). </li>
99 * <li> During xdc.runtime.Startup.lastFxns. </li>
100 * <li> During main().</li>
101 * <li> During BIOS.startupFxns.</li>
102 * </ul>
103 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
104 * <ul>
105 * <li> During xdc.runtime.Startup.firstFxns.</li>
106 * <li> In your module startup before this module is started (e.g. Hwi_Module_startupDone() returns FALSE).</li>
107 * </ul>
108 * </ul>
109 * </td></tr>
110 * </table>
111 * @p
112 *
113 */
114
115 @Template("./Hwi.xdt")
116 @ModuleStartup
117
118 module Hwi inherits ti.sysbios.interfaces.IHwi
119 {
120
121
122 //! Dispatcher supports 16 interrupts.
123 const Int NUM_INTERRUPTS = 16;
124
125
126
127 //! @_nodoc Hwi plug function type definition.
128 typedef Void (*PlugFuncPtr)(UInt);
129
130 //! Isr function type definition.
131 typedef Void (*IsrFxn)(UInt);
132
133 /*! Assert: invalid interrupt number.
134 *
135 * Interrupt number must be greater than or equal to 0 and less
136 * than {@link #NUM_INTERRUPTS}.
137 *
138 * @a(Raised_In)
139 * @p(html)
140 * {@link #disableInterrupt}<br />
141 * {@link #enableInterrupt}<br />
142 * {@link #plug}<br />
143 * {@link ti.sysbios.interfaces.IHwi#post}<br />
144 *
145 * @a(See_Also)
146 * @p(html)
147 * {@link xdc.runtime.Assert}<br />
148 * {@link xdc.runtime.Diags}<br />
149 * @p
150 */
151 config Assert.Id A_interNum = {
152 msg: "A_interNum: interrupt number must be less then NUM_INTERRUPTS"
153 };
154
155 /*! Assert: there must be a pending interrupt
156 *
157 * The Hwi module decided to take an interrupt, but upon inspecting
158 * the IER and IFR registers did not find an enabled pending interrupt.
159 */
160 config Assert.Id A_noPendingIntr = {
161 msg: "A_noPendingIntr: there must be a pending interrupt"
162 };
163
164 /*! Assert: an unplugged interrupt was raised.
165 *
166 * An interrupt was raised which does not have an ISR plugged into
167 * the Interrupt Service Table (IST).
168 *
169 * @a(Raised_In)
170 * @p(html)
171 * {@link #post}<br />
172 * @p
173 */
174 config Assert.Id A_pluggedIntr = {
175 msg: "interrupt must be plugged"
176 };
177
178 /*! Error: memory allocation request failed.
179 *
180 * A request into the Windows runtime library for memory has failed.
181 *
182 * @a(Raised_In)
183 * @p(html)
184 * {@link #startup}<br />
185 * @p
186 */
187 config Error.Id E_calloc = {
188 msg: "calloc failed"
189 };
190
191 /*! Error: CreateEvent failed.
192 *
193 * A CreateEvent call into the Win32 API has failed.
194 *
195 * @a(Raised_In)
196 * @p(html)
197 * {@link #startup}<br />
198 * @p
199 */
200 config Error.Id E_event = {
201 msg: "CreateEvent failed"
202 };
203
204 /*!
205 * Error raised when Hwi is already defined
206 */
207 config Error.Id E_alreadyDefined = {
208 msg: "E_alreadyDefined: Hwi already defined: intr# %d"
209 };
210
211 /*!
212 * Issued just prior to Hwi function invocation (with interrupts disabled)
213 */
214 config Log.Event LM_begin = {
215 mask: Diags.USER1 | Diags.USER2,
216 msg: "LM_begin: hwi: 0x%x, func: 0x%x, preThread: %d, intNum: %d"
217 };
218
219 /*!
220 * Issued just after return from Hwi function (with interrupts disabled)
221 */
222 config Log.Event LD_end = {
223 mask: Diags.USER2,
224 msg: "LD_end: hwi: 0x%x"
225 };
226
227 /*! Log: missed interrupt detected
228 *
229 * An interrupt is being raised which has a previous instance
230 * recorded in the IFR register still waiting to be serviced.
231 *
232 * @a(Raised_In)
233 * @p(html)
234 * {@link #post}<br />
235 * @p
236 */
237 config Log.Event LW_missedIntr = {
238 mask: Diags.USER3,
239 msg: "Warning: LW_missedIntr: missed interrupt detected: %d"
240 };
241
242
243
244 /*! Non-dispatched interrupt object.
245 *
246 * Provided so that XGCONF users can easily plug non-dispatched
247 * interrupts.
248 */
249 metaonly struct NonDispatchedInterrupt {
250 Int intNum; //! interrupt number
251 PlugFuncPtr fxn; //! plugged ISR function
252 Bool enableInt; //! interrupt enable flag
253 Int eventId; //! source event id
254 };
255
256 /*! Non-dispatched interrupt array.
257 *
258 * Provided so that XGCONF users can easily plug non-dispatched
259 * interrupts.
260 */
261 metaonly config NonDispatchedInterrupt nonDispatchedInterrupts[string];
262
263
264
265 /*!
266 * ======== disableIER ========
267 * Disable certain maskable interrupts.
268 *
269 * Atomically disables specific interrupts by clearing the bits
270 * specified by mask in the Interrupt Enable Register (IER).
271 *
272 * The IER bits to be cleared should be set to 1 in the mask.
273 *
274 * @param(mask) Bitmask of interrupts to disable.
275 * @b(returns) Previous IER settings bitmask.
276 */
277 Bits16 disableIER(Bits16 mask);
278
279 /*!
280 * ======== enableIER ========
281 * Enable certain maskable interrupts.
282 *
283 * Atomically enables specific interrupts by setting the bits
284 * specified by mask in the Interrupt Enable Register (IER).
285 *
286 * The IER bits to be set should be set to 1 in the mask.
287 *
288 * @param(mask) Bitmask of interrupts to enable.
289 * @b(returns) Previous IER settings bitmask.
290 */
291 Bits16 enableIER(Bits16 mask);
292
293 /*!
294 * ======== restoreIER ========
295 * Restore maskable interrupts to the state they were in
296 * when either disableIER() or enableIER() was called.
297 *
298 * Atomically writes the given mask to the IER register. Typically used
299 * to restore the IER register to the state returned from a call to
300 * either {@link #disableIER()} or {@link #enableIER()}.
301 *
302 * @param(mask) Bitmask of interrupts to restore.
303 * @b(returns) Previous IER settings bitmask.
304 */
305 Bits16 restoreIER(Bits16 mask);
306
307 /*!
308 * ======== getHandle ========
309 * Return a pointer to an Hwi instance object.
310 *
311 * @param(intNum) Interrupt number.
312 */
313 Handle getHandle(UInt intNum);
314
315 /*!
316 * @_nodoc
317 * ======== inUseMeta ========
318 * Check for Hwi already in use.
319 *
320 * For internal SYS/BIOS use only. Should be called prior
321 * to any internal Hwi.create().
322 *
323 * @param(intNum) Interrupt number.
324 */
325 metaonly Bool inUseMeta(UInt intNum);
326
327 /*!
328 * @_nodoc
329 * ======== plug ========
330 * Plug an interrupt vector with an ISR address at runtime.
331 *
332 * Writes the ISR address into the Interrupt Service Table (IST)
333 * at the address corresponding to the `intNum`. This function
334 * does not enable the interrupt. Use {@link #enableIER()} to
335 * enable the interrupt.
336 *
337 * @param(intNum) Interrupt number. The interrupt number must be
338 * in the range 0 - ({@link #NUM_INTERRUPTS} - 1).
339 * @param(fxn) Pointer to ISR function. The ISR function
340 * pointer cannot be NULL.
341 *
342 * @a(Asserts)
343 * @p(html)
344 * {@link #A_interNum}<br />
345 * @p
346 *
347 * @a(See_Also)
348 * {@link #enableIER()}
349 */
350 Void plug(UInt intNum, PlugFuncPtr fxn);
351
352 /*!
353 * ======== plugMeta ========
354 * Plug an interrupt vector with an ISR address at config time.
355 *
356 * @param(intNum) Interrupt number. The interrupt number must be
357 * in the range 0 - ({@link #NUM_INTERRUPTS} - 1).
358 * @param(fxn) Pointer to ISR function. The ISR function
359 * pointer cannot be NULL.
360 */
361 metaonly Void plugMeta(UInt intNum, PlugFuncPtr fxn);
362
363 instance:
364
365 /*!
366 * Dispatcher auto-nesting interrupt disable mask.
367 *
368 * When the dispatcher's auto interrupt nesting support feature
369 * is enabled (see {@link #dispatcherAutoNestingSupport}),
370 * this mask defines which IER bits are disabled prior to invoking
371 * the user's ISR function with GIE = 1.
372 *
373 * disableMask bits set to 1 correspond to IER bits that will be cleared
374 * prior to invoking the ISR.
375 *
376 * The value of this mask is normally auto-calculated based on the
377 * value of the maskSetting. However, manual setting of this
378 * mask is enabled by setting the maskSetting to
379 * {@link #MaskingOption MaskingOption_BITMASK}.
380 *
381 * The default value is derived from the
382 * {@link #MaskingOption MaskingOption_SELF}
383 * maskSetting.
384 */
385 config Bits16 disableMask = 0;
386
387 /*!
388 * Dispatcher auto-nesting interrupt restore mask.
389 *
390 * When the dispatcher's auto interrupt nesting support feature
391 * is enabled (see {@link #dispatcherAutoNestingSupport}),
392 * this mask defines which IER bits are restored to their previous
393 * setting upon return from the user's ISR function.
394 *
395 * restoreMask bits set to 1 correspond to IER bits that will be restored.
396 *
397 * The value of this mask is normally auto-calculated based on the
398 * value of the maskSetting. However, manual setting of this
399 * mask is enabled by setting the maskSetting to
400 * {@link #MaskingOption MaskingOption_BITMASK}.
401 *
402 * The default value is derived from the
403 * {@link #MaskingOption MaskingOption_SELF}
404 * maskSetting.
405 */
406 config Bits16 restoreMask = 0;
407
408 /*!
409 * Interrupt priority. Not supported on this target.
410 */
411 override config Int priority = 0;
412
413 /*!
414 * ======== reconfig ========
415 * Reconfigure a dispatched interrupt.
416 */
417 Void reconfig(FuncPtr fxn, const Params *params);
418
419 internal:
420
421 422 423 424 425 426
427 config UInt (*swiDisable)();
428 config Void (*swiRestoreHwi)(UInt);
429 config UInt (*taskDisable)();
430 config Void (*taskRestoreHwi)(UInt);
431
432 433 434 435
436 Void dispatch(UInt intNum);
437
438 439 440
441 Void init();
442
443 444 445 446
447 Void unPluggedInterrupt(UInt num);
448
449
450 config HookSet hooks[length] = [];
451
452 /*! Meta World Only Hwi Configuration Object. */
453 metaonly struct InterruptObj {
454 String name;
455 Bool used;
456 Bool useDispatcher;
457 FuncPtr fxn;
458 PlugFuncPtr pfxn;
459 };
460
461 /*!
462 * Meta-only array of interrupt objects.
463 * This meta-only array of Hwi config objects is initialized
464 * in Hwi.xs:module$meta$init().
465 */
466 metaonly config InterruptObj interrupt[NUM_INTERRUPTS];
467
468 struct PrivateData;
469
470 struct Instance_State {
471 Bits16 disableMask;
472 Bits16 restoreMask;
473 UArg arg;
474 FuncPtr fxn;
475 Irp irp;
476 Ptr hookEnv[];
477 };
478
479 struct Module_State {
480 Bits16 ierMask;
481 Handle dispatchTable[NUM_INTERRUPTS];
482 Bool GIE;
483 Bits16 IER;
484 Bits16 IFR;
485 UInt intrNum;
486 IsrFxn IST[NUM_INTERRUPTS];
487 PrivateData *privateData;
488 };
489 }
490 491 492 493
494