1    /*
     2     * Copyright (c) 2013-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     *  ======== Event.xdc ========
    34     *
    35     *1                     aren't synced to Semaphore state
    36     *! 04-Mar-2008 agd     Stripped down to support binary only and
    37     *!                     single task.
    38     *! 23-Jan-2008 agd     01/22/08 review changes
    39     *! 13-Dec-2007 agd     Added Event_Id_NONE
    40     *! 10-Dec-2007 connell updated call context table
    41     *! 23-May-2007 agd     Addressed SDSCM00017698
    42     *! 11-May-2007 agd     Addressed SDSCM00016595
    43     *! 16-Apr-2007 cmcc    Added calling context table
    44     *! 01-Feb-2007 rt      Added Log.Events
    45     *! 16-Jan-2007 agd     Moved to ipc package
    46     *! 12-Dec-2006 agd     integrate 12/5/06 code review comments
    47     *! 27-Sep-2006 agd     reworked pre-defined event masks
    48     *! 21-Apr-2006 agd     reworked to support counting Events
    49     *! 02-Mar-2006 agd     redefined default event mask constants
    50     *! 14-Feb-2006 agd     reworked to conform to
    51     *!                     current design requirements
    52     *! 31-Jan-2006 nitya/agd created
    53     */
    54    
    55    package ti.sysbios.knl;
    56    
    57    import xdc.rov.ViewInfo;
    58    
    59    import xdc.runtime.Assert;
    60    import xdc.runtime.Diags;
    61    import xdc.runtime.Log;
    62    
    63    import ti.sysbios.knl.Queue;
    64    import ti.sysbios.knl.Clock;
    65    import ti.sysbios.knl.Task;
    66    
    67    /*!
    68     *  ======== Event ========
    69     *  Event Manager.
    70     *
    71     *  SYS/BIOS events are a means of communication between Tasks and other
    72     *  threads such as Hwis, Swis, and other Tasks, or between Tasks and
    73     *  other SYS/BIOS objects. Other SYS/BIOS objects include semaphores,
    74     *  mailboxes,
    75     *  message queues, etc. Only tasks can wait for events; whereas tasks,
    76     *  Hwis, Swis, or SYS/BIOS objects can post them.
    77     *
    78     *  In order for a task to be notified of an event from a SYS/BIOS object an
    79     *  event object must first be registered with that object. Separate APIs
    80     *  are provided (in their respective modules) for each of the SYS/BIOS object
    81     *  types that support this feature.
    82     *
    83     *  Events are synchronous in nature, meaning that a receiving task will
    84     *  block or pend while waiting for the events to occur. When the desired
    85     *  events are received, the pending task continues its execution, as it
    86     *  would after a call to Semaphore_pend(), for example.
    87     *
    88     *  Tasks can also wait on events that are not linked to other SYS/BIOS objects.
    89     *  These events are explicitly posted from other threads such as tasks,
    90     *  Swis, or Hwis. A task does not register to receive these events; the
    91     *  sending thread simply posts its event(s) to the event object the task
    92     *  is pending on. This scenario is similar to having an ISR post a
    93     *  semaphore.
    94     *
    95     *  A task can wait on events from multiple resources and/or threads; thus,
    96     *  it can be waiting for a semaphore to be posted and for a message to
    97     *  arrive in a message queue or an ISR thread to signal that an event has
    98     *  occurred.
    99     *
   100     *  Events are binary. Events become available (posted) on each Event_post()
   101     *  of the eventId and become non-available (consumed) on each qualifying
   102     *  Event_pend() mask.
   103     *
   104     *  Unlike Semaphores, only a single task can pend on an Event object.
   105     *
   106     *  {@link #pend} is used to wait for events. The andMask & orMask
   107     *  determine which
   108     *  event(s) must occur before returning from {@link #pend}. The timeout
   109     *  parameter
   110     *  allows the task to wait until a timeout, wait indefinitely, or not wait
   111     *  at all. A return value of zero indicates that a timeout has occurred. A
   112     *  non-zero return value is the set of events that were active at the time
   113     *  the task was unblocked.
   114     *
   115     *  The andMask defines a set of events that must ALL occur to allow
   116     *  {@link #pend} to return.
   117     *
   118     *  The orMask defines a set of events that will cause {@link #pend} to
   119     *  return if ANY of them occur.
   120     *
   121     *  All active events present in the orMask are consumed (ie removed from
   122     *  the event object) upon return from {@link #pend}. Only when all events
   123     *  present in the andMask are active are they consumed on return from
   124     *  {@link #pend}.
   125     *
   126     *  {@link #pend} returns immediately if the andMask OR orMask conditions
   127     *  are true upon entry.
   128     *
   129     *  {@link #post} is used to signal events. If a task is waiting for the event
   130     *  and all of the event conditions are met, {@link #post} unblocks the task.
   131     *  If no task is waiting, {@link #post} simply registers the event with the
   132     *  event object and returns.
   133     *
   134     *  The maximum number of eventIds supported is target specific and depends
   135     *  on the number of bits in a UInt data type.
   136     *  For 6x and ARM devices the maximum number of eventIds is therefore 32.
   137     *  For 28x and MSP430 devices, the maximum number of eventIds is 16.
   138     *
   139     *  @p(html)
   140     *  <h3> Calling Context </h3>
   141     *  <table border="1" cellpadding="3">
   142     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
   143     *    </colgroup>
   144     *
   145     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
   146     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   147     *    <!--                                                                  -->
   148     *    <tr><td> {@link #create}          </td><td>   N    </td><td>   N    </td>
   149     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   150     *    <tr><td> {@link #Params_init}     </td><td>   Y    </td><td>   Y    </td>
   151     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   152     *    <tr><td> {@link #construct}       </td><td>   N    </td><td>   N    </td>
   153     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   154     *    <tr><td> {@link #delete}          </td><td>   N    </td><td>   N    </td>
   155     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   156     *    <tr><td> {@link #destruct}        </td><td>   N    </td><td>   N    </td>
   157     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   158     *    <tr><td> {@link #getPostedEvents} </td><td>   Y    </td><td>   Y    </td>
   159     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   160     *    <tr><td> {@link #pend}            </td><td>   N*   </td><td>   N*   </td>
   161     *    <td>   Y    </td><td>   N*   </td><td>   N    </td></tr>
   162     *    <tr><td> {@link #post}            </td><td>   Y    </td><td>   Y    </td>
   163     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   164     *    <tr><td colspan="6"> Definitions: (N* means OK to call iff the timeout
   165     *           parameter is set to '0'.)<br />
   166     *       <ul>
   167     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   168     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   169     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   170     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   171     *           <ul>
   172     *             <li> In your module startup after this module is started
   173     *    (e.g. Event_Module_startupDone() returns TRUE). </li>
   174     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   175     *             <li> During main().</li>
   176     *             <li> During BIOS.startupFxns.</li>
   177     *           </ul>
   178     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   179     *           <ul>
   180     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   181     *             <li> In your module startup before this module is started
   182     *    (e.g. Event_Module_startupDone() returns FALSE).</li>
   183     *           </ul>
   184     *       </ul>
   185     *    </td></tr>
   186     *
   187     *  </table>
   188     *  @p
   189     */
   190    
   191    @DirectCall
   192    /*
   193     *  To remove Event.Ids not defined for targets with 16 bit Ints
   194     */
   195    @CustomHeader
   196    @InstanceInitStatic     /* Construct/Destruct CAN becalled at runtime */
   197    
   198    module Event
   199    {
   200        /*!
   201         *  Pre-defined Event Ids
   202         *
   203         *  Event_Ids are provided to simplify the specification of
   204         *  andMasks and orMasks arguments to {@link #pend Event_pend()}.
   205         *
   206         *  Since each Event_Id is a bitmask composed of only a single bit,
   207         *  a group of Event_Ids within an andMask or orMask can be indicated
   208         *  by simply adding them together. For instance, to indicate that a task
   209         *  is to be awakened only when both Event_Id_00 and Event_Id_01 have
   210         *  been posted, the andMask for Event_pend() would be constructed
   211         *  as below:
   212         *
   213         *  @p(code)
   214         *  Event_pend(event, Event_Id_00+EventId_01, Event_Id_NONE,
   215         *             BIOS_WAIT_FOREVER);
   216         *  @p
   217         *
   218         *  As shown above, Event_Id_NONE is to be used as an empty (NULL)
   219         *  andMask or orMask.
   220         *
   221         *  @a(Note)
   222         *  For targets where a UInt is 32 bits in length,
   223         *  Event_Id_00 thru Event_Id_31 can be used.
   224         *
   225         *  For targets where a UInt is 16 bits in length,
   226         *  Event_Id_00 thru Event_Id_15 can be used.
   227         */
   228    
   229        const UInt Id_00 = 0x1;
   230        const UInt Id_01 = 0x2;         /*! @see #Id_00 Pre-defined Event IDs. */
   231        const UInt Id_02 = 0x4;         /*! @see #Id_00 Pre-defined Event IDs. */
   232        const UInt Id_03 = 0x8;         /*! @see #Id_00 Pre-defined Event IDs. */
   233        const UInt Id_04 = 0x10;        /*! @see #Id_00 Pre-defined Event IDs. */
   234        const UInt Id_05 = 0x20;        /*! @see #Id_00 Pre-defined Event IDs. */
   235        const UInt Id_06 = 0x40;        /*! @see #Id_00 Pre-defined Event IDs. */
   236        const UInt Id_07 = 0x80;        /*! @see #Id_00 Pre-defined Event IDs. */
   237        const UInt Id_08 = 0x100;       /*! @see #Id_00 Pre-defined Event IDs. */
   238        const UInt Id_09 = 0x200;       /*! @see #Id_00 Pre-defined Event IDs. */
   239        const UInt Id_10 = 0x400;       /*! @see #Id_00 Pre-defined Event IDs. */
   240        const UInt Id_11 = 0x800;       /*! @see #Id_00 Pre-defined Event IDs. */
   241        const UInt Id_12 = 0x1000;      /*! @see #Id_00 Pre-defined Event IDs. */
   242        const UInt Id_13 = 0x2000;      /*! @see #Id_00 Pre-defined Event IDs. */
   243        const UInt Id_14 = 0x4000;      /*! @see #Id_00 Pre-defined Event IDs. */
   244        const UInt Id_15 = 0x8000;      /*! @see #Id_00 Pre-defined Event IDs. */
   245        const UInt Id_16 = 0x10000;     /*! @see #Id_00 Pre-defined Event IDs. */
   246        const UInt Id_17 = 0x20000;     /*! @see #Id_00 Pre-defined Event IDs. */
   247        const UInt Id_18 = 0x40000;     /*! @see #Id_00 Pre-defined Event IDs. */
   248        const UInt Id_19 = 0x80000;     /*! @see #Id_00 Pre-defined Event IDs. */
   249        const UInt Id_20 = 0x100000;    /*! @see #Id_00 Pre-defined Event IDs. */
   250        const UInt Id_21 = 0x200000;    /*! @see #Id_00 Pre-defined Event IDs. */
   251        const UInt Id_22 = 0x400000;    /*! @see #Id_00 Pre-defined Event IDs. */
   252        const UInt Id_23 = 0x800000;    /*! @see #Id_00 Pre-defined Event IDs. */
   253        const UInt Id_24 = 0x1000000;   /*! @see #Id_00 Pre-defined Event IDs. */
   254        const UInt Id_25 = 0x2000000;   /*! @see #Id_00 Pre-defined Event IDs. */
   255        const UInt Id_26 = 0x4000000;   /*! @see #Id_00 Pre-defined Event IDs. */
   256        const UInt Id_27 = 0x8000000;   /*! @see #Id_00 Pre-defined Event IDs. */
   257        const UInt Id_28 = 0x10000000;  /*! @see #Id_00 Pre-defined Event IDs. */
   258        const UInt Id_29 = 0x20000000;  /*! @see #Id_00 Pre-defined Event IDs. */
   259        const UInt Id_30 = 0x40000000;  /*! @see #Id_00 Pre-defined Event IDs. */
   260        const UInt Id_31 = 0x80000000;  /*! @see #Id_00 Pre-defined Event IDs. */
   261    
   262        const UInt Id_NONE = 0;         /*! @see #Id_00 Pre-defined Event IDs. */
   263        /*!
   264         *  ======== BasicView ========
   265         *  @_nodoc
   266         */
   267        metaonly struct BasicView {
   268            String          label;
   269            String          postedEvents;
   270            String          pendedTask;
   271            String          andMask;
   272            String          orMask;
   273            String          timeout;
   274        };
   275    
   276        /*!
   277         *  ======== rovViewInfo ========
   278         *  @_nodoc
   279         */
   280        @Facet
   281        metaonly config ViewInfo.Instance rovViewInfo =
   282            ViewInfo.create({
   283                viewMap: [
   284                    ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic',
   285                    structName: 'BasicView'}]
   286                ]
   287            });
   288    
   289        // -------- Module Parameters --------
   290    
   291        // Logs
   292    
   293        /*! Logged on calls to Event_post() */
   294        config Log.Event LM_post = {
   295            mask: Diags.USER1 | Diags.USER2,
   296            msg: "LM_post: event: 0x%x, currEvents: 0x%x, eventId: 0x%x"
   297        };
   298    
   299        /*! Logged on calls to Event_pend() */
   300        config Log.Event LM_pend = {
   301            mask: Diags.USER1 | Diags.USER2,
   302            msg: "LM_pend: event: 0x%x, currEvents: 0x%x, andMask: 0x%x, orMask: 0x%x, timeout: %d"
   303        };
   304    
   305        // Asserts
   306    
   307        /*!
   308         *  Asserted when {@link #pend} is called with andMask and orMask == 0
   309         */
   310        config Assert.Id A_nullEventMasks = {
   311            msg: "A_nullEventMasks: orMask and andMask are null."
   312        };
   313    
   314        /*!
   315         *  Asserted when {@link #post} is called with eventId == 0
   316         */
   317        config Assert.Id A_nullEventId = {
   318            msg: "A_nullEventId: posted eventId is null."
   319        };
   320    
   321        /*!
   322         *  Asserted when {@link #pend} is called by multiple tasks on the same
   323         *  Event object.
   324         */
   325        config Assert.Id A_eventInUse = {
   326            msg: "A_eventInUse: Event object already in use."
   327        };
   328    
   329        /*!
   330         *  Asserted when {@link #pend} is called with non-zero timeout from other
   331         *  than a Task context.
   332         */
   333        config Assert.Id A_badContext = {
   334            msg: "A_badContext: bad calling context. Must be called from a Task."
   335        };
   336    
   337        /*!
   338         *  ======== A_pendTaskDisabled ========
   339         *  Asserted in Event_pend()
   340         *
   341         *  Assert raised if Event_pend() is called with the Task or
   342         *  Swi scheduler disabled.
   343         */
   344        config Assert.Id A_pendTaskDisabled = {
   345            msg: "A_pendTaskDisabled: Cannot call Event_pend() while the Task or Swi scheduler is disabled."
   346        };
   347    
   348    instance:
   349    
   350        /*!
   351         *  ======== create ========
   352         *  Create an Event object.
   353         *
   354         *  This function creates a new Event object.
   355         */
   356        create();
   357    
   358        /*!
   359         *  ======== pend ========
   360         *  Wait for events defined in 'and' OR 'or' masks.
   361         *
   362         *  pend() is used to wait for events. The andMask and orMask determine
   363         *  which
   364         *  event(s) must occur before returning from pend(). The timeout parameter
   365         *  allows the task to wait until a timeout, wait indefinitely, or not wait
   366         *  at all. A return value of zero indicates that a timeout has occurred. A
   367         *  non-zero return value is the set of events that were active at the time
   368         *  the task was unblocked.
   369         *
   370         *  The andMask defines a set of events that must
   371         *  ALL occur to allow pend() to return.
   372         *
   373         *  The orMask defines a set of events
   374         *  that will cause pend() to return if ANY of them occur.
   375         *
   376         *  All active events
   377         *  present in the orMask are consumed (i.e. removed from the event object)
   378         *  upon return from pend(). Only when all events present in the andMask
   379         *  are active are they consumed on return from pend().
   380         *
   381         *  The pend conditions are satisfied when either ALL of the events
   382         *  in the andMask occur or ANY of the events in the orMask occur.
   383         *
   384         *  A timeout value of
   385         *  {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes
   386         *  the task to wait indefinitely for matching events to be posted.
   387         *
   388         *  A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT}
   389         *  causes Event_pend to return immediately.
   390         *
   391         *  @param(andMask)         return from pend() when ALL of these
   392         *                          events have occurred
   393         *  @param(orMask)          return from pend() when ANY of these
   394         *                          events have occurred
   395         *  @param(timeout)         return from pend() after this many system
   396         *                          time units
   397         *
   398         *  @b(returns)             All consumed events or zero if timeout.
   399         */
   400        UInt pend(UInt andMask, UInt orMask, UInt32 timeout);
   401    
   402        /*!
   403         *  ======== post ========
   404         *  Post event(s) to an event object.
   405         *
   406         *  Event_post() is used to signal events. If a task is waiting for the
   407         *  event and the event conditions are met, post() unblocks the
   408         *  task. If no tasks are waiting, post() simply registers the event with
   409         *  the event object and returns.
   410         *
   411         *  @param(eventMask)         mask of eventIds to post (must be non-zero)
   412         */
   413        Void post(UInt eventMask);
   414    
   415        /*!
   416         *  ======== getPostedEvents ========
   417         *  Returns the set of events that have not been consumed by a task
   418         *  (ie those events that have not fully satisfied any pend() conditions).
   419         *  No events are consumed!
   420         *
   421         *  @b(returns)             All un-consumed events posted to the event.
   422         */
   423        UInt getPostedEvents();
   424    
   425        /*!
   426         *  @_nodoc
   427         *  ======== sync ========
   428         *  synchronize an eventId to the value given
   429         *  must call with interrupts disabled
   430         *
   431         *  @param(eventId)         eventId to sync
   432         *  @param(count)           count
   433         */
   434        Void sync(UInt eventId, UInt count);
   435    
   436        /*!
   437         *  @_nodoc
   438         *  ======== syncMeta ========
   439         *  synchronize an eventId to the value given (static version)
   440         *
   441         *  @param(eventId)         eventId to sync
   442         *  @param(count)           count
   443         */
   444        metaonly Void syncMeta(UInt eventId, UInt count);
   445    
   446    internal:
   447    
   448        /*!
   449         *  ======== pendTimeout ========
   450         *  This function is the clock event handler for pend
   451         */
   452        Void pendTimeout(UArg arg);
   453    
   454        /*
   455         *  ======== checkEvents ========
   456         *  Checks postedEvents for matching event conditions.
   457         *  Returns matchingEvents if a match and consumes matched events,
   458         *  else returns 0 and consumes nothing.
   459         *  Called with ints disabled
   460         */
   461        UInt checkEvents (Object *event, UInt andMask, UInt orMask);
   462    
   463        /*
   464         *  Static instance array used by Semaphore module
   465         *  to enable Grace to display a list of Event instances
   466         *  to choose from to configure a Semaphore's 'event' config
   467         *  parameter.
   468         */
   469        metaonly config Any eventInstances[];
   470    
   471        /* pendQ Element PendStates */
   472        enum PendState {
   473            PendState_TIMEOUT = 0,          /* Clock timeout */
   474            PendState_POSTED = 1,           /* posted by post */
   475            PendState_CLOCK_WAIT = 2,       /* in Clock queue */
   476            PendState_WAIT_FOREVER = 3      /* not in Clock queue */
   477        };
   478    
   479        /* Event pendQ Element */
   480        struct PendElem {
   481            Task.PendElem           tpElem;
   482            PendState               pendState;
   483            UInt                    matchingEvents;
   484            UInt                    andMask;
   485            UInt                    orMask;
   486        };
   487    
   488        struct Instance_State {
   489            volatile UInt           postedEvents;   /* Current unconsumed events */
   490            Queue.Object            pendQ;          /* queue of PendElems  */
   491                                                    /* for compatibility with */
   492                                                    /* Semaphore */
   493        };
   494    }