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