1    /*
     2     * Copyright (c) 2015-2018, 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         *  Event Combiner registers template
   213         */
   214        struct Registers {
   215            UInt EVTFLAG[4];
   216            UInt hole1[4];
   217            UInt EVTSET[4];
   218            UInt hole2[4];
   219            UInt EVTCLR[4];
   220            UInt hole3[12];
   221            UInt EVTMASK[4];
   222            UInt hole4[4];
   223            UInt MEVTFLAG[4];
   224            UInt hole5[4];
   225            UInt EXPMASK[4];
   226            UInt hole6[4];
   227            UInt MEXPMASK[4];
   228        };
   229    
   230        /*!
   231         *  Event Combiner registers base address
   232         */
   233        config Registers *EVTRegs;
   234    
   235        /*!
   236         *  Assert raised when an invalid event id number is specified
   237         */
   238        config Assert.Id A_invalidEventId = {
   239            msg: "A_invalidEventId: Invalid event Id specified"
   240        };
   241    
   242        /*!
   243         *  Error raised when an unplug Event is executed.
   244         */
   245        config Error.Id E_unpluggedEvent = {
   246            msg: "E_unpluggedEvent: Event# %d is unplugged"
   247        };
   248    
   249        // -------- Module Parameters --------
   250    
   251        /*!
   252         *  ======== EVTMASK ========
   253         *  Holds the initialization values for the C64+ EVTMASK registers (0-3).
   254         *
   255         *  It is assigned values based on the 'unmask' member of the 'events'
   256         *  configuration array.  It can also be assigned manually in the program
   257         *  configuration script.
   258         */
   259        config Bits32 EVTMASK[4];
   260    
   261        /*!
   262         *  ======== events ========
   263         *  For holding configuration values for all C64+ events.
   264         *
   265         *  Array elements can be configured in the program
   266         *  configuration script.
   267         */
   268        metaonly config EventObj events[NUM_EVENTS];
   269    
   270        /*!
   271         *  ======== eventGroupHwiNum ========
   272         *  Configures the mapping of a C64+ combined event group to an interrupt.
   273         *
   274         *  There is one element per combined event group (0-3).
   275         */
   276        metaonly config Int eventGroupHwiNum[4];
   277    
   278        /*!
   279         *  ======== dispatchEventGroup ========
   280         *  Configuration method for assigning the eventGroupHwiNum array.
   281         *
   282         *  It accomplishes the same thing as directly setting
   283         *  eventGroupHwiNum[0-3].
   284         *
   285         *  @param(evt)     event id
   286         *  @param(hwiVec)  the Hwi vector to use
   287         */
   288        metaonly Void dispatchEventGroup(UInt evt, UInt hwiVec);
   289    
   290        /*!
   291         *  ======== disableEvent ========
   292         *  Disables 'evt' from contributing to its combined event group.
   293         *
   294         *  It accomplishes this by setting the corresponding
   295         *  bit in the C64+ EVTMASK array to 1 (to mask it).
   296         *
   297         *  @param(evt)     event id
   298         */
   299        Void disableEvent(UInt evt);
   300    
   301        /*!
   302         *  ======== enableEvent ========
   303         *  Enables 'evt' to contribute to its combined event group.
   304         *
   305         *  It accomplishes this by setting the corresponding
   306         *  bit in the C64+ EVTMASK array to 0 (to unmask it).
   307         *
   308         *  @param(evt)     event id
   309         */
   310        Void enableEvent(UInt evt);
   311    
   312        /*!
   313         *  ======== dispatch ========
   314         *  The Event Combiner dispatcher.
   315         *
   316         *  It is mostly used internally, but can be used directly by the user.
   317         *
   318         *  @param(evt)     event id
   319         */
   320        Void dispatch(UInt evt);
   321    
   322        /*!
   323         *  ======== dispatchPlug ========
   324         *  Used to configure a dispatcher entry for 'evt'.
   325         *
   326         *  This function plugs the dispatch table with the specified fxn and attrs.
   327         *  It does not map the corresponding combined event group to a Hwi
   328         *  interrupt - such an action needs to be performed either using the
   329         *  event combiner configuration or using the Hwi module.
   330         *
   331         *  @param(evt)     event id
   332         *  @param(fxn)     function to call
   333         *  @param(arg)     argument to the function
   334         *  @param(unmask)  whether to enable the event or not
   335         */
   336        Void dispatchPlug(UInt evt, FuncPtr fxn, UArg arg, Bool unmask);
   337    
   338        /*!
   339         *  @_nodoc
   340         *  ======== unused ========
   341         *  unused exists simply to map a call in the Ecm dispatcher calling
   342         *  context to the System_exit calling context (casts UArg to Int).
   343         *
   344         *  @param(arg)     argument to function
   345         */
   346        Void unused(UArg arg);
   347    
   348    internal:
   349    
   350        struct DispatchTabElem {
   351            FuncPtr fxn;
   352            UArg arg;
   353        };
   354    
   355        struct Module_State {
   356            DispatchTabElem dispatchTab[NUM_EVENTS];
   357        };
   358    
   359    }
   360