tr_port.h

Go to the documentation of this file.
00001 /** \file
00002  * @brief  Generic template for porting guidelines
00003  *
00004  * <H2> Configuration Options: Document your configuration options
00005  * here ########</H2>
00006  * <OL>
00007  *    <LI>  ## Config option 1.
00008  *    <LI>  ## Config option 2.
00009  * </OL>
00010  *
00011  */
00012 
00013 /* Author: Ratish J. Punnoose, 2006
00014  * This file is part of TiROS, the Tickless Real-Time Operating System.
00015  * Copyright(c) 2006, 2007: Ratish J. Punnoose.
00016  * Copyright(c) 2006 Sandia Corporation. Under the terms of Contract
00017  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
00018  * certain rights in this software. 
00019  * 
00020  * TiROS is free software; you can redistribute it and/or modify it under
00021  * the terms of the GNU General Public License as published by the Free
00022  * Software Foundation; either version 2 or (at your option) any later version.
00023  *
00024  * TiROS is distributed in the hope that it will be useful, but WITHOUT ANY
00025  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00026  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00027  * for more details.
00028  *
00029  * You should have received a copy of the GNU General Public License along
00030  * with TiROS; if not, write to the Free Software Foundation, Inc.,
00031  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00032  *
00033  * As a special exception, if other files instantiate templates or use macros
00034  * or inline functions from this file, or you compile this file and link it
00035  * with other works to produce a work based on this file, this file does not
00036  * by itself cause the resulting work to be covered by the GNU General Public
00037  * License. However the source code for this file must still be made available
00038  * in accordance with section (3) of the GNU General Public License.
00039  *
00040  * This exception does not invalidate any other reasons why a work based on
00041  * this file might be covered by the GNU General Public License.
00042  *
00043  */
00044 
00045 
00046 
00047 /* Change this define to reflect your port name */
00048 #ifndef __TEMPLATE_TIROS_PORT_H
00049 #define __TEMPLATE_TIROS_PORT_H
00050 
00051 
00052 /**
00053  * @page porting_guide Porting Guide
00054  * This section describes the porting of TiROS to a new platform.
00055  * The hardware specific port includes several files located in ROOT/src/tiros/port/port_xxx
00056  * A tr_port.h is required. There may be an associated tr_port.c and other assembly files if needed.
00057  * There will also be a file called porttime.h which contains the
00058  * time addition, subtraction specific to your port.
00059  * The tr_port.h file has several sections.
00060  * <OL>
00061  *  <LI> In a comment section at the top of the file, describe the
00062  *  port and the configuration options specific to the port.
00063  *  <LI> Include the user's configuration file proj_config.h.
00064  *  <LI> \ref port_config.
00065  *  <LI> \ref port_crit_secs.
00066  *  <LI> \ref port_ctxt_funcs.
00067  *  <LI> \ref port_time_funcs.
00068  *  <LI> \ref port_kernel_trap.
00069  *  <LI> \ref port_debug.
00070  * </OL> 
00071  * 
00072  */
00073 
00074 /*@ignore@*/
00075 
00076 /** Include the user's project configuration file */
00077 #include "proj_config.h"
00078 /*@end@*/
00079 
00080 /* Add any include files necessary */
00081 //#include <yourincludefiles.h>
00082 
00083 
00084 /** @defgroup port_config  Define basic types and OS configuration  for your port
00085  * 
00086  * @{ */
00087 
00088 /** Define the different integer types. or include a header file such
00089  * as stdint.h that
00090  * already has these defined. */
00091 typedef unsigned char uint8_t;
00092 typedef char int8_t;
00093 
00094 typedef unsigned short uint16_t;
00095 typedef short int16_t;
00096 
00097 typedef unsigned long uint32_t;
00098 typedef long int32_t;
00099 
00100 
00101 
00102 /** Define the type field used for subunits in the time structure */
00103 #define subtime_t uint16_t
00104 /** Do you want the time functions inlined ? */
00105 #define LT_INLINE static inline 
00106 
00107 
00108 
00109 #include <tiros/tr_time.h>
00110 /** Insert your port for time functions for your hardware */
00111 #include "porttime.h"
00112 
00113 
00114 /** Define the value of infinite time for this port */
00115 #define TRPORT_INF_TIME {~0 , ~0 }
00116 
00117 
00118 /** Will you be using register passing?  
00119  * This is an optimization and
00120  *   may be difficult on some platforms.  In that case, comment this out. */
00121 #define TIROS_REGISTER_PASSING
00122 
00123 
00124 /** Basic type for the hardware word.  An 8 bit system would have an
00125  * 8-bit integer, a 16-bit system would have a 16 bit integer, etc.
00126  * On a system with stdint.h, this could be uintptr_t */
00127 typedef unsigned int osword_t;
00128 
00129 
00130 
00131 /** Type to use for generic pointer. 
00132  *  Pointer types: Separate pointer types are defined for a generic
00133  *  pointer, stack pointer, and function pointer.  On many
00134  *  architectures, this may be the same.  However, there may be a need
00135  *  to keep this different on some hardware.  For example, on an 8051,
00136  *  the generic pointer may be set to refer to the IDATA memory, while
00137  *  the stack pointer may be set to XDATA (which takes more bytes for
00138  *  address storage).  Other hardware with interesting addressing such
00139  *  as a 20-bit address or a 23-bit address may need to keep these
00140  *  different types of pointers separate */
00141 typedef void*         osptr_t;
00142 
00143 /** Type to use for stack pointer */
00144 typedef osword_t*    osstkptr_t;
00145 
00146 /** Type to use for a function pointer */
00147 typedef void (* osfnptr_t)(void *);
00148 
00149 /** This is an integer type that can fully represent osptr_t.  If a
00150  * pointer takes two bytes of storage, then a 16 bit integer should be
00151  * used, if it takes 3 bytes of storage, then a 32 bit integer should
00152  * be used, etc.  If your system has a <stdint.h> file, then this
00153  * could be of type uintptr_t (defined in stdint.h) */
00154 typedef unsigned int osptrword_t; 
00155 
00156 /** Create a definition for an invalid stack pointer */ 
00157 #define ILLEGAL_STACK ((osstkptr_t) ~0)
00158 /** Create a definition for an illegal memory address */
00159 #define ILLEGAL_ADDR  ((osptr_t)    ~0)
00160 
00161 /** @} */
00162 
00163 /** @defgroup port_crit_secs Critical Sections and Interrupts
00164  * These functions are defined for using critical sections and dealing
00165  * with interrupts.
00166  * @{ */
00167 
00168 /** Enable critical section calls in the the called function
00169  *
00170  *  OS_PORT_CRITICAL_ENABLE() will be called at the beginning of any
00171  *  function that uses  OS_CRITICAL_BEGIN or OS_CRITICAL_END.  This will be the
00172  *  first call after variable declaration. This is a good place to
00173  *  define variables that may be used by OS_BEGIN_CRITICAL and
00174  *  OS_CRITICAL_END
00175  */
00176 #define OS_PORT_CRITICAL_ENABLE()   
00177 
00178 /** Begin a critical section 
00179  * A simple way to do this would be to disable interrupts. However, it
00180  * would be better if the current interrupt state were stored and then
00181  * interrupts were disabled.  Upon ending the critical section, the
00182  * stored state should be restored.  The stored state can be saved in
00183  * a local variable, which can be defined within
00184  * OS_PORT_CRITICAL_ENABLE() */
00185 #define OS_PORT_CRITICAL_BEGIN()   /* Implement this here */
00186 
00187 
00188 /** End a critical section
00189  * This may be as simple as reenabling interrupts, but it is better to
00190  * renable the interrupt state stored in OS_PORT_BEGIN_CRITICAL() */
00191 #define OS_PORT_CRITICAL_END()   /* Implement this here */
00192 
00193 
00194 /** This macro will be called at the beginning of an ISR.
00195  * Leave this as such  */
00196 #define OS_PORT_ISR_BEGIN()                                     \
00197         extern uint8_t os_isr_nesting;                          \
00198         os_isr_nesting++;
00199 
00200 /** Enable interrupts
00201  * This allows the user to explicitly enable interrupts */
00202 #define OS_PORT_INT_ENABLE()     /* Implement this here */
00203 
00204 /** Disable interrupts
00205  * This allows the user to explicitly disable interrupts */
00206 #define OS_PORT_INT_DISABLE()     /* Implement this here */
00207 
00208 
00209 /* @} */
00210 
00211 
00212 /** @defgroup port_ctxt_funcs Context Switching Functions
00213  * These functions should be implemented to manage a per task stack,
00214  * and saving and restoring context.  The context is stored so that it
00215  * looks like the way the stack would if all the registers were stored
00216  * by an interrupt function.
00217  *
00218  * @{ */
00219 
00220 /** Define the minimum size of the context in oswords */
00221 #define TRPORT_MIN_CTXT_SZ         64
00222 
00223 /** Initialize a stack and create a new context for a task.
00224  * @param stk  Pointer to the stack.
00225  * @param stacksize  Size of the stack.
00226  * @param PC   Program counter.
00227  * @param init_arg   Initial argument passed to the task.
00228  * @return  The pointer to the task context to be used in load/save context. */
00229 osstkptr_t hal_stk_init(osword_t *stk, osword_t stacksize, osfnptr_t pc,
00230                         osptr_t init_arg); 
00231 
00232 /* If register passing is being used then define hal_retval_set */
00233 #ifdef TIROS_REGISTER_PASSING
00234 /** Set a return value for a task whose context is stored.
00235  * This is only needed if TIROS_REGISTER_PASSING is defined for your port.
00236  * This injects a return value into the context of a task that is currently frozen.
00237  * @param ctxt_ptr  Pointer to the context of the task.
00238  * @param retval    The return value to be injected into the task context */
00239 static inline void hal_retval_set(/*@unused@*/osstkptr_t ctxt_ptr, 
00240                                   /*@unused@*/osptr_t retval)
00241 {
00242 }
00243 #endif
00244 
00245 
00246 /** Context switch from user level (non-ISR)
00247  *  This function is called from within an OS call, to switch the
00248  *  running process.  It also provides a return value. This is a
00249  *  pseudo return-value,  This function does not actually determine
00250  *  the value returned.  The return value is set by hal_retval_set
00251  *  which is often invoked when waking the process up from a blocked
00252  *  state. 
00253  *  This function may have to be implemented in assembly based on the
00254  *  port. 
00255  *  The function takes the following form
00256  * \code
00257  * osstkptr_t hal_ctxt_switch(void) {
00258  *      osstkptr_t new_ctxtptr, current_ctxtptr;
00259  *      current_ctxtptr = save_current_context();
00260  *      new_ctxtptr = osint_taskswitcher(current_ctxtptr);
00261  *      load_new_context(new_ctxtptr);
00262  * 
00263  *      // The code should not reach this far.  When 
00264  *      // new context is loaded, it will jump out of the
00265  *      // hal_ctxt_switch function.
00266  *      return 0; 
00267  * }
00268  * \endcode   
00269  *
00270  * The function may also take the following form when there is no easy
00271  * access to the current stack value.
00272  * \code
00273  * osstkptr_t hal_ctxt_switch(void) {
00274  *      osstkptr_t ctxt_ptr, new_ctxt_ptr;
00275  *      ctxt_ptr = osint_running_task_ctxt();
00276  *      if (stkptr != ILLEGAL_STACK) {
00277  *            save_current_context(ctxt_ptr);
00278  *            new_ctxt_ptr = osint_taskswitcher(ctxt_ptr);
00279  *            load_new_context(new_ctxt_ptr);
00280  *      } else {
00281  *            new_ctxt_ptr = osint_taskswitcher(ctxt_ptr);
00282  *            load_new_context(new_ctxt_ptr);
00283  *      }
00284  *      // The code should not reach this far.  When 
00285  *      // new context is loaded, it will jump out of the
00286  *      // hal_ctxt_switch function.
00287  *      return 0; 
00288  * }
00289  * \endcode   
00290  *
00291  * @return  Return value.  */
00292 osstkptr_t hal_ctxt_switch(void);
00293 
00294 
00295 /** Load the given context
00296  * @param ctxt_ptr   Pointer to task context  */
00297 void hal_ctxt_load(osstkptr_t ctxt_ptr);
00298 
00299 /** Initialize the hardware.
00300  * Any hardware specific initialization can be performed her.
00301  *  Timer and kernel trap initialization 
00302  * can also be performed within this function. */
00303 void hal_init(void);
00304 
00305 
00306 
00307  /* Bypass SPLINT verification */
00308 
00309 /** @} End context switching functions  */      
00310 
00311 
00312 /** @defgroup port_time_funcs  Port specific time functions
00313  * @{ */
00314 
00315 /** Get the current time.
00316  * @param[out] lt Pointer to time structure */
00317 void hal_time_get(trtime_t * lt);
00318 
00319 /** Set the current time.
00320  * This may not always be possible, depending on the port.
00321  * @param[in] lt Pointer to time structure.  
00322  * @return 1 if successful, 0 if not possible. */
00323 int hal_time_set( const trtime_t * lt);
00324 
00325 
00326 /** Set an alarm for the specified time.
00327  *  When the alarm is reached, osint_alarm_reached is called
00328  * @param[in] lt Pointer to time structure. If lt is set to zero, then
00329  * disable alarms. */
00330 void  hal_alarm_set(/*@null@*/ const trtime_t *lt);
00331 
00332 
00333 
00334 
00335 #ifndef TRPORT_RESPONSE_TIME
00336 
00337 /**  OS response time.
00338  * The OS wakes a task at the absolute time specified.  There might
00339  * however be some little overhead involved in waking it up that might 
00340  * delay the wakeup.  So a task that wants to wake up for a very short
00341  * duration of time might actually get delayed because it takes some
00342  * time for the OS to put it to sleep and wake it up. To avoid this,
00343  * TiROS takes the response overhead into account when scheduling */
00344 #define TRPORT_RESPONSE_TIME  { 0, 80 }
00345 #endif
00346 
00347 /** @} End time related functions */
00348 
00349 
00350 /** @defgroup port_kernel_trap Setup for the kernel trap
00351  * The kernel trap is used to reduce interrupt latency.  When an
00352  * interrupt occurs, the task context is not saved.  At the end of the
00353  * ISR,  there is a check made to see if a new task has been enabled
00354  * by the processing within the interrupt.  
00355  * 
00356  * In most cases, there is no
00357  * change and processing returns to the task that was interrupted.  If
00358  * this is the case, there is no overhead for saving and restoring all
00359  * the task context.
00360  *
00361  * In cases where a different task must run, a software interrupt is
00362  * raised at the end of the ISR.  When the ISR returns, the kernel
00363  * trap ISR is invoked due to the software interrupt.  This can save
00364  * the context for the current task and restore the context for the
00365  * new task.
00366  *
00367  *
00368  * @{ */
00369 
00370 #ifndef TIROS_KERNEL_TRAP_ENABLED
00371 
00372 /** Is a kernel trap possible on this architecture?  
00373  * If not, set TIROS_KERNEL_TRAP_ENABLED to 0 */
00374 #define TIROS_KERNEL_TRAP_ENABLED  1
00375 #endif
00376 
00377 
00378 /** Implement the code to Invoke a kernel trap (i.e., create a
00379  * software interrupt).  OS_KERNEL_TRAP() is called
00380  * from within an ISR. On hardware where kernel trap is not
00381  * possible, this function may set a flag which determines if the
00382  * scheduler has to be invoked at the end of the ISR.   */
00383 void OS_KERNEL_TRAP(void);
00384 /** @} End kernel trap */
00385 
00386 
00387 /** @defgroup port_debug Debug Functions
00388  *
00389  * These group of functions enhance the debugging capability of TiROS.
00390  * @{ */
00391 
00392 
00393 
00394 #ifdef TIROSINT_DATA_DEBUG
00395 /** Compute the program counter, from the stored context 
00396  * This function is used for debugging.  Implement this by extracting
00397  * the program counter out of the context (or stack pointer) if possible.
00398  *
00399  * @param ctxt_ptr  The pointer to the task context 
00400  * @return The program counter */
00401 osptr_t hal_pc_from_ctxt(osstkptr_t ctxt_ptr);
00402 
00403 
00404 #ifdef TIROS_STK_CHECK
00405 /** Return the maximum stack occupancy of the task.
00406  * This hal implemented function should provide the 
00407  * maximum stack occupancy of the task whose context is given.
00408  * This is used for debugging.  It is valid for this function to
00409  * return 0, if this information is not readily extractable.
00410  * @param ctxt_ptr        Context of the task.
00411  * @param base_stkptr   The initialization stack value for this task
00412  *                       that was passed to hal_stk_init
00413  * @param stksize        The initial stack size for this task that was 
00414  *                       passed to hal_stk_init
00415  * @return The maximum stack occupancy */
00416 osword_t hal_stkusage_max(osstpktr_t ctxt_ptr, osstkptr_t base_stkptr,
00417                           osword_t stksize);
00418 
00419 /** Return the current stack occupancy of the task.
00420  * This hal implemented function should provide the 
00421  * current stack occupancy of the task whose context is given.
00422  * This is used for debugging.  It is valid for this function to
00423  * return 0, if this information is not readily extractable.
00424  * @param ctxt_ptr   Context of the task.
00425  * @param base_stkptr   The initialization stack value for this task
00426  *                       that was passed to hal_stk_init
00427  * @param stksize        The initial stack size for this task that was 
00428  *                       passed to hal_stk_init
00429  * @return The current stack occupancy */
00430 osword_t hal_stkusage_curr(osstpktr_t ctxt_ptr, osstkptr_t base_stkptr,
00431                            osword_t stksize);
00432 #endif /*TIROS_STK_CHECK */
00433 
00434 
00435 
00436 #endif /*TIROSINT_DATA_DEBUG */
00437 
00438 /** @} End group port_debug  */
00439 
00440 
00441 
00442 
00443 
00444 #endif   /* End of tr_port.h */

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