1    /*
     2     * Copyright (c) 2015-2016, 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    package ti.sysbios.family.arm.v7r.vim;
    36    
    37    import xdc.runtime.Diags;
    38    import xdc.runtime.Error;
    39    import xdc.runtime.Log;
    40    import xdc.rov.ViewInfo;
    41    
    42    import ti.sysbios.interfaces.IHwi;
    43    
    44    /*!
    45     *  ======== Hwi ========
    46     *  Hardware Interrupt Support Module.
    47     *
    48     *  This Hwi module provides Hercules VIM specific implementations of the
    49     *  APIs defined in {@link ti.sysbios.interfaces.IHwi IHwi}.
    50     *
    51     *  Additional ARM device-specific APIs are also provided.
    52     *
    53     *  @a(Minimal Latency Interrupts)
    54     *  For applications requiring extremely low interrupt latency, this Hwi module
    55     *  allows the user to create FIQ interrupts that bypass the SYS/BIOS interrupt
    56     *  dispatcher. Though not a precisely correct classification, these interrupts
    57     *  are referred to as "Zero latency" interrupts.
    58     *
    59     *  "FIQ" aka "Zero latency" interrupts can be created by setting the Hwi_Param
    60     *  {@link #type} to Hwi_Type_FIQ. FIQ interrupts offer low interrupt latency
    61     *  as they do not have to pass through the regular SYS/BIOS interrupt
    62     *  dispatcher and are always enabled. When auto nesting is enabled and masking
    63     *  option ALL or LOWER is used, some or all of the VIM interrupt channels will
    64     *  be disabled while the interrupt is being serviced. However, none of the
    65     *  channels corresponding to "Zero latency" interrupts are disabled (masked).
    66     *
    67     *  The ISR handler function for a "Zero latency" interrupt must use the
    68     *  "interrupt" keyword in the function definition and should have no
    69     *  parameters. Using the "interrupt" keyword will ensure that the necessary
    70     *  registers are saved on entry into the interrupt routine and are restored
    71     *  upon exit from the interrupt routine.
    72     *
    73     *  Since the function pointer passed to Hwi_create()/Hwi_construct() has a
    74     *  different function signature (i.e. it accepts an argument), the
    75     *  "Zero latency" function must be type-casted to {@link #FuncPtr Hwi_FuncPtr}
    76     *  type before being passed to Hwi_create()/Hwi_construct() in order to avoid
    77     *  any compiler warnings.
    78     *
    79     *  Unlike regular IRQ interrupts, FIQ interrupts do not run on the System stack
    80     *  but on their own FIQ stack. The stack pointer, size and section name for the
    81     *  FIQ stack can be set using the {@link #fiqStack}, {@link #fiqStackSize}
    82     *  and {@link #fiqStackSection} module wide configuration params.
    83     *
    84     *  @a(Constraints of using "FIQ" aka "Zero latency" interrupts)
    85     *  Interrupts configured to bypass the dispatcher are not allowed
    86     *  to call ANY SYS/BIOS APIs that effect thread scheduling. Examples
    87     *  of API that should no be invoked are:
    88     *
    89     *  @p(dlist)
    90     *    - Swi_post(),
    91     *    - Semaphore_post(),
    92     *    - Event_post(),
    93     *    - Task_yield()
    94     *  @p
    95     *
    96     *  Here's an example showing how to create a Hwi of FIQ type:
    97     *  @p(code)
    98     *  *.cfg:
    99     *  var Hwi = xdc.useModule('ti.sysbios.family.arm.v7r.vim.Hwi');
   100     *  Hwi.fiqStackSize = 2048;
   101     *  Hwi.fiqStackSection = ".myFiqStack"
   102     *  Program.sectMap[".myFiqStack"] = "RAM";
   103     *
   104     *  *.c:
   105     *  #include <xdc/std.h>
   106     *  #include <xdc/runtime/System.h>
   107     *
   108     *  #include <ti/sysbios/BIOS.h>
   109     *  #include <ti/sysbios/family/arm/v7r/vim/Hwi.h>
   110     *
   111     *  #include <xdc/cfg/global.h>
   112     *
   113     *  Void interrupt myIsrFIQ()
   114     *  {
   115     *      ...
   116     *  }
   117     *
   118     *  Void main(Void)
   119     *  {
   120     *      Hwi_Params hwiParams;
   121     *
   122     *      Hwi_Params_init(&hwiParams);
   123     *      hwiParams.type = Hwi_Type_FIQ;
   124     *      Hwi_create(INT_NUM_FIQ, (Hwi_FuncPtr)myIsrFIQ, &hwiParams, NULL);
   125     *      ...
   126     *
   127     *      BIOS_start();
   128     *  }
   129     *  @p
   130     *
   131     *  @a(Interrupt Channel configuration)
   132     *  Each VIM interrupt request (source) can be mapped to any of the interrupt
   133     *  channels (same as intNums). Lower numbered channels in each FIQ and IRQ
   134     *  have higher priority. Therefore, channel mapping provides a mechanism for
   135     *  prioritizing the interrupt requests.
   136     *
   137     *  Additionally, it is possible to configure a channel interrupt as a wakeup
   138     *  interrupt so it can bring the core out of low power mode (LPM).
   139     *
   140     *  This module has a {@link #configChannelMeta Hwi.configChannelMeta()}
   141     *  function that can be invoked from the cfg script to statically
   142     *  (at build time) change the channel mapping and wakeup functionality of a
   143     *  channel interrupt.
   144     *
   145     *  By default, all interrupt request sources are direct mapped to channels
   146     *  (i.e. interrupt request N is mapped to channel N) and wakeup feature is
   147     *  enabled for all interrupts.
   148     *
   149     *  Here's an example showing how to use this function:
   150     *  @p(code)
   151     *  *.cfg:
   152     *  var Hwi = xdc.useModule('ti.sysbios.family.arm.v7r.vim.Hwi');
   153     *
   154     *  // Map interrupt request line 86 to channel 2 (i.e. intNum 2) and disable
   155     *  // wakeup feature
   156     *  Hwi.configChannelMeta(2, 86, false);
   157     *  @p
   158     *
   159     *  @a(More Hwi examples)
   160     *  Here's an example showing how to construct a Hwi at runtime:
   161     *  @p(code)
   162     *  *.c:
   163     *  #include <ti/sysbios/family/arm/v7r/vim/Hwi.h>
   164     *
   165     *  Hwi_Struct hwiStruct;
   166     *
   167     *  Void myIsrIRQ(UArg arg)
   168     *  {
   169     *      ...
   170     *  }
   171     *
   172     *  Void main(Void)
   173     *  {
   174     *      Hwi_Params hwiParams;
   175     *
   176     *      Hwi_Params_init(&hwiParams);
   177     *      Hwi_construct(&hwiStruct, INT_NUM_IRQ, myIsrIRQ, &hwiParams, NULL);
   178     *      ...
   179     *      BIOS_start();
   180     *  }
   181     *  @p
   182     *
   183     *  @p(html)
   184     *  <h3> Calling Context </h3>
   185     *  <table border="1" cellpadding="3">
   186     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
   187     *
   188     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   189     *    <!--                                                                                                                 -->
   190     *    <tr><td> {@link #clearInterrupt}   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   191     *    <tr><td> {@link #create}           </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   192     *    <tr><td> {@link #disable}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   193     *    <tr><td> {@link #disableInterrupt} </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   194     *    <tr><td> {@link #disableIRQ}       </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   195     *    <tr><td> {@link #enable}           </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   196     *    <tr><td> {@link #enableInterrupt}  </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   197     *    <tr><td> {@link #enableIRQ}        </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   198     *    <tr><td> {@link #getHandle}        </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   199     *    <tr><td> {@link #Params_init}      </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   200     *    <tr><td> {@link #restore}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   201     *    <tr><td> {@link #restoreInterrupt} </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   202     *    <tr><td> {@link #restoreIRQ}       </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   203     *    <tr><td> {@link #construct}        </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   204     *    <tr><td> {@link #delete}           </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   205     *    <tr><td> {@link #destruct}         </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   206     *    <tr><td> {@link #getHookContext}   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   207     *    <tr><td> {@link #reconfig}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   208     *    <tr><td> {@link #setFunc}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   209     *    <tr><td> {@link #setHookContext}   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   210     *    <tr><td colspan="6"> Definitions: <br />
   211     *       <ul>
   212     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   213     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   214     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   215     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   216     *           <ul>
   217     *             <li> In your module startup after this module is started (e.g. Hwi_Module_startupDone() returns TRUE). </li>
   218     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   219     *             <li> During main().</li>
   220     *             <li> During BIOS.startupFxns.</li>
   221     *           </ul>
   222     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   223     *           <ul>
   224     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   225     *             <li> In your module startup before this module is started (e.g. Hwi_Module_startupDone() returns FALSE).</li>
   226     *           </ul>
   227     *       </ul>
   228     *    </td></tr>
   229     *
   230     *
   231     *  </table>
   232     *  @p
   233     */
   234    
   235    @Template("./Hwi.xdt")  /* generates the vector table and the dispatcher */
   236    @ModuleStartup          /* generates call to Hwi_Module_startup at startup */
   237    @InstanceInitStatic     /* allow constructs in static only systems */
   238    @CustomHeader
   239    
   240    module Hwi inherits ti.sysbios.interfaces.IHwi
   241    {
   242    
   243        // -------- Module Constants --------
   244    
   245        config UInt NUM_INTERRUPTS;
   246    
   247        // -------- Module Types --------
   248    
   249        /*! Hwi vector function type definition. */
   250        typedef Void (*VectorFuncPtr)(void);
   251    
   252        /*! @_nodoc Hwi plug function type definition. */
   253        typedef Void (*PlugFuncPtr)(void);
   254    
   255        /*! Interrupt type. IRQ or FIQ */
   256        enum Type {
   257            Type_IRQ,               /*! IRQ interrupt. */
   258            Type_FIQ                /*! FIQ interrupt. */
   259        };
   260    
   261        /*!
   262         *  @_nodoc
   263         *  Vectored Interrupt Manager (VIM) Registers
   264         */
   265        struct VIM {
   266            UInt32 ECCSTAT;         /*! VIM RAM ECC Status Register */
   267            UInt32 ECCCTL;          /*! VIM RAM ECC Control Register */
   268            UInt32 UERRADDR;        /*! Uncorrectable Error Address Register */
   269            UInt32 FBVECADDR;       /*! Fallback Vector Address Register */
   270            UInt32 SBERRADDR;       /*! Single Bit Error Address Register */
   271    
   272            UInt32 IRQINDEX;        /*! IRQ Index Offset Vector Register */
   273            UInt32 FIQINDEX;        /*! FIQ Index Offset Vector Register */
   274            UInt32 RES00[2];        /*! Reserved */
   275    
   276            UInt32 FIRQPR[4];       /*! FIQ/IRQ Program Control Registers */
   277            UInt32 INTREQ[4];       /*! Pending Interrupt Read Location Registers */
   278    
   279            UInt32 REQENASET[4];    /*! Interrupt Enable Set Registers */
   280            UInt32 REQENACLR[4];    /*! Interrupt Enable Clear Registers */
   281    
   282            UInt32 WAKEENASET[4];   /*! Wake-up Enable Set Registers */
   283            UInt32 WAKEENACLR[4];   /*! Wake-up Enable Clear Registers */
   284    
   285            UInt32 IRQVECREG;       /*! IRQ Interrupt Vector Register */
   286            UInt32 FIQVECREG;       /*! FIQ Interrupt Vector Register */
   287    
   288            UInt32 CAPEVT;          /*! Capture Event Register */
   289            UInt32 RES01;           /*! Reserved */
   290    
   291            UInt8 CHANCTRL[128];    /*! VIM Interrupt Control Registers */
   292        };
   293    
   294        /*!
   295         *  @_nodoc
   296         *  Symbol "Hwi_vim" is a physical device
   297         */
   298        extern volatile VIM vim;
   299    
   300        /*! @_nodoc */
   301        metaonly struct BasicView {
   302            Ptr         halHwiHandle;
   303            String      label;
   304            String      type;
   305            Int         intNum;
   306            String      fxn;
   307            UArg        arg;
   308            Ptr         irp;
   309            String      status;
   310        };
   311    
   312        /*! @_nodoc */
   313        metaonly struct ChannelMapView {
   314            UInt        channelId;
   315            UInt        interruptRequestId;
   316        };
   317    
   318        /*! @_nodoc */
   319        metaonly struct ModuleView {
   320            String      options[4];
   321            UInt        spuriousInterrupts;
   322            SizeT       hwiStackPeak;
   323            SizeT       hwiStackSize;
   324            Ptr         hwiStackBase;
   325        };
   326    
   327        /*! @_nodoc */
   328        @Facet
   329        metaonly config ViewInfo.Instance rovViewInfo =
   330            ViewInfo.create({
   331                viewMap: [
   332                    ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
   333                    ['ChannelMap', {type: ViewInfo.MODULE_DATA, viewInitFxn: 'viewChannelMap', structName: 'ChannelMapView'}],
   334                    ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}]
   335                ]
   336            });
   337    
   338        // -------- Module Parameters --------
   339    
   340        /*!
   341         *  ======== core0VectorTableAddress ========
   342         *  Determines the location of Core0's Interrupt Vector Table on a
   343         *  Dual-Core device. Default is device dependent.
   344         *
   345         *  On Dual-Core devices, both Cortex-R5 cores share a common reset
   346         *  vector table. In order to allow the 2 cores to register their own
   347         *  exception handlers, each core generates its own clone of the reset
   348         *  vector table and initializes it with its own exception handler
   349         *  addresses. The core specific vector tables are placed at fixed
   350         *  addresses so that the exception handler functions called by the
   351         *  common reset vector table known each core's vector table address
   352         *  and are able to reference it once they detect which core the
   353         *  application is currently running on.
   354         *
   355         *  The address of Core0's vector table is determined by this parameter.
   356         *
   357         *  Here are the default Core0 vector table addresses for all supported
   358         *  Dual-Core devices:
   359         *  @p(code)
   360         *   ----------------------------------------------------
   361         *  | Device name | Core0's default vector table address |
   362         *   ----------------------------------------------------
   363         *  | RM57D8xx    | 0x100                                |
   364         *   ----------------------------------------------------
   365         *  @p
   366         *
   367         *  @a(Note)
   368         *  If changing Core0's vector table address, it is not necessary to
   369         *  rebuild Core1's application as it does not need to know the location
   370         *  of Core0's vector table.
   371         */
   372        config Ptr core0VectorTableAddress;
   373    
   374        /*!
   375         *  ======== core1VectorTableAddress ========
   376         *  Determines the location of Core1's Interrupt Vector Table on a
   377         *  Dual-Core device. Default is device dependent.
   378         *
   379         *  On Dual-Core devices, both Cortex-R5 cores share a common reset
   380         *  vector table. In order to allow the 2 cores to register their own
   381         *  exception handlers, each core generates its own clone of the reset
   382         *  vector table and initializes it with its own exception handler
   383         *  addresses. The core specific vector tables are placed at fixed
   384         *  addresses so that the exception handler functions called by the
   385         *  common reset vector table known each core's vector table address
   386         *  and are able to reference it once they detect which core the
   387         *  application is currently running on.
   388         *
   389         *  Core0's vector table is always placed at 0x100 while the address of
   390         *  Core1's vector table is determined by this parameter.
   391         *
   392         *  Here are the default Core1 vector table addresses for all supported
   393         *  Dual-Core devices:
   394         *  @p(code)
   395         *   ----------------------------------------------------
   396         *  | Device name | Core1's default vector table address |
   397         *   ----------------------------------------------------
   398         *  | RM57D8xx    | 0x200000                             |
   399         *   ----------------------------------------------------
   400         *  @p
   401         *
   402         *  @a(Note)
   403         *  If changing Core1's vector table address, it is important to rebuild
   404         *  Core0's application with the same change as Core0 owns the common
   405         *  reset vector table and the common exception handler functions need
   406         *  to know Core1's vector table address so they can determine the
   407         *  address of the handler function they need to jump to.
   408         */
   409        config Ptr core1VectorTableAddress;
   410    
   411        /*! Reset Handler. Default is c_int00 */
   412        metaonly config VectorFuncPtr resetFunc;
   413    
   414        /*!
   415         *  Undefined instruction exception handler.
   416         *  Default is set to an internal exception handler.
   417         */
   418        metaonly config VectorFuncPtr undefinedInstFunc;
   419    
   420        /*! SWI Handler. Default is internal SWI handler */
   421        metaonly config VectorFuncPtr swiFunc;
   422    
   423        /*!
   424         *  Prefetch abort exception handler.
   425         *  Default is set to an internal exception handler.
   426         */
   427        metaonly config VectorFuncPtr prefetchAbortFunc;
   428    
   429        /*!
   430         *  Data abort exception handler.
   431         *  Default is set to an internal exception handler.
   432         */
   433        metaonly config VectorFuncPtr dataAbortFunc;
   434    
   435        /*!
   436         *  Reserved exception handler.
   437         *  Default is set to an internal exception handler.
   438         */
   439        metaonly config VectorFuncPtr reservedFunc;
   440    
   441        /*!
   442         *  IRQ exception handler.
   443         *  Default is set to internal IRQ dispatcher.
   444         */
   445        metaonly config VectorFuncPtr irqFunc;
   446    
   447        /*!
   448         *  Phantom interrupt handler.
   449         *  Default is set to internal phantom interrupt handler.
   450         */
   451        config VectorFuncPtr phantomFunc;
   452    
   453        /*!
   454         *  FIQ stack pointer. Default = null.
   455         *  (Indicates that stack is to be created using
   456         *  staticPlace())
   457         */
   458        config Ptr fiqStack = null;
   459    
   460        /*!
   461         *  FIQ stack size in MAUs.
   462         *  Default is 1024 bytes.
   463         */
   464        metaonly config SizeT fiqStackSize = 1024;
   465    
   466        /*!
   467         *  Memory section used for FIQ stack
   468         *  Default is null.
   469         */
   470        metaonly config String fiqStackSection = null;
   471    
   472        /*!
   473         * @_nodoc
   474         * VIM base address
   475         */
   476        metaonly config Ptr vimBaseAddress;
   477    
   478        /*!
   479         *  ======== errataInitESM ========
   480         *  Clear ESM errors for AR1xxx devices. Default is true for AR1xxx devices.
   481         *
   482         *  Errata brief description:
   483         *  Cortex-R4 on AR14xx devices generates a VIM RAM compare error
   484         *  during startup due to a ROM code bug. This error needs to be cleared
   485         *  before SYS/BIOS is started and interrupts are enabled.
   486         */
   487        config Bool errataInitEsm = false;
   488    
   489        /*!
   490         *  ======== resetVIM ========
   491         *  Reset VIM hardware. Default is true for AR1xxx devices.
   492         *
   493         *  This feature is available only on certain devices.
   494         */
   495        config Bool resetVIM = false;
   496    
   497        /*!
   498         *  ======== A_badChannelId ========
   499         *  Assert raised when an invalid channelId is passed to Hwi_mapChannel()
   500         *  function.
   501         */
   502        config xdc.runtime.Assert.Id A_badChannelId  = {
   503            msg: "A_badChannelId: ChannelId is either not re-mappable or invalid."
   504        };
   505    
   506        /*!
   507         *  Error raised when Hwi is already defined
   508         */
   509        config Error.Id E_alreadyDefined = {
   510            msg: "E_alreadyDefined: Hwi already defined: intr# %d"
   511        };
   512    
   513        /*!
   514         *  Error raised if an attempt is made to create a Hwi
   515         *  with an interrupt number greater than Hwi_NUM_INTERRUPTS - 1.
   516         */
   517        config Error.Id E_badIntNum = {
   518            msg: "E_badIntNum, intnum: %d is out of range"
   519        };
   520    
   521        /*!
   522         *  Error raised when an undefined interrupt has fired.
   523         */
   524        config Error.Id E_undefined = {
   525            msg: "E_undefined: Hwi undefined, intnum: %d"
   526        };
   527    
   528        /*!
   529         *  Error raised when an unsupported Hwi.MaskingOption used.
   530         */
   531        config Error.Id E_unsupportedMaskingOption = {
   532            msg: "E_unsupportedMaskingOption: Unsupported masking option passed."
   533        };
   534    
   535        /*!
   536         *  Error raised when a phantom interrupt occurs.
   537         */
   538        config Error.Id E_phantomInterrupt = {
   539            msg: "E_phantomInterrupt: A phantom interrupt has occurred."
   540        };
   541    
   542        /*!
   543         *  Issued just prior to Hwi function invocation (with interrupts disabled)
   544         */
   545        config Log.Event LM_begin = {
   546            mask: Diags.USER1 | Diags.USER2,
   547            msg: "LM_begin: hwi: 0x%x, func: 0x%x, preThread: %d, intNum: %d, irp: 0x%x"
   548        };
   549    
   550        /*!
   551         *  Issued just after return from Hwi function (with interrupts disabled)
   552         */
   553        config Log.Event LD_end = {
   554            mask: Diags.USER2,
   555            msg: "LD_end: hwi: 0x%x"
   556        };
   557    
   558    
   559        // -------- Module Functions --------
   560    
   561        /*!
   562         *  ======== disable ========
   563         *  Globally disable interrupts.
   564         *
   565         *  Hwi_disable globally disables hardware interrupts and returns an
   566         *  opaque key indicating whether interrupts were globally enabled or
   567         *  disabled on entry to Hwi_disable().
   568         *  The actual value of the key is target/device specific and is meant
   569         *  to be passed to Hwi_restore().
   570         *
   571         *  Call Hwi_disable before a portion of a function that needs
   572         *  to run without interruption. When critical processing is complete, call
   573         *  Hwi_restore or Hwi_enable to reenable hardware interrupts.
   574         *
   575         *  Servicing of interrupts that occur while interrupts are disabled is
   576         *  postponed until interrupts are reenabled. However, if the same type
   577         *  of interrupt occurs several times while interrupts are disabled,
   578         *  the interrupt's function is executed only once when interrupts are
   579         *  reenabled.
   580         *
   581         *  A context switch can occur when calling Hwi_enable or Hwi_restore if
   582         *  an enabled interrupt occurred while interrupts are disabled.
   583         *
   584         *  Hwi_disable may be called from main(). However, since Hwi interrupts
   585         *  are already disabled in main(), such a call has no effect.
   586         *
   587         *  @a(constraints)
   588         *  If a Task switching API such as
   589         *  {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()},
   590         *  {@link ti.sysbios.knl.Semaphore#post Semaphore_post()},
   591         *  {@link ti.sysbios.knl.Task#sleep Task_sleep()}, or
   592         *  {@link ti.sysbios.knl.Task#yield Task_yield()}
   593         *  is invoked which results in a context switch while
   594         *  interrupts are disabled, an embedded call to
   595         *  {@link #enable Hwi_enable} occurs
   596         *  on the way to the new thread context which unconditionally re-enables
   597         *  interrupts. Interrupts will remain enabled until a subsequent
   598         *  {@link #disable Hwi_disable}
   599         *  invocation.
   600         *
   601         *  Swis always run with interrupts enabled.
   602         *  See {@link ti.sysbios.knl.Swi#post Swi_post()} for a discussion Swis and
   603         *  interrupts.
   604         *
   605         *  @b(returns)     opaque key for use by Hwi_restore()
   606         */
   607        @Macro
   608        override UInt disable();
   609    
   610        /*!
   611         *  ======== enable ========
   612         */
   613        @Macro
   614        override UInt enable();
   615    
   616        /*!
   617         *  ======== restore ========
   618         */
   619        @Macro
   620        override Void restore(UInt key);
   621    
   622        /*!
   623         *  @_nodoc
   624         *  ======== inUseMeta ========
   625         *  Check for Hwi already in use.
   626         *  For internal SYS/BIOS use only.
   627         *  Should be called prior to any internal Hwi.create().
   628         *
   629         *  @param(intNum)  interrupt number
   630         */
   631        metaonly Bool inUseMeta(UInt intNum);
   632    
   633        /*!
   634         *  ======== getHandle ========
   635         *  Returns pointer to Hwi instance object.
   636         *
   637         *  @param(intNum)  interrupt number
   638         */
   639        Object *getHandle(UInt intNum);
   640    
   641        /*!
   642         *  ======== enableIRQ ========
   643         *  Enable IRQ interrupts.
   644         *
   645         *  @param(key)     enable/disable state to restore
   646         */
   647        UInt enableIRQ();
   648    
   649        /*!
   650         *  ======== disableIRQ ========
   651         *  Disable IRQ interrupts.
   652         *
   653         *  @b(returns)     previous IRQ interrupt enable/disable state
   654         */
   655        UInt disableIRQ();
   656    
   657        /*!
   658         *  ======== restoreIRQ ========
   659         *  Restore IRQ interrupts.
   660         *
   661         *  @param(key)     enable/disable state to restore
   662         */
   663        Void restoreIRQ(UInt key);
   664    
   665        /*!
   666         *  ======== configChannelMeta ========
   667         *  Configure which VIM interrupt request this channel maps to and
   668         *  whether this channel's interrupt is a wakeup interrupt
   669         *
   670         *  Each VIM interrupt request (source) can be mapped to any of
   671         *  the interrupt channels. Lower numbered channels in each FIQ
   672         *  and IRQ have higher priority. Therefore, channel mapping
   673         *  provides a mechanism for prioritizing the interrupt requests.
   674         *
   675         *  A channel interrupt can also be configured to be a wakeup interrupt
   676         *  so it can bring the core out of low power mode (LPM).
   677         *
   678         *  @param(channelId)       Channel number (intNum)
   679         *  @param(intRequestId)    VIM Interrupt request (source) number
   680         *  @param(wakeupEnable)    Enable wakeup interrupt functionality ?
   681         */
   682        metaonly Void configChannelMeta(UInt channelId, UInt intRequestId,
   683            Bool wakeupEnable);
   684    
   685        /*!
   686         *  @_nodoc
   687         *  ======== setType ========
   688         *  Set an interrupt's type (FIQ/IRQ).
   689         *
   690         *  Not an instance function so that it can be used
   691         *  with non-dispatched interrupts.
   692         *
   693         *  @param(intNum)      ID of interrupt
   694         *  @param(type)        type = FIQ/IRQ
   695         */
   696        Void setType(UInt intNum, Type type);
   697    
   698    instance:
   699    
   700        /*! Interrupt type (IRQ/FIQ. Default is IRQ. */
   701        config Type type = Type_IRQ;
   702    
   703        /*!
   704         *  Default setting for this Hwi module is IHwi.MaskingOption_LOWER
   705         */
   706        override config IHwi.MaskingOption maskSetting = IHwi.MaskingOption_LOWER;
   707    
   708        /*!
   709         *  ======== reconfig ========
   710         *  Reconfigure a dispatched interrupt.
   711         */
   712        Void reconfig(FuncPtr fxn, const Params *params);
   713    
   714    internal:   /* not for client use */
   715    
   716        metaonly config Bool lockstepDevice;
   717    
   718        /*
   719         *  ======== channelMap ========
   720         */
   721        config UInt8 channelMap[];
   722    
   723        /*
   724         *  ======== intReqEnaSet ========
   725         *  Initial interrupt request enable value
   726         */
   727        config UInt32 intReqEnaSet[];
   728    
   729        /*
   730         *  ======== wakeEnaSet ========
   731         *  Initial wakeup enable value
   732         */
   733        config UInt32 wakeEnaSet[];
   734    
   735        /*
   736         * Swi and Task module function pointers.
   737         * Used to decouple Hwi from Swi and Task when
   738         * dispatcherSwiSupport or
   739         * dispatcherTaskSupport is false.
   740         */
   741        config UInt (*swiDisable)();
   742        config Void (*swiRestoreHwi)(UInt);
   743        config UInt (*taskDisable)();
   744        config Void (*taskRestoreHwi)(UInt);
   745    
   746        /*
   747         *  ======== initEsm ========
   748         */
   749        Void initEsm();
   750    
   751        /*
   752         *  ======== postInit ========
   753         *  finish initializing static and dynamic Hwis
   754         */
   755        Int postInit(Object *hwi, Error.Block *eb);
   756    
   757        /*
   758         *  ======== initIntController ========
   759         */
   760        Void initIntController();
   761    
   762        /* assembly code mode registers setup */
   763        Void init();
   764    
   765        /* Interrupt Dispatcher assembly code wrapper */
   766        Void dispatchIRQ();
   767    
   768        /* IRQ Interrupt Dispatcher */
   769        Void dispatchIRQC(Irp irp);
   770    
   771        /* default Phantom Interrupt Handler */
   772        Void phantomIntHandler();
   773    
   774        /*
   775         *  ======== mapChannel ========
   776         *  Map interrupt request to given channel
   777         *
   778         *  @param(channelId)       Channel number
   779         *  @param(intRequestId)    VIM Interrupt request (source) number
   780         */
   781        Void mapChannel(UInt channelId, UInt intRequestId);
   782    
   783        /* non plugged interrupt handler */
   784        Void nonPluggedHwiHandler(UArg arg);
   785    
   786        /*
   787         *  ======== plug ========
   788         *  Plug an interrupt vector with an ISR address.
   789         *
   790         *  @param(intNum)  interrupt number
   791         *  @param(fxn)     pointer to ISR function
   792         */
   793        Void plug(UInt intNum, PlugFuncPtr fxn);
   794    
   795        /*!
   796         *  const array to hold all HookSet objects.
   797         */
   798        config HookSet hooks[length] = [];
   799    
   800        /*! Meta World Only Hwi Configuration Object. */
   801        metaonly struct InterruptObj {
   802            Bool used;              /* Interrupt already defined? */
   803            FuncPtr fxn;            /* Dispatched ISR function */
   804        };
   805    
   806        /*!
   807         * Meta-only array of interrupt objects.
   808         * This meta-only array of Hwi config objects is initialized
   809         * in Hwi.xs:module$meta$init().
   810         */
   811        metaonly config InterruptObj interrupt[];
   812    
   813        struct Instance_State {
   814            Type        type;                   // Interrupt Type
   815            UArg        arg;                    // Argument to Hwi function.
   816            FuncPtr     fxn;                    // Hwi function.
   817            Int         intNum;                 // Interrupt number
   818            Irp         irp;                    // current IRP
   819            Ptr         hookEnv[];
   820            UInt        disableMask[4];
   821        };
   822    
   823        struct Module_State {
   824            Char        *taskSP;                // temporary storage of interrupted
   825                                                // Task's SP during ISR execution
   826            Char        *isrStack;              // Points to isrStack address
   827            Ptr         isrStackBase;           // _stack
   828            Ptr         isrStackSize;           // _STACK_SIZE
   829            Char        fiqStack[];             // buffer used for FIQ stack
   830            SizeT       fiqStackSize;
   831            UInt        *vimRam;                // VIM RAM
   832            Handle      dispatchTable[];        // dispatch table
   833            UInt        zeroLatencyFIQMask[4];
   834            UInt        spuriousInts;           // Count of spurious interrupts
   835        };
   836    }