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     *  ======== Task.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.knl;
    38    
    39    import xdc.rov.ViewInfo;
    40    
    41    import xdc.runtime.Error;
    42    import xdc.runtime.Assert;
    43    import xdc.runtime.Diags;
    44    import xdc.runtime.Log;
    45    import xdc.runtime.IHeap;
    46    
    47    import ti.sysbios.knl.Queue;
    48    
    49    /*!
    50     *  ======== Task ========
    51     *  Task Manager.
    52     *
    53     *  The Task module makes available a set of functions that manipulate task
    54     *  objects accessed through pointers of type {@link #Handle}. Tasks represent
    55     *  independent threads of control that conceptually execute functions in
    56     *  parallel within a single C program; in reality, concurrency is achieved
    57     *  by switching the processor from one task to another.
    58     *
    59     *  When you create a task, it is provided with its own run-time stack,
    60     *  used for storing local variables as well as for further nesting of
    61     *  function calls. Each stack must be large enough to handle normal
    62     *  subroutine calls and one task preemption context.
    63     *  A task preemption context is the context that gets saved when one task
    64     *  preempts another as a result of an interrupt thread readying
    65     *  a higher-priority task.
    66     *
    67     *  All tasks executing within a single program share a common set of
    68     *  global variables, accessed according to the standard rules of scope
    69     *  defined for C functions.
    70     *
    71     *  Each task is in one of five modes of execution at any point in time:
    72     *  running, ready, blocked, terminated, or inactive. By design, there is 
    73     *  always one
    74     *  (and only one) task currently running, even if it is only the idle task
    75     *  managed internally by Task. The current task can be suspended from
    76     *  execution by calling certain Task functions, as well as functions
    77     *  provided by other modules like the Semaphore or Event Modules. 
    78     *  The current task
    79     *  can also terminate its own execution. In either case, the processor
    80     *  is switched to the highest priority task that is ready to run.
    81     *
    82     *  You can assign numeric priorities to tasks. Tasks are
    83     *  readied for execution in strict priority order; tasks of the same
    84     *  priority are scheduled on a first-come, first-served basis. 
    85     *  The priority of the currently running task is never lower
    86     *  than the priority of any ready task. Conversely, the running task
    87     *  is preempted and re-scheduled for execution whenever there exists
    88     *  some ready task of higher priority.
    89     *
    90     *  @a(Task Deletion)
    91     *
    92     *  Any dynamically created task that is not in the Task_Mode_RUNNING 
    93     *  state (ie not the currently running task) can be deleted using the 
    94     *  {@link #delete} API. 
    95     *
    96     *  Task_delete() removes the task from all internal queues and calls
    97     *  Memory_free() to free the task object and stack.
    98     *  Memory_free() must acquire a lock to the memory before proceeding. 
    99     *  If another task already holds a lock to the memory, then there is 
   100     *  a context switch.
   101     *  
   102     *  You can specify application-wide Delete hook functions that
   103     *  run whenever a task is deleted. See the discussion of Hook Functions
   104     *  below for details.
   105     *  
   106     *  Note: Unless the mode of the deleted task is Task_Mode_TERMINATED,
   107     *  Task_delete should be called with care. For example, if the task has
   108     *  obtained exclusive access to a resource, deleting the task makes the
   109     *  resource unavailable.
   110     *  
   111     *  Task_delete() constraints:
   112    
   113     *  @p(blist)
   114     *  -The task cannot be the currently executing task (Task_self()).
   115     *  -Task_delete cannot be called from a Swi or Hwi.
   116     *  -No check is performed to prevent Task_delete from being used on a
   117     *  statically-created object. If a program attempts to delete a task object
   118     *  that was created statically, the Memory_free() call will result in an
   119     *  assertion failure in its corresponding Heap manager, causing the 
   120     *  application to exit.
   121     *  @p
   122     *  
   123     *  @a(Stack Alignment)
   124     *  
   125     *  Stack size parameters for both static and dynamic tasks are rounded
   126     *  up to the nearest integer multiple of a target-specific alignment
   127     *  requirement.
   128     *  
   129     *  In the case of Task's which are created with a user-provided stack,
   130     *  both the base address and the stackSize are aligned. The base address
   131     *  is increased to the nearest aligned address. The stack size is decreased
   132     *  accordingly and then rounded down to the nearest integer multiple of the 
   133     *  target-specific required alignment.
   134     *
   135     *  @p(html)
   136     *  <a name="hookfunc"></a>
   137     *  @p
   138     *
   139     *  @a(Hook Functions)
   140     *
   141     *  Sets of hook functions can be specified for the Task module.  Each
   142     *  set can contains these hook functions:
   143     *  @p(blist)
   144     *  -Register: A function called before any statically created tasks
   145     *      are initialized at runtime.  The register hook is called at boot time
   146     *      before main() and before interrupts are enabled.
   147     *  -Create: A function that is called when a task is created. 
   148     *      This includes tasks that are created statically and those
   149     *      created dynamically using {@link #create} or {@link #construct}.
   150     *      The create hook is called outside of a Task_disable/enable block and
   151     *   before the task has been added to the ready list.
   152     *  -Ready: A function that is called when a task becomes ready to run.
   153     *   The ready hook is called from within a Task_disable/enable block with
   154     *   interrupts enabled.
   155     *  -Switch: A function that is called just before a task switch
   156     *      occurs. The 'prev' and 'next' task handles are passed to the Switch
   157     *      hook. 'prev' is set to NULL for the initial task switch that occurs
   158     *      during SYS/BIOS startup.  The Switch hook is called from within a
   159     *      Task_disable/enable block with interrupts enabled.
   160     *  -Exit:      A function that is called when a task exits using
   161     *      {@link #exit}.  The exit hook is passed the handle of the exiting
   162     *      task.  The exit hook is called outside of a Task_disable/enable block
   163     *      and before the task has been removed from the kernel lists.
   164     *  -Delete: A function that is called when any task is deleted at
   165     *      run-time with {@link #delete}.  The delete hook is called outside
   166     *      of a Task_disable/enable block.
   167     *  @p
   168     *  Hook functions can only be configured statically.
   169     *
   170     *  If you define more than one set of hook functions, all the functions
   171     *  of a particular type will be run when a Swi triggers that type of 
   172     *  hook.
   173     *
   174     *  @p(html)
   175     *  <B>Register Function</B>
   176     *  @p
   177     *
   178     *  The Register function is provided to allow a hook set to store its
   179     *  hookset ID.  This id can be passed to {@link #setHookContext} and 
   180     *  {@link #getHookContext} to set or get hookset-specific context.  The
   181     *  Register function must be specified if the hook implementation
   182     *  needs to use {@link #setHookContext} or {@link #getHookContext}.
   183     *  The registerFxn hook function is called during system initialization
   184     *  before interrupts have been enabled. 
   185     *
   186     *  @p(code)
   187     *  Void myRegisterFxn(Int id);
   188     *  @p
   189     *
   190     *  @p(html)
   191     *  <B>Create and Delete Functions</B>
   192     *  @p
   193     *
   194     *  The create and delete functions are called whenever a Task is created
   195     *  or deleted.  They are called with interrupts enabled (unless called 
   196     *  at boot time or from main()).
   197     *
   198     *  @p(code)
   199     *  Void myCreateFxn(Task_Handle task, Error_Block *eb);
   200     *  @p
   201     *
   202     *  @p(code)
   203     *  Void myDeleteFxn(Task_Handle task);
   204     *  @p
   205     *
   206     *  @p(html)
   207     *  <B>Switch Function</B>
   208     *  @p
   209     *
   210     *  If a switch function is specified, it is invoked just before the new task
   211     *  is switched to.  The switch function is called with interrupts enabled.
   212     *
   213     *  This function can be used to save/restore additional task context (for
   214     *  example, external hardware registers), to check for task stack overflow,
   215     *  to monitor the time used by each task, etc.
   216     *
   217     *  @p(code)
   218     *  Void mySwitchFxn(Task_Handle prev, Task_Handle next);
   219     *  @p
   220     *
   221     *  To properly handle the switch to the first task your switchFxn should
   222     *  check for "prev == NULL" before using prev:
   223     *
   224     *  @p(code)
   225     *  Void mySwitchFxn(Task_Handle prev, Task_Handle next)
   226     *  {
   227     *      if (prev != NULL) {
   228     *          ...
   229     *      }
   230     *      ...
   231     *  }
   232     *  @p
   233     *
   234     *  @p(html)
   235     *  <B>Ready Function</B>
   236     *  @p
   237     *
   238     *  If a ready function is specified, it is invoked whenever a task is made
   239     *  ready to run.   The ready function is called  with interrupts enabled
   240     *  (unless called at boot time or from main()).
   241     *
   242     *  @p(code)
   243     *  Void myReadyFxn(Task_Handle task);
   244     *  @p
   245     * 
   246     *  @p(html)
   247     *  <B>Exit Function</B>
   248     *  @p
   249     *
   250     *  If an exit function is specified, it is invoked when a task exits (via
   251     *  call to Task_exit() or when a task returns from its' main function).
   252     *  The Exit Function is called with interrupts enabled. 
   253     *
   254     *  @p(code)
   255     *  Void myExitFxn(Task_Handle task);
   256     *  @p
   257     *
   258     *  @p(html)
   259     *  <h3> Calling Context </h3>
   260     *  <table border="1" cellpadding="3">
   261     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
   262     *  </colgroup>
   263     *    
   264     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
   265     *  <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   266     *    <!--                                                       -->
   267     *    <tr><td> {@link #create}          </td><td>   N    </td><td>   N    </td>
   268     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   269     *    <tr><td> {@link #disable}         </td><td>   Y    </td><td>   Y    </td>
   270     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   271     *    <tr><td> {@link #exit}            </td><td>   N    </td><td>   N    </td>
   272     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   273     *    <tr><td> {@link #getIdleTask}     </td><td>   Y    </td><td>   Y    </td>
   274     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   275     *    <tr><td> {@link #Params_init}     </td><td>   Y    </td><td>   Y    </td>
   276     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   277     *    <tr><td> {@link #restore}         </td><td>   Y    </td><td>   Y    </td>
   278     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   279     *    <tr><td> {@link #self}            </td><td>   Y    </td><td>   Y    </td>
   280     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   281     *    <tr><td> {@link #sleep}           </td><td>   N    </td><td>   N    </td>
   282     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   283     *    <tr><td> {@link #yield}           </td><td>   Y    </td><td>   Y    </td>
   284     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   285     *    <tr><td> {@link #construct}       </td><td>   N    </td><td>   N    </td>
   286     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   287     *    <tr><td> {@link #delete}          </td><td>   N    </td><td>   N    </td>
   288     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   289     *    <tr><td> {@link #destruct}        </td><td>   N    </td><td>   N    </td>
   290     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   291     *    <tr><td> {@link #getEnv}          </td><td>   Y    </td><td>   Y    </td>
   292     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   293     *    <tr><td> {@link #getHookContext}  </td><td>   Y    </td><td>   Y    </td>
   294     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   295     *    <tr><td> {@link #getMode}         </td><td>   Y    </td><td>   Y    </td>
   296     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   297     *    <tr><td> {@link #getPri}          </td><td>   Y    </td><td>   Y    </td>
   298     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   299     *    <tr><td> {@link #setEnv}          </td><td>   Y    </td><td>   Y    </td>
   300     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   301     *    <tr><td> {@link #setHookContext}  </td><td>   Y    </td><td>   Y    </td>
   302     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   303     *    <tr><td> {@link #setPri}          </td><td>   Y    </td><td>   Y    </td>
   304     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   305     *    <tr><td> {@link #stat}            </td><td>   Y    </td><td>   Y    </td>
   306     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   307     *    <tr><td colspan="6"> Definitions: <br />
   308     *       <ul>
   309     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   310     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   311     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   312     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   313     *           <ul>
   314     *             <li> In your module startup after this module is started 
   315     *  (e.g. Task_Module_startupDone() returns TRUE). </li>
   316     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   317     *             <li> During main().</li>
   318     *             <li> During BIOS.startupFxns.</li>
   319     *           </ul>
   320     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   321     *           <ul>
   322     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   323     *             <li> In your module startup before this module is started 
   324     *  (e.g. Task_Module_startupDone() returns FALSE).</li>
   325     *           </ul>
   326     *       </ul>
   327     *    </td></tr>
   328     *  
   329     *  </table>
   330     *  @p
   331     */
   332    
   333    @ModuleStartup      /* generate a call to Task_Module_startup at startup */
   334    @InstanceFinalize   /* generate call to Task_Instance_finalize on delete */
   335    @InstanceInitError  /* instance init can fail */
   336    
   337    module Task
   338    {
   339    
   340        // -------- Module Constants --------
   341    
   342        // -------- Module Types --------
   343    
   344        /*! Task function type definition. */
   345        typedef Void (*FuncPtr)(UArg, UArg);
   346    
   347        /*! "All Task Blocked" function type definition. */
   348        typedef Void (*AllBlockedFuncPtr)(Void);
   349    
   350        /*! 
   351         *  Task execution modes. 
   352         *
   353         *  These enumerations are the range of modes or states that 
   354         *  a task can be in. A task's current mode can be gotten using
   355         *  {@link #stat}.
   356         */
   357        enum Mode {
   358            Mode_RUNNING,           /*! Task is currently executing. */
   359            Mode_READY,             /*! Task is scheduled for execution. */
   360            Mode_BLOCKED,           /*! Task is suspended from execution. */
   361            Mode_TERMINATED,        /*! Task is terminated from execution. */
   362            Mode_INACTIVE           /*! Task is on inactive task list */
   363        };
   364    
   365        /*! 
   366         *  Task Status Buffer. 
   367         *
   368         *  Passed to and filled in by {@link #stat};
   369         */
   370        struct Stat {
   371            Int     priority;       /*! Task priority. */
   372            Ptr     stack;          /*! Task stack. */
   373            SizeT   stackSize;      /*! Task stack size. */
   374            IHeap.Handle stackHeap; /*! Heap used to alloc stack. */
   375            Ptr     env;            /*! Global environment struct. */
   376            Mode    mode;           /*! Task's current mode. */
   377            Ptr     sp;             /*! Task's current stack pointer. */
   378            SizeT   used;           /*! max # of words used on stack. */
   379        };
   380    
   381        /*! 
   382         *  Task hook set type definition.
   383         * 
   384         *  Sets of hook functions can be specified for the Task module. 
   385         *  See {@link #hookfunc Hook Functions} for details. 
   386         */
   387        struct HookSet {
   388            Void (*registerFxn)(Int);
   389            Void (*createFxn)(Handle, Error.Block *);       
   390            Void (*readyFxn)(Handle);
   391            Void (*switchFxn)(Handle, Handle);
   392            Void (*exitFxn)(Handle);
   393            Void (*deleteFxn)(Handle);
   394        };
   395    
   396        /*!  @_nodoc */
   397        metaonly struct BasicView {
   398            String      label;
   399            Int         priority;
   400            String      mode;
   401            String      fxn[]; 
   402            UArg        arg0; 
   403            UArg        arg1; 
   404            SizeT       stackSize;
   405            Ptr         stackBase; 
   406        }
   407        
   408        /*!  @_nodoc */
   409        metaonly struct DetailedView {
   410            String      label;
   411            Int         priority;
   412            String      mode;
   413            String      fxn[]; 
   414            UArg        arg0; 
   415            UArg        arg1; 
   416            SizeT       stackPeak;
   417            SizeT       stackSize;
   418            Ptr         stackBase; 
   419            String      blockedOn;
   420        }
   421    
   422        /*!  @_nodoc */
   423        metaonly struct ModuleView {
   424            String      schedulerState;
   425            String      readyQMask;
   426            Bool        workPending;
   427            UInt        numVitalTasks;
   428            Ptr         currentTask;
   429            SizeT       hwiStackPeak;
   430            SizeT       hwiStackSize;
   431            Ptr         hwiStackBase;
   432        }
   433           
   434        /*! @_nodoc */
   435        @Facet
   436        metaonly config ViewInfo.Instance rovViewInfo = 
   437            ViewInfo.create({
   438                viewMap: [
   439                    ['Basic',    {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic',    structName: 'BasicView'}],
   440                    ['Detailed', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}],
   441                    ['Module',   {type: ViewInfo.MODULE,   viewInitFxn: 'viewInitModule',   structName: 'ModuleView'}],
   442                ]
   443            });
   444    
   445        // -------- Module Parameters --------
   446    
   447        // Logs
   448        
   449        /*! Logged on every task switch */
   450        config Log.Event LM_switch = {
   451            mask: Diags.USER1 | Diags.USER2,
   452            msg: "LM_switch: oldtsk: 0x%x, oldfunc: 0x%x, newtsk: 0x%x, newfunc: 0x%x"
   453        };
   454    
   455        /*! Logged on calls to Task_sleep */
   456        config Log.Event LM_sleep = {
   457            mask: Diags.USER1 | Diags.USER2,
   458            msg: "LM_sleep: tsk: 0x%x, func: 0x%x, timeout: %d"
   459        };
   460    
   461        /*! Logged when a task is made ready to run (ie Semaphore_post()) */
   462        config Log.Event LD_ready = {
   463            mask: Diags.USER2,
   464            msg: "LD_ready: tsk: 0x%x, func: 0x%x, pri: %d"
   465        };
   466    
   467        /*! Logged when a task is blocked (ie Semaphore_pend()) */
   468        config Log.Event LD_block = {
   469            mask: Diags.USER2,
   470            msg: "LD_block: tsk: 0x%x, func: 0x%x"
   471        };
   472    
   473        /*! Logged on calls to Task_yield */
   474        config Log.Event LM_yield = {
   475            mask: Diags.USER1 | Diags.USER2,
   476            msg: "LM_yield: tsk: 0x%x, func: 0x%x, currThread: %d"
   477        };
   478    
   479        /*! Logged on calls to Task_setPri */
   480        config Log.Event LM_setPri = {
   481            mask: Diags.USER1 | Diags.USER2,
   482            msg: "LM_setPri: tsk: 0x%x, func: 0x%x, oldPri: %d, newPri %d"
   483        };
   484    
   485        /*! 
   486         *  Logged when Task functions fall thru the bottom 
   487         *  or when Task_exit() is explicitly called.
   488         */
   489        config Log.Event LD_exit = {
   490            mask: Diags.USER2,
   491            msg: "LD_exit: tsk: 0x%x, func: 0x%x"
   492        };
   493    
   494        // Errors
   495    
   496        /*! 
   497         *  Error raised when a stack overflow (or corruption) is detected.
   498         *
   499         *  This error is raised by kernel's stack checking function.  This
   500         *  function checks the stacks before every task switch to make sure
   501         *  that reserved word at top of stack has not been modified.
   502         *
   503         *  The stack checking logic is enabled by the {@link #initStackFlag} and
   504         *  {@link #checkStackFlag} configuration parameters.  If both of these
   505         *  flags are set to true, the kernel will validate the stacks.
   506         */
   507        config Error.Id E_stackOverflow  = {
   508            msg: "E_stackOverflow: Task 0x%x stack overflow."
   509        };
   510    
   511        /*! 
   512         *  Error raised when a task's stack pointer (SP) does not point
   513         *  somewhere within the task's stack.
   514         *
   515         *  This error is raised by kernel's stack checking function.  This
   516         *  function checks the SPs before every task switch to make sure
   517         *  they point within the task's stack.
   518         *
   519         *  The stack checking logic is enabled by the {@link #initStackFlag} and
   520         *  {@link #checkStackFlag} configuration parameters.  If both of these
   521         *  flags are set to true, the kernel will validate the stack pointers.
   522         */
   523        config Error.Id E_spOutOfBounds  = {
   524            msg: "E_spOutOfBounds: Task 0x%x stack error, SP = 0x%x."
   525        };
   526    
   527        // Asserts
   528    
   529        /*! Asserted in Task_create and Task_delete */
   530        config Assert.Id A_badThreadType = {
   531            msg: "A_badThreadType: Cannot create/delete a task from Hwi or Swi thread."
   532        };
   533    
   534        /*! Asserted in Task_delete */
   535        config Assert.Id A_badTaskState = {
   536            msg: "A_badTaskState: Can't delete a task in RUNNING state."
   537        };
   538    
   539        /*! Asserted in Task_delete */
   540        config Assert.Id A_noPendElem = {
   541            msg: "A_noPendElem: Not enough info to delete BLOCKED task."
   542        };
   543    
   544        /*! Asserted in Task_create */
   545        config Assert.Id A_taskDisabled = {
   546            msg: "A_taskDisabled: Cannot create a task when tasking is disabled."
   547        };
   548    
   549        /*! Asserted in Task_create */
   550        config Assert.Id A_badPriority = {
   551            msg: "A_badPriority: An invalid task priority was used."
   552        };
   553    
   554        /*! Asserted in Task_sleep */
   555        config Assert.Id A_badTimeout = {
   556            msg: "A_badTimeout: Can't sleep FOREVER."
   557        };
   558    
   559        /*! 
   560         *  Number of Task priorities supported. Default is 16.
   561         *
   562         *  The maximum number of priorities supported is
   563         *  target specific and depends on the number of 
   564         *  bits in a UInt data type. For 6x and ARM devices
   565         *  the maximum number of priorities is therefore 32.
   566         *  For 28x, 55x, and MSP430 devices, the maximum number of
   567         *  priorities is 16.
   568         */
   569        config UInt numPriorities = 16;
   570    
   571        /*!
   572         *  Default stack size (in MAUs) used for all tasks.
   573         *
   574         *  Default is obtained from the family-specific TaskSupport module 
   575          *  (e.g. {@link ti.sysbios.family.arm.m3.TaskSupport}, 
   576          *  {@link ti.sysbios.family.c62.TaskSupport}).
   577         */
   578        config SizeT defaultStackSize;
   579    
   580        /*!
   581         *  Default memory section used for all statically created task stacks.
   582         *
   583         *  The default stack section name is target/device specific.
   584         *  For C6x targets it is ".far:taskStackSection".
   585         *  For C28x targets it is ".taskStackSection".
   586         *  For all other targets it is ".bss:taskStackSection".
   587         *
   588         *  By default, all statically created task stacks are grouped together
   589         *  into the defaultStackSection and placed where ever
   590         *  the target specific defaultStackSection base section name 
   591         *  (ie .bss, .far, .ebss) is placed.
   592         *
   593         *  To place all task stacks into a different memory segment, 
   594         *  add the following to your config script:
   595         *
   596         *  @p(code)
   597         *  Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
   598         *  Program.sectMap[Task.defaultStackSection].loadSegment = 
   599         *                   "yourMemorySegment";
   600         *  @p
   601         *
   602         *  To group all task stacks into a different section AND place that 
   603         *  section into a specific memory segment, add the following to your 
   604         *  config script:
   605         *
   606         *  @p(code)
   607         *  Task.defaultStackSection = ".yourSectionName";
   608         *  Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
   609         *  Program.sectMap[Task.defaultStackSection].loadSegment =
   610         *                   "yourMemorySegment";
   611         *  @p
   612         *
   613         *  Where "yourSectionName" can be just about anything, and
   614         *                   "yourMemorySegment" 
   615         *  must be a memory segment defined for your board.
   616         */
   617        metaonly config String defaultStackSection;
   618    
   619        /*!
   620         *  Default Mem heap used for all dynamically created task stacks.
   621         *
   622         *  Default is null.
   623         */
   624        config IHeap.Handle defaultStackHeap;
   625    
   626        /*! 
   627         *  Create a task (of priority 0) to run the Idle functions in.
   628         *
   629         *  When set to true, a task is created that continuously calls the 
   630         *  {@link Idle#run Idle_run()} function, which, in turn calls each of
   631         *  the configured Idle functions. 
   632         *
   633         *  When set to false, no Idle Task is created and it is up to the
   634         *  user to call the Idle_run() function if the configured Idle 
   635         *  functions need to be run. Or, by adding the following lines to
   636         *  the config script, the Idle functions will run whenever all
   637         *  tasks are blocked ({@link #allBlockedFunc Task.allBlockedFunc}):
   638         *
   639         *  @p(code)
   640         *  Task.enableIdleTask = false;
   641         *  Task.allBlockedFunc = Idle.run;
   642         *  @p
   643         *
   644         *  Default is true.
   645         *
   646         *  @see #idleTaskStackSize
   647         *  @see #idleTaskStackSection
   648         *  @see #idleTaskVitalTaskFlag
   649         *  @see #allBlockedFunc
   650         */
   651        metaonly config Bool enableIdleTask = true;
   652    
   653        /*! 
   654         *  Idle task stack size in MAUs. 
   655         *
   656         *  Default is inherited from module config defaultStackSize.
   657         */
   658        metaonly config SizeT idleTaskStackSize;
   659    
   660        /*! 
   661         *  Idle task stack section
   662         *
   663         *  Default is inherited from module config defaultStackSection;
   664         */
   665        metaonly config String idleTaskStackSection;
   666    
   667        /*! 
   668         *  Idle task's vitalTaskFlag.
   669         *  (see {@link #vitalTaskFlag}).
   670         *
   671         *  Default is true.
   672         */
   673        metaonly config Bool idleTaskVitalTaskFlag = true;
   674    
   675        /*! 
   676         *  Function to call while all tasks are blocked.
   677         *
   678         *  This function will be called repeatedly while no tasks are
   679         *  ready to run.
   680         *
   681         *  Ordinarily (in applications that have tasks ready to run at startup),
   682         *  the function will run in the context of the last task to block. 
   683         *
   684         *  In an application where there are no tasks ready to run 
   685         *  when BIOS_start() is called, the allBlockedFunc function is
   686         *  called within the BIOS_start() thread which runs on the system/ISR 
   687         *  stack.
   688         *
   689         *  By default, allBlockedFunc is initialized to point to an internal
   690         *  function that simply returns.
   691         *
   692         *  By adding the following lines to the config script, the Idle 
   693         *  functions will run whenever all tasks are blocked:
   694         *
   695         *  @p(code)
   696         *  Task.enableIdleTask = false;
   697         *  Task.allBlockedFunc = Idle.run;
   698         *  @p
   699         *
   700         *  @see #enableIdleTask
   701         *
   702         *  @a(constraints)
   703         *  The configured allBlockedFunc is designed to be called repeatedly.
   704         *  It must return in order for the task scheduler to check if all
   705         *  tasks are STILL blocked and if not, run the highest priority task
   706         *  currently ready to run.
   707         *
   708         *  The configured allBlockedFunc function is called with interrupts
   709         *  disabled. If your function must run with interrupts enabled, 
   710         *  surround the body of your code with  Hwi_enable()/Hwi_restore() 
   711         *  function calls per the following example:
   712         *
   713         *  @p(code)
   714         *  Void yourFunc() {
   715         *      UInt hwiKey;
   716         *
   717         *      hwiKey = Hwi_enable();
   718         *
   719         *      ...         // your code here
   720         *
   721         *      Hwi_restore(hwiKey);
   722         *  }
   723         *  @p
   724         */
   725        config AllBlockedFuncPtr allBlockedFunc;
   726    
   727        /*! 
   728         *  Initialize stack with known value for stack checking at runtime
   729         *  (see {@link #checkStackFlag}).
   730         *
   731         *  This is also useful for inspection of stack in debugger or core
   732         *  dump utilities.
   733         *  Default is true.
   734         */
   735        config Bool initStackFlag = true;
   736    
   737        /*! 
   738         *  Check 'from' and 'to' task stacks before task context switch.
   739         *
   740         *  The check consists of testing the top of stack value against
   741         *  its initial value (see {@link #initStackFlag}). If it is no
   742         *  longer at this value, the assumption is that the task has
   743         *  overrun its stack. If the test fails, then the 
   744         *  {@link #E_stackOverflow} error is raised.
   745         *
   746         *  Runtime stack checking is only performed if {@link #initStackFlag} is
   747         *  also true.
   748         *
   749         *  Default is true.
   750         *
   751         *  To enable or disable full stack checking, you should set both this
   752         *  flag and the {@link ti.sysbios.hal.Hwi#checkStackFlag}.
   753         */
   754        metaonly config Bool checkStackFlag = true;
   755    
   756        /*! 
   757         *  Automatically delete terminated tasks.
   758         *
   759         *  If this feature is enabled, an Idle function is installed that
   760         *  deletes dynamically created Tasks that have terminated either
   761         *  by falling through their task function or by explicitly calling
   762         *  Task_exit().
   763         *
   764         *  A list of terminated Tasks that were created dynmically is 
   765         *  maintained internally. Each invocation of the installed Idle function
   766         *  deletes the first Task on this list. This one-at-a-time process 
   767         *  continues until the list is empty.
   768         *
   769         *  @a(Note)
   770         *  This feature is disabled by default.
   771         *
   772         *  If this feature is enable, the user's application must not 
   773         *  also delete terminated tasks or undefined and/or potentially 
   774         *  catastrophic behavior will result.
   775         */
   776        config Bool deleteTerminatedTasks = false;
   777    
   778        /*!
   779         *  Const array that holds the HookSet objects.
   780         *
   781         *  See {@link #hookfunc Hook Functions} for details about HookSets. 
   782         */
   783        config HookSet hooks[length] = [];
   784    
   785        // -------- Module Functions --------
   786    
   787        /*!
   788         *  ======== addHookSet ========
   789         *  addHookSet is used in a config file to add a hook set.
   790         *
   791         *  Configures a set of hook functions for the 
   792         *  Task module. Each set contains these hook functions:
   793         *
   794         *  @p(blist)
   795         *  -Register: A function called before any statically created tasks
   796         *  are initialized at runtime.  The register hook is called at boot time
   797         *  before main() and before interrupts are enabled.
   798         *  -Create: A function that is called when a task is created. 
   799         *  This includes tasks that are created statically and those
   800         *  created dynamically using {@link #create} or {@link #construct}.
   801         *  The create hook is called outside of a Task_disable/enable block and
   802         *   before the task has been added to the ready list.
   803         *  -Ready: A function that is called when a task becomes ready to run.
   804         *   The ready hook is called from within a Task_disable/enable block with
   805         *   interrupts enabled.
   806         *  -Switch: A function that is called just before a task switch
   807         *  occurs. The 'prev' and 'next' task handles are passed to the Switch
   808         *  hook. 'prev' is set to NULL for the initial task switch that occurs
   809         *  during SYS/BIOS startup.  The Switch hook is called from within a
   810         *  Task_disable/enable block with interrupts enabled.
   811         *  -Exit:  A function that is called when a task exits using
   812         *  {@link #exit}.  The exit hook is passed the handle of the exiting
   813         *  task.  The exit hook is called outside of a Task_disable/enable block
   814         *  and before the task has been removed from the kernel lists.
   815         *  -Delete: A function that is called when any task is deleted at
   816         *  run-time with {@link #delete}.  The delete hook is called outside
   817         *  of a Task_disable/enable block.
   818         *  @p
   819         *  Hook functions can only be configured statically.
   820         *
   821         *  See {@link #hookfunc Hook Functions} for more details. 
   822         *
   823         *  HookSet structure elements may be omitted, in which case those
   824         *  elements will not exist.
   825         *
   826         *  For example, the following configuration code defines a HookSet:
   827         *
   828         *  @p(code)
   829         *  // Hook Set 1 
   830         *  Task.addHookSet({
   831         *     registerFxn: '&myRegister1',
   832         *     createFxn:   '&myCreate1',
   833         *     readyFxn:    '&myReady1',
   834         *     switchFxn:   '&mySwitch1',
   835         *     exitFxn:     '&myExit1',
   836         *     deleteFxn:   '&myDelete1'
   837         *  });
   838         *  @p
   839         *
   840         *  @param(hook)    structure of type HookSet
   841         */
   842        metaonly Void addHookSet(HookSet hook);
   843    
   844        /*!
   845         *  @_nodoc
   846         *  ======== Task_startup ========
   847         *  Start the task scheduler.
   848         *
   849         *  Task_startup signals the end of boot operations, enables
   850         *  the Task scheduler and schedules the highest priority ready
   851         *  task for execution.
   852         *
   853         *  Task_startup is called by BIOS_start() after Hwi_enable() 
   854         *  and Swi_enable(). There is no return from this function as the 
   855         *  execution thread is handed to the highest priority ready task.
   856         */
   857        @DirectCall
   858        Void startup();
   859    
   860        /*!
   861         *  ======== Task_disable ========
   862         *  Disable the task scheduler.
   863         *
   864         *  {@link #disable} and {@link #restore} control Task scheduling.
   865         *  {@link #disable} disables all other Tasks from running until
   866         *  {@link #restore} is called. Hardware and Software interrupts
   867         *  can still run.
   868         *
   869         *  {@link #disable} and {@link #restore} allow you to ensure that 
   870         *  statements
   871         *  that must be performed together during critical processing are not
   872         *  preempted by other Tasks.
   873         *
   874         *  The value of the key returned is opaque to applications and is meant
   875         *  to be passed to Task_restore().
   876         *
   877         *  In the following example, the critical section is
   878         *  not preempted by any Tasks.
   879         *
   880         *  @p(code)
   881         *  key = Task_disable();
   882         *      `critical section`
   883         *  Task_restore(key);
   884         *  @p
   885         *
   886         *  You can also use {@link #disable} and {@link #restore} to 
   887         *  create several Tasks and allow them to be invoked in 
   888         *  priority order.
   889         *
   890         *  {@link #disable} calls can be nested.
   891         *
   892         *  @b(returns)     key for use with {@link #restore}
   893         *
   894         *  @a(constraints)
   895         *  Do not call any function that can cause the current task to block 
   896         *  within a {@link #disable}/{@link #restore} block. For example, 
   897         *  {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend} 
   898         *  (if timeout is non-zero), 
   899         *  {@link #sleep}, {@link #yield}, and Memory_alloc can all
   900         *  cause blocking. 
   901         */
   902        @DirectCall
   903        UInt disable();
   904    
   905        /*!
   906         *  @_nodoc
   907         *  ======== enable ========
   908         *  Enable the task scheduler.
   909         *
   910         *  {@link #enable} unconditionally enables the Task scheduler and
   911         *  schedules the highest priority ready task for execution.
   912         *
   913         *  This function is called by {@link #startup} (which is called by
   914         *  {@link ti.sysbios.BIOS#start BIOS_start}) to begin multi-tasking
   915         *  operations.
   916         */
   917        @DirectCall
   918        Void enable();
   919    
   920        /*!
   921         *  ======== restore ========
   922         *  Restore Task scheduling state.
   923         *
   924         *  {@link #disable} and {@link #restore} control Task scheduling
   925         *  {@link #disable} disables all other Tasks from running until
   926         *  {@link #restore} is called. Hardware and Software interrupts
   927         *  can still run.
   928         *
   929         *  {@link #disable} and {@link #restore} allow you to ensure that 
   930         *  statements
   931         *  that must be performed together during critical processing are not
   932         *  preempted.
   933    
   934         *  In the following example, the critical section is not preempted
   935         *  by any Tasks.
   936         *
   937         *  @p(code)
   938         *  key = Task_disable();
   939         *      `critical section`
   940         *  Task_restore(key);
   941         *  @p
   942         *
   943         *  You can also use {@link #disable} and {@link #restore} to create 
   944         *  several Tasks and allow them to be performed in priority order.
   945         *
   946         *  {@link #disable} calls can be nested.
   947         *
   948         *  {@link #restore} returns with interrupts enabled if the key unlocks
   949         *  the scheduler
   950         *
   951         *  @param(key)     key to restore previous Task scheduler state
   952         *
   953         *  @a(constraints)
   954         *  Do not call any function that can cause the current task to block 
   955         *  within a {@link #disable}/{@link #restore} block. For example, 
   956         *  {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()} 
   957         *  (if timeout is non-zero), 
   958         *  {@link #sleep}, {@link #yield}, and Memory_alloc can all
   959         *  cause blocking. 
   960         *
   961         *  {@link #restore} internally calls Hwi_enable() if the key passed
   962         *  to it results in the unlocking of the Task scheduler (ie if this
   963         *  is root Task_disable/Task_restore pair).
   964         */
   965        @DirectCall
   966        Void restore(UInt key);
   967    
   968        /*!
   969         *  @_nodoc
   970         *  ======== restoreHwi ========
   971         *  Restore Task scheduling state.
   972         *  Used by dispatcher. Does not re-enable Ints.
   973         */
   974        @DirectCall
   975        Void restoreHwi(UInt key);
   976    
   977        /*!
   978         *  ======== self ========
   979         *  Returns a handle to the currently executing Task object.
   980         *
   981         *  Task_self returns the object handle for the currently executing task. 
   982         *  This function is useful when inspecting the object or when the current 
   983         *  task changes its own priority through {@link #setPri}.
   984         *  
   985         *  No task switch occurs when calling Task_self.
   986         *  
   987         *  Task_self will return NULL until Tasking is initiated at the end of 
   988         *  BIOS_start().
   989         *
   990         *  @b(returns)     address of currently executing task object
   991         */
   992        @DirectCall
   993        Handle self();
   994    
   995        /*!
   996         *  ======== selfMacro ========
   997         *  Returns a handle to the currently executing Task object.
   998         *
   999         *  Task_selfMacro is identical to {@link #self} but is implemented as
  1000         *  and inline macro.
  1001         *
  1002         *  @b(returns)     address of currently executing task object
  1003         */
  1004        @Macro
  1005        Handle selfMacro();
  1006    
  1007        /*!
  1008         *  @_nodoc
  1009         *  ======== checkStacks ========
  1010         *  Check for stack overflow.
  1011         *
  1012         *  This function is usually called by the {@link #HookSet} switchFxn to 
  1013         *  make sure task stacks are valid before performing the context 
  1014         *  switch.
  1015         *
  1016         *  If a stack overflow is detected on either the oldTask or the
  1017         *  newTask, a {@link #E_stackOverflow} Error is raised and the system 
  1018         *  exited.
  1019         *
  1020         *  In order to work properly, {@link #checkStacks} requires that the
  1021         *  {@link #initStackFlag} set to true, which it is by default.
  1022         *
  1023         *  You can call {@link #checkStacks} directly from your application. 
  1024         *  For example, you can check the current task's stack integrity 
  1025         *  at any time with a call like the following:
  1026         *
  1027         *  @p(code)
  1028         *  Task_checkStacks(Task_self(), Task_self());
  1029         *  @p
  1030         *
  1031         *  @param(oldTask)  leaving Task Object Ptr
  1032         *  @param(newTask)  entering Task Object Ptr
  1033         */
  1034        @DirectCall
  1035        Void checkStacks(Handle oldTask, Handle newTask);
  1036    
  1037        /*!
  1038         *  ======== exit ========
  1039         *  Terminate execution of the current task.
  1040         *
  1041         *  Task_exit terminates execution of the current task, changing its mode
  1042         *  from {@link #Mode_RUNNING} to {@link #Mode_TERMINATED}. If all tasks 
  1043         *  have been terminated, or if all remaining tasks have their 
  1044         *  vitalTaskFlag attribute set to FALSE, then SYS/BIOS terminates the 
  1045         *  program as a whole by calling the function System_exit with a status 
  1046         *  code of 0.
  1047         * 
  1048         *  Task_exit is automatically called whenever a task returns from its 
  1049         *  top-level function.
  1050         * 
  1051         *  Exit Hooks (see exitFxn in {@link #HookSet}) can be used to provide 
  1052         *  functions that run whenever a task is terminated. The exitFxn Hooks 
  1053         *  are called before the task has been blocked and marked 
  1054         *  {@link #Mode_TERMINATED}.
  1055         *  See {@link #hookfunc Hook Functions} for more information. 
  1056         *
  1057         *  Any SYS/BIOS function can be called from an Exit Hook function. 
  1058         *
  1059         *  Calling {@link #self} within an Exit function returns the task
  1060         *  being exited. Your Exit function declaration should be similar to 
  1061         *  the following:
  1062         *  @p(code)
  1063         *  Void myExitFxn(Void);
  1064         *  @p
  1065         * 
  1066         *  A task switch occurs when calling Task_exit unless the program as a
  1067         *  whole is terminated
  1068         *
  1069         *  @a(constraints)
  1070         *  Task_exit cannot be called from a Swi or Hwi.
  1071         *
  1072         *  Task_exit cannot be called from the program's main() function.
  1073         */
  1074        @DirectCall
  1075        Void exit();
  1076    
  1077        /*!
  1078         *  ======== sleep ========
  1079         *  Delay execution of the current task.
  1080         *
  1081         *  Task_sleep changes the current task's mode from {@link #Mode_RUNNING} 
  1082         *  to {@link #Mode_BLOCKED}, and delays its execution for nticks 
  1083         *  increments of the {@link Clock system clock}. The actual time
  1084         *  delayed can be up to 1 system clock tick less than nticks due to
  1085         *  granularity in system timekeeping and the time elapsed per
  1086         *  tick is determined by {@link Clock#tickPeriod Clock_tickPeriod}.
  1087         *  
  1088         *  After the specified period of time has elapsed, the task reverts to 
  1089         *  the {@link #Mode_READY} mode and is scheduled for execution.
  1090         *  
  1091         *  A task switch always occurs when calling Task_sleep if nticks > 0.
  1092         *
  1093         *  @param(nticks)  number of system clock ticks to sleep
  1094         *
  1095         *  @a(constraints)
  1096         *  Task_sleep cannot be called from a Swi or Hwi, or within a
  1097         *  {@link #disable} / {@link #restore} block.
  1098         *
  1099         *  Task_sleep cannot be called from the program's main() function.
  1100         *
  1101         *  Task_sleep should not be called from within an Idle function. Doing 
  1102         *  so prevents analysis tools from gathering run-time information.
  1103         *
  1104         *  nticks cannot be {@link ti.sysbios.BIOS#WAIT_FOREVER BIOS_WAIT_FOREVER}.
  1105         */
  1106        @DirectCall
  1107        Void sleep(UInt nticks);
  1108    
  1109        /*!
  1110         *  ======== yield ========
  1111         *  Yield processor to equal priority task.
  1112         *
  1113         *  Task_yield yields the processor to another task of equal priority.
  1114         *  
  1115         *  A task switch occurs when you call Task_yield if there is an equal 
  1116         *  priority task ready to run.
  1117         *  
  1118         *  Tasks of higher priority preempt the currently running task without 
  1119         *  the need for a call to Task_yield. If only lower-priority tasks are 
  1120         *  ready to run when you call Task_yield, the current task continues to 
  1121         *  run. Control does not pass to a lower-priority task.
  1122         *
  1123         *  @a(constraints)
  1124         *  When called within an Hwi, the code sequence calling Task_yield
  1125         *  must be invoked by the Hwi dispatcher.
  1126         *
  1127         *  Task_yield cannot be called from the program's main() function.
  1128         */
  1129        @DirectCall
  1130        Void yield();
  1131    
  1132        /*!
  1133         *  ======== getIdleTask ========
  1134         *  returns a handle to idle task object
  1135         */
  1136        @DirectCall
  1137        Handle getIdleTask();
  1138        
  1139        /*!
  1140         *  ======== getNickName ========
  1141         *  
  1142         */
  1143        metaonly String getNickName(Any tskView);
  1144    
  1145    instance:
  1146    
  1147        /*!
  1148         *  ======== create ========
  1149         *  Create a Task.
  1150         *
  1151         *  Task_create creates a new task object. If successful, Task_create
  1152         *  returns the handle of the new task object. If unsuccessful, 
  1153         *  Task_create returns NULL unless it aborts.
  1154         *
  1155         *  The fxn parameter uses the {@link #FuncPtr} type to pass a pointer to 
  1156         *  the function the Task object should run. For example, if myFxn is a 
  1157         *  function in your program, your C code can create a Task object 
  1158         *  to call that 
  1159         *  function as follows: 
  1160         *  
  1161         *  @p(code)
  1162         *  Task_Params taskParams;
  1163         *  
  1164         *  // Create task with priority 15 
  1165         *  Task_Params_init(&taskParams);
  1166         *  taskParams.stackSize = 512;
  1167         *  taskParams.priority = 15;
  1168         *  Task_create((Task_FuncPtr)myFxn, &taskParams, &eb);
  1169         *  @p
  1170         *
  1171         *  The following statements statically create a task in the 
  1172         *  configuration file: 
  1173         *  
  1174         *  @p(code)
  1175         *  var params = new Task.Params;
  1176         *  params.instance.name = "tsk0";
  1177         *  params.arg0 = 1;
  1178         *  params.arg1 = 2;
  1179         *  params.priority = 1;
  1180         *  Task.create('&tsk0_func', params);
  1181         *  @p
  1182         *
  1183         *  If NULL is passed instead of a pointer to an actual Task_Params 
  1184         *  struct, a
  1185         *  default set of parameters is used. The "eb" is an error block that 
  1186         *  you can use
  1187         *  to handle errors that may occur during Task object creation.
  1188         *
  1189         *  The newly created task is placed in {@link #Mode_READY} mode, and is 
  1190         *  scheduled to begin concurrent execution of the following function 
  1191         *  call:
  1192         *
  1193         *  @p(code)
  1194         *  (*fxn)(arg1, arg2);
  1195         *  @p
  1196         *
  1197         *  As a result of being made ready to run, the task runs any
  1198         *  application-wide Ready functions that have been specified.
  1199         *
  1200         *  Task_exit is automatically called if and when the task returns 
  1201         *  from fxn. 
  1202         *  
  1203         *  @p(html)
  1204         *  <B>Create Hook Functions</B>
  1205         *  @p
  1206         *  
  1207         *  You can specify application-wide Create hook functions in your config
  1208         *  file that run whenever a task is created. This includes tasks that 
  1209         *  are created statically and those created dynamically using 
  1210         *  Task_create.
  1211         *
  1212         *  For Task objects created statically, Create functions are called
  1213         *  during the Task module initialization phase of the program startup 
  1214         *  process prior to main().
  1215         *
  1216         *  For Task objects created dynamically, Create functions 
  1217         *  are called after the task handle has been initialized but before the 
  1218         *  task has been placed on its ready queue.
  1219         *
  1220         *  Any SYS/BIOS function can be called from Create functions.
  1221         *  SYS/BIOS passes the task handle of the task being created to each of 
  1222         *  the Create functions. 
  1223         *
  1224         *  All Create function declarations should be similar to this:
  1225         *  @p(code)
  1226         *  Void myCreateFxn(Task_Handle task);
  1227         *  @p
  1228         *
  1229         *  @param(fxn)     Task Function
  1230         *  
  1231         *  @a(constraints)
  1232         *  @p(blist)
  1233         *  - The fxn parameter and the name attribute cannot be NULL.
  1234         *  - The priority attribute must be less than or equal to 
  1235         *  ({@link #numPriorities} - 1) and greater than or equal to one (1)
  1236         *  (priority 0 is owned by the Idle task). 
  1237         *  - The priority can be set to -1 for tasks that will not execute
  1238         *  until another task changes the priority to a positive value.
  1239         *  - The stackHeap attribute must identify a valid memory Heap.
  1240         *  @p
  1241         */
  1242        @DirectCall
  1243        create(FuncPtr fxn);
  1244    
  1245        // -------- Handle Parameters --------
  1246    
  1247        /*! Task function argument. Default is 0 */
  1248        config UArg arg0 = 0;
  1249    
  1250        /*! Task function argument. Default is 0 */
  1251        config UArg arg1 = 0;
  1252    
  1253        /*!
  1254         *  Task priority (0 to numPriorities-1 or -1).
  1255         *  Default is 1.
  1256         */
  1257        config Int priority = 1;
  1258    
  1259        /*!
  1260         *  Task stack pointer. Default = null.
  1261         *
  1262         *  Null indicates that the stack is to be allocated by create().
  1263         *
  1264         *  Example: To statically initialize "tsk0"'s stack to a literal
  1265         *  address, use the following syntax:
  1266         *
  1267         *  @p(code)
  1268         *      Program.global.tsk0.stack = $addr(literal);
  1269         *  @p
  1270         *
  1271         */
  1272        config Ptr stack = null;
  1273    
  1274        /*! 
  1275         *  Task stack size in MAUs. 
  1276         *
  1277         *  The default value of 0 means that the module config 
  1278         *  {@link #defaultStackSize} is used.
  1279         */
  1280        config SizeT stackSize = 0;
  1281    
  1282        /*!
  1283         *  Mem section used for statically created task stacks.
  1284         *
  1285         *  Default is inherited from module config defaultStackSection.
  1286         */
  1287        metaonly config String stackSection;
  1288    
  1289        /*!
  1290         *  Mem heap used for dynamically created task stack.
  1291         *
  1292         *  The default value of NULL means that the module config 
  1293         *  {@link #defaultStackHeap} is used.
  1294         */
  1295        config IHeap.Handle stackHeap = null;
  1296    
  1297        /*! Environment data struct. */
  1298        config Ptr env = null;
  1299    
  1300        /*!
  1301         *  Exit system immediately when the last task with this
  1302         *  flag set to TRUE has terminated. 
  1303         *
  1304         *  Default is true.
  1305         */
  1306        config Bool vitalTaskFlag = true;
  1307    
  1308        // -------- Handle Functions --------
  1309    
  1310        /*!
  1311         *  @_nodoc
  1312         *  ======== getArg0 ========
  1313         *  Returns arg0 passed via params to create.
  1314         *
  1315         *  @b(returns)     task's arg0
  1316         */
  1317        @DirectCall
  1318        UArg getArg0();
  1319    
  1320        /*!
  1321         *  @_nodoc
  1322         *  ======== getArg1 ========
  1323         *  Returns arg1 passed via params to create.
  1324         *
  1325         *  @b(returns)     task's arg1
  1326         */
  1327        @DirectCall
  1328        UArg getArg1();
  1329    
  1330        /*!
  1331         *  ======== getEnv ========
  1332         *  Get task environment pointer.
  1333         *
  1334         *  Task_getEnv returns the environment pointer of the specified task. The
  1335         *  environment pointer references an arbitrary application-defined data 
  1336         *  structure.
  1337         *  
  1338         *  If your program uses multiple hook sets, {@link #getHookContext} 
  1339         *  allows you to get environment pointers you have set for a particular 
  1340         *  hook set and Task object combination.
  1341         *
  1342         *  @b(returns)     task environment pointer
  1343         */
  1344        @DirectCall
  1345        Ptr getEnv();
  1346    
  1347        /*!
  1348         *  ======== getHookContext ========
  1349         *  Get hook set's context for a task.
  1350         *
  1351         *  For example, this C code gets the HookContext, prints it,
  1352         *  and sets a new value for the HookContext.
  1353         *
  1354         *  @p(code)
  1355         *  Ptr pEnv;
  1356         *  Task_Handle myTask;
  1357         *  Int myHookSetId1;
  1358         * 
  1359         *  pEnv = Task_getHookContext(task, myHookSetId1);
  1360         * 
  1361         *  System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n", 
  1362         *                (ULong)pEnv, (ULong)Timestamp_get32());
  1363         * 
  1364         *  Task_setHookContext(task, myHookSetId1, (Ptr)0xc0de1);
  1365         *  @p
  1366         *
  1367         *  See {@link #hookfunc Hook Functions} for more details. 
  1368         *
  1369         *  @param(id)      hook set ID
  1370         *  @b(returns)     hook set context for task
  1371         */
  1372        @DirectCall
  1373        Ptr getHookContext(Int id);
  1374    
  1375        /*!
  1376         *  ======== getPri ========
  1377         *  Get task priority.
  1378         *
  1379         *  Task_getPri returns the priority of the referenced task.
  1380         *
  1381         *  @b(returns)     task priority
  1382         */
  1383        @DirectCall
  1384        Int getPri();
  1385    
  1386        /*!
  1387         *  @_nodoc
  1388         *  ======== setArg0 ========
  1389         *  Set arg0 (used primarily for legacy support)
  1390         */
  1391        @DirectCall
  1392        Void setArg0(UArg arg);
  1393    
  1394        /*!
  1395         *  @_nodoc
  1396         *  ======== setArg1 ========
  1397         *  Set arg1 (used primarily for legacy support)
  1398         */
  1399        @DirectCall
  1400        Void setArg1(UArg arg);
  1401    
  1402        /*!
  1403         *  ======== setEnv ========
  1404         *  Set task environment.
  1405         *
  1406         *  Task_setEnv sets the task environment pointer to env. The
  1407         *  environment pointer references an arbitrary application-defined
  1408         *  data structure.
  1409         *
  1410         *  If your program uses multiple hook sets, {@link #setHookContext} 
  1411         *  allows you to set environment pointers for any
  1412         *  hook set and Task object combination.
  1413         *
  1414         *  @param(env)     task environment pointer
  1415         */
  1416        @DirectCall
  1417        Void setEnv(Ptr env);
  1418    
  1419        /*!
  1420         *  ======== setHookContext ========
  1421         *  Set hook instance's context for a task.
  1422         *
  1423         *  For example, this C code gets the HookContext, prints it,
  1424         *  and sets a new value for the HookContext.
  1425         *
  1426         *  @p(code)
  1427         *  Ptr pEnv;
  1428         *  Task_Handle myTask;
  1429         *  Int myHookSetId1;
  1430         * 
  1431         *  pEnv = Task_getHookContext(task, myHookSetId1);
  1432         * 
  1433         *  System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n", 
  1434         *                (ULong)pEnv, (ULong)Timestamp_get32());
  1435         * 
  1436         *  Task_setHookContext(task, myHookSetId1, (Ptr)0xc0de1);
  1437         *  @p
  1438         *
  1439         *  See {@link #hookfunc Hook Functions} for more details. 
  1440         *
  1441         *  @param(id)              hook set ID
  1442         *  @param(hookContext)     value to write to context
  1443         */
  1444        @DirectCall
  1445        Void setHookContext(Int id, Ptr hookContext);
  1446    
  1447        /*!
  1448         *  ======== setPri ========
  1449         *  Set a task's priority
  1450         *
  1451         *  Task_setpri sets the execution priority of task to newpri, and returns
  1452         *  that task's old priority value. Raising or lowering a task's priority
  1453         *  does not necessarily force preemption and re-scheduling of the caller:
  1454         *  tasks in the {@link #Mode_BLOCKED} mode remain suspended despite a
  1455         *  change in priority; and tasks in the {@link #Mode_READY} mode gain
  1456         *  control only if their new priority is greater than that of the
  1457         *  currently executing task.
  1458         *  
  1459         *  newpri should be set to a value greater than or equal to 1 and
  1460         *  less than or equal to ({@link #numPriorities} - 1).  newpri can also
  1461         *  be set to -1 which puts the the task into the INACTIVE state and the
  1462         *  task will not run until its priority is raised at a later time by
  1463         *  another task.  Priority 0 is reserved for the idle task.
  1464         *  If newpri equals ({@link #numPriorities} - 1), execution of the task
  1465         *  effectively locks out all other program activity, except for the
  1466         *  handling of interrupts.
  1467         *  
  1468         *  The current task can change its own priority (and possibly preempt its
  1469         *  execution) by passing the output of {@link #self} as the value of the 
  1470         *  task parameter.
  1471         *  
  1472         *  A context switch occurs when calling Task_setpri if a currently 
  1473         *  running task priority is set lower than the priority of another 
  1474         *  currently ready task, or if another ready task is made to have a
  1475         *  higher priority than the currently running task.
  1476         *
  1477         *  Task_setpri can be used for mutual exclusion.
  1478         *
  1479         *  If a task's new priority is different than its previous priority, 
  1480         *  then its relative placement in its new ready task priority 
  1481         *  queue can be different than the one it was removed from. This can 
  1482         *  effect the relative order in which it becomes the running task.
  1483         *
  1484         *  The effected task is placed at the head of its new priority queue
  1485         *  if it is the currently running task. Otherwise it is placed at
  1486         *  at the end of its new task priority queue.
  1487         *
  1488         *  @param(newpri) task's new priority
  1489         *  @b(returns)    task's old priority
  1490         *
  1491         *  @a(constraints)
  1492         *  newpri must be a value between 1 and ({@link #numPriorities} - 1) or -1.
  1493         *
  1494         *  The task cannot be in the {@link #Mode_TERMINATED} mode.
  1495         *
  1496         *  The new priority should not be zero (0). This priority level is 
  1497         *  reserved for the Idle task.
  1498         */
  1499        @DirectCall
  1500        UInt setPri(Int newpri);
  1501    
  1502        /*!
  1503         *  ======== stat ========
  1504         *  Retrieve the status of a task.
  1505         *
  1506         *  Task_stat retrieves attribute values and status information about a 
  1507         *  task.
  1508         *  
  1509         *  Status information is returned through statbuf, which references a
  1510         *  structure of type {@link #Stat}.
  1511         *  
  1512         *  When a task is preempted by a software or hardware interrupt, the task
  1513         *  execution mode returned for that task by Task_stat is still 
  1514         *  {@link #Mode_RUNNING}  because the task runs when the preemption ends.
  1515         *
  1516         *  The current task can inquire about itself by passing the output of
  1517         *  {@link #self} as the first argument to Task_stat. However, the task 
  1518         *  stack pointer (sp) in the {@link #Stat} structure is the value from 
  1519         *  the previous context switch.
  1520         *
  1521         *  Task_stat has a non-deterministic execution time. As such, it is not
  1522         *  recommended to call this API from Swis or Hwis.
  1523         *
  1524         *  @param(statbuf) pointer to task status structure
  1525         *
  1526         *  @a(constraints)
  1527         *  statbuf cannot be NULL;
  1528         */
  1529        @DirectCall
  1530        Void stat(Stat *statbuf);
  1531    
  1532        /*!
  1533         *  ======== getMode ========
  1534         *  Retrieve the {@link #Mode} of a task.
  1535         */
  1536        @DirectCall
  1537        Mode getMode();
  1538    
  1539        /*!
  1540         *  @_nodoc
  1541         *  ======== block ========
  1542         *  Block a task.
  1543         *
  1544         *  Remove a task from its ready list.
  1545         *  The effect of this API is manifest the next time the internal
  1546         *  Task scheduler is invoked. 
  1547         *  This can be done directly by embedding the call within a 
  1548         *  {@link #disable}/{@link #restore} block.
  1549         *  Otherwise, the effect will be manifest as a result of processing
  1550         *  the next dispatched interrupt, or by posting a Swi, or by falling
  1551         *  through the task function.
  1552         *
  1553         *  @a(constraints)
  1554         *  If called from within a Hwi or a Swi, or main(), there is no need 
  1555         *  to embed the call within a {@link #disable}/{@link #restore} block.
  1556         */
  1557        @DirectCall
  1558        Void block();
  1559    
  1560        /*!
  1561         *  @_nodoc
  1562         *  ======== unblock ========
  1563         *  Unblock a task.
  1564         *
  1565         *  Place task in its ready list.
  1566         *  The effect of this API is manifest the next time the internal
  1567         *  Task scheduler is invoked. 
  1568         *  This can be done directly by embedding the call within a 
  1569         *  {@link #disable}/{@link #restore} block.
  1570         *  Otherwise, the effect will be manifest as a result of processing
  1571         *  the next dispatched interrupt, or by posting a Swi, or by falling
  1572         *  through the task function.
  1573         *
  1574         *  @a(constraints)
  1575         *  If called from within a Hwi or a Swi, or main(), there is no need 
  1576         *  to embed the call within a {@link #disable}/{@link #restore} block.
  1577         */
  1578        @DirectCall
  1579        Void unblock();
  1580    
  1581        /*!
  1582         *  @_nodoc
  1583         *  ======== blockI ========
  1584         *  Block a task.
  1585         *
  1586         *  Remove a task from its ready list.
  1587         *  Must be called within Task_disable/Task_restore block
  1588         *  with interrupts disabled.
  1589         *  This API is meant to be used internally.
  1590         */
  1591        @DirectCall
  1592        Void blockI();
  1593    
  1594        /*!
  1595         *  @_nodoc
  1596         *  ======== unblockI ========
  1597         *  Unblock a task.
  1598         *
  1599         *  Place task in its ready list.
  1600         *  Must be called within Task_disable/Task_restore block
  1601         *  with interrupts disabled.
  1602         *  This API is meant to be used internally.
  1603         *
  1604         *  @param(hwiKey) key returned from Hwi_disable()
  1605         */
  1606        @DirectCall
  1607        Void unblockI(UInt hwiKey);
  1608    
  1609    
  1610    internal:   /* not for client use */
  1611    
  1612        /*! Target-specific support functions. */
  1613        proxy SupportProxy inherits ti.sysbios.interfaces.ITaskSupport;
  1614    
  1615        /*
  1616         *  ======== schedule ========
  1617         *  Find highest priority ready task and invoke it.
  1618         *
  1619         *  Must be called with interrupts disabled.
  1620         */
  1621        Void schedule();
  1622    
  1623        /*
  1624         *  ======== enter ========
  1625         *  Task's initial entry point before entering task function.
  1626         */
  1627        Void enter();
  1628    
  1629        /*
  1630         *  ======== sleepTimeout ========
  1631         *  This function is the clock event handler for sleep.
  1632         */
  1633        Void sleepTimeout(UArg arg);
  1634    
  1635        /*
  1636         *  ======== postInit ========
  1637         *  finish initializing static and dynamic Tasks
  1638         */
  1639        Int postInit(Object *swi, Error.Block *eb);
  1640    
  1641        /*
  1642         *  Number of statically constructed Task objects.
  1643         *  Shouldn't be set directly by the user's
  1644         *  config (it gets set by instance$static$init).
  1645         */
  1646        config UInt numConstructedTasks = 0;
  1647    
  1648        /*
  1649         *  ======== allBlockedFunction ========
  1650         *  default function to be called
  1651         */
  1652        Void allBlockedFunction();
  1653    
  1654        /*
  1655         *  ======== deleteTerminatedTasksFunc ========
  1656         *  Idle func that deletes the first terminated task it finds
  1657         *  in the queue of dynamically created tasks
  1658         */
  1659        Void deleteTerminatedTasksFunc();
  1660    
  1661        /* 
  1662         *  Common object used by all blocked tasks to enable Task_delete()
  1663         *  to remove a task from any pend Q it is placed on while blocked.
  1664         */
  1665        struct PendElem {
  1666            Queue.Elem              qElem;
  1667            Task.Handle             task;
  1668            Clock.Handle            clock;
  1669        };
  1670    
  1671        struct Instance_State {
  1672            Queue.Elem      qElem;      // Task's readyQ element
  1673            volatile Int    priority;   // Task priority
  1674            UInt            mask;       // curSet mask = 1 << priority
  1675            Ptr             context;    // ptr to Task's saved context
  1676                                        // while not in RUNNING mode.
  1677            Mode            mode;       // READY, BLOCKED, RUNNING, etc
  1678            PendElem        *pendElem;  // ptr to Task, Semaphore, Event,
  1679                                        // or GateMutexPri PendElem
  1680            SizeT           stackSize;  // Task's stack buffer size
  1681            Char            stack[];    // buffer used for Task's stack
  1682            IHeap.Handle    stackHeap;  // Heap to allocate stack from
  1683            FuncPtr         fxn;        // Task function
  1684            UArg            arg0;       // Task function 1st arg
  1685            UArg            arg1;       // Task function 2nd arg
  1686            Ptr             env;        // Task environment pointer
  1687            Ptr             hookEnv[];  // ptr to Task's hook env array
  1688            Bool            vitalTaskFlag; // TRUE = shutdown system if
  1689                                        // last task like this exits
  1690            Queue.Handle    readyQ;     // This Task's readyQ
  1691        };
  1692    
  1693        struct Module_State {
  1694            Bool            locked;     // Task scheduler locked flag
  1695            volatile UInt   curSet;     // Bitmask reflects readyQ states
  1696            Bool            workFlag;   // Scheduler work is pending.
  1697                                        // Optimization. Must be set
  1698                                        // whenever readyQs are modified.
  1699            UInt            vitalTasks; // number of tasks with
  1700                                        // vitalTaskFlag = true
  1701            Handle          curTask;    // current Task instance
  1702            Queue.Handle    curQ;       // current Task's readyQ
  1703            Queue.Object    readyQ[];   // Task ready queues
  1704            Queue.Object    inactiveQ;  // Task's with -1 priority
  1705            Queue.Object    terminatedQ;// terminated dynamically created Tasks
  1706            Handle          idleTask;   // Idle Task
  1707            Handle          constructedTasks[]; // array of statically 
  1708                                        // constructed Tasks
  1709        };
  1710    }
  1711    
  1712    /*
  1713     *  @(#) ti.sysbios.knl; 2, 0, 0, 0,545; 3-20-2012 14:03:35; /db/vtree/library/trees/avala/avala-q31x/src/ xlibrary
  1714    
  1715     */
  1716