1    /* 
     2     * Copyright (c) 2011, 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>   Y*   </td><td>   Y*  </td>
   108     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   109     *    <tr><td> {@link #post}              </td><td>   Y    </td><td>   Y   </td>
   110     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   111     *    <tr><td colspan="6"> Definitions: <br />
   112     *       <ul>
   113     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   114     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   115     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   116     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   117     *           <ul>
   118     *             <li> In your module startup after this module is started 
   119     *    (e.g. Mailbox_Module_startupDone() returns TRUE). </li>
   120     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   121     *             <li> During main().</li>
   122     *             <li> During BIOS.startupFxns.</li>
   123     *           </ul>
   124     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   125     *           <ul>
   126     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   127     *             <li> In your module startup before this module is started 
   128     *    (e.g. Mailbox_Module_startupDone() returns FALSE).</li>
   129     *           </ul>
   130     *       <li> <b>*</b>: Yes but only for a timeout value of zero. </li>
   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        metaonly struct BasicView {
   145            String label;
   146            SizeT  msgSize;
   147            UInt   numMsgs;
   148        }
   149        
   150        metaonly struct DetailedView {
   151            String label;
   152            SizeT  msgSize;
   153            UInt   numMsgs;
   154            UInt   curNumMsgs;
   155            UInt   freeSlots;
   156            String pendQueue[];
   157            String postQueue[];
   158        }
   159    
   160        @Facet
   161        metaonly config ViewInfo.Instance rovViewInfo = 
   162            ViewInfo.create({
   163                viewMap: [
   164                [
   165                    'Basic',
   166                    {
   167                        type: ViewInfo.INSTANCE,
   168                        viewInitFxn: 'viewInitBasic',
   169                        structName: 'BasicView'
   170                    }
   171                ],
   172                [
   173                    'Detailed',
   174                    {
   175                        type: ViewInfo.INSTANCE,
   176                        viewInitFxn: 'viewInitDetailed',
   177                        structName: 'DetailedView'
   178                    }
   179                ]
   180                ]
   181            });
   182    
   183        struct MbxElem {
   184            Queue.Elem      elem;
   185        };
   186    
   187        /*!
   188         *  Assert raised when the bufSize parameter is too small
   189         *  to handle (size of messages + sizeof(MbxElem)) * number of messages. See
   190         *  {@link ti.sysbios.knl.MailBox#buf} for more information on the buf
   191         *  parameter.
   192         */
   193        config xdc.runtime.Assert.Id A_invalidBufSize =
   194            {msg: "Mailbox_create's bufSize parameter is invalid (too small)"};
   195    
   196    instance:
   197    
   198        /*!
   199         *  ======== create ========
   200         *  Create a mailbox
   201         *
   202         *  Mailbox_create creates a mailbox object which is initialized to contain
   203         *  numMsgs messages of size msgSize.
   204         *
   205         *  @param(msgSize)         size of message
   206         *  @param(numMsgs)         length of mailbox
   207         */
   208        @DirectCall
   209        create(SizeT msgSize, UInt numMsgs);
   210    
   211        /*!
   212         *  ======== heap ========
   213         * The IHeap instance used for dynamic creates. 
   214         *
   215         *  This heap is used only for dynamic instances is ignored  for static 
   216         *  instances.
   217         */
   218        config xdc.runtime.IHeap.Handle heap = null;
   219    
   220        /*!
   221         *  ======== sectionName ========
   222         *  Section name for the buffer managed by the instance.
   223         *
   224         *  The default section is the 'dataSection' in the platform.
   225         */
   226        metaonly config String sectionName = null;
   227        
   228        /*!
   229         *  ======== readerEvent ========
   230         *  Mailbox not empty event if using Events. Default is null.
   231         *
   232         *  Posted whenever a mailbox is written to.
   233         *  Reader task pends on this event. 
   234         *  Note that {@link ti.sysbios.knl.Semaphore#supportsEvents 
   235         *  Semaphore.supportsEvents} has to be 
   236         *  set to true for Mailbox to support Events.
   237         */
   238        config Event.Handle readerEvent = null;
   239    
   240        /*!
   241         *  ======== readerEventId ========
   242         *  Mailbox not empty event Id if using Events. Default is 1.
   243         *
   244         *  Posted whenever a mailbox is written to.
   245         *  Reader task pends on this eventId.
   246         *  Note that {@link ti.sysbios.knl.Semaphore#supportsEvents
   247         *  Semaphore.supportsEvents} has to be 
   248         *  set to true for Mailbox to support Events.
   249         */
   250        config UInt readerEventId = 1;
   251    
   252        /*!
   253         *  ======== writerEvent ========
   254         *  Mailbox not full event if using Events. Default is null.
   255         *
   256         *  Posted whenever a mailbox is read from.
   257         *  Writer 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 writerEvent = null;
   263    
   264        /*!
   265         *  ======== writerEventId ========
   266         *  Mailbox not full event Id if using Events. Default is 1.
   267         *
   268         *  Posted whenever a mailbox is read from.
   269         *  Writer 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 writerEventId = 1;
   275    
   276        /*!
   277         *  ======== buf ========
   278         *  The address of the buffer used for creating messages.
   279         *
   280         *  This property is only used for dynamically created Mailboxes.
   281         *  If set to 'null', the messages will be allocated from the heap
   282         *  during runtime, otherwise the user may set this to a buffer of their
   283         *  creation to be used for allocating the messages.
   284         *  
   285         *  The module will split the buf into
   286         *  {@link ti.sysbios.knl.Mailbox#numMsgs} number of blocks (one block per
   287         *  Mailbox message).
   288         *
   289         *  Please note that if the buffer is user supplied, then it is the user's
   290         *  responsibility to ensure that it is aligned properly and is also large
   291         *  enough to contain {@link ti.sysbios.knl.Mailbox#numMsgs} number of
   292         *  blocks.  The size of each block is defined as follows:
   293         *  @p(code)
   294         *  sizeof(Mailbox_MbxElem) + msgSize
   295         *  @p
   296         *
   297         *  Since the buffer must be a aligned properly, it may be necessary to
   298         *  'round up' the total size of the buffer to the next multiple of the
   299         *  alignment for odd sized messages.
   300         *
   301         */
   302        config Ptr buf = null;
   303    
   304        /*!
   305         *  ======== bufSize ========
   306         *  The size of the buffer that 'buf' points to.
   307         *
   308         *  This property is only used for dynamically created Mailboxes.
   309         */
   310        config UInt bufSize = 0;
   311    
   312        /*!
   313         *  ======== getNumFreeMsgs ========
   314         *  Returns the number messages available for use for a Mailbox instance.
   315         */
   316        @DirectCall
   317        Int getNumFreeMsgs();
   318    
   319        /*!
   320         *  ======== getNumPendingMsgs ========
   321         *  Returns the number of messages that are ready to be read for a Mailbox
   322         *  instance.
   323         */
   324        @DirectCall
   325        Int getNumPendingMsgs();
   326    
   327        /*!
   328         *  ======== pend ========
   329         *  Wait for a message from mailbox
   330         *
   331         *  If the mailbox is not empty, Mailbox_pend copies the first message into
   332         *  msg and returns TRUE. Otherwise, Mailbox_pend suspends the execution of
   333         *  the current task until Mailbox_post is called or the timeout expires. 
   334         *
   335         *  A timeout value of 
   336         *  {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes 
   337         *  the task to wait indefinitely  for a message. 
   338         *
   339         *  A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   340         *  causes Mailbox_pend to return immediately. 
   341         *
   342         *  The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   343         *  should be passed to Mailbox_pend() to retrieve a message after
   344         *  Event_pend() is called outside of Mailbox_pend to wait on an incoming
   345         *  message.
   346         *
   347         *  Mailbox_pend's return value indicates whether the mailbox was signaled
   348         *  successfully.
   349         *
   350         *  @param(msg)     message pointer
   351         *  @param(timeout) maximum duration in system clock ticks
   352         *  @b(returns)     TRUE if successful, FALSE if timeout
   353         */
   354        @DirectCall
   355        Bool pend(Ptr msg, UInt timeout);
   356    
   357        /*!
   358         *  ======== post ========
   359         *  Post a message to mailbox
   360         *
   361         *  Mailbox_post checks to see if there are any free message slots before
   362         *  copying msg into the mailbox. Mailbox_post readies the first task 
   363         *  (if any) waiting on the mailbox. If the mailbox is full and a timeout 
   364         *  is specified  the task remains suspended until Mailbox_pend is called 
   365         *  or the timeout expires.
   366         *
   367         *  A timeout value of 
   368         *  {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes 
   369         *  the task to wait indefinitely for a free slot.
   370         *
   371         *  A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   372         *  causes  Mailbox_post to return immediately.
   373         *
   374         *  The timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   375         *  should be passed to Mailbox_post() to post a message after
   376         *  Event_pend() is called outside of Mailbox_post to wait on an 
   377         *  available message buffer.
   378         *
   379         *  Mailbox_post's return value indicates whether the msg was 
   380         *  copied or not.
   381         *
   382         *  @param(msg)     message pointer
   383         *  @param(timeout) maximum duration in system clock ticks
   384         *  @b(returns)     TRUE if successful, FALSE if timeout
   385         */
   386        @DirectCall
   387        Bool post(Ptr msg, UInt timeout);
   388    
   389    internal:
   390    
   391        Void cleanQue(Queue.Handle obj);
   392        
   393        /*
   394         *  ======== postInit ========
   395         *  finish initializing static and dynamic instances
   396         */
   397        Int postInit(Object *obj, SizeT blockSize);
   398    
   399        /* -------- Internal Structures -------- */
   400        struct Instance_State {
   401            xdc.runtime.IHeap.Handle    heap;
   402            SizeT                       msgSize;
   403            UInt                        numMsgs;
   404            Ptr                         buf;
   405            Queue.Object                dataQue;
   406            Queue.Object                freeQue;
   407            Semaphore.Object            dataSem;
   408            Semaphore.Object            freeSem;
   409            UInt                        numFreeMsgs;
   410            Char                        allocBuf[];
   411        };
   412    }
   413    /*
   414     *  @(#) ti.sysbios.knl; 2, 0, 0, 0,451; 2-2-2011 15:07:13; /db/vtree/library/trees/avala/avala-o27x/src/ xlibrary
   415    
   416     */
   417