tiros.h

Go to the documentation of this file.
00001 /** @file 
00002  * @brief Application Programming Interface (API) 
00003  */
00004 
00005 #ifndef __TIROS_H_
00006 #define __TIROS_H_
00007 
00008 /* Author: Ratish J. Punnoose, 2006
00009  * This file is part of TiROS, the Tickless Real-Time Operating System.
00010  * Copyright(c) 2006, 2007: Ratish J. Punnoose.
00011  * Copyright(c) 2006 Sandia Corporation. Under the terms of Contract
00012  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
00013  * certain rights in this software. 
00014  * 
00015  * TiROS is free software; you can redistribute it and/or modify it under
00016  * the terms of the GNU General Public License as published by the Free
00017  * Software Foundation; either version 2 or (at your option) any later version.
00018  *
00019  * TiROS is distributed in the hope that it will be useful, but WITHOUT ANY
00020  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00021  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00022  * for more details.
00023  *
00024  * You should have received a copy of the GNU General Public License along
00025  * with TiROS; if not, write to the Free Software Foundation, Inc.,
00026  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00027  *
00028  * As a special exception, if other files instantiate templates or use macros
00029  * or inline functions from this file, or you compile this file and link it
00030  * with other works to produce a work based on this file, this file does not
00031  * by itself cause the resulting work to be covered by the GNU General Public
00032  * License. However the source code for this file must still be made available
00033  * in accordance with section (3) of the GNU General Public License.
00034  *
00035  * This exception does not invalidate any other reasons why a work based on
00036  * this file might be covered by the GNU General Public License.
00037  *
00038  */
00039 
00040 
00041 /**
00042  * @page config_usage TiROS Configuration
00043  * <H2> Main Configuration Options </H2>
00044  * These configuration options can be placed in the proj_config.h file.
00045  * <DL>
00046  *    <DT> TIROS_MAX_ISR_NESTING [1]:<DD>  Define the maximum
00047  *    nesting level for ISRs.   TiROS supports nested
00048  *    interrupts.  By default, TIROS_MAX_ISR_NESTING is set to 1. This
00049  *    specifies that only one ISR will run at a time (interrupts should
00050  *    not be enabled within ISRs.)   TiROS cannot enforce this, so the
00051  *    user should ensure that interrupts are not reenabled within an
00052  *    ISR beyond this defined level. \sa isr.
00053  *    <DT> TIROS_MAX_PROCS: <DD> (Integer value) The maximum number of tasks.
00054  *    This should also include the idle task.
00055  *    <DT> TIROS_ENABLE_MUTEX [1 | 0] : <DD> By default mutexes are
00056  *    enabled.  If they should be disabled, then define
00057  *    TIROS_ENABLE_MUTEX to be 0 in the proj_config.h file.
00058  *    <DT> TIROS_MAX_MUTEXES [255]: <DD> Maximum number or mutexes
00059  *    that can be held by a single task.  This can be overridden by
00060  *    defining TIROS_MAX_MUTEXES in proj_config.h
00061  *    <DT> TIROS_ALLOW_SLEEP_W_MUTEX [0 | 1] : <DD>By default TiROS does
00062  *    not allow tasks that are holding a mutex to sleep. An error code
00063  *    is returned.  This is done to prevent unbounded locking.  This
00064  *    behaviour can be overridden by defining this directive to 1 in
00065  *    the user's configuration file.
00066  *    <DT> TIROS_PRIO_INHERIT_PROTOCOL: <DD> Define this in the user configuration
00067  * file, if priority inheritance will be used.  By default, priority
00068  * ceiling will be used.
00069  *    <DT> TIROS_ENABLE_CSEM [1 | 0] : <DD> By default counting semaphores are
00070  *    enabled.  If they should be disabled, then define
00071  *    TIROS_ENABLE_CSEM to be 0 in the proj_config.h file.
00072  *    <DT> TIROS_ENABLE_MSGQ [1 | 0] : <DD> By default message queues are
00073  *    enabled.  If they should be disabled, then define
00074  *    TIROS_ENABLE_MSGQ to be 0 in the proj_config.h file.
00075  *    <DT> TIROS_ENABLE_EFLAG [1 | 0] : <DD> By default event flags are
00076  *    enabled.  If they should be disabled, then define
00077  *    TIROS_ENABLE_EFLAG to be 0 in the proj_config.h file.
00078  *    <DT> TIROS_USER_CTXT_UPCALL: <DD> This can be used to perform user defined
00079  *    functions when tasks are switched.  This  is an upcall made by
00080  *    the scheduler upon task switch.  If this is defined, the
00081  *    user_ctxt_upcall function defined in the API MUST be implemented by
00082  *    the user.   This feature can be used in imaginative
00083  *    ways to set task-specific settings.  For example, a user can
00084  *    implement per task power control. \sa os_advanced.
00085  *    <DT> TIROS_DEBUG_LEVEL 0-4 [0]: <DD> Debugging messages can be
00086  *    output from TiROS by setting TIROS_DEBUG_LEVEL.
00087  *    \verbatim
00088       0 - No debugging messages.
00089       1 - Critical error messages.
00090       2 - Adds warning mesages.
00091       3 - Adds informational messages.
00092       4 - Adds trace messages.
00093       \endverbatim
00094       The debugging messages are output by calling the putchar()
00095       function.  This function may be adapted by the user to direct
00096       the output to a serial port, or to a file depending on the
00097       hardware platform. \sa os_advanced.
00098  *    <DT> TIROSINT_DATA_DEBUG : <DD> If this is defined, the
00099  *    functions to access internal TiROS data structures is enabled.
00100  *    This is useful for debugging.  \sa os_advanced.
00101  *    <DT> TIROS_STK_CHECK : <DD> If this is defined, TiROS keeps
00102  *    track of additional information that can be used for getting
00103  *    useful information about stack usage.  \sa os_advanced.
00104  *    <DT> TIROS_C90_COMPATIBLE [0 | 1]: <DD> Use code downward compatible with an
00105  *    ISO C90 standard compiler. The code of concern is the definition
00106  *    of the message queue structure.  Some older compilers or strict
00107  *    C++ compilers don't support zero-length array/flexible
00108  *    arrays/variable-length array/.  These are useful as the last
00109  *    element of a structure which is really a header for a variable
00110  *    length object.  TiROS uses such a construct to save memory when
00111  *    initializing message queues. 
00112  *    The default behaviour is to work with GCC or
00113  *    any ISO C99 standard compiler.  If your compiler complains that
00114  *    struct msgQ or msgQ_t has incomplete type or that the sizeof
00115  *    operator cannot be applied to this struct, then define this to
00116  *    be 1 in your proj_config.h file. 
00117  *
00118  *    <DT> TiROS Data Type configuration: <DD>  Some of the data types used within
00119  *        TiROS data structures can be modified by the user.
00120  *        Normally, this is not necessary.  In special cases, the user
00121  *    may want to override the defaults.  For example, by default, the
00122  *    counting semaphores use an 8 bit integer (signed) to represent
00123  *    count. This limits the maximum count to 127.  The user can
00124  *    override this default and force TiROS to use a 16 bit integer for
00125  *    the count.  This vastly increases the count range.  For a
00126  *    comprehensive list of these options, see tr_types.h.
00127  *
00128  *   <DT> Other options: <DD> There can be other hardware port specific configuration
00129  * options.  For a description of this, look in the tr_port.h file in the
00130  * appropriate port directory.   
00131  * </DL>
00132  *
00133  * @page os_api Application Programming Interface (API)
00134  * <H2> The Application Programming Interface (API) is described in
00135  *     the following major sections.</H2>
00136  * <OL>
00137  *   <LI> \ref crit_secs.
00138  *   <LI> \ref isr.
00139  *   <LI> \ref os_initialization.
00140  *   <LI> \ref os_task.
00141  *   <LI> \ref os_time.
00142  *   <LI> \ref os_time_utils.
00143  *   <LI> \subpage os_sync.
00144  *   <LI> \ref os_advanced.
00145  * </OL>
00146  */
00147 
00148 
00149 
00150 
00151 #include <tiros/tr_types.h>
00152 
00153 
00154 
00155 
00156 /** @defgroup func_options  Function Options
00157  * These option flags can be used with the various API functions.
00158  * @{ */
00159 
00160 /** Do not block while performing this command. */
00161 #define O_NONBLOCKING           0x01
00162 
00163 /** Use effective priority instead of real priority for this
00164     command. */
00165 #define O_EFFECTIVE_PRIO        0x01
00166 
00167 /** Use relative time instead of absolute time */
00168 #define O_RELATIVE_TIME         0x02
00169 
00170 
00171 
00172 /** Clear an event flag instead of setting it.
00173  * This is only used while setting an event flag. */
00174 #define O_EFLAG_CLEAR           0x04
00175 
00176 /** Trigger an event flag, rather than permanently setting it 
00177  * This is only used while setting an event flag. */
00178 #define O_EFLAG_TRIGGER         0x08
00179 
00180 /**  Wait for all the events corresponding to requested bits.
00181  * Only applicable to event flags. */
00182 #define O_EFLAG_AND             0x04
00183 
00184 /** Wait for any of the events correspoind to the requested bits. */
00185 #define O_EFLAG_OR              0x00
00186 
00187 
00188 /** @} */
00189 
00190 
00191 
00192 /** @defgroup crit_secs Critical Sections
00193  * 
00194  * Critical Sections can be used to prevent preemption.
00195  * Within a
00196  * critical section, a task will not be interrupted. The following
00197  * code structure is used to implement critical sections:
00198  * 
00199  Eg.
00200  *\code
00201  * unsigned char port_status;  // This is global, may be accessed
00202  *                             // through an interrupt and its
00203  *                             // access must be protected with
00204  *                             // critical sections
00205  *
00206  * void tst(void) {
00207  *  int a;
00208  *  char x;
00209  *  char txt[20];
00210  *  OS_CRITICAL_ENABLE();  // This should be declared immediately after
00211  *                        // other variable declarations.
00212  *
00213  *  tst[0] = 3;
00214  *
00215  *  OS_CRITICAL_BEGIN();      // Protect port_status using critical
00216  *  if (port_status) {        // sections 
00217  *      x = port_status;
00218  *      port_status = 0;
00219  *  }
00220  *  OS_CRITICAL_END();
00221  * }
00222  * \endcode
00223  * @{ */
00224 
00225 /** Enable a critical section within a function. 
00226  * This must be the first call in the functions after the variable
00227  * declarations. This has to be called before  OS_BEGIN_CRITICAL() or
00228  *  OS_CRITICAL_END() can be called.  See example for critical sections. */
00229 #define OS_CRITICAL_ENABLE()     OS_PORT_CRITICAL_ENABLE()
00230 
00231 /** Begin a critical section.
00232  *  
00233  *  This should always be matched with an
00234  *   OS_CRITICAL_END() in the same function. Critical sections should be
00235  *  enabled in the function using  OS_CRITICAL_ENABLE() */
00236 #define OS_CRITICAL_BEGIN()      OS_PORT_CRITICAL_BEGIN()
00237 
00238 /** End a critical section.
00239  * This should be matched to a corresponding \ref OS_BEGIN_CRITICAL() call. */
00240 #define OS_CRITICAL_END()        OS_PORT_CRITICAL_END()
00241 
00242 /** Explicitly enable interrupts.
00243  * Ideally, there should be no need to use this call.  The
00244  * OS_CRITICAL_BEGIN() and  OS_CRITICAL_END() calls are much safer,
00245  * since they will store the interrupt state at the beginning of a
00246  * critical section and restore the state at the end of a critical
00247  * section.  There might be rare occassions where this call may be
00248  * needed (for example to explicitly re-enable interrupts within an
00249  * ISR) */
00250 #define OS_INT_ENABLE()          OS_PORT_INT_ENABLE()
00251 
00252 
00253 /** Explicitly disable interrupts.
00254  * Ideally, there should be no need to use this call.  The
00255  *  OS_CRITICAL_BEGIN() and  OS_CRITICAL_END() calls are much safer,
00256  * since they will store the interrupt state at the beginning of a
00257  * critical section and restore the state at the end of a critical
00258  * section.  There might be rare occassions where this call may be
00259  * needed to explicitly disable interrupts. */
00260 #define OS_INT_DISABLE()          OS_PORT_INT_DISABLE()
00261 
00262 
00263 /** @}  End Critical Sections. */
00264 
00265 
00266 
00267 /** @defgroup isr Usage with Interrupt Service Routines
00268  * TiROS API calls can be used within ISRs.
00269  * Mark the beginning and end of an ISR, so that TiROS can
00270  * appropriately perform task scheduling if needed.  
00271  * Interrupt service routines are notoriusly hardware and compiler
00272  * dependent, so use the instructions for your  hardware/compiler
00273  * port.
00274  *
00275  * TiROS supports three ways of servicing interrupts:
00276  * <OL>
00277  *  <LI> Simple Usage:  An ISR can be written as
00278  * you would normally write one for your hardware only if all of the
00279  * following are true:
00280  *  <UL> 
00281  *        <LI> Interrupts will stay disabled while the ISR is being
00282  * invoked.
00283  *        <LI> The ISR will not call any TiROS api calls.
00284  *        <LI> The ISR will not perform any action that will cause any
00285  * task to become unblocked, or in general, will not change the state
00286  * of any task.
00287  * </UL> 
00288  *  <LI> Saving context per interrupt response: This is the standard
00289  * way to service interrupts. Due to the presence of an OS, the
00290  * sequence of steps to be taken are as follows:
00291  * \code
00292  *     function ISR( ) {
00293  *        stkptr = save_context_of_task();  // See port instructions.
00294  *         // stkptr = pointer to stack of saved task.
00295  *         
00296  *         perform_functions();
00297  *        newstkptr = osint_taskswitcher(stkptr);
00298  *        load_context_of_newtask(newstkptr);    
00299  *     }
00300  * \endcode
00301  * The exact implementation depends on the hardware port. See the port
00302  *        documentation for more details.
00303  *        
00304  *       
00305  * <LI> Using Kernel Traps: TiROS can take advantage of  hardware
00306  *        architectures that can support a software initiated
00307  *        interrupt (kernel trap).  This is the most preferable
00308  *        option because interrupt service routines have very low
00309  *        overhead and can yet use all of the TiROS calls and interact
00310  *        with tasks.  If your port supports this, use this.  It also
00311  *        makes writing the ISRs very simple. The way this works is
00312  *        that the context of a task is not saved on entry to the
00313  *        ISR. Instead, at the end of the ISR,  OS_ISR_END() determines
00314  *        if the task has to be switched out. If so, it invokes a
00315  *        kernel trap.  The kernel trap is entered as soon as the ISR
00316  *        ends. The kernel trap performs the context switch. 
00317  *        Thus, the context switch overhead is only invoked when
00318  *        necessary, not at every ISR.
00319  * Eg. 
00320  * \code
00321  * void ISR_function(void) 
00322  * {
00323  *   int x;
00324  *   OS_CRITICAL_ENABLE();   // Only needed if any critical sections
00325  *                           // will be used and interrupt nesting is enabled.
00326  *
00327  *   OS_ISR_BEGIN();         // Mark the beginning of an ISR. Note
00328  *                           // that if OS_CRITICAL_ENABLE() is also
00329  *                           // present, then this comes after 
00330  *                           // that. 
00331  *  
00332  *  x = 3;
00333  *    Do more stuff ....
00334  *  
00335  *  OS_ISR_END();
00336  * }
00337  * \endcode
00338  * 
00339  * </OL>
00340  * TiROS supports nested interrupts.  However, for reliability, try
00341  * not to use nested interrupts unless absolutely necessary.
00342  * Interrupt service routines use the stack of the task that was
00343  * running when the interrupt occured.  Nested interrupts can cause
00344  * the stack to grow unpredictably and overflow.
00345  * 
00346  * To use nested interrupts, write code as below:
00347  * \code
00348  * extern uint8_t os_isr_nesting; // Internal TiROS variable that keeps track
00349  *                                // of nesting level.
00350  * void ISR_function(void) 
00351  * {
00352  *   int x;
00353  *   OS_CRITICAL_ENABLE();   // Only needed if any critical sections
00354  *                           // will be used and interrupt nesting is enabled.
00355  *
00356  *   OS_ISR_BEGIN();         // Mark the beginning of an ISR. Note
00357  *                           // that if OS_CRITICAL_ENABLE() is also
00358  *                           // present, then this comes after 
00359  *                           // that. 
00360  *
00361  *  if (os_isr_nesting < TIROS_MAX_ISR_NESTING) {
00362  *     // Interrupts should only be reenabled if the current nesting level
00363  *     // is less than or equal to the maximum configured nesting level.
00364  *     renable_interrupts();
00365  *  }
00366  *  x = 3;
00367  *    Do more stuff ....
00368  *  
00369  *  OS_ISR_END();
00370  * }
00371  * \endcode
00372  *
00373  * @{ */
00374 
00375 
00376 
00377 /** Enable this within ISRs immediately after any variable
00378  *  declarations, and after any OS_CRITICAL_ENABLE(). */
00379 #define OS_ISR_BEGIN()           OS_PORT_ISR_BEGIN()
00380 
00381 /** Mark the end of an ISR. 
00382  *  This should be called at the end of an ISR.  There must exist a
00383  *  corresponding OS_ISR_BEGIN() statement.
00384 */
00385 void OS_ISR_END(void);
00386 /** @} */
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 /** @defgroup os_initialization OS initialization and running
00395  * Routines to initialize and start the OS.
00396  * @{ */
00397 
00398 /** Initialize the OS.
00399  * This initializes the OS data structures.  This should be the first
00400  * OS API called. */
00401 void os_init(void);
00402 
00403 /** Start the OS by running tasks in the ready list.
00404  * Note: Tasks should have been created and made ready to run before
00405  * this function is called. */
00406 void os_start(void);
00407 /** @} */
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 /** @defgroup os_task Task creation and management
00418  * This group of functions provides routines to create, delete, and
00419  * manipulate the state of tasks.
00420  * @{ */
00421 
00422 /** Minimum amount of space is oswwords (not bytes) */
00423 #define TIROS_MIN_CTXT_SZ      TRPORT_MIN_CTXT_SZ
00424 
00425 /** Task Prototype.
00426  *  This specifies the form of the function that begins a task.  
00427  */
00428 typedef  void (* taskfunc_t)(void *);
00429 
00430 
00431 
00432 /** Create a task.
00433  *
00434  * Calling Context: 
00435  *  -# Before os_start().
00436  *  -# From within a task.
00437  *  -# From an ISR.
00438  *
00439  * \code
00440   #define TASK1_STKSZ  (TIROS_MIN_CTXT_SZ  + 64)  // 64 words more than min
00441   osword_t task1_stk[TASK1_STKSZ]; 
00442   void task1(void *arg)
00443   {
00444   //  Task does something. never exits 
00445   }
00446   
00447   void main(void)
00448   {
00449     tid_t t1_tid;
00450     tid_t idle_tid; 
00451     int arg_to_pass_to_task1
00452     os_init();
00453     t1_tid = os_task_create(task1, (osptr_t) arg_to_pass_to_task1,
00454                             task1_stk, TASK1_STKSZ, TASK1_PRIO);
00455    
00456     if (t1_tid == ILLEGAL_ELEM) {
00457       error("task1 error");
00458     }  
00459               .
00460               .
00461               .
00462               
00463 
00464     os_start();     
00465   }
00466  * \endcode
00467  * @param func  Function pointer to the task.
00468  * @param param The parameter to be passed to the task.
00469  * @param stack Pointer to the stack to be used.
00470  * @param stacksize  Size of the stack. NOTE: This is specified in
00471  *                 osword_t not in bytes.  This is so that the stack
00472  *                 is not misaligned.  Use the TIROS_MIN_CTXT_SZ value
00473  *                 to help in sizing the stack appropriately.
00474  * @param priority  Task priority.
00475  * @return ID of the task created or ILLEGAL_ELEM if call failed. This
00476            happens if there are no TCBs or if a task is already
00477            allocated to the priority level. */
00478 tid_t os_task_create(taskfunc_t func, /*@shared@*/ osptr_t param, 
00479                      /*@shared@*/ osword_t *stack, osword_t stacksize, 
00480                      tid_t priority);
00481 
00482 
00483 /** A task's self identification
00484  *
00485  * Calling Context: 
00486  *  -# From within a task.
00487  *  -# From an ISR.
00488  *
00489  * @return  Return the task id or ILLEGAL_ELEM if called from an ISR. */
00490 tid_t os_self_tid(void);
00491 
00492 
00493 /** Set the priority of a task.
00494  * This modifies the base priority of a task.
00495  * The function returns \ref SUCCESS if the priority change was successful
00496  * OR if the current priority of the task is the same as the desired
00497  * priority.
00498  * When the default priority ceiling algorithm is used for mutual
00499  * exclusion,  the priority of a task holding a mutex cannot be
00500  * changed.  Attempting this returns \ref ERR_WOULDBLOCK_MUTEX
00501  *
00502  * Calling Context: 
00503  *  -# From within a task.
00504  *  -# From an ISR.
00505  *
00506  * @param task  ID of the task to have a priority change.
00507  * @param prio  New priority.
00508  * @return {\ref SUCCESS,         
00509  *          \ref ERR_NOSUCHTASK, 
00510  *          \ref ERR_PRIO_IN_USE, 
00511  *          \ref ERR_WOULDBLOCK_MUTEX    }. */
00512 int8_t os_prio_set(tid_t task, tid_t prio);
00513 
00514 
00515 
00516 /** Get the priority of a task.
00517  * @param task  ID of the task whose priority is queried.
00518  * @param options Get either the real or effective priority.  If
00519  * \ref O_EFFECTIVE_PRIO is specified, then the effective priority is
00520  * returned. 
00521  *
00522  * Calling Context: 
00523  *  -# Before os_start().
00524  *  -# From within a task.
00525  *  -# From an ISR.
00526  *
00527  * @param task ID of the task
00528  * @param options [ \ref O_EFFECTIVE_PRIO ]
00529  * @return ILLEGAL_ELEM if failed or the task priority */ 
00530 tid_t os_prio_get(tid_t task, uint8_t options);
00531 
00532 /** Delete a task.
00533  * A task can be deleted if it is not in possession of any mutexes.
00534  * A task can also delete itself.
00535  *
00536  * Calling Context: 
00537  *  -# From within a task.
00538  *  -# From an ISR.
00539  *
00540  * @param task  Task to be deleted.  This can be the current task.
00541  * @return  {\ref SUCCESS, 
00542  *           \ref ERR_NOSUCHTASK, 
00543  *           \ref ERR_TASKBLOCKED}. */
00544 int8_t os_task_del(tid_t task);
00545 
00546 /** Suspend a task.
00547  *  A task can only be suspended if it is not holding any mutexes.
00548  *   This is by design: If a task holding a mutex were to be
00549  *  suspended, it could result in a priority inversion or starvation.  
00550  *  A task can also suspend itself. In this case, it will only resume
00551  *  running after some other task resumes it (\sa os_task_resume).
00552  *  When the task resumes, it returns \ref SUCCESS (not
00553  *  \ref ERR_RESUMED), since this is the intended operation.
00554  *
00555  * Calling Context: 
00556  *  -# From within a task.
00557  *  -# From an ISR.
00558  *
00559  * @param task  Task to be suspended. 
00560  * @return  {\ref SUCCESS, 
00561  *           \ref ERR_NOSUCHTASK, 
00562  *           \ref ERR_TASKBLOCKED} . */
00563 int8_t os_task_suspend(tid_t task);
00564 
00565 /** Resume a task.
00566  *
00567  * This call can be used to forcibly resume: 1) a task that is waiting
00568  * on a lock,  2) one that has been suspended, 3) one that is
00569  * sleeping.
00570  * The effect of this call is to make the designated task ready for
00571  * running. 
00572  * Note: a task that is  sleeping may be woken up earlier than its sleeptime, explicitly by
00573  * the resume command.  Similarly, a task that is waiting on a lock will be
00574  * forcibly readied and scheduled even before its timeout expires.
00575  * If a task is already in the ready queue, then it is not altered.
00576  *
00577  * Calling Context: 
00578  *  -# From within a task.
00579  *  -# From an ISR.
00580  *
00581  * @param task  Task to be resumed.
00582  * @return  {\ref SUCCESS, 
00583  *           \ref ERR_NOSUCHTASK }.  */
00584 int8_t os_task_resume(tid_t task);
00585 /** @} */
00586 
00587 
00588 
00589 
00590 
00591 
00592 /** @defgroup os_time  Time services provided by the OS 
00593  * This set of API calls allows time related functions.
00594  * TiROS operates with high-resolution time.  Sleep and timeouts are
00595  * specified in absolute or  relative time (using the \ref
00596  * O_RELATIVE_TIME option).  Time is represented using the 
00597  * \ref  trtime_t structure.  This structure consists of two elements:
00598  *  <OL>
00599  * <LI> A subsecond unit (could be milli-seconds, nano-seconds,etc.) </LI>
00600  * <LI> A supersecond unit ( could be a unit of 1 second, 10 secs, 1
00601  *    minute etc. </LI>
00602  * </OL>
00603  * This choice of time is kept deliberately vague, since the
00604  * application is an embedded system, where these functions have to be
00605  * fast, take advantage of the hardware, and cannot waste cycles
00606  * converting time units from the hardware representation to a
00607  * standard form.  The actual representation of the time structure is
00608  * specified by the platform specific port.
00609  * @{ */
00610 
00611 /** Get the current time.
00612  *
00613  * Calling Context: 
00614  *  -# From within a task.
00615  *  -# From an ISR.
00616  *
00617  * @param [out] curr_time Pointer to structure where the time should
00618  * be  stored. 
00619  */
00620 void os_time_get(/*@out@*/ trtime_t *curr_time);
00621 
00622 
00623 /** Set the current time.
00624  * This sets the current time.  This has to be used with care.
00625  * This can affect tasks that have been sleeping or waiting for a lock.
00626  * Such tasks will be woken up if the new time set is beyond their
00627  * wakeup deadline.
00628  * This system call may not be possible on some hardware ports.
00629  *
00630  * 
00631  * Calling Context: 
00632  *  -# From within a task.
00633  *  -# From an ISR.
00634  *
00635  * To set the time before the os has started use the hal_time_set
00636  * function directly, which is supplied by the hardware port.
00637  *
00638  * @param new_time  Pointer to structure with the new time.
00639  * @return {\ref SUCCESS,
00640  *          \ref ERR_FAILED}
00641  */
00642 int8_t os_time_set(const trtime_t *new_time);
00643 
00644 /** Wake the invoking task at a specific time.
00645  * The task can be woken up earlier by an explicit resume.
00646  * The task is not allowed to sleep if it holds a mutex lock.
00647  * This call is not allowed from an ISR.
00648  *
00649  * Calling Context: 
00650  *  -# From within a task.
00651  *  -# Call from ISR will result in an error.
00652  *
00653  * @param [in] wake_time  Time at which to be woken up.
00654  * @param  options Default is absolute time. For relative time, set
00655  *  \ref O_RELATIVE_TIME. 
00656  * @return {\ref SUCCESS, 
00657  *          \ref ERR_RESUMED, 
00658  *          \ref ERR_WOULDBLOCK_MUTEX, 
00659  *          \ref ERR_WOULDBLOCK_ISR} */
00660 int8_t os_wake_at(const trtime_t * wake_time, uint8_t options);
00661 /** @} */
00662 
00663 
00664 
00665 
00666 
00667 
00668 /** @page os_sync Task cooperation and synchronization primitives
00669  * TiROS synchronization mechanisms include mutexes, counting
00670  * semaphores, message queues, and event flags.  For all of these,
00671  * TiROS supports blocking and non-blocking operation and timeouts. 
00672  * In all cases, the highest priority task that is waiting on any of
00673  * these synchronization primitives has first access.
00674  *<OL>
00675  *<LI> \ref os_mutex.
00676  *<LI> \ref os_csem.
00677  *<LI> \ref os_msgq.
00678  *<LI> \ref os_eflag.
00679  *</OL>
00680  */
00681 
00682 #if (TIROS_ENABLE_MUTEX == 1)
00683 /** @defgroup os_mutex Mutexes
00684  * This page contains the API for mutex management.   Mutexes are used
00685  * to synchronize access by cooperating tasks to shared
00686  * resources.  For every shared resource, create an associated shared
00687  * mutex.  Mutexes should be locked by a task before beginning usage
00688  * of the shared resource and then unlocked after the usage is over.
00689  * A task cannot lock a mutex that is already locked by another
00690  * mutex.  It will either block for the mutex to unlock or will return
00691  * an error code (depending on the options used).  Mutexes must always
00692  * be used in a lock/unlock sequence.
00693  * \code
00694  * mutex_t resource_mutex; // Previously initialized (possibly in main)
00695  * void task1(void *dummy)
00696  * {
00697  *     while(1) {
00698  *       mutex_lock(&resource_mutex, 0, 0);
00699  *       do_stuff();
00700  *       mutex_unlock(&resource_mutex);
00701  *       do_other_stuff();
00702  *     }
00703  * }
00704  * \endcode
00705  * 
00706  * A detailed description of the design and implementation of
00707  * mutexes within TiROS are provided in the
00708  * \ref mutex_properties section. 
00709  *
00710  * NOTE: Always initialize before use.
00711  * @{ */
00712 
00713 /** Initialize mutex.
00714  *
00715  * Calling Context: 
00716  *  -# Before os_start().
00717  *  -# From within a task.
00718  *  -# From an ISR.
00719  * 
00720  * @param m  Pointer to mutex structure
00721  * @param prio_ceiling  The priority ceiling, if the priority celing
00722  * protocol is used.  If priority inheritance is used, then the
00723  * prio_ceiling should be set to ILLEGAL_ELEM.
00724  * The prio_ceiling MUST be unique (no task should have this as its
00725  * base priority).
00726  */
00727 void mutex_init(/*@shared@*/ mutex_t *m, tid_t prio_ceiling);
00728 
00729 /** Get mutex owner
00730  * This returns the task id of the owner of a specified mutex.  This
00731  * is an instantaneous snapshot of the state of the mutex. 
00732  * Due to preemption, the owner may have changed by the time the
00733  * callee acts on this information.
00734  * Example:
00735  * \code
00736  *    tid_t tmp;
00737  *    tmp = mutex_owner( m);  // M has been initialized previously 
00738  *    do_other_stuff();
00739  *    if (tmp == other_task)  
00740  *        do_more_stuff();    // the owner of m may have changed.
00741  * \endcode
00742  * Use critical sections to prevent a block of code from being
00743  * executed uninterrupted.
00744  * NOTE: The mutex must be intialized before this call, else the
00745  * return value is meaningless.
00746  *
00747  * Calling Context: 
00748  *  -# Before os_start().
00749  *  -# From within a task.
00750  *  -# From an ISR.
00751  *
00752  * @return The id of the mutex owner or ILLEGAL_ELEM if it is unlocked.
00753  */ 
00754 tid_t mutex_owner(/*@shared@*/ mutex_t *m);
00755 
00756 /** Lock mutex.
00757  * This is used to exclusively lock a mutex by a task.  The locking
00758  * behavior depends on the mutex protocol that has been configured.
00759  * If the specified mutex is not locked, it is locked by the calling
00760  * task at the end of the call, and a SUCCESS is returned.  Attempts
00761  * by a task to lock a mutex that it already holds also return
00762  * SUCCESS. 
00763  *  Attempts by an ISR to lock a mutex will result in an
00764  * error code of ERR_LOCK_ISR, since ISRs are not allowed to lock
00765  * mutexes. If a task already has locked TIROS_MAX_MUTEXES mutexes,
00766  * then ERR_FULL will be returned, as it is not allowed to lock any
00767  * more mutexes.
00768  * Attempts to lock a mutex owned by a different task will
00769  * result in blocking.  If the O_NONBLOCKING option is specified, then
00770  * the ERR_WOULDBLOCK error code is returned, else the task is made to
00771  * wait until the timeout, when ERR_TIMEOUT is returned.  If the
00772  * task is explicitly resumed during its wait, it receives the
00773  * ERR_RESUMED code.  
00774  *
00775  *
00776  * Calling Context: 
00777  *  -# From within a task.
00778  *  -# Call from ISR will error.
00779  *
00780  * @param m Pointer to mutex
00781  * @param timeout   Timeout. This can be 0 for infinite timeout.
00782  * @param options   Combination of [\ref O_RELATIVE_TIME | \ref O_NONBLOCKING].
00783  * @return {\ref SUCCESS , 
00784  *          \ref ERR_LOCK_ISR, 
00785  *          \ref ERR_LOCK_PRIO_CEIL,
00786  *          \ref ERR_WOULDBLOCK, 
00787  *          \ref ERR_TIMEOUT, 
00788  *          \ref ERR_RESUMED, 
00789  *          \ref ERR_FULL}.
00790  */
00791 int8_t mutex_lock(/*@shared@*/ mutex_t *m, const trtime_t* timeout, 
00792                   uint8_t  options);
00793 
00794 /** Unlock Mutex.
00795  *
00796  * Calling Context: 
00797  *  -# From within a task.  Must be owner to succeed.
00798  *  -# Call from ISR will error.
00799  *
00800  * @param m Pointer to mutex.
00801  * @return {\ref SUCCESS, 
00802  *          \ref ERR_NOTOWNER} */
00803 int8_t mutex_unlock(/*@shared@*/ mutex_t *m);
00804 /** @} */
00805 #endif /* TIROS_ENABLE_MUTEX */
00806 
00807 
00808 
00809 
00810 
00811 
00812 
00813 #if (TIROS_ENABLE_CSEM == 1)
00814 /** @defgroup os_csem Counting semaphores
00815  * Counting semaphores can be used to keep a shared count by different
00816  * tasks. They have a value between 0 to a specified MAX value.
00817  *
00818  * The P() operation (Prolaag) decreases the count of the counting
00819  * semaphore. If the count is zero, the task blocks since it cannot be
00820  * decreased further.  The V() operation (Verhoog) increments the
00821  * count of the counting semaphore.  This operation is non-blocking.
00822  *
00823  * Counting semaphores are useful for event notifications.  For
00824  * example, a message server task can perform a P() operation on a message
00825  * counting semaphore.  When a message has to be sent to the message
00826  * server, a message client task performs a V() operation on the same
00827  * semaphore. This unblocks the message server.  If multiple client
00828  * tasks send messages, the message server has a count of the number
00829  * of times the message counter has been V()ed.
00830  *  
00831  * If multiple servers are blocked on a counting semaphore, the
00832  * highest priority blocked server is alerted when the semaphore is
00833  * incremented. 
00834  *
00835  * NOTE: A custom type csemval_t is used for the semaphore count.  This is of
00836  * type signed integer.  By default, it is an 8-bit integer (max val
00837  * of 127).  This can be overridden (see tr_types.h).
00838  *
00839  * NOTE: Always initialize before use.
00840  *
00841  * \code
00842  * csem_t cs; // Previously initialized (possibly in main)
00843  * void task1(void *dummy)
00844  * {
00845  *     while(1) {
00846  *       csem_P(&cs, 0, 0);  // Wait for semaphore
00847  *       do_stuff();
00848  *     }
00849  * }
00850  * void task2(void *dummy)
00851  * {
00852  *     while(1) {
00853  *       do_stuff();
00854  *       do_other_stuff();
00855  *       // Release task1 
00856  *       csem_V(&cs);       // Release semaphore
00857  *       do_stuff();
00858  *     }
00859  * }
00860  *
00861  *
00862  * \endcode
00863 
00864  * @{ */
00865 
00866 /** Initialize counting semaphore.
00867  *
00868  * Calling Context: 
00869  *  -# Before os_start().
00870  *  -# From within a task.
00871  *  -# From an ISR.
00872  *
00873  * @param cs  Pointer to counting semaphore
00874  * @param init_val  Initial value 
00875  * @param max_val   Maximum value for the counting semaphore. The
00876  * semaphore cannot be incremented past this number.   */
00877 void csem_init(/*@shared@*/ csem_t *cs, csemval_t init_val, csemval_t max_val);
00878 
00879 /** Obtain the value of a counting semaphore
00880  * 
00881  * Calling Context: 
00882  *  -# Before os_start().
00883  *  -# From within a task.
00884  *  -# From an ISR.
00885  *
00886  * NOTE: the counting semaphore must previously have been initialized
00887  * for this to have any meaningful return value.
00888  * @param cs Pointer to counting semaphore
00889  * @return The value of the semaaphore */
00890 csemval_t csem_count(csem_t *cs);
00891 
00892 /** Decrease (prolaag) the value of a counting semaphore.
00893  *
00894  *  This decreases the value of a counting semaphore.  If the value is
00895  * zero, the caller blocks until another task increments the
00896  * semaphore OR until the timeout duration OR until another task
00897  * explicitly resumes (\sa os_task_resume) this task.
00898  * The caller can prevent blocking by using the O_NONBLOCKING option.
00899  * On success, the value returned is the value of the semaphore
00900  * immediately after the decrease.
00901  *
00902  * Calling Context: 
00903  *  -# From within a task.
00904  *  -# From an ISR (error if blocking needed).
00905  *
00906  * @param cs Pointer to counting semaphore
00907  * @param timeout  Timeout.  This can be 0, for infinite timeout.
00908  * @param options   [\ref O_RELATIVE_TIME | \ref O_NONBLOCKING]
00909  * @return {Semaphore count if successful,  
00910  *          \ref ERR_WOULDBLOCK_ISR,
00911  *          \ref ERR_WOULDBLOCK_MUTEX, 
00912  *          \ref ERR_TIMEOUT, 
00913  *          \ref ERR_RESUMED } */
00914 csemval_t csem_P(/*@shared@*/ csem_t *cs,  const trtime_t* timeout, uint8_t options);
00915 
00916 /** Increase (verhoog) the value of a counting semaphore.
00917  * This is a non-blocking function.  If the maximum value of the
00918  * semaphore is reached, an ERR_FULL message is returned.
00919  *
00920  * NOTE: On success, the value returned is the value of the semaphore 
00921  * immediately after the increase.  If there are other tasks waiting
00922  * to csem_P on the counting semaphore, the value returned is that
00923  * before these other tasks have completed the csem_P operation.
00924  * Example:
00925  * \code
00926  * csemval_t tmp;
00927  * // Current state of counting semaphore cs is 0.  There are two
00928  * // tasks blocked doing a csem_P on it.
00929  * tmp = csem_V(&cs);  // Value of tmp is 1, because of the csem_V
00930  * 
00931  * tmp = csem_count(&cs); // Value of tmp is 0, because one of the tasks that
00932  *                        // that was blocked on csem_P(&cs) has
00933  *                        // completed the prolaag and now the value
00934  *                        // of cs is back to zero.
00935  * \endcode
00936  *
00937  * Calling Context: 
00938  *  -# From within a task.
00939  *  -# From an ISR.
00940  *
00941  * @param cs Pointer to counting semaphore
00942  * @return {Semaphore count or \ref ERR_FULL} */
00943 csemval_t csem_V(/*@shared@*/ csem_t *cs);
00944 /** @} */
00945 #endif /* TIROS_ENABLE_CSEM */
00946 
00947 
00948 
00949 
00950 
00951 
00952 
00953 #if (TIROS_ENABLE_MSGQ == 1)
00954 /** @defgroup os_msgq Message Queues
00955  * Message Queues can be used to send arbitrary messages between
00956  * tasks.  Messages are sent in the form of generic pointers to
00957  * memory.  TiROS handles these message pointers in an opaque manner
00958  * and does not care what they point to.
00959  * It is important to note that the maximum size of the message queue
00960  * has to be known when the message queue is intialized.  It cannot be
00961  * resized on the fly.  A message server can wait on a message queue
00962  * or poll it (with the O_NONBLOCKING option).  A message client can
00963  * send a message on the queue which will unblock any waiting server.
00964  * If multiple tasks are waiting on the same message queue, the
00965  * one with the highest priority will be unblocked first.
00966  *
00967  * NOTE: A custom type mqind_t is used for the queue length.  This is of
00968  * type unsigned integer.  By default, it is an 8-bit integer (max val
00969  * of 255).  This can be overridden (see tr_types.h).
00970  *
00971  * NOTE: Always initialize before use.
00972  *
00973  * \code
00974  * #define TST_QSZ 4
00975  * osword_t tst_Q[msgQ_MEMSZ(TST_QSZ)];   // Previously initialized
00976  * void task1(void *dummy)
00977  * {
00978  *   int8_t rc;
00979  *   osptr_t rx_val;
00980  *   while(1) {
00981  *       rc = msgQ_recv( (msgQ_t*)tst_Q, 0, 0, &rx_val);
00982  *       if (rc == SUCCESS) {
00983  *          do_something(rx_val);
00984  *       }
00985  *   }
00986  * }
00987  * void task2(void *dummy)
00988  * {
00989  *   int8_t rc;
00990  *   while(1) {
00991  *       rc = msgQ_send( (msgQ_t*)tst_Q, 7); // Send 7 to task1
00992  *   }
00993  * }
00994  *
00995  * \endcode
00996  * @{ */
00997 
00998 /** Get the memory size for a message queue
00999  * This macro makes sure that the memory is word aligned.
01000  * @param qlen Length of the message queue
01001  * @return Memory occupied (in words) */
01002 #define msgQ_MEMSZ(qlen)  ((sizeof(struct msgQ) +  \
01003                 (mqind_t)qlen * sizeof(osptr_t) + \
01004                 sizeof(osword_t)-1) /   sizeof(osword_t)) 
01005 
01006 
01007 /** Initialize a message queue.
01008  *
01009  * Calling Context: 
01010  *  -# Before os_start().
01011  *  -# From within a task.
01012  *  -# From an ISR.
01013  *
01014  * @param m  Pointer to message queue
01015  * @param qlen  Length of the queue.
01016  *  NOTE: The queue memory is contained in the msgQ structure.
01017  *  It is EXTREMELY IMPORTANT that the qlen argument to this call be
01018  *  less than or equal to the length of the message queue that was
01019  *  used as an argument for msgQ_MEMSZ( ). Failing to follow this rule
01020  *  will result in buffer overflows.
01021  *
01022  * Eg.:  
01023  * \code
01024  *   msgQ_t *m;
01025  *   qlen = 10;
01026  *
01027  *   osword_t dummy[ msgQ_MEMSZ(qlen)];
01028  *   m = (msgQ_t *) dummy;
01029  *   msgQ_init(m, qlen);
01030  * \endcode
01031  * The memory should not be transient.  It should be global, or
01032  * allocated on the heap. 
01033 */
01034 void msgQ_init(/*@shared@*/ msgQ_t * m, mqind_t qlen);
01035 
01036 /** The number of messages in the queue.
01037  *
01038  * Calling Context: 
01039  *  -# Before os_start().
01040  *  -# From within a task.
01041  *  -# From an ISR.
01042  *
01043  * Note: The message queue must be initialized before this call, else
01044  * the return value is meaningless 
01045  * @param m Pointer to the message queue
01046  * @return Number of messages in the queue */
01047 mqind_t msgQ_count(/*@shared@*/ msgQ_t *m);
01048 
01049 /** Post a message to the queue.
01050  *
01051  * Calling Context: 
01052  *  -# From within a task.
01053  *  -# From an ISR.
01054  *
01055  * In the current implementation, if the queue is full, an error is
01056  * returned.  The task is not allowed to block here.  This may be
01057  * changed in the future.
01058  * @param m  Pointer to message queue
01059  * @param tx_value  The value to be added to the queue.
01060  * @return {\ref SUCCESS, 
01061  *          \ref ERR_FULL}  */
01062 int8_t msgQ_send(/*@shared@*/ msgQ_t *m, 
01063                  /*@shared@*/ osptr_t tx_value);
01064 
01065 /** Wait for message.
01066  *
01067  * Calling Context: 
01068  *  -# From within a task.
01069  *  -# From an ISR (error if blocking needed).
01070  *
01071  * @param m Pointer to message queue
01072  * @param timeout  Timeout. This can be 0 for infinite timeout.
01073  * @param options [\ref O_NONBLOCKING | \ref O_RELATIVE_TIME ].
01074  * @param [out] rx_value  Pointer to memory where the message should
01075  *                        be stored.
01076  * @return {\ref SUCCESS, 
01077  *          \ref ERR_WOULDBLOCK_ISR, 
01078  *          \ref ERR_WOULDBLOCK_MUTEX,
01079  *          \ref ERR_TIMEOUT, 
01080  *          \ref ERR_RESUMED}.
01081 */
01082 int8_t msgQ_recv(/*@shared@*/ msgQ_t *m, const trtime_t * timeout, uint8_t options, 
01083                  /*@out@*/ osptr_t* rx_value);
01084 /** @} */
01085 #endif   /* TIROS_ENABLE_MSGQ */
01086 
01087 
01088 
01089 
01090 
01091 
01092 
01093 #if (TIROS_ENABLE_EFLAG == 1)
01094 /** @defgroup os_eflag Event Flags
01095  *  Event flags allow tasks to wait for a specific combination of
01096  *  events.  An event flag is a bitmask.  Waiting tasks can specify a
01097  *  subset of the bitmask as events of interest.  They can either wait
01098  *  for ALL of the events to occur or ANY of the events to occur. 
01099  *
01100  * NOTE: Always initialize before use.
01101  * \code
01102 
01103  * eflag_t notification;   // Previously initialized
01104  * #define ALERT0  0x01
01105  * #define ALERT1  0x02
01106  * void task1(void *dummy)
01107  * {
01108  *   int8_t rc;
01109  *   while(1) {
01110  *       rc = eflag_wait( &notification, ALERT0, 0, 0, );
01111  *       if (rc == SUCCESS) {
01112  *          do_something();
01113  *       }
01114  *   }
01115  * }
01116  * void task2(void *dummy)
01117  * {
01118  *   int8_t rc;
01119  *   while(1) {
01120  *       // Trigger event
01121  *       rc = eflag_set(&notification, ALERT0|ALERT1, O_EFLAG_TRIGGER); 
01122  *       do_other_stuff();
01123  *   }
01124  * }
01125  *\endcode
01126  *
01127  * @{ */
01128 
01129 /** Initialize an event flag. *
01130  *
01131  * Calling Context: 
01132  *  -# Before os_start().
01133  *  -# From within a task.
01134  *  -# From an ISR.
01135  *
01136  *  @param ef Pointer to the event flag.
01137  *  @param initval Initial value for the event flag */
01138 void eflag_init(eflag_t *ef, flag_t initval);
01139 
01140 /** Set an event flag. 
01141  *
01142  * Calling Context: 
01143  *  -# From within a task.
01144  *  -# From an ISR.
01145  *
01146  * @param ef Pointer to the event flag.
01147  * @param setbits The new bitvalues to be set or cleared.
01148  * @param options [\ref O_EFLAG_CLEAR, \ref O_EFLAG_TRIGGER]
01149  *\verbatim
01150    O_EFLAG_CLEAR   : Clear the specified bits.  Default is to set them. 
01151    O_EFLAG_TRIGGER : Just pulse the values in the prescribed
01152                      fashion. Don't set them permanently.  If any of the 
01153                      flag values were set before the trigger, they stay
01154                      set after the call.
01155  \endverbatim
01156  * @return {\ref SUCCESS,  
01157  *          \ref ERR_FAILED}
01158  **/
01159 int8_t eflag_set(eflag_t *ef, flag_t setbits, uint8_t options);
01160 
01161 /** Peek at the value of an event flag.
01162  * This can be used for polling.
01163  *
01164  * Calling Context: 
01165  *  -# Before os_start().
01166  *  -# From within a task.
01167  *  -# From an ISR.
01168  *
01169  * @param ef Pointer to the flag.
01170  * @return Current setting for the event flag */
01171 flag_t eflag_get(eflag_t *ef);
01172 
01173 /** Wait for an event flag.
01174  *
01175  * A blocking call from an ISR will result in an error. So, there is
01176  * usually no need to call this from an ISR. eflag_get may be
01177  * preferable. 
01178  *
01179  * Calling Context: 
01180  *  -# From within a task.
01181  *  -# From an ISR (error if blocking needed).
01182  *
01183  * @param     ef Pointer to the event flag.
01184  * @param     checkbits  Bits to be checked.
01185  * @param [in] timeout  Timeout. This can be 0 for infinite timeout.
01186  * @param options [\ref O_NONBLOCKING | \ref O_RELATIVE_TIME | 
01187  *                 \ref O_EFLAG_AND | \ref O_EFLAG_OR ].
01188  * @return {\ref SUCCESS, 
01189  *          \ref ERR_WOULDBLOCK_ISR, 
01190  *          \ref ERR_WOULDBLOCK_MUTEX,
01191  *          \ref ERR_TIMEOUT, 
01192  *          \ref ERR_RESUMED}
01193  */
01194 int8_t eflag_wait(eflag_t *ef, flag_t checkbits, const trtime_t * timeout, 
01195                  uint8_t options );
01196 /** @}  End Eflags */
01197 #endif   /* TIROS_ENABLE_EFLAG */
01198 
01199 
01200 
01201 /** @defgroup os_advanced Advanced Features and Debugging
01202  * TiROS has API calls for debugging and per-task customization.
01203  * 
01204  * <H4> Notification of context switching </H4>
01205  * Using the TIROS_USER_CTXT_UPCALL feature, a user supplied function, 
01206  * user_ctxt_upcall(), can be kept informed of context switching.
01207  * This can be used in creative ways to implement per-task hardware
01208  * customization.  For example, the upcall can be used to save the
01209  * low-power state of the current task and set the low-power state of
01210  * the next task.  This will result in per-task power control.
01211  *
01212  * <H4> Debugging with TiROS </H4>
01213  * Two types of debugging information can be retrieved from TiROS.
01214  * <OL>
01215  * <LI> One
01216  * is a simple text based error log that is activated by setting
01217  * TIROS_DEBUG_LEVEL higher than 0.  Output messages depend on the
01218  * debug level.
01219      \verbatim
01220       0 - No debugging messages.
01221       1 - Critical error messages.
01222       2 - Adds warning mesages.
01223       3 - Adds informational messages.
01224       4 - Adds trace messages.
01225       \endverbatim
01226  * The debug output from TiROS gets channeled to the putchar(int char)
01227  * function. To get debugging information, ensure that putchar() is
01228  * properly implemented.  By implementing putchar() appropriately, the
01229  * output can be directed to a serial port or to a file.
01230  * 
01231  * </LI>
01232  * <LI> Another method of debugging (and the most powerful) is to periodically capture the
01233  * internal state of TiROS.  This is done by a user task by calling
01234  * the osint_snapshot function. To enable this function, define
01235  * TIROSINT_DATA_DEBUG in the proj_config.h file, and include
01236  * tr_debug.h in your source file.  The osint_snapshot() function can be used to
01237  * capture the TiROS state into a memory buffer (no need for putchar()) which
01238  * can then be output as  desired.   An example of the use of this
01239  * form of debugging is provided as an example in os_examples/os_debug_example
01240  * </LI>
01241  * </OL>
01242 
01243  *
01244  * @{ */
01245 
01246 
01247 #ifdef TIROS_USER_CTXT_UPCALL
01248 /** User context upcall when the scheduler schedules tasks.
01249  * This upcall can be used to inform the user program of task
01250  * rescheduling.  This function is only available if TIROS_USER_CTXT_UPCALL
01251  * is defined.  This function is not implemented by the OS.  It should be
01252  * implemented by the user and TIROS_USER_CTXT_UPCALL should be defined in
01253  * the proj_config.h file if this feature 
01254  * @param curr_task  The task id of the task being switched out.
01255  * @param next_task  The next task that is going to run.
01256  */
01257 void user_ctxt_upcall(tid_t curr_task, tid_t next_task);
01258 #endif
01259 
01260 /** @} */
01261 
01262 
01263 
01264 
01265 /** @defgroup ret_codes Return Codes.
01266  *
01267  * The common return codes and their descriptions are given
01268  * below. Error return codes have a major and minor number.  The major
01269  * number provides the error family.  The minor number gives more detail.
01270  * @{ */
01271 
01272 /** Extract the major error code out of the return value */
01273 #define ERR_MAJOR(x) (x & (~7) )
01274 /** Extract the minor error code out of the return value */
01275 #define ERR_MINOR(x) (x & 7)
01276 
01277 
01278 /** Notation for an invalid task */
01279 #define ILLEGAL_ELEM  ((tid_t) ~0)
01280 
01281 
01282 /** Return code success. */                  
01283 #define SUCCESS                 0       
01284 
01285 /** Minor error code indicating that error occurence was due to
01286  *  invocation from an ISR */
01287 #define EMINOR_ISR              0x01
01288 
01289 /** Minor error code indicating that action would violate rules to
01290  *  prevent priority inversion */
01291 #define EMINOR_PRIO_RULE        0x02
01292 
01293 
01294 
01295 
01296 /** Mutex locking error */
01297 #define ERR_LOCK                -8
01298 
01299 /** Mutex locking error: locking from ISR */
01300 #define ERR_LOCK_ISR            (ERR_LOCK | EMINOR_ISR)
01301 
01302 /** Mutex locking error: denied by priority ceiling  */
01303 #define ERR_LOCK_PRIO_CEIL      (ERR_LOCK | EMINOR_PRIO_RULE)
01304 
01305 
01306 
01307 
01308 /** Operation would cause blocking, option O_NONBLOCKING  specified */
01309 #define ERR_WOULDBLOCK          -16
01310 
01311 /** This has been called from an ISR but would result in blocking */
01312 #define ERR_WOULDBLOCK_ISR      (ERR_WOULDBLOCK | EMINOR_ISR)
01313 
01314 /** This call would block and is denied because a Mutex is being held.
01315  *  The current combination of synchronization primitives would
01316  *     result in the unwanted blocking of a mutex.  */
01317 #define ERR_WOULDBLOCK_MUTEX    (ERR_WOULDBLOCK | EMINOR_PRIO_RULE)
01318 
01319 
01320 
01321 
01322 
01323 /** A message queue is full or a counting semaphore is maxed out */
01324 #define ERR_FULL                -24
01325 
01326 
01327 
01328 /** Failure: Not the owner of the specified mutex, or the mutex is not
01329  * locked.*/
01330 #define ERR_NOTOWNER            -32
01331 
01332 
01333 
01334 /** A timeout has occured. */
01335 #define ERR_TIMEOUT             -40
01336 
01337 /** Task was resumed while sleeping or waiting for a lock */
01338 #define ERR_RESUMED             -48
01339 
01340 
01341 /** Specified task does not exist. */
01342 #define ERR_NOSUCHTASK          -56
01343 
01344 
01345 /** The operation cannot be completed because a specified task
01346  *    is blocked. */
01347 #define ERR_TASKBLOCKED         -64
01348 
01349 /** The operation failed because the desired priority is in use */
01350 #define ERR_PRIO_IN_USE         -72
01351 
01352 /** Failure: reason unspecified. */
01353 #define ERR_FAILED              -80
01354 
01355 
01356 /** @} ret_codes */
01357 
01358 
01359 
01360 #endif

TiROS User Manual: Last Updated on Fri Jul 20 10:52:23 2007