tr_port.h

Go to the documentation of this file.
00001 
00002 /* Author: Ratish J. Punnoose, 2006
00003  * This file is part of TiROS, the Tickless Real-Time Operating System.
00004  * Copyright(c) 2006, 2007: Ratish J. Punnoose.
00005  * Copyright(c) 2006 Sandia Corporation. Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
00007  * certain rights in this software. 
00008  * 
00009  * TiROS is free software; you can redistribute it and/or modify it under
00010  * the terms of the GNU General Public License as published by the Free
00011  * Software Foundation; either version 2 or (at your option) any later version.
00012  *
00013  * TiROS is distributed in the hope that it will be useful, but WITHOUT ANY
00014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016  * for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License along
00019  * with TiROS; if not, write to the Free Software Foundation, Inc.,
00020  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00021  *
00022  * As a special exception, if other files instantiate templates or use macros
00023  * or inline functions from this file, or you compile this file and link it
00024  * with other works to produce a work based on this file, this file does not
00025  * by itself cause the resulting work to be covered by the GNU General Public
00026  * License. However the source code for this file must still be made available
00027  * in accordance with section (3) of the GNU General Public License.
00028  *
00029  * This exception does not invalidate any other reasons why a work based on
00030  * this file might be covered by the GNU General Public License.
00031  *
00032  */
00033 
00034 
00035  /** \file
00036  * @brief Posix port of the RTOS.  
00037  *
00038  * @page posix_port  Posix HAL
00039  * This port makes a posix system look like real
00040  * hardware to TiROS. TiROS runs within a posix process. 
00041  * This port provides the 
00042  * context switching and time 
00043  * functions to TiROS.
00044  * It simulates interrupts using posix signals.
00045  *  The posix port does not use kernel traps (They work
00046  *  on  Linux but do not work reliably on Cygwin).  
00047  * The signal implementation under Cygwin is such that storing and
00048  * restoring a  context within a signal handler does not work
00049  * properly. So we bypass this for the Cygwin environment and use
00050  * direct Win32 api calls.
00051  * This port has been tested on Linux 2.6.x kernel series/Glibc and on
00052  * Cygwin 5.1.
00053  * This port does not work on Mac OS X (as of 10.4), because the
00054  * needed posix functions are not implemented.
00055  *
00056  * This port does not allow the time to be set.
00057  *
00058  * Currently, this port does not use the user provided stack memory
00059  * for the task stack.  This port stores the context on the user
00060  * provided memory.  For the task stack, it allocates new memory
00061  * (memory size defined by TIROS_POSIX_STKSZ)
00062  *
00063  * <H2> Configuration Options: </H2>
00064  * <DL>
00065  *  <DT> PORT_TIMER_TYPE : <DD>Options are 1 or 2.  Setting PORT_TIMER_TYPE to 1
00066  * uses the system real time.  Setting PORT_TIMER_TYPE to 2, uses the
00067  * process time. This option is irrelevant to Cygwin as only real time
00068  * is available.
00069  *  <DT> TIROS_POSIX_STKSZ : <DD> The stack size allocated to each task.
00070  *  When os_task_create is called, the stack location and stack size
00071  * for the task are passed along to the port. The Posix port stores
00072  * the context at this provided stack location.  The context size is
00073  * fixed based on the registers etc.  The rest of this provided stack
00074  * is unused.  The stack for the task is allocated separately using a
00075  * mmap. By default, this stack is 16384 bytes.  This was done because
00076  * sometimes simple calls like printf  on a posix system will easily
00077  * overrun a small stack (tens of bytes) that might be specified for an embedded
00078  * system.  Allocating a larger stack on a posix system might help in
00079  * running the code on both platforms without modification.  Override
00080  * the default by specifying TIROS_POSIX_STKSZ.
00081  * </DL>
00082  * 
00083  *  
00084  * <H2>Writing ISRs for the Posix port</H2>
00085  *  The posix port uses unix/posix
00086  * signals to fake interrupts.  Interrupt handlers are thus signal
00087  * handlers.  The posix port does not use kernel traps (for
00088  * compatibility).  So the form of the ISR must be as follows.
00089  * 
00090  * \code
00091  * extern int halint_kernel_trap_flagged;  // Flag in hal
00092  * extern uint8_t os_isr_nesting;
00093  * void signal_handler(int sig)
00094  * { 
00095  *   OS_ISR_BEGIN();
00096  *   halint_kernel_trap_flagged = 0;
00097  *   // Perform actions
00098  *   xxx();
00099  *   
00100  *     // Re-enable interrupts if desired
00101  *   if (os_isr_nesting  < TIROS_MAX_ISR_NESTING) {
00102  *      OS_INT_ENABLE();
00103  *      yyy();
00104  *   } 
00105  *   zzz();
00106  *   // End actions
00107  *   OS_ISR_END();
00108  *   if (halint_kernel_trap_flagged) {
00109  *      hal_ctxt_switch();
00110  *   }
00111  * }
00112  * \endcode
00113  *
00114  */
00115 
00116 
00117 
00118 #ifndef __POSIX_TIROS_PORT_H
00119 #define __POSIX_TIROS_PORT_H
00120 
00121 
00122 /*@ignore@*/
00123 #include "proj_config.h"
00124 /*@end@*/
00125 
00126 
00127 #include <signal.h>
00128 #include <stdint.h>
00129 
00130 #define subtime_t long
00131 #define LT_INLINE static inline
00132 
00133 
00134 #include <tiros/tr_time.h>
00135 #include "porttime.h"
00136 
00137 
00138 /* Define the value of infinite time for this port */
00139 #define TRPORT_INF_TIME {~0 , ~0 }
00140 
00141 
00142 /* The posix port does not use register passing. It is almost
00143     impossible to implement in a portable manner. */
00144 /* #define TIROS_REGISTER_PASSING */
00145 
00146 
00147 
00148 
00149 #ifndef  TIROS_POSIX_STKSZ  
00150 #define TIROS_POSIX_STKSZ  16384
00151 #endif
00152 
00153 /* Define basic types for   the hardware word, boolean, and pointer */
00154 typedef uintptr_t osword_t;
00155 typedef void*        osptr_t;
00156 typedef osword_t*        osstkptr_t;
00157 typedef void (* osfnptr_t)(void *);
00158 typedef uintptr_t osptrword_t;
00159 
00160 #define ILLEGAL_STACK ((osstkptr_t) ~0)
00161 #define ILLEGAL_ADDR  ((osptr_t)    ~0)
00162 
00163 
00164 /* Port specific function implemented in tr_port.c */
00165 
00166 /* \name Context_switching_functions
00167  * @{ */
00168 
00169 #ifdef __CYGWIN__
00170 
00171 #include <windows.h>
00172 typedef CONTEXT ctxt_t;
00173 
00174 /* The context includes the registers, a place for storing the signal
00175  * state, and in this case, a location where the pointer to the true
00176  * posix stack can be stored */
00177 #define TRPORT_MIN_CTXT_SZ    ( (sizeof(ctxt_t) + sizeof(sigset_t) + sizeof(osstkptr_t) )/sizeof(osword_t) )
00178 
00179 #else
00180 #include <ucontext.h>
00181 typedef ucontext_t ctxt_t;
00182 #define TRPORT_MIN_CTXT_SZ   ( (sizeof(ctxt_t) + sizeof(osstkptr_t))/sizeof(osword_t) )
00183 
00184 
00185 #endif
00186 
00187 /* \brief Initialize the stack for a task.
00188  * @param stk  Pointer to the stack.
00189  * @param stacksize  Size of the stack.
00190  * @param PC   Program counter.
00191  * @param init_arg   Initial argument passed to the task 
00192  * @return  The pointer to the task context to be used in load/save context. */
00193 osstkptr_t hal_stk_init(osword_t *stk, osword_t stacksize, 
00194                      osfnptr_t pc,
00195                      osptr_t init_arg); 
00196 
00197 
00198 
00199 
00200 /* Enable critical section calls in the the called function
00201  *
00202  *  This has to be called at the beginning of the function before
00203  *  calling OS_CRITICAL_BEGIN or OS_CRITICAL_END.  This should be the
00204  *  first call after variable declaration.  These section should not
00205  *  be added within an ISR if Interrupt nesting is turned on, because
00206  *  the interrupt nesting adds this in automatically, and duplication
00207  *  will result in compiler complaints. */
00208 #define OS_PORT_CRITICAL_ENABLE()   \
00209         sigset_t signal_status_old; \
00210         sigset_t signal_status_new;
00211 
00212 #define OS_PORT_ISR_BEGIN()                                     \
00213         extern uint8_t os_isr_nesting;                          \
00214         os_isr_nesting++;
00215 
00216 
00217 
00218 
00219 /* Begin a critical section 
00220  * 
00221  * The current interrupt state is saved in signal_status and then
00222  * interrupts are disabled */
00223 #define OS_PORT_CRITICAL_BEGIN() \
00224         sigfillset(&signal_status_new); \
00225         sigprocmask(SIG_SETMASK, &signal_status_new, &signal_status_old);
00226 
00227 /*
00228 #define OS_PORT_CRITICAL_BEGIN() \
00229         sigemptyset(&signal_status_new); \
00230         sigaddset(&signal_status_new, SIGALRM);  \
00231         sigaddset(&signal_status_new, SIGVTALRM);  \
00232         sigprocmask(SIG_SETMASK, &signal_status_new, &signal_status_old);
00233 */
00234 
00235 /* End a critical section
00236  *
00237  * The saved interrupt state is restored */
00238 #define OS_PORT_CRITICAL_END()  \
00239         sigprocmask(SIG_SETMASK, &signal_status_old, 0);
00240 
00241 
00242 static inline void OS_PORT_INT_ENABLE(void)
00243 {
00244         sigset_t signal_status;
00245         sigemptyset(&signal_status);
00246         sigprocmask(SIG_SETMASK, &signal_status, 0);
00247 }
00248 
00249 
00250 static inline void OS_PORT_INT_DISABLE(void)
00251 {
00252         sigset_t signal_status;
00253         sigfillset(&signal_status);
00254         sigprocmask(SIG_SETMASK, &signal_status, 0);
00255 }
00256 
00257 
00258 
00259 /* Context switch from user level (non-ISR)
00260  *  This function is called from within an OS call, to switch the
00261  *  running process.  It also provides a return value. This is a
00262  *  pseudo return-value.  This function does not actually determine
00263  *  the value returned.  The return value is set by hal_retval_set
00264  *  which is often invoked when waking the process up from a blocked
00265  *  state. 
00266  *  The function takes the following form
00267  * \code
00268  * osstkptr_t hal_ctxt_switch(void) 
00269  * { 
00270  *   osstkptr_t ctxtptr = storecurrcontext_on_stk();
00271  *   ctxtptr = osint_taskswitcher(ctxtptr);
00272  *   loadnewcontext_from_stk(ctxtptr);
00273  * }
00274  * \endcode 
00275  * @return  Return value.  */
00276 osstkptr_t hal_ctxt_switch(void);
00277 
00278 
00279 void hal_ctxt_load(osstkptr_t ctxt_ptr);
00280 
00281 
00282 /* @} End context switching functions  */       
00283 
00284 
00285 
00286 
00287 
00288 void hal_time_get(trtime_t *t);
00289 int hal_time_set(const trtime_t *t);
00290 
00291 
00292 /* \brief Set an alarm.
00293  *  When the alarm is reached, osint_alarm_reached is called
00294  * @param lt Pointer to time */
00295 void  hal_alarm_set(const trtime_t *lt);
00296 
00297 void hal_init(void);
00298 
00299 
00300 
00301 
00302 
00303 
00304 extern int halint_kernel_trap_flagged;
00305 
00306 
00307 
00308 
00309 static inline void OS_KERNEL_TRAP(void)
00310 {       halint_kernel_trap_flagged = 1;  }
00311 
00312 
00313 
00314 
00315 
00316 /* 10 us response time */
00317 #define TRPORT_RESPONSE_TIME    {0, 10000}
00318 
00319 
00320 /* Port options are 0, 1.
00321  * 1 - uses the system real time.
00322  * 2 - uses the process time. */
00323 #ifndef PORT_TIMER_TYPE
00324 #define PORT_TIMER_TYPE  1
00325 #endif
00326 
00327 
00328 
00329 #ifdef TIROSINT_DATA_DEBUG
00330 /* Compute the program counter, from the stored context (stack
00331  * pointer)
00332  * This function is used for debugging.  Implement this by extracting
00333  * the program counter out of the stack pointer if possible.
00334  *
00335  * @param stkptr  The stkptr that is used by the hal to save/load
00336  * context.
00337  * @return The program counter */
00338 osptr_t hal_pc_from_ctxt(osstkptr_t stkptr);
00339 
00340 /* Return the maximum stack occupancy of the task.
00341  * This hal implemented function should provide the 
00342  * maximum stack occupancy of the task whose context is given.
00343  * This is used for debugging.  It is valid for this function to
00344  * return 0, if this information is not readily extractable.
00345  * @param ctxt_ptr        Context of the task.
00346  * @param base_stkptr   The initialization stack value for this task
00347  *                       that was passed to hal_stk_init
00348  * @param stksize        The initial stack size for this task that was 
00349  *                       passed to hal_stk_init
00350  * @return The maximum stack occupancy */
00351 osword_t hal_stkusage_max(osstkptr_t ctxt_ptr, osstkptr_t base_stkptr,
00352                           osword_t stksize);
00353 
00354 /* Return the current stack occupancy of the task.
00355  * This hal implemented function should provide the 
00356  * current stack occupancy of the task whose context is given.
00357  * This is used for debugging.  It is valid for this function to
00358  * return 0, if this information is not readily extractable.
00359  * @param ctxt_ptr   Context of the task.
00360  * @param base_stkptr   The initialization stack value for this task
00361  *                       that was passed to hal_stk_init
00362  * @param stksize        The initial stack size for this task that was 
00363  *                       passed to hal_stk_init
00364  * @return The current stack occupancy */
00365 osword_t hal_stkusage_curr(osstkptr_t ctxt_ptr, osstkptr_t base_stkptr,
00366                            osword_t stksize);
00367 
00368 
00369 #endif
00370 
00371 
00372 
00373 #endif   /* End of tr_port.h */

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