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 */