1    /* 
     2     * Copyright (c) 2012, 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     *  ======== Mailbox.xdc ========
    34     *
    35     */
    36    package ti.sysbios.knl;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    import xdc.runtime.IHeap;
    41    
    42    /*!
    43     *  ======== Mailbox ========
    44     *  Mailbox Manager
    45     *
    46     *  The Mailbox module makes available a set of functions that manipulate
    47     *  mailbox objects accessed through handles of type Mailbox_Handle.
    48     *
    49     *  {@link #pend()} is used to wait for a message from a mailbox. 
    50     *  The timeout parameter to Mailbox_pend allows the task to wait until a 
    51     *  timeout specified in terms of system clock ticks. 
    52     *  A timeout value of {@link ti.sysbios.BIOS#WAIT_FOREVER BIOS_WAIT_FOREVER}
    53     *  causes the task to wait indefinitely  for a message. 
    54     *  A timeout value of {@link ti.sysbios.BIOS#NO_WAIT BIOS_NO_WAIT} 
    55     *  causes Mailbox_pend to return immediately. 
    56     *  Mailbox_pend's return value indicates whether the mailbox was signaled 
    57     *  successfully.
    58     *
    59     *  When a Mailbox has been configured with a {@link #readerEvent} Event
    60     *  object and a task has returned from {@link Event#pend()} with the 
    61     *  corresponding {@link #readerEventId}, then BIOS_NO_WAIT
    62     *  should be passed to Mailbox_pend() to retrieve the message.
    63     *
    64     *  NOTE: Since only a single reader can pend on a {@link #readerEvent} 
    65     *  Event object,
    66     *  a Mailbox configured with a {@link #readerEvent} Event object does not
    67     *  support multiple readers. 
    68     *
    69     *  {@link #post()} is used to send a message to a mailbox. 
    70     *  The timeout parameter to Mailbox_post specifies the amount of time the 
    71     *  calling task waits if the mailbox is full. 
    72     *
    73     *  When a Mailbox has been configured with a {@link #writerEvent} Event
    74     *  object and a task has returned from {@link Event#pend()} with the 
    75     *  corresponding {@link #writerEventId}, then BIOS_NO_WAIT
    76     *  should be passed to Mailbox_post() knowing that the message
    77     *  will be successfully posted.
    78     *
    79     *  NOTE: Since only a single writer can pend on a {@link #writerEvent} 
    80     *  Event object,
    81     *  a Mailbox configured with a {@link #writerEvent} Event object does not
    82     *  support multiple writers.
    83     *
    84     *  @p(html)
    85     *  <h3> Calling Context </h3>
    86     *  <table border="1" cellpadding="3">
    87     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    88     *    </colgroup>
    89     *
    90     *    <tr><th> Function        </th><th>  Hwi   </th><th>  Swi   </th>
    91     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    92     *    <!--                                                        -->
    93     *    <tr><td> {@link #Params_init}       </td><td>   Y    </td><td>   Y   </td>
    94     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    95     *    <tr><td> {@link #construct}         </td><td>   N    </td><td>   N   </td>
    96     *    <td>   Y    </td><td>   Y    </td><td>   N    </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 #delete}            </td><td>   N    </td><td>   N   </td>
   100     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   101     *    <tr><td> {@link #destruct}          </td><td>   N    </td><td>   N   </td>
   102     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   103     *    <tr><td> {@link #getNumFreeMsgs}    </td><td>   Y    </td><td>   Y   </td>
   104     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   105     *    <tr><td> {@link #getNumPendingMsgs} </td><td>   Y    </td><td>   Y   </td>
   106     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   107     *    <tr><td> {@link #pend}              </td><td>   N*   </td><td>   N*  </td>
   108     *    <td>   Y    </td><td>   N*   </td><td>   N    </td></tr>
   109     *    <tr><td> {@link #post}              </td><td>   N*   </td><td>   N*  </td>
   110     *    <td>   Y    </td><td>   N*   </td><td>   N    </td></tr>
   111     *    <tr><td colspan="6"> Definitions: (N* means OK to call iff the timeout
   112     *           parameter is set to '0'.)<br />
   113     *       <ul>
   114     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   115     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   116     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   117     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   118     *           <ul>
   119     *             <li> In your module startup after this module is started 
   120     *    (e.g. Mailbox_Module_startupDone() returns TRUE). </li>
   121     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   122     *             <li> During main().</li>
   123     *             <li> During BIOS.startupFxns.</li>
   124     *           </ul>
   125     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   126     *           <ul>
   127     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   128     *             <li> In your module startup before this module is started 
   129     *    (e.g. Mailbox_Module_startupDone() returns FALSE).</li>
   130     *           </ul>
   131     *       </ul>
   132     *    </td></tr>
   133     *
   134     *  </table>
   135     *  @p 
   136     */
   137    
   138    @ModuleStartup     /* Instances require more initialization at startup */
   139    @InstanceFinalize
   140    @InstanceInitError
   141    
   142    module Mailbox 
   143    {
   144        /*!
   145         *  ======== BasicView ========
   146         *  @_nodoc
   147         */
   148        metaonly struct BasicView {
   149            String label;
   150            SizeT  msgSize;
   151            UInt   numMsgs;
   152        }
   153        
   154        /*!
   155         *  ======== DetailedView ========
   156         *  @_nodoc
   157         */
   158        metaonly struct DetailedView {
   159            String label;
   160            SizeT  msgSize;
   161            UInt   numMsgs;
   162            UInt   curNumMsgs;
   163            UInt   freeSlots;
   164            String pendQueue[];
   165            String postQueue[];
   166        }
   167    
   168        /*!
   169         *  ======== rovViewInfo ========
   170         *  @_nodoc
   171         */
   172        @Facet
   173        metaonly config ViewInfo.Instance rovViewInfo = 
   174            ViewInfo.create({
   175                viewMap: [
   176                [
   177                    'Basic',
   178                    {
   179                        type: ViewInfo.INSTANCE,
   180                        viewInitFxn: 'viewInitBasic',
   181                        structName: 'BasicView'
   182                    }
   183                ],
   184                [
   185                    'Detailed',
   186                    {
   187                        type: ViewInfo.INSTANCE,
   188                        viewInitFxn: 'viewInitDetailed',
   189                        structName: 'DetailedView'
   190                    }
   191                ]
   192                ]
   193            });
   194    
   195        /*!
   196         *  ======== MbxElem ========
   197         *  The header used to save each Mailbox message
   198         *
   199         *  Mailbox messages are stored in a queue that requires a header in
   200         *  front of each message.  This structure defines that header and its
   201         *  size must be factored into the total data size requirements for a
   202         *  mailbox instance.
   203         */
   204        struct MbxElem {
   205            Queue.Elem elem;
   206        };
   207    
   208        /*!
   209         *  ======== A_invalidBufSize ========
   210         *  Assert raised when the bufSize parameter is too small
   211         *
   212         *  This assert is raised when bufSize is too small to handle
   213         *  (size of messages + sizeof(MbxElem)) * number of messages.
   214         *  See {@link ti.sysbios.knl.MailBox#buf} for more information on the buf
   215         *  parameter.
   216         */
   217        config xdc.runtime.Assert.Id A_invalidBufSize =
   218            {msg: "Mailbox_create's bufSize parameter is invalid (too small)"};
   219    
   220    instance:
   221    
   222        /*!
   223         *  ======== create ========
   224         *  Create a mailbox
   225         *
   226         *  Mailbox_create creates a mailbox object which is initialized to contain
   227         *  numMsgs messages of size msgSize.
   228         *
   229         *  @param(msgSize)         size of message
   230         *  @param(numMsgs)         length of mailbox
   231         */
   232        @DirectCall
   233        create(SizeT msgSize, UInt numMsgs);
   234    
   235        /*!
   236         *  ======== heap ========
   237         *  The IHeap instance used for dynamic creates
   238         *
   239         *  This heap is used only for dynamic instances is ignored  for static 
   240         *  instances.
   241         */
   242        config xdc.runtime.IHeap.Handle heap = null;
   243    
   244        /*!
   245         *  ======== sectionName ========
   246         *  Section name for the buffer managed by the instance
   247         *
   248         *  The default section is the 'dataSection' in the platform.
   249         */
   250        metaonly config String sectionName = null;
   251        
   252        /*!
   253         *  ======== readerEvent ========
   254         *  Mailbox not empty event if using Events. Default is null
   255         *
   256         *  Posted whenever a mailbox is written to.
   257         *  Reader task pends on this event. 
   258         *  Note that {@link ti.sysbios.knl.Semaphore#supportsEvents 
   259         *  Semaphore.supportsEvents} has to be 
   260         *  set to true for Mailbox to support Events.
   261         */
   262        config Event.Handle readerEvent = null;
   263    
   264        /*!
   265         *  ======== readerEventId ========
   266         *  Mailbox not empty event Id if using Events. Default is 1
   267         *
   268         *  Posted whenever a mailbox is written to.
   269         *  Reader task pends on this eventId.
   270         *  Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
   271         *  Semaphore.supportsEvents} has to be 
   272         *  set to true for Mailbox to support Events.
   273         */
   274        config UInt readerEventId = 1;
   275    
   276        /*!
   277         *  ======== writerEvent ========
   278         *  Mailbox not full event if using Events. Default is null
   279         *
   280         *  Posted whenever a mailbox is read from.
   281         *  Writer task pends on this event.
   282         *  Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
   283         *  Semaphore.supportsEvents} has to be 
   284         *  set to true for Mailbox to support Events.
   285         */
   286        config Event.Handle writerEvent = null;
   287    
   288        /*!
   289         *  ======== writerEventId ========
   290         *  Mailbox not full event Id if using Events
   291         *
   292         *  Posted whenever a mailbox is read from.
   293         *  Writer task pends on this eventId.
   294         *  Note that {@link ti.sysbios.knl.Semaphore#supportsEvents 
   295         *  Semaphore.supportsEvents} has to be 
   296         *  set to true for Mailbox to support Events.
   297         */
   298        config UInt writerEventId = 1;
   299    
   300        /*!
   301         *  ======== buf ========
   302         *  The address of the buffer used for creating messages
   303         *
   304         *  This property is only used for dynamically created Mailboxes.
   305         *  If set to 'null', the messages will be allocated from the heap
   306         *  during runtime, otherwise the user may set this to a buffer of their
   307         *  creation to be used for allocating the messages.
   308         *  
   309         *  The module will split the buf into
   310         *  {@link ti.sysbios.knl.Mailbox#numMsgs} number of blocks (one block per
   311         *  Mailbox message).
   312         *
   313         *  Please note that if the buffer is user supplied, then it is the user's
   314         *  responsibility to ensure that it is aligned properly and is also large
   315         *  enough to contain {@link ti.sysbios.knl.Mailbox#numMsgs} number of
   316         *  blocks.  The size of each block is defined as follows:
   317         *  @p(code)
   318         *      sizeof(Mailbox_MbxElem) + msgSize
   319         *  @p
   320         *
   321         *  Since the buffer must be a aligned properly, it may be necessary to
   322         *  'round up' the total size of the buffer to the next multiple of the
   323         *  alignment for odd sized messages.
   324         *
   325         *  @see #MbxElem
   326         */
   327        config Ptr buf = null;
   328    
   329        /*!
   330         *  ======== bufSize ========
   331         *  The size of the buffer that 'buf' references
   332         *
   333         *  This property is only used for dynamically created Mailboxes.
   334         */
   335        config UInt bufSize = 0;
   336    
   337        /*!
   338         *  ======== getMsgSize ========
   339         *  Get the message size
   340         */
   341        @DirectCall
   342        SizeT getMsgSize();
   343    
   344        /*!
   345         *  ======== getNumFreeMsgs ========
   346         *  Get the number messages available for use
   347         */
   348        @DirectCall
   349        Int getNumFreeMsgs();
   350    
   351        /*!
   352         *  ======== getNumPendingMsgs ========
   353         *  Get the number of messages that are ready to be read
   354         */
   355        @DirectCall
   356        Int getNumPendingMsgs();
   357    
   358        /*!
   359         *  ======== pend ========
   360         *  Wait for a message from mailbox
   361         *
   362         *  If the mailbox is not empty, Mailbox_pend copies the first message into
   363         *  msg and returns TRUE. Otherwise, Mailbox_pend suspends the execution of
   364         *  the current task until Mailbox_post is called or the timeout expires. 
   365         *
   366         *  A timeout value of 
   367         *  {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes 
   368         *  the task to wait indefinitely  for a message. 
   369         *
   370         *  A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   371         *  causes Mailbox_pend to return immediately. 
   372         *
   373         *  The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   374         *  should be passed to Mailbox_pend() to retrieve a message after
   375         *  Event_pend() is called outside of Mailbox_pend to wait on an incoming
   376         *  message.
   377         *
   378         *  Mailbox_pend's return value indicates whether the mailbox was signaled
   379         *  successfully.
   380         *
   381         *  @param(msg)     message pointer
   382         *  @param(timeout) maximum duration in system clock ticks
   383         *  @b(returns)     TRUE if successful, FALSE if timeout
   384         */
   385        @DirectCall
   386        Bool pend(Ptr msg, UInt timeout);
   387    
   388        /*!
   389         *  ======== post ========
   390         *  Post a message to mailbox
   391         *
   392         *  Mailbox_post checks to see if there are any free message slots before
   393         *  copying msg into the mailbox. Mailbox_post readies the first task 
   394         *  (if any) waiting on the mailbox. If the mailbox is full and a timeout 
   395         *  is specified  the task remains suspended until Mailbox_pend is called 
   396         *  or the timeout expires.
   397         *
   398         *  A timeout value of 
   399         *  {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes 
   400         *  the task to wait indefinitely for a free slot.
   401         *
   402         *  A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   403         *  causes  Mailbox_post to return immediately.
   404         *
   405         *  The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   406         *  should be passed to Mailbox_post() to post a message after
   407         *  Event_pend() is called outside of Mailbox_post to wait on an 
   408         *  available message buffer.
   409         *
   410         *  Mailbox_post's return value indicates whether the msg was 
   411         *  copied or not.
   412         *
   413         *  @param(msg)     message pointer
   414         *  @param(timeout) maximum duration in system clock ticks
   415         *  @b(returns)     TRUE if successful, FALSE if timeout
   416         */
   417        @DirectCall
   418        Bool post(Ptr msg, UInt timeout);
   419    
   420    internal:
   421    
   422        Void cleanQue(Queue.Handle obj);
   423        
   424        /*
   425         *  ======== postInit ========
   426         *  finish initializing static and dynamic instances
   427         */
   428        Int postInit(Object *obj, SizeT blockSize);
   429    
   430        /* -------- Internal Structures -------- */
   431        struct Instance_State {
   432            xdc.runtime.IHeap.Handle    heap;
   433            SizeT                       msgSize;
   434            UInt                        numMsgs;
   435            Ptr                         buf;
   436            Queue.Object                dataQue;
   437            Queue.Object                freeQue;
   438            Semaphore.Object            dataSem;
   439            Semaphore.Object            freeSem;
   440            UInt                        numFreeMsgs;
   441            Char                        allocBuf[];
   442        };
   443    }
   444    /*
   445     *  @(#) ti.sysbios.knl; 2, 0, 0, 0,542; 2-24-2012 11:41:02; /db/vtree/library/trees/avala/avala-q28x/src/ xlibrary
   446    
   447     */
   448