1    /*
     2     * Copyright (c) 2015, 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     *  ======== EventCombiner.xdc ========
    34     *
    35     *
    36     */
    37    
    38    package ti.sysbios.family.c64p;
    39    
    40    import xdc.runtime.Assert;
    41    import xdc.runtime.Error;
    42    
    43    /*!
    44     *  ======== EventCombiner ========
    45     *  Event Combiner Manager module
    46     *
    47     *  The event combiner allows the user to combine up to 32 system events
    48     *  into a single combined event.  The events 0, 1, 2, and 3 are the events
    49     *  associated with the event combiner.  Using the EventCombiner module
    50     *  along with the Hwi module, allows the user to route a combined event
    51     *  to any of the 12 maskable CPU interrupts available on GEM.  The
    52     *  EventCombiner supports up to 128 system events.  Users can specify
    53     *  a function and an argument for each system event and can choose to
    54     *  enable whichever system events they want.
    55     *
    56     *  An example of using the EventCombiner during runtime to plug the ISR
    57     *  handlers for events 65 and 66 on the same Hwi:
    58     *
    59     *  @p(code)
    60     *
    61     *  Hwi_Params params;
    62     *  Error_Block eb;
    63     *
    64     *  // Initialize the error block
    65     *  Error_init(&eb);
    66     *
    67     *  // Plug the function and argument for event 65 then enable it
    68     *  EventCombiner_dispatchPlug(65, &myEvent65Fxn, 0, TRUE);
    69     *
    70     *  // Plug the function and argument for event 66 then enable it
    71     *  EventCombiner_dispatchPlug(66, &myEvent66Fxn, 1, TRUE);
    72     *
    73     *  // Initialize the Hwi parameters
    74     *  Hwi_Params_init(&params);
    75     *
    76     *  // The eventId must be set to the combined event for event 65 or 66.
    77     *  // The combined event is event 2 for both.  If the combined events are
    78     *  // different, then another Hwi must be used for the other combined event
    79     *  params.eventId = 65 / 32;
    80     *
    81     *  // The arg must be set to params.eventId.
    82     *  params.arg = params.eventId;
    83     *
    84     *  // Enable the interrupt.
    85     *  params.enableInt = TRUE;
    86     *
    87     *  // Events 65 and 66 are on the same combined event so create a single Hwi.
    88     *  // Create the Hwi on interrupt 7 then specify 'EventCombiner_dispatch'
    89     *  // as the function.
    90     *  Hwi_create(7, &EventCombiner_dispatch, &params, &eb);
    91     *
    92     *  @p
    93     *
    94     *  An example of using the EventCombiner during static creation to plug the
    95     *  ISR handlers for events 31 and 63 on different Hwis:
    96     *
    97     *  @p(code)
    98     *
    99     *  // Use EventCombiner module
   100     *  var EventCombiner = xdc.useModule('ti.sysbios.family.c64p.EventCombiner');
   101     *
   102     *  // Plug function and argument for event 31 then enable it.
   103     *  EventCombiner.events[31].fxn = '&myEvent31Fxn';
   104     *  EventCombiner.events[31].arg = 31;
   105     *  EventCombiner.events[31].unmask = true;
   106     *
   107     *  // Plug function and argument for event 63 then enable it.
   108     *  EventCombiner.events[63].fxn = '&myEvent63Fxn';
   109     *  EventCombiner.events[63].arg = 63;
   110     *  EventCombiner.events[63].unmask = true;
   111     *
   112     *  // Map event 0 (combine events 0-31) to vector 8
   113     *  EventCombiner.eventGroupHwiNum[0] = 8;
   114     *
   115     *  // Map event 1 (combine events 32-63) to vector 9
   116     *  EventCombiner.eventGroupHwiNum[1] = 9;
   117     *
   118     *  @p
   119     *
   120     *  @p(html)
   121     *  <h3> Calling Context </h3>
   122     *  <table border="1" cellpadding="3">
   123     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
   124     *
   125     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   126     *    <!--                                                                                                                 -->
   127     *    <tr><td> {@link #disableEvent}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   128     *    <tr><td> {@link #dispatch}        </td><td>   Y    </td><td>   N    </td><td>   N    </td><td>   N    </td><td>   N    </td></tr>
   129     *    <tr><td> {@link #dispatchPlug}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   130     *    <tr><td> {@link #enableEvent}     </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   131     *    <tr><td colspan="6"> Definitions: <br />
   132     *       <ul>
   133     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   134     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   135     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   136     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   137     *           <ul>
   138     *             <li> In your module startup after this module is started (e.g. EventCombiner_Module_startupDone() returns TRUE). </li>
   139     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   140     *             <li> During main().</li>
   141     *             <li> During BIOS.startupFxns.</li>
   142     *           </ul>
   143     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   144     *           <ul>
   145     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   146     *             <li> In your module startup before this module is started (e.g. EventCombiner_Module_startupDone() returns FALSE).</li>
   147     *           </ul>
   148     *       </ul>
   149     *    </td></tr>
   150     *
   151     *  </table>
   152     *  @p
   153     */
   154    
   155    @ModuleStartup
   156    @DirectCall
   157    module EventCombiner
   158    {
   159        /*!
   160         *  ======== EventView ========
   161         *  @_nodoc
   162        */
   163        metaonly struct EventView {
   164            UInt         eventId;
   165            String       fxn;
   166            String       arg;
   167        };
   168    
   169        /*!
   170         *  ======== rovViewInfo ========
   171         *  @_nodoc
   172         */
   173        @Facet
   174        metaonly config xdc.rov.ViewInfo.Instance rovViewInfo =
   175            xdc.rov.ViewInfo.create({
   176                viewMap: [
   177                    ['Events',
   178                        {
   179                            type: xdc.rov.ViewInfo.MODULE_DATA,
   180                            viewInitFxn: 'viewInitEvents',
   181                            structName: 'EventView'
   182                        }
   183                    ]
   184                ]
   185            });
   186    
   187        // -------- Module Constants --------
   188    
   189        /*! C64+ supports 128 events. */
   190        const Int NUM_EVENTS = 128;
   191    
   192        // -------- Module Types --------
   193    
   194        /*! Event Combiner dispatcher function type definition. */
   195        typedef Void (*FuncPtr)(UArg);
   196    
   197        /*!
   198         *  Event Configuration Object.
   199         *
   200         *  unmask - Boolean value that specifies if an event should be
   201         *      unmasked in the C64+ EVTMASK registers.
   202         *  fxn - function to call when this event occurs.
   203         *  arg - arg to fxn.
   204         */
   205        metaonly struct EventObj {
   206            Bool unmask;
   207            FuncPtr fxn;
   208            UArg arg;
   209        };
   210    
   211        /*!
   212         *  Assert raised when an invalid event id number is specified
   213         */
   214        config Assert.Id A_invalidEventId = {
   215            msg: "A_invalidEventId: Invalid event Id specified"
   216        };
   217    
   218        /*!
   219         *  Error raised when an unplug Event is executed.
   220         */
   221        config Error.Id E_unpluggedEvent = {
   222            msg: "E_unpluggedEvent: Event# %d is unplugged"
   223        };
   224    
   225        // -------- Module Parameters --------
   226    
   227        /*!
   228         *  ======== EVTMASK ========
   229         *  Holds the initialization values for the C64+ EVTMASK registers (0-3).
   230         *
   231         *  It is assigned values based on the 'unmask' member of the 'events'
   232         *  configuration array.  It can also be assigned manually in the program
   233         *  configuration script.
   234         */
   235        config Bits32 EVTMASK[4];
   236    
   237        /*!
   238         *  ======== events ========
   239         *  For holding configuration values for all C64+ events.
   240         *
   241         *  Array elements can be configured in the program
   242         *  configuration script.
   243         */
   244        metaonly config EventObj events[NUM_EVENTS];
   245    
   246        /*!
   247         *  ======== eventGroupHwiNum ========
   248         *  Configures the mapping of a C64+ combined event group to an interrupt.
   249         *
   250         *  There is one element per combined event group (0-3).
   251         */
   252        metaonly config Int eventGroupHwiNum[4];
   253    
   254        /*!
   255         *  ======== dispatchEventGroup ========
   256         *  Configuration method for assigning the eventGroupHwiNum array.
   257         *
   258         *  It accomplishes the same thing as directly setting
   259         *  eventGroupHwiNum[0-3].
   260         *
   261         *  @param(evt)     event id
   262         *  @param(hwiVec)  the Hwi vector to use
   263         */
   264        metaonly Void dispatchEventGroup(UInt evt, UInt hwiVec);
   265    
   266        /*!
   267         *  ======== disableEvent ========
   268         *  Disables 'evt' from contributing to its combined event group.
   269         *
   270         *  It accomplishes this by setting the corresponding
   271         *  bit in the C64+ EVTMASK array to 1 (to mask it).
   272         *
   273         *  @param(evt)     event id
   274         */
   275        Void disableEvent(UInt evt);
   276    
   277        /*!
   278         *  ======== enableEvent ========
   279         *  Enables 'evt' to contribute to its combined event group.
   280         *
   281         *  It accomplishes this by setting the corresponding
   282         *  bit in the C64+ EVTMASK array to 0 (to unmask it).
   283         *
   284         *  @param(evt)     event id
   285         */
   286        Void enableEvent(UInt evt);
   287    
   288        /*!
   289         *  ======== dispatch ========
   290         *  The Event Combiner dispatcher.
   291         *
   292         *  It is mostly used internally, but can be used directly by the user.
   293         *
   294         *  @param(evt)     event id
   295         */
   296        Void dispatch(UInt evt);
   297    
   298        /*!
   299         *  ======== dispatchPlug ========
   300         *  Used to configure a dispatcher entry for 'evt'.
   301         *
   302         *  This function plugs the dispatch table with the specified fxn and attrs.
   303         *  It does not map the corresponding combined event group to a Hwi
   304         *  interrupt - such an action needs to be performed either using the
   305         *  event combiner configuration or using the Hwi module.
   306         *
   307         *  @param(evt)     event id
   308         *  @param(fxn)     function to call
   309         *  @param(arg)     argument to the function
   310         *  @param(unmask)  whether to enable the event or not
   311         */
   312        Void dispatchPlug(UInt evt, FuncPtr fxn, UArg arg, Bool unmask);
   313    
   314        /*!
   315         *  @_nodoc
   316         *  ======== unused ========
   317         *  unused exists simply to map a call in the Ecm dispatcher calling
   318         *  context to the System_exit calling context (casts UArg to Int).
   319         *
   320         *  @param(arg)     argument to function
   321         */
   322        Void unused(UArg arg);
   323    
   324    internal:
   325    
   326        struct DispatchTabElem {
   327            FuncPtr fxn;
   328            UArg arg;
   329        };
   330    
   331        struct Module_State {
   332            DispatchTabElem dispatchTab[NUM_EVENTS];
   333        };
   334    
   335    }
   336