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( ¬ification, 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(¬ification, 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