1    /*
     2     * Copyright (c) 2015-2017, 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.hal;
    37    
    38    import xdc.runtime.Error;
    39    
    40    /*!
    41     *  ======== Hwi ========
    42     *  Hardware Interrupt Manager Proxy.
    43     *
    44     *  This module provides APIs for managing hardware interrupts.
    45     *  These APIs are generic across all supported targets and devices
    46     *  and should provide sufficient functionality for most applications.
    47     *
    48     *  The actual implementations of the Hwi module APIs are
    49     *  provided by the Hwi module delegates.
    50     *  Additional, family-specific Hwi module APIs may also be provided by
    51     *  the Hwi module delegates.
    52     *  See the list of
    53     *  {@link ./../family/doc-files/delegates.html Delegate Mappings}
    54     *  to determine which Hwi delegate is used
    55     *  for your target/device.
    56     *
    57     *  You can statically or dynamically assign functions that run when
    58     *  specific hardware interrupts occur. Dynamic assignment of Hwi
    59     *  functions to interrupts at run-time is done
    60     *  using the {@link #create Hwi_create} function.
    61     *
    62     *  Interrupt routines can be written completely in C, completely in
    63     *  assembly, or in a mix of C and assembly. In order to support interrupt
    64     *  routines
    65     *  written completely in C, an interrupt dispatcher is provided that performs
    66     *  the requisite prolog and epilog for an interrupt routine.
    67     *
    68     *  Some routines are assigned to interrupts by the other SYS/BIOS
    69     *  modules. For example, the
    70     *  {@link ti.sysbios.knl.Clock} module configures its own timer interrupt
    71     *  handler.
    72     *
    73     *  @a(constraints)
    74     *  Since the hal Hwi module has no knowledge of the delegate Hwi
    75     *  module's instance definition, Hwi_construct() can NOT be properly
    76     *  supported.
    77     *
    78     *  If {@link ti.sysbios.BIOS#runtimeCreatesEnabled BIOS.runtimeCreatesEnabled}
    79     *  is set to true, both Hwi_create() and Hwi_construct()
    80     *  will attempt to dynamically create (ie NOT construct) a delegate Hwi
    81     *  object.
    82     *
    83     *  If {@link ti.sysbios.BIOS#runtimeCreatesEnabled BIOS.runtimeCreatesEnabled}
    84     *  is set to false, both Hwi_create() and Hwi_construct() will fail.
    85     *
    86     *  @p(html)
    87     *  <h3> Calling Context </h3>
    88     *  <table border="1" cellpadding="3">
    89     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    90     *    </colgroup>
    91     *
    92     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
    93     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    94     *    <!--                                                         -->
    95     *    <tr><td> {@link #clearInterrupt}   </td><td>   Y    </td><td>   Y    </td>
    96     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    97     *    <tr><td> {@link #create}           </td><td>   N    </td><td>   N    </td>
    98     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    99     *    <tr><td> {@link #disable}          </td><td>   Y    </td><td>   Y    </td>
   100     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   101     *    <tr><td> {@link #disableInterrupt} </td><td>   Y    </td><td>   Y    </td>
   102     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   103     *    <tr><td> {@link #enable}           </td><td>   Y    </td><td>   Y    </td>
   104     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   105     *    <tr><td> {@link #enableInterrupt}  </td><td>   Y    </td><td>   Y    </td>
   106     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   107     *    <tr><td> {@link #Params_init}      </td><td>   Y    </td><td>   Y    </td>
   108     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   109     *    <tr><td> {@link #restore}          </td><td>   Y    </td><td>   Y    </td>
   110     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   111     *    <tr><td> {@link #restoreInterrupt} </td><td>   Y    </td><td>   Y    </td>
   112     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   113     *    <tr><td> {@link #construct}        </td><td>   N    </td><td>   N    </td>
   114     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   115     *    <tr><td> {@link #delete}           </td><td>   N    </td><td>   N    </td>
   116     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   117     *    <tr><td> {@link #destruct}         </td><td>   N    </td><td>   N    </td>
   118     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   119     *    <tr><td> {@link #getHookContext}   </td><td>   Y    </td><td>   Y    </td>
   120     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   121     *    <tr><td> {@link #setFunc}          </td><td>   Y    </td><td>   Y    </td>
   122     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   123     *    <tr><td> {@link #setHookContext}   </td><td>   Y    </td><td>   Y    </td>
   124     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   125     *    <tr><td colspan="6"> Definitions: <br />
   126     *       <ul>
   127     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   128     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   129     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   130     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   131     *           <ul>
   132     *             <li> In your module startup after this module is started
   133     *    (e.g. Hwi_Module_startupDone() returns TRUE). </li>
   134     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   135     *             <li> During main().</li>
   136     *             <li> During BIOS.startupFxns.</li>
   137     *           </ul>
   138     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   139     *           <ul>
   140     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   141     *             <li> In your module startup before this module is started
   142     *    (e.g. Hwi_Module_startupDone() returns FALSE).</li>
   143     *           </ul>
   144     *       </ul>
   145     *    </td></tr>
   146     *
   147     *  </table>
   148     *  @p
   149     *
   150     *  @a(Runtime Hwi Creation)
   151     *
   152     *  Below is an example that configures an interrupt at runtime.
   153     *  Typically such code would be placed in main().
   154     *
   155     *  @p(code)
   156     *  #include <xdc/runtime/Error.h>
   157     *  #include <ti/sysbios/hal/Hwi.h>
   158     *
   159     *  Hwi_Handle myHwi;
   160     *
   161     *  Int main(Int argc, char* argv[])
   162     *  {
   163     *      Hwi_Params hwiParams;
   164     *      Error_Block eb;
   165     *
   166     *      Hwi_Params_init(&hwiParams);
   167     *      Error_init(&eb);
   168     *
   169     *      // set the argument you want passed to your ISR function
   170     *      hwiParams.arg = 1;
   171     *
   172     *      // set the event id of the peripheral assigned to this interrupt
   173     *      hwiParams.eventId = 10;
   174     *
   175     *      // don't allow this interrupt to nest itself
   176     *      hwiParams.maskSetting = Hwi_MaskingOption_SELF;
   177     *
   178     *      //
   179     *      // Configure interrupt 5 to invoke "myIsr".
   180     *      // Automatically enables interrupt 5 by default
   181     *      // set params.enableInt = FALSE if you want to control
   182     *      // when the interrupt is enabled using Hwi_enableInterrupt()
   183     *      //
   184     *
   185     *      myHwi = Hwi_create(5, myIsr, &hwiParams, &eb);
   186     *
   187     *      if (Error_check(&eb)) {
   188     *          // handle the error
   189     *      }
   190     *  }
   191     *
   192     *  Void myIsr(UArg arg)
   193     *  {
   194     *      // this runs when interrupt #5 goes off
   195     *  }
   196     *  @p
   197     *
   198     *  @a(Hook Functions)
   199     *
   200     *  Sets of hook functions can be specified for the Hwi module
   201     *  using the configuration tool.  Each set contains these hook
   202     *  functions:
   203     *  @p(blist)
   204     *  -Register:  A function called before any statically-created Hwis
   205     *      are initialized at runtime.  The register hook is called at boot time
   206     *      before main() and before interrupts are enabled.
   207     *  -Create:    A function that is called when a Hwi is created.
   208     *      This includes hwis that are created statically and those
   209     *      created dynamically using {@link #create Hwi_create}.
   210     *  -Begin:     A function that is called just prior to running a Hwi.
   211     *  -End:       A function that is called just after a Hwi finishes.
   212     *  -Delete:    A function that is called when a Hwi is deleted at
   213     *      run-time with {@link #delete Hwi_delete}.
   214     *  @p
   215     *
   216     *  Register Function
   217     *
   218     *  The Register function is provided to allow a hook set to store its
   219     *  hookset ID.  This id can be passed to
   220     *  {@link #setHookContext Hwi_setHookContext} and
   221     *  {@link #getHookContext Hwi_getHookContext} to set or get
   222     *  hookset-specific context.  The
   223     *  Register function must be specified if the hook implementation
   224     *  needs to use {@link #setHookContext  Hwi_setHookContext} or
   225     *  {@link #getHookContext  Hwi_getHookContext}.
   226     *  The registerFxn hook function is called during system initialization
   227     *  before interrupts have been enabled.
   228     *
   229     *  @p(code)
   230     *  Void myRegisterFxn(Int id);
   231     *  @p
   232     *
   233     *  Create and Delete Functions
   234     *
   235     *  The create and delete functions are called whenever a Hwi is created
   236     *  or deleted.  They are called with interrupts enabled (unless called
   237     *  at boot time or from main()).
   238     *
   239     *  @p(code)
   240     *  Void myCreateFxn(Hwi_Handle hwi, Error_Block *eb);
   241     *  @p
   242     *
   243     *  @p(code)
   244     *  Void myDeleteFxn(Hwi_Handle hwi);
   245     *  @p
   246     *
   247     *  Begin and End Functions
   248     *
   249     *  The beginFxn and endFxn function hooks are called with interrupts
   250     *  globally disabled, therefore any hook processing function will contribute
   251     *  to the overall system interrupt response latency.  In order to minimize
   252     *  this impact, carefully consider the processing time spent in an Hwi
   253     *  beginFxn or endFxn function hook.
   254     *
   255     *  @p(code)
   256     *  Void myBeginFxn(Hwi_Handle hwi);
   257     *  @p
   258     *
   259     *  @p(code)
   260     *  Void myEndFxn(Hwi_Handle hwi);
   261     *  @p
   262     *
   263     *  Hook functions can only be configured statically.
   264     *
   265     */
   266    
   267    @ModuleStartup      /* generate a call to startup function */
   268    
   269    module Hwi inherits ti.sysbios.interfaces.IHwi
   270    {
   271        /*!
   272         *  Error raised when a stack overflow (or corruption) is detected.
   273         *
   274         *  This error is raised by kernel's stack checking function.  This
   275         *  function checks the stacks before every task switch to make sure
   276         *  that reserved word at top of stack has not been modified.
   277         *
   278         *  The stack checking logic is enabled by the {@link #checkStackFlag}
   279         *  configuration parameter. If this flag is set to true, the kernel will
   280         *  validate the stacks.
   281         */
   282        config Error.Id E_stackOverflow  = {
   283            msg: "E_stackOverflow: ISR stack overflow."
   284        };
   285    
   286        /*!
   287         *  Initialize ISR stack with known value for stack checking at runtime
   288         *
   289         *  This is also useful for inspection of stack in debugger or core
   290         *  dump utilities for stack overflow and depth.
   291         *
   292         *  Default is true.
   293         *  (see {@link #checkStackFlag}).
   294         */
   295        metaonly config Bool initStackFlag = true;
   296    
   297        /*!
   298         *  Check for Hwi stack overrun during Idle loop.
   299         *
   300         *  If true, then an idle function is added to the idle loop
   301         *  that checks for a Hwi stack overrun condition and raises
   302         *  an Error if one is detected.
   303         *
   304         *  The check consists of testing the top of stack value against
   305         *  its initial value (see {@link #initStackFlag}). If it is no
   306         *  longer at this value, the assumption is that the ISR stack
   307         *  has been overrun. If the test fails, then the
   308         *  {@link #E_stackOverflow} error is raised.
   309         *
   310         *  Runtime stack depth computation is only performed if {@link #initStackFlag} is
   311         *  also true.
   312         *
   313         *  Default is true.
   314         *  (see {@link #initStackFlag}).
   315         *
   316         *  To enable or disable full stack checking, you should set both this
   317         *  flag and the {@link ti.sysbios.knl.Task#checkStackFlag}.
   318         */
   319        metaonly config Bool checkStackFlag = true;
   320    
   321        /*!
   322         *  ======== disable ========
   323         *  Globally disable interrupts.
   324         *
   325         *  Hwi_disable globally disables hardware interrupts and returns an
   326         *  opaque key indicating whether interrupts were globally enabled or
   327         *  disabled on entry to Hwi_disable().
   328         *  The actual value of the key is target/device specific and is meant
   329         *  to be passed to Hwi_restore().
   330         *
   331         *  Call Hwi_disable before a portion of a function that needs
   332         *  to run without interruption. When critical processing is complete, call
   333         *  Hwi_restore or Hwi_enable to reenable hardware interrupts.
   334         *
   335         *  Servicing of interrupts that occur while interrupts are disabled is
   336         *  postponed until interrupts are reenabled. However, if the same type
   337         *  of interrupt occurs several times while interrupts are disabled,
   338         *  the interrupt's function is executed only once when interrupts are
   339         *  reenabled.
   340         *
   341         *  A context switch can occur when calling Hwi_enable or Hwi_restore if
   342         *  an enabled interrupt occurred while interrupts are disabled.
   343         *
   344         *  Hwi_disable may be called from main(). However, since Hwi interrupts
   345         *  are already disabled in main(), such a call has no effect.
   346         *
   347         *  @a(constraints)
   348         *  If a Task switching API such as
   349         *  {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()},
   350         *  {@link ti.sysbios.knl.Semaphore#post Semaphore_post()},
   351         *  {@link ti.sysbios.knl.Task#sleep Task_sleep()}, or
   352         *  {@link ti.sysbios.knl.Task#yield Task_yield()}
   353         *  is invoked which results in a context switch while
   354         *  interrupts are disabled, an embedded call to
   355         *  {@link #enable Hwi_enable} occurs
   356         *  on the way to the new thread context which unconditionally re-enables
   357         *  interrupts. Interrupts will remain enabled until a subsequent
   358         *  {@link #disable Hwi_disable}
   359         *  invocation.
   360         *
   361         *  Swis always run with interrupts enabled.
   362         *  See {@link ti.sysbios.knl.Swi#post Swi_post()} for a discussion Swis and
   363         *  interrupts.
   364         *
   365         *  @b(returns)     opaque key for use by Hwi_restore()
   366         */
   367        @Macro
   368        override UInt disable();
   369    
   370        /*!
   371         *  ======== enable ========
   372         */
   373        @Macro
   374        override UInt enable();
   375    
   376        /*!
   377         *  ======== restore ========
   378         */
   379        @Macro
   380        override Void restore(UInt key);
   381    
   382        /*!
   383         *  ======== viewGetHandle ========
   384         *  @_nodoc
   385         *  Returns the corresponding hal Hwi handle for a delegate Hwi handle
   386         *
   387         *  @b(returns)     hal Hwi handle
   388         */
   389        metaonly Handle viewGetHandle(Ptr pi);
   390    
   391        /*!
   392         *  ======== viewGetLabel ========
   393         *  @_nodoc
   394         *  Returns the corresponding hal Hwi label for a delegate Hwi handle
   395         *
   396         *  @b(returns)     hal Hwi Label
   397         */
   398        metaonly String viewGetLabel(Ptr pi);
   399    
   400    instance:
   401    
   402        /*!
   403         *  ======== create ========
   404         *  Create a dispatched interrupt.
   405         *
   406         *  To cause a C function to run in response to a particular system
   407         *  interrupt, you create a Hwi object that encapsulates information
   408         *  regarding the interrupt required by the Hwi module.
   409         *
   410         *  The standard static and dynamic forms of the "create" function are
   411         *  supported by the ti.sysbios.hal.Hwi module.
   412         *  The following C code configures interrupt 5 with the "myIsr"
   413         *  C function.
   414         *
   415         *  @p(code)
   416         *  #include <ti/sysbios/hal/Hwi>
   417         *
   418         *  Hwi_create(5, myIsr, NULL, NULL);
   419         *  @p
   420         *
   421         *  The NULL, NULL arguments are used when the default instance
   422         *  parameters and generic error handling is satisfactory for creating
   423         *  a Hwi object.
   424         *
   425         *  A Hwi dispatcher table entry is created and filled with the
   426         *  function specified by the fxn parameter and the attributes
   427         *  specified by the params parameter.
   428         *
   429         *  If params is NULL, the Hwi's dispatcher properties are assigned a
   430         *  default set of values. Otherwise, the following properties
   431         *  are specified by a structure of type Hwi_Params.
   432         *
   433         *  @p(blist)
   434         *  - The arg element is a generic argument that is passed to the plugged
   435         *  function as its only parameter. The default value is 0.
   436         *  - The enableInt element determines whether the interrupt should be
   437         *  enabled in the IER by create.
   438         *  - The maskSetting element defines the dispatcherAutoNestingSupport
   439         *  behavior of the interrupt.
   440         *  @p
   441         *
   442         *  Hwi_create returns a pointer to the created Hwi object.
   443         *
   444         *  @param(intNum)  interrupt number
   445         *  @param(hwiFxn)  pointer to ISR function
   446         */
   447        override create(Int intNum, FuncPtr hwiFxn);
   448    
   449        /*!
   450         *  ======== getHookContext ========
   451         *  Get hook instance's context for a Hwi.
   452         *
   453         *  The Handle passed to this API must be the handle passed
   454         *  to any of the Hook functions, not the one returned by
   455         *  {@link #create Hwi_create}.
   456         *
   457         *  @b(returns)     hook instance's context for hwi
   458         */
   459        override Ptr getHookContext(Int id);
   460    
   461        /*!
   462         *  ======== setHookContext ========
   463         *  Set hook instance's context for a Hwi.
   464         *
   465         *  The Handle passed to this API must be the handle passed
   466         *  to any of the Hook functions, not the one returned by
   467         *  {@link #create Hwi_create}.
   468         *
   469         *  @param(id)            hook instance's ID
   470         *  @param(hookContext)   value to write to context
   471         */
   472        override Void setHookContext(Int id, Ptr hookContext);
   473    
   474    internal:   /* not for client use */
   475    
   476        /* keep track of the number of hooks defined */
   477        metaonly config UInt numHooks = 0;
   478    
   479        /*! target/device-specific Hwi implementation. */
   480        proxy HwiProxy inherits ti.sysbios.interfaces.IHwi;
   481    
   482        struct Instance_State {
   483            HwiProxy.Handle pi;
   484        };
   485    }