1    /* 
     2     * Copyright (c) 2012, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     * */
    32    /*
    33     *  ======== Hwi.xdc ========
    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")  /* generates the vector table and the dispatcher */
   103    @ModuleStartup          /* generate a call to startup function */
   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        // -------- Module Types --------
   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            SizeT       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        // -------- Module Parameters --------
   149    
   150        // Logs
   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        // Asserts
   169    
   170        /*! Assert when bad maskSetting parameter provided */
   171        config Assert.Id A_unsupportedMaskingOption = {
   172            msg: "A_unsupportedMaskingOption: unsupported maskSetting."
   173        };
   174    
   175        // Errors
   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        // configs
   198    
   199        /*!
   200         *  ======== fillVectors ========
   201         *  Plug all unused interrupt vectors
   202         *
   203         *  This parameter allows one to plug all unused interrupt vectors
   204         *  a common "stub", {@link #nullIsrFunc}.  This allows one to more
   205         *  easily catch unexpected interrupts and "run away" code.
   206         */
   207        metaonly config Bool fillVectors = true;
   208    
   209        /*!
   210         *  ======== nullIsrFunc ========
   211         *  Unused vector handler
   212         *
   213         *  This parameter specifies the interrupt service routine used
   214         *  when filling unused interrupt vectors.  It defaults to a function
   215         *  that simply loops to itself.
   216         */
   217        metaonly config FuncPtr nullIsrFunc;
   218    
   219        /*!
   220         *  ======== resetFunc ========
   221         *  Reset handler
   222         *
   223         *  This parameter specifies the interrupt service routine triggered on
   224         *  reset. The default is c_int00.
   225         */
   226        metaonly config VectorFuncPtr resetFunc;
   227    
   228        /*!
   229         *  ======== alwaysWake ========
   230         *  Always keep the CPU awake upon return from interrupt?
   231         *
   232         *  This parameter serves as a global 'switch' to control whether the
   233         *  CPU is kept awake (i.e., not allowed to return to a low power mode) at
   234         *  the end of servicing a hardware interrupt (Hwi) managed by SYS/BIOS.  
   235         *  The behavior of each interrupt instance can be controlled individually
   236         *  (see {@link #keepAwakeEnabled}); when set to true, this parameter serves
   237         *  as an override of the individual instance selection, to force keep awake 
   238         *  of the CPU. This parameter is provided to assist with debug, and to 
   239         *  ease use and transition of legacy code to work with SYS/BIOS.
   240         */
   241        metaonly config Bool alwaysWake = false;
   242    
   243        /*!
   244         *  ======== alwaysLog ========
   245         *  Always emit Log messages from interrupt stubs?
   246         *
   247         *  This parameter serves as a global 'switch' to control whether Log
   248         *  begin and end messages will be emitted from interrupt stubs.
   249         *  Note that the behavior of each interrupt instance can be controlled
   250         *  individually (see {@link #loggingEnabled}); when set to true, alwaysLog
   251         *  serves as an override of the individual instance selections, forcing 
   252         *  logging from the stubs of all configured interrupts.
   253         */
   254        metaonly config Bool alwaysLog = false;
   255    
   256        // -------- Module Functions --------
   257    
   258        /*!
   259         *  ======== disable ========
   260         */
   261        @Macro
   262        override UInt disable();
   263    
   264        /*!
   265         *  ======== enable ========
   266         */
   267        @Macro
   268        override UInt enable();
   269    
   270        /*!
   271         *  ======== restore ========
   272         */
   273        @Macro
   274        override Void restore(UInt key);
   275    
   276        /*!
   277         *  ======== inUseMeta ========
   278         *  @_nodoc
   279         *  Check for Hwi already in use
   280         *
   281         *  For internal SYS/BIOS use only. 
   282         *  Should be called prior to any internal Hwi.create().
   283         *
   284         *  @param(intNum)  interrupt number
   285         */
   286        metaonly Bool inUseMeta(UInt intNum);
   287    
   288        /*!
   289         *  ======== plugMeta ========
   290         *  Statically plug an interrupt vector with an ISR address
   291         *
   292         *  @param(intNum)  interrupt number
   293         *  @param(fxn)     pointer to ISR function
   294         */
   295        metaonly Void plugMeta(UInt intNum, Fxn fxn);
   296    
   297        /*!
   298         *  @_nodoc
   299         *  ======= logBegin ========
   300         *  Log the LM_begin from within Hwi module scope
   301         */
   302        @DirectCall
   303        Void logBegin(Log.Event evt, IArg a1, IArg a2, IArg a3, IArg a4, IArg a5);
   304    
   305        /*!
   306         *  @_nodoc
   307         *  ======= logEnd ========
   308         *  Log the LD_end from within Hwi module scope
   309         */
   310        @DirectCall
   311        Void logEnd(Log.Event evt, IArg a1);
   312    
   313    instance:
   314    
   315        /*! override maskSetting - Hwi does not manage nesting on 430 */
   316        override config IHwi.MaskingOption maskSetting = IHwi.MaskingOption_ALL;
   317    
   318        /*! 
   319         *  Does this interrupt support posting of Swis? Default is true.
   320         *
   321         *  If "true", the interrupt stub will disable the Swi scheduler upon stub
   322         *  entry, and restore it upon interrupt completion. 
   323         *
   324         *  If no Swi-scheduling APIs (for example, Swi_post()) are called from 
   325         *  within this interrupt's ISR function, then swiEnabled can be set to 
   326         *  "false".
   327         */
   328        metaonly config Bool swiEnabled = true;
   329    
   330        /*! 
   331         *  Does this interrupt support task pre-emption? Default is true.
   332         *
   333         *  If "true", the interrupt stub will disable the Task scheduler upon 
   334         *  stub entry, and restore it upon interrupt completion. 
   335         *
   336         *  If no Task-scheduling APIs (e.g., Semaphore_post()) are called from 
   337         *  within this interrupt's ISR function, then taskEnabled can be set to 
   338         *  "false".
   339         */
   340        metaonly config Bool taskEnabled = true;
   341    
   342        /*! 
   343         *  Switch to ISR stack for this interrupt? Default is true.
   344         *
   345         *  If "true", the SYS/BIOS interrupt/system stack will be used when 
   346         *  running this interrupt's ISR function (instead of the interrupted 
   347         *  Task's dedicated stack).  If "false", no switching to the 
   348         *  interrupt/system stack will occur for this interrupt. 
   349         *
   350         *  Note that this parameter is only relevant for the Task module; if 
   351         *  the Task module is not enabled in the application only a single stack
   352         *  is used (i.e., the "system/interrupt stack").
   353         */
   354        metaonly config Bool isrStackEnabled = true;
   355    
   356        /*! 
   357         *  Does this interrupt allow nesting by other interrupts? Default is 
   358         *  false.
   359         *
   360         *  Set to "true" if the configured ISR function will enable global 
   361         *  interrupts temporarily within the function, to allow other interrupts
   362         *  to nest on top of this interrupt.  If the ISR does not enable other
   363         *  interrupts, then leave as the default of "false".
   364         *
   365         */
   366        metaonly config Bool nestingEnabled = false;
   367    
   368        /*! 
   369         *  Does this interrupt support logging?
   370         *
   371         *  If set to true, {@link xdc.runtime.Log Log} statements are inserted
   372         *  into the generated interrupt stub that calls the user's interrupt
   373         *  function.  The stub posts an {@link #LM_begin} event at the beginning
   374         *  of the interrupt service routine and a {@link #LD_end} event after
   375         *  the user's function returns.
   376         *
   377         *  In addition to enabling this flag, you must also enable USER1 and/or
   378         *  USER2 logging for this module.  Otherwise, the events posted by the
   379         *  inserted Log statments will be ignored.
   380         */
   381        metaonly config Bool loggingEnabled = false;
   382    
   383        /*! 
   384         *  Does this interrupt support thread-type tracking? Default is true. 
   385         *
   386         *  If "true", this stub will enable full tracking of the execution 
   387         *  context.  For example, if the ISR function (or one of the functions
   388         *  it calls) were to call BIOS_getThreadType(), the returned value would be
   389         *  BIOS_ThreadType_Hwi.  
   390         *
   391         *  Setting this parameter to "false" will slightly reduce the interrupt 
   392         *  stub overhead, but may result in an incorrect thread type being 
   393         *  reported during the processing of the interrupt.
   394         */
   395        metaonly config Bool threadTypeEnabled = true;
   396    
   397        /*! 
   398         *  Should keep CPU awake following this interrupt? Default is false. 
   399         * 
   400         *  If "true", this interrupt stub will modify the status register (SR)
   401         *  value that was pushed onto the stack (automatically, at the start of
   402         *  servicing the interrupt), so that when it is restored by the RETI 
   403         *  instruction, the CPU will stay in the Active mode. 
   404         *
   405         *  If left as "false", the unmodified SR value will be restored by the
   406         *  RETI instruction, and the CPU may return to a previous low power mode
   407         *  (LPM) that was in effect when the interrupt was triggered. 
   408         */
   409        metaonly config Bool keepAwakeEnabled = false;
   410    
   411    internal:   /* not for client use */
   412    
   413        /*!
   414         *  ======== init ========
   415         *  Setup Hwi stack
   416         */
   417        Void init();
   418    
   419        /*!
   420         *  ======== nonPluggedIsr ========
   421         *  Interrupt service routine that never returns
   422         *
   423         *  This function can be used to plug interrupts that should never
   424         *  occur.  If one does, rather than jumping to an undefined location
   425         *  the program stops with the CPU in a spin lock within this function.
   426         */
   427        Void nonPluggedIsr(UArg intNum);
   428    
   429        /*!
   430         *  const array to hold all HookSet objects.
   431         */
   432        config HookSet hooks[length] = [];
   433    
   434        /*! Meta World Only Hwi Configuration Object. */
   435        metaonly struct InterruptObj {
   436            String name;            /* symbol used for vector table entry */
   437            Bool used;              /* Interrupt already defined? */
   438            Bool generateStub;      /* handler is generated? */
   439            Bool swiEnabled;
   440            Bool taskEnabled;
   441            Bool nestingEnabled;
   442            Bool isrStackEnabled;
   443            Bool lmBeginEnabled;
   444            Bool ldEndEnabled;
   445            Bool threadTypeEnabled;
   446            Bool keepAwakeEnabled;
   447            String handle;
   448            FuncPtr fxn;            /* "wrapped" ISR function */
   449            Fxn pfxn;               /* non "wrapped" ISR function */
   450            UArg arg;               /* Argument to fxn */
   451        };
   452    
   453        /*!
   454         * Meta-only array of interrupt objects.
   455         *
   456         * This meta-only array of Hwi config objects is initialized
   457         * in Hwi.xs:module$meta$init().
   458         */
   459        metaonly config InterruptObj interrupt[];
   460    
   461        struct Instance_State {
   462            Int             intNum;         // Interrupt number
   463            Irp             irp;            // current IRP
   464            Ptr             hookEnv[];
   465        };
   466     
   467        struct Module_State {
   468            Char        *taskSP;        // Temporary storage of interrupted
   469                                        // Task's SP during ISR execution
   470            /* ROM */
   471            Char        *isrStack;      // Points to isrStack address
   472        };
   473    }
   474    /*
   475     *  @(#) ti.sysbios.family.msp430; 1, 0, 0, 0,205; 2-24-2012 11:40:24; /db/vtree/library/trees/avala/avala-q28x/src/ xlibrary
   476    
   477     */
   478