|
ChibiOS/RT
2.5.1 |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 00003 2011,2012 Giovanni Di Sirio. 00004 00005 This file is part of ChibiOS/RT. 00006 00007 ChibiOS/RT is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 ChibiOS/RT is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 /** 00022 * @file cosmic/STM8/chcore.h 00023 * @brief STM8 (Cosmic) architecture port macros and structures. 00024 * 00025 * @addtogroup STM8_COSMIC_CORE 00026 * @{ 00027 */ 00028 00029 #ifndef _CHCORE_H_ 00030 #define _CHCORE_H_ 00031 00032 #if CH_DBG_ENABLE_STACK_CHECK 00033 #error "option CH_DBG_ENABLE_STACK_CHECK not supported by this port" 00034 #endif 00035 00036 /*===========================================================================*/ 00037 /* Port configurable parameters. */ 00038 /*===========================================================================*/ 00039 00040 /** 00041 * @brief Enables the use of the WFI instruction in the idle thread loop. 00042 */ 00043 #ifndef STM8_ENABLE_WFI_IDLE 00044 #define STM8_ENABLE_WFI_IDLE FALSE 00045 #endif 00046 00047 /*===========================================================================*/ 00048 /* Port exported info. */ 00049 /*===========================================================================*/ 00050 00051 /** 00052 * @brief Unique macro for the implemented architecture. 00053 */ 00054 #define CH_ARCHITECTURE_STM8 00055 00056 /** 00057 * @brief Name of the implemented architecture. 00058 */ 00059 #define CH_ARCHITECTURE_NAME "STM8" 00060 00061 /** 00062 * @brief Name of the compiler supported by this port. 00063 */ 00064 #define CH_COMPILER_NAME "Cosmic" 00065 00066 /** 00067 * @brief Port-specific information string. 00068 */ 00069 #define CH_PORT_INFO "None" 00070 00071 /*===========================================================================*/ 00072 /* Port implementation part. */ 00073 /*===========================================================================*/ 00074 00075 /** 00076 * @brief Base type for stack alignment. 00077 * @note No alignment constraints so uint8_t. 00078 */ 00079 typedef uint8_t stkalign_t; 00080 00081 /** 00082 * @brief Generic STM8 function pointer. 00083 * @note It is used to allocate the proper size for return addresses in 00084 * context-related structures. 00085 */ 00086 typedef void (*stm8func_t)(void); 00087 00088 /** 00089 * @brief Interrupt saved context. 00090 * @details This structure represents the stack frame saved during a 00091 * preemption-capable interrupt handler. 00092 * @note The structure requires one dummy field at its start because the 00093 * stack is handled as preincremented/postdecremented. 00094 */ 00095 struct extctx { 00096 uint8_t _next; 00097 uint8_t c_lreg[4]; 00098 uint8_t c_y[3]; 00099 uint8_t c_x[3]; 00100 uint8_t cc; 00101 uint8_t a; 00102 uint16_t x; 00103 uint16_t y; 00104 uint8_t pce; 00105 uint8_t pch; 00106 uint8_t pcl; 00107 }; 00108 00109 /** 00110 * @brief System saved context. 00111 * @details This structure represents the inner stack frame during a context 00112 * switching.. 00113 * @note The structure requires one dummy field at its start because the 00114 * stack is handled as preincremented/postdecremented. 00115 */ 00116 struct intctx { 00117 uint8_t _next; 00118 stm8func_t pc; /* Function pointer sized return address. */ 00119 }; 00120 00121 /** 00122 * @brief Platform dependent part of the @p Thread structure. 00123 * @details This structure usually contains just the saved stack pointer 00124 * defined as a pointer to a @p intctx structure. 00125 */ 00126 struct context { 00127 struct intctx *sp; 00128 }; 00129 00130 /** 00131 * @brief Start context. 00132 * @details This context is the stack organization for the trampoline code 00133 * @p _port_thread_start(). 00134 */ 00135 struct stm8_startctx { 00136 uint8_t _next; 00137 stm8func_t ts; /* Trampoline address. */ 00138 void *arg; /* Thread argument. */ 00139 stm8func_t pc; /* Thread function address. */ 00140 stm8func_t ret; /* chThdExit() address. */ 00141 }; 00142 00143 /** 00144 * @brief Platform dependent part of the @p chThdCreateI() API. 00145 * @details This code usually setup the context switching frame represented 00146 * by an @p intctx structure. 00147 */ 00148 #define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ 00149 struct stm8_startctx *scp; \ 00150 scp = (struct stm8_startctx *)((uint8_t *)workspace + wsize - \ 00151 sizeof(struct stm8_startctx)); \ 00152 scp->ts = _port_thread_start; \ 00153 scp->arg = arg; \ 00154 scp->pc = (stm8func_t)pf; \ 00155 scp->ret = (stm8func_t)chThdExit; \ 00156 tp->p_ctx.sp = (struct intctx *)scp; \ 00157 } 00158 00159 /** 00160 * @brief Stack size for the system idle thread. 00161 * @details This size depends on the idle thread implementation, usually 00162 * the idle thread should take no more space than those reserved 00163 * by @p PORT_INT_REQUIRED_STACK. 00164 */ 00165 #ifndef PORT_IDLE_THREAD_STACK_SIZE 00166 #define PORT_IDLE_THREAD_STACK_SIZE 0 00167 #endif 00168 00169 /** 00170 * @brief Per-thread stack overhead for interrupts servicing. 00171 * @details This is a safe value, you may trim it down after reading the 00172 * right size in the map file. 00173 */ 00174 #ifndef PORT_INT_REQUIRED_STACK 00175 #define PORT_INT_REQUIRED_STACK 48 00176 #endif 00177 00178 /** 00179 * @brief Enforces a correct alignment for a stack area size value. 00180 */ 00181 #define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) 00182 00183 /** 00184 * @brief Computes the thread working area global size. 00185 */ 00186 #define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ 00187 (sizeof(struct intctx) - 1) + \ 00188 (sizeof(struct extctx) - 1) + \ 00189 (n) + (PORT_INT_REQUIRED_STACK)) 00190 00191 /** 00192 * @brief Static working area allocation. 00193 * @details This macro is used to allocate a static thread working area 00194 * aligned as both position and size. 00195 */ 00196 #define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] 00197 00198 /** 00199 * @brief IRQ prologue code. 00200 * @details This macro must be inserted at the start of all IRQ handlers 00201 * enabled to invoke system APIs. 00202 */ 00203 #define PORT_IRQ_PROLOGUE() 00204 00205 /** 00206 * @brief IRQ epilogue code. 00207 * @details This macro must be inserted at the end of all IRQ handlers 00208 * enabled to invoke system APIs. 00209 */ 00210 #define PORT_IRQ_EPILOGUE() { \ 00211 dbg_check_lock(); \ 00212 if (chSchIsPreemptionRequired()) \ 00213 chSchDoReschedule(); \ 00214 dbg_check_unlock(); \ 00215 } 00216 00217 /** 00218 * @brief IRQ handler function declaration. 00219 * @note @p id can be a function name or a vector number depending on the 00220 * port implementation. 00221 */ 00222 #define PORT_IRQ_HANDLER(id) @far @interrupt @svlreg void vector##id(void) 00223 00224 /** 00225 * @brief Port-related initialization code. 00226 * @note None in this port. 00227 */ 00228 #define port_init() 00229 00230 /** 00231 * @brief Kernel-lock action. 00232 * @note Implemented as global interrupts disable. 00233 */ 00234 #define port_lock() _asm("sim") 00235 00236 /** 00237 * @brief Kernel-unlock action. 00238 * @note Implemented as global interrupts enable. 00239 */ 00240 #define port_unlock() _asm("rim") 00241 00242 /** 00243 * @brief Kernel-lock action from an interrupt handler. 00244 * @note This function is empty in this port. 00245 */ 00246 #define port_lock_from_isr() 00247 00248 /** 00249 * @brief Kernel-unlock action from an interrupt handler. 00250 * @note This function is empty in this port. 00251 */ 00252 #define port_unlock_from_isr() 00253 00254 /** 00255 * @brief Disables all the interrupt sources. 00256 * @note Implemented as global interrupts disable. 00257 * @note Of course non-maskable interrupt sources are not included. 00258 */ 00259 #define port_disable() _asm("sim") 00260 00261 /** 00262 * @brief Disables the interrupt sources that are not supposed to preempt 00263 * the kernel. 00264 * @note Same as @p port_disable() in this port, there is no difference 00265 * between the two states. 00266 */ 00267 #define port_suspend() _asm("sim") 00268 00269 /** 00270 * @brief Enables all the interrupt sources. 00271 * @note Implemented as global interrupt enable. 00272 */ 00273 #define port_enable() _asm("rim") 00274 00275 /** 00276 * @brief Enters an architecture-dependent halt mode. 00277 * @note Implemented with the specific "wfi" instruction. 00278 */ 00279 #if STM8_ENABLE_WFI_IDLE || defined(__DOXYGEN__) 00280 #define port_wait_for_interrupt() _asm("wfi") 00281 #else 00282 #define port_wait_for_interrupt() 00283 #endif 00284 00285 /** 00286 * @brief Performs a context switch between two threads. 00287 * @details This is the most critical code in any port, this function 00288 * is responsible for the context switch between 2 threads. 00289 * @note Implemented as a call to a low level assembler routine. 00290 * 00291 * @param ntp the thread to be switched in 00292 * @param otp the thread to be switched out 00293 */ 00294 #define port_switch(ntp, otp) _port_switch(otp) 00295 00296 #ifdef __cplusplus 00297 extern "C" { 00298 #endif 00299 void _port_switch(Thread *otp); 00300 void _port_thread_start(void); 00301 void port_halt(void); 00302 #ifdef __cplusplus 00303 } 00304 #endif 00305 00306 /*===========================================================================*/ 00307 /* Scheduler captured code. */ 00308 /*===========================================================================*/ 00309 00310 #define PORT_OPTIMIZED_RLIST_VAR 00311 #define PORT_OPTIMIZED_RLIST_EXT 00312 #define PORT_OPTIMIZED_READYLIST_STRUCT 00313 00314 typedef struct { 00315 ThreadsQueue r_queue; 00316 tprio_t r_prio; 00317 Thread *r_current; 00318 #if CH_USE_REGISTRY 00319 Thread *r_newer; 00320 Thread *r_older; 00321 #endif 00322 /* End of the fields shared with the Thread structure.*/ 00323 #if CH_TIME_QUANTUM > 0 00324 cnt_t r_preempt; 00325 #endif 00326 } ReadyList; 00327 00328 @tiny extern ReadyList rlist; 00329 00330 #endif /* _CHCORE_H_ */ 00331 00332 /** @} */