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 package ti.sysbios.family.msp430;
37
38 import xdc.rov.ViewInfo;
39 import xdc.runtime.Diags;
40 import xdc.runtime.Log;
41 import xdc.runtime.Assert;
42 import xdc.runtime.Error;
43
44 import ti.sysbios.interfaces.IHwi;
45
46 /*!
47 * ======== Hwi ========
48 * MSP430 Hardware Interrupt Manager
49 *
50 * This module implements the generic Hwi module functions
51 * Hwi_enable, Hwi_disable, and Hwi_restore as defined by
52 * {@link ti.sysbios.interfaces.IHwi IHwi}.
53 *
54 * @p(html)
55 * <h3> Calling Context </h3>
56 * <table border="1" cellpadding="3">
57 * <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
58 *
59 * <tr><th> Function </th><th> Hwi </th><th> Swi </th><th> Task </th><th> Main </th><th> Startup </th></tr>
60 * <!-- -->
61 * <tr><td> {@link #clearInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
62 * <tr><td> {@link #create} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
63 * <tr><td> {@link #disable} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
64 * <tr><td> {@link #disableInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
65 * <tr><td> {@link #enable} </td><td> Y </td><td> Y </td><td> Y </td><td> N </td><td> N </td></tr>
66 * <tr><td> {@link #enableInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
67 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
68 * <tr><td> {@link #restore} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
69 * <tr><td> {@link #restoreInterrupt} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
70 * <tr><td> {@link #construct} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
71 * <tr><td> {@link #delete} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
72 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td><td> Y </td><td> Y </td><td> N </td></tr>
73 * <tr><td> {@link #getHookContext} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
74 * <tr><td> {@link #setFunc} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
75 * <tr><td> {@link #setHookContext} </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
76 * <tr><td colspan="6"> Definitions: <br />
77 * <ul>
78 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
79 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
80 * <li> <b>Task</b>: API is callable from a Task thread. </li>
81 * <li> <b>Main</b>: API is callable during any of these phases: </li>
82 * <ul>
83 * <li> In your module startup after this module is started (e.g. Hwi_Module_startupDone() returns TRUE). </li>
84 * <li> During xdc.runtime.Startup.lastFxns. </li>
85 * <li> During main().</li>
86 * <li> During BIOS.startupFxns.</li>
87 * </ul>
88 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
89 * <ul>
90 * <li> During xdc.runtime.Startup.firstFxns.</li>
91 * <li> In your module startup before this module is started (e.g. Hwi_Module_startupDone() returns FALSE).</li>
92 * </ul>
93 * </ul>
94 * </td></tr>
95 *
96 * </table>
97 * @p
98 *
99 */
100
101
102 @Template("./Hwi.xdt")
103 @ModuleStartup
104
105 module Hwi inherits ti.sysbios.interfaces.IHwi
106 {
107 /*!
108 * The MSP430 supports up to 64 interrupts/exceptions.
109 *
110 * The actual number supported is device specific and provided by
111 * the catalog device specification.
112 */
113 readonly config Int NUM_INTERRUPTS;
114
115
116
117 /*! Hwi vector function type definition. */
118 typedef Void (*VectorFuncPtr)(void);
119
120 /*! @_nodoc */
121 metaonly struct BasicView {
122 Ptr halHwiHandle;
123 String label;
124 Int intNum;
125 String fxn;
126 UArg arg;
127 Ptr irp;
128 };
129
130 /*! @_nodoc */
131 metaonly struct ModuleView {
132 String options[4];
133 String hwiStackPeak;
134 SizeT hwiStackSize;
135 Ptr hwiStackBase;
136 };
137
138 /*! @_nodoc */
139 @Facet
140 metaonly config ViewInfo.Instance rovViewInfo =
141 ViewInfo.create({
142 viewMap: [
143 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
144 ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}]
145 ]
146 });
147
148
149
150
151
152 /*!
153 * Issued just prior to Hwi function invocation (with interrupts disabled)
154 */
155 config Log.Event LM_begin = {
156 mask: Diags.USER1 | Diags.USER2,
157 msg: "LM_begin: hwi: 0x%x, func: 0x%x, preThread: %d, intNum: %d, irp: 0x%x"
158 };
159
160 /*!
161 * Issued just after return from Hwi function (with interrupts disabled)
162 */
163 config Log.Event LD_end = {
164 mask: Diags.USER2,
165 msg: "LD_end: hwi: 0x%x"
166 };
167
168
169
170 /*! Assert when bad maskSetting parameter provided */
171 config Assert.Id A_unsupportedMaskingOption = {
172 msg: "A_unsupportedMaskingOption: unsupported maskSetting."
173 };
174
175
176
177 /*!
178 * Error raised when Hwi is already defined
179 */
180 config Error.Id E_alreadyDefined = {
181 msg: "E_alreadyDefined: Hwi already defined: intr# %d"
182 };
183
184 /*!
185 * Error raised when an unimplemented Hwi function is called
186 *
187 * The MSP430 does not implement all of the functions defined
188 * by {@link ti.sysbios.interfaces.IHwi}. If applications
189 * call such a function, an E_notImplemented error is raised
190 * with the name of the unimplemented function passed as an
191 * argument. See {@link xdc.runtime.Error#raise}.
192 */
193 config Error.Id E_notImplemented = {
194 msg: "E_notImplemented: Function not implemented: %s"
195 };
196
197
198
199 /*!
200 * ======== fillVectors ========
201 * Plug all unused interrupt vectors
202 *
203 * This parameter allows one to plug all unused interrupt vectors
204 * with a spin loop, to catch unexpected interrupts and "run away" code.
205 */
206 metaonly config Bool fillVectors = true;
207
208 /*!
209 * ======== resetFunc ========
210 * Reset handler
211 *
212 * This parameter specifies the interrupt service routine triggered on
213 * reset. The default is c_int00.
214 */
215 metaonly config VectorFuncPtr resetFunc;
216
217 /*!
218 * ======== alwaysWake ========
219 * Always keep the CPU awake upon return from interrupt?
220 *
221 * This parameter serves as a global 'switch' to control whether the
222 * CPU is kept awake (i.e., not allowed to return to a low power mode) at
223 * the end of servicing a hardware interrupt (Hwi) managed by SYS/BIOS.
224 * The behavior of each interrupt instance can be controlled individually
225 * (see {@link #keepAwakeEnabled}); when set to true, this parameter serves
226 * as an override of the individual instance selection, to force keep awake
227 * of the CPU. This parameter is provided to assist with debug, and to
228 * ease use and transition of legacy code to work with SYS/BIOS.
229 */
230 metaonly config Bool alwaysWake = false;
231
232 /*!
233 * ======== alwaysLog ========
234 * Always emit Log messages from interrupt stubs?
235 *
236 * This parameter serves as a global 'switch' to control whether Log
237 * begin and end messages will be emitted from interrupt stubs.
238 * Note that the behavior of each interrupt instance can be controlled
239 * individually (see {@link #loggingEnabled}); when set to true, alwaysLog
240 * serves as an override of the individual instance selections, forcing
241 * logging from the stubs of all configured interrupts.
242 */
243 metaonly config Bool alwaysLog = false;
244
245
246
247 /*!
248 * ======== disable ========
249 * Globally disable interrupts.
250 *
251 * Hwi_disable globally disables hardware interrupts and returns an
252 * opaque key indicating whether interrupts were globally enabled or
253 * disabled on entry to Hwi_disable().
254 * The actual value of the key is target/device specific and is meant
255 * to be passed to Hwi_restore().
256 *
257 * Call Hwi_disable before a portion of a function that needs
258 * to run without interruption. When critical processing is complete, call
259 * Hwi_restore or Hwi_enable to reenable hardware interrupts.
260 *
261 * Servicing of interrupts that occur while interrupts are disabled is
262 * postponed until interrupts are reenabled. However, if the same type
263 * of interrupt occurs several times while interrupts are disabled,
264 * the interrupt's function is executed only once when interrupts are
265 * reenabled.
266 *
267 * A context switch can occur when calling Hwi_enable or Hwi_restore if
268 * an enabled interrupt occurred while interrupts are disabled.
269 *
270 * Hwi_disable may be called from main(). However, since Hwi interrupts
271 * are already disabled in main(), such a call has no effect.
272 *
273 * @a(constraints)
274 * If a Task switching API such as
275 * {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()},
276 * {@link ti.sysbios.knl.Semaphore#post Semaphore_post()},
277 * {@link ti.sysbios.knl.Task#sleep Task_sleep()}, or
278 * {@link ti.sysbios.knl.Task#yield Task_yield()}
279 * is invoked which results in a context switch while
280 * interrupts are disabled, an embedded call to
281 * {@link #enable Hwi_enable} occurs
282 * on the way to the new thread context which unconditionally re-enables
283 * interrupts. Interrupts will remain enabled until a subsequent
284 * {@link #disable Hwi_disable}
285 * invocation.
286 *
287 * Swis always run with interrupts enabled.
288 * See {@link ti.sysbios.knl.Swi#post Swi_post()} for a discussion Swis and
289 * interrupts.
290 *
291 * @b(returns) opaque key for use by Hwi_restore()
292 */
293 @Macro
294 override UInt disable();
295
296 /*!
297 * ======== enable ========
298 */
299 @Macro
300 override UInt enable();
301
302 /*!
303 * ======== restore ========
304 */
305 @Macro
306 override Void restore(UInt key);
307
308 /*!
309 * ======== inUseMeta ========
310 * @_nodoc
311 * Check for Hwi already in use
312 *
313 * For internal SYS/BIOS use only.
314 * Should be called prior to any internal Hwi.create().
315 *
316 * @param(intNum) interrupt number
317 */
318 metaonly Bool inUseMeta(UInt intNum);
319
320 /*!
321 * ======== plugMeta ========
322 * Statically plug an interrupt vector with an ISR address
323 *
324 * @param(intNum) interrupt number
325 * @param(fxn) pointer to ISR function
326 */
327 metaonly Void plugMeta(UInt intNum, Fxn fxn);
328
329 /*!
330 * @_nodoc
331 * ======= logBegin ========
332 * Log the LM_begin from within Hwi module scope
333 */
334 Void logBegin(Log.Event evt, IArg a1, IArg a2, IArg a3, IArg a4, IArg a5);
335
336 /*!
337 * @_nodoc
338 * ======= logEnd ========
339 * Log the LD_end from within Hwi module scope
340 */
341 Void logEnd(Log.Event evt, IArg a1);
342
343 instance:
344
345 /*! override maskSetting - Hwi does not manage nesting on 430 */
346 override config IHwi.MaskingOption maskSetting = IHwi.MaskingOption_ALL;
347
348 /*!
349 * Does this interrupt support posting of Swis? Default is true.
350 *
351 * If "true", the interrupt stub will disable the Swi scheduler upon stub
352 * entry, and restore it upon interrupt completion.
353 *
354 * If no Swi-scheduling APIs (for example, Swi_post()) are called from
355 * within this interrupt's ISR function, then swiEnabled can be set to
356 * "false".
357 */
358 metaonly config Bool swiEnabled = true;
359
360 /*!
361 * Does this interrupt support task pre-emption? Default is true.
362 *
363 * If "true", the interrupt stub will disable the Task scheduler upon
364 * stub entry, and restore it upon interrupt completion.
365 *
366 * If no Task-scheduling APIs (e.g., Semaphore_post()) are called from
367 * within this interrupt's ISR function, then taskEnabled can be set to
368 * "false".
369 */
370 metaonly config Bool taskEnabled = true;
371
372 /*!
373 * Switch to ISR stack for this interrupt? Default is true.
374 *
375 * If "true", the SYS/BIOS interrupt/system stack will be used when
376 * running this interrupt's ISR function (instead of the interrupted
377 * Task's dedicated stack). If "false", no switching to the
378 * interrupt/system stack will occur for this interrupt.
379 *
380 * Note that this parameter is only relevant for the Task module; if
381 * the Task module is not enabled in the application only a single stack
382 * is used (i.e., the "system/interrupt stack").
383 */
384 metaonly config Bool isrStackEnabled = true;
385
386 /*!
387 * Does this interrupt allow nesting by other interrupts? Default is
388 * false.
389 *
390 * Set to "true" if the configured ISR function will enable global
391 * interrupts temporarily within the function, to allow other interrupts
392 * to nest on top of this interrupt. If the ISR does not enable other
393 * interrupts, then leave as the default of "false".
394 *
395 */
396 metaonly config Bool nestingEnabled = false;
397
398 /*!
399 * Does this interrupt support logging?
400 *
401 * If set to true, {@link xdc.runtime.Log Log} statements are inserted
402 * into the generated interrupt stub that calls the user's interrupt
403 * function. The stub posts an {@link #LM_begin} event at the beginning
404 * of the interrupt service routine and a {@link #LD_end} event after
405 * the user's function returns.
406 *
407 * In addition to enabling this flag, you must also enable USER1 and/or
408 * USER2 logging for this module. Otherwise, the events posted by the
409 * inserted Log statments will be ignored.
410 */
411 metaonly config Bool loggingEnabled = false;
412
413 /*!
414 * Does this interrupt support thread-type tracking? Default is true.
415 *
416 * If "true", this stub will enable full tracking of the execution
417 * context. For example, if the ISR function (or one of the functions
418 * it calls) were to call BIOS_getThreadType(), the returned value would be
419 * BIOS_ThreadType_Hwi.
420 *
421 * Setting this parameter to "false" will slightly reduce the interrupt
422 * stub overhead, but may result in an incorrect thread type being
423 * reported during the processing of the interrupt.
424 */
425 metaonly config Bool threadTypeEnabled = true;
426
427 /*!
428 * Should keep CPU awake following this interrupt? Default is false.
429 *
430 * If "true", this interrupt stub will modify the status register (SR)
431 * value that was pushed onto the stack (automatically, at the start of
432 * servicing the interrupt), so that when it is restored by the RETI
433 * instruction, the CPU will stay in the Active mode.
434 *
435 * If left as "false", the unmodified SR value will be restored by the
436 * RETI instruction, and the CPU may return to a previous low power mode
437 * (LPM) that was in effect when the interrupt was triggered.
438 */
439 metaonly config Bool keepAwakeEnabled = false;
440
441 internal:
442
443 444 445 446
447 Int postInit(Object *hwi, Error.Block *eb);
448
449 /*!
450 * ======== init ========
451 * Setup Hwi stack
452 */
453 Void init();
454
455 /*!
456 * const array to hold all HookSet objects.
457 */
458 config HookSet hooks[length] = [];
459
460 /*! Meta World Only Hwi Configuration Object. */
461 metaonly struct InterruptObj {
462 String name;
463 Bool used;
464 Bool generateStub;
465 Bool swiEnabled;
466 Bool taskEnabled;
467 Bool nestingEnabled;
468 Bool isrStackEnabled;
469 Bool lmBeginEnabled;
470 Bool ldEndEnabled;
471 Bool threadTypeEnabled;
472 Bool keepAwakeEnabled;
473 String handle;
474 FuncPtr fxn;
475 Fxn pfxn;
476 UArg arg;
477 };
478
479 /*!
480 * Meta-only array of interrupt objects.
481 *
482 * This meta-only array of Hwi config objects is initialized
483 * in Hwi.xs:module$meta$init().
484 */
485 metaonly config InterruptObj interrupt[];
486
487 struct Instance_State {
488 Int intNum;
489 Irp irp;
490 Ptr hookEnv[];
491 };
492
493 struct Module_State {
494 Char *taskSP;
495
496
497 Char *isrStack;
498 };
499 }