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         *  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        // -------- Module Functions --------
   246    
   247        /*!
   248         *  ======== disable ========
   249         */
   250        @Macro
   251        override UInt disable();
   252    
   253        /*!
   254         *  ======== enable ========
   255         */
   256        @Macro
   257        override UInt enable();
   258    
   259        /*!
   260         *  ======== restore ========
   261         */
   262        @Macro
   263        override Void restore(UInt key);
   264    
   265        /*!
   266         *  ======== inUseMeta ========
   267         *  @_nodoc
   268         *  Check for Hwi already in use
   269         *
   270         *  For internal SYS/BIOS use only. 
   271         *  Should be called prior to any internal Hwi.create().
   272         *
   273         *  @param(intNum)  interrupt number
   274         */
   275        metaonly Bool inUseMeta(UInt intNum);
   276    
   277        /*!
   278         *  ======== plugMeta ========
   279         *  Statically plug an interrupt vector with an ISR address
   280         *
   281         *  @param(intNum)  interrupt number
   282         *  @param(fxn)     pointer to ISR function
   283         */
   284        metaonly Void plugMeta(UInt intNum, Fxn fxn);
   285    
   286        /*!
   287         *  @_nodoc
   288         *  ======= logBegin ========
   289         *  Log the LM_begin from within Hwi module scope
   290         */
   291        @DirectCall
   292        Void logBegin(Log.Event evt, IArg a1, IArg a2, IArg a3, IArg a4, IArg a5);
   293    
   294        /*!
   295         *  @_nodoc
   296         *  ======= logEnd ========
   297         *  Log the LD_end from within Hwi module scope
   298         */
   299        @DirectCall
   300        Void logEnd(Log.Event evt, IArg a1);
   301    
   302    instance:
   303    
   304        /*! override maskSetting - Hwi does not manage nesting on 430 */
   305        override config IHwi.MaskingOption maskSetting = IHwi.MaskingOption_ALL;
   306    
   307        /*! 
   308         *  Does this interrupt support posting of Swis? Default is true.
   309         *
   310         *  If "true", the interrupt stub will disable the Swi scheduler upon stub
   311         *  entry, and restore it upon interrupt completion. 
   312         *
   313         *  If no Swi-scheduling APIs (for example, Swi_post()) are called from 
   314         *  within this interrupt's ISR function, then swiEnabled can be set to 
   315         *  "false".
   316         */
   317        metaonly config Bool swiEnabled = true;
   318    
   319        /*! 
   320         *  Does this interrupt support task pre-emption? Default is true.
   321         *
   322         *  If "true", the interrupt stub will disable the Task scheduler upon 
   323         *  stub entry, and restore it upon interrupt completion. 
   324         *
   325         *  If no Task-scheduling APIs (e.g., Semaphore_post()) are called from 
   326         *  within this interrupt's ISR function, then taskEnabled can be set to 
   327         *  "false".
   328         */
   329        metaonly config Bool taskEnabled = true;
   330    
   331        /*! 
   332         *  Switch to ISR stack for this interrupt? Default is true.
   333         *
   334         *  If "true", the SYS/BIOS interrupt/system stack will be used when 
   335         *  running this interrupt's ISR function (instead of the interrupted 
   336         *  Task's dedicated stack).  If "false", no switching to the 
   337         *  interrupt/system stack will occur for this interrupt. 
   338         *
   339         *  Note that this parameter is only relevant for the Task module; if 
   340         *  the Task module is not enabled in the application only a single stack
   341         *  is used (i.e., the "system/interrupt stack").
   342         */
   343        metaonly config Bool isrStackEnabled = true;
   344    
   345        /*! 
   346         *  Does this interrupt allow nesting by other interrupts? Default is 
   347         *  false.
   348         *
   349         *  Set to "true" if the configured ISR function will enable global 
   350         *  interrupts temporarily within the function, to allow other interrupts
   351         *  to nest on top of this interrupt.  If the ISR does not enable other
   352         *  interrupts, then leave as the default of "false".
   353         *
   354         */
   355        metaonly config Bool nestingEnabled = false;
   356    
   357        /*! 
   358         *  Does this interrupt support logging?
   359         *
   360         *  If set to true, {@link xdc.runtime.Log Log} statements are inserted
   361         *  into the generated interrupt stub that calls the user's interrupt
   362         *  function.  The stub posts an {@link #LM_begin} event at the beginning
   363         *  of the interrupt service routine and a {@link #LD_end} event after
   364         *  the user's function returns.
   365         *
   366         *  In addition to enabling this flag, you must also enable USER1 and/or
   367         *  USER2 logging for this module.  Otherwise, the events posted by the
   368         *  inserted Log statments will be ignored.
   369         */
   370        metaonly config Bool loggingEnabled = false;
   371    
   372        /*! 
   373         *  Does this interrupt support thread-type tracking? Default is true. 
   374         *
   375         *  If "true", this stub will enable full tracking of the execution 
   376         *  context.  For example, if the ISR function (or one of the functions
   377         *  it calls) were to call BIOS_getThreadType(), the returned value would be
   378         *  BIOS_ThreadType_Hwi.  
   379         *
   380         *  Setting this parameter to "false" will slightly reduce the interrupt 
   381         *  stub overhead, but may result in an incorrect thread type being 
   382         *  reported during the processing of the interrupt.
   383         */
   384        metaonly config Bool threadTypeEnabled = true;
   385    
   386        /*! 
   387         *  Should keep CPU awake following this interrupt? Default is false. 
   388         * 
   389         *  If "true", this interrupt stub will modify the status register (SR)
   390         *  value that was pushed onto the stack (automatically, at the start of
   391         *  servicing the interrupt), so that when it is restored by the RETI 
   392         *  instruction, the CPU will stay in the Active mode. 
   393         *
   394         *  If left as "false", the unmodified SR value will be restored by the
   395         *  RETI instruction, and the CPU may return to a previous low power mode
   396         *  (LPM) that was in effect when the interrupt was triggered. 
   397         */
   398        metaonly config Bool keepAwakeEnabled = false;
   399    
   400    internal:   /* not for client use */
   401    
   402        /*
   403         *  ======== postInit ========
   404         *  finish initializing static and dynamic Hwis
   405         */
   406        Int postInit(Object *hwi, Error.Block *eb);
   407    
   408        /*!
   409         *  ======== init ========
   410         *  Setup Hwi stack
   411         */
   412        Void init();
   413    
   414        /*!
   415         *  const array to hold all HookSet objects.
   416         */
   417        config HookSet hooks[length] = [];
   418    
   419        /*! Meta World Only Hwi Configuration Object. */
   420        metaonly struct InterruptObj {
   421            String name;            /* symbol used for vector table entry */
   422            Bool used;              /* Interrupt already defined? */
   423            Bool generateStub;      /* handler is generated? */
   424            Bool swiEnabled;
   425            Bool taskEnabled;
   426            Bool nestingEnabled;
   427            Bool isrStackEnabled;
   428            Bool lmBeginEnabled;
   429            Bool ldEndEnabled;
   430            Bool threadTypeEnabled;
   431            Bool keepAwakeEnabled;
   432            String handle;
   433            FuncPtr fxn;            /* "wrapped" ISR function */
   434            Fxn pfxn;               /* non "wrapped" ISR function */
   435            UArg arg;               /* Argument to fxn */
   436        };
   437    
   438        /*!
   439         * Meta-only array of interrupt objects.
   440         *
   441         * This meta-only array of Hwi config objects is initialized
   442         * in Hwi.xs:module$meta$init().
   443         */
   444        metaonly config InterruptObj interrupt[];
   445    
   446        struct Instance_State {
   447            Int             intNum;         // Interrupt number
   448            Irp             irp;            // current IRP
   449            Ptr             hookEnv[];
   450        };
   451     
   452        struct Module_State {
   453            Char        *taskSP;        // Temporary storage of interrupted
   454                                        // Task's SP during ISR execution
   455            /* ROM */
   456            Char        *isrStack;      // Points to isrStack address
   457        };
   458    }