|
ChibiOS/RT
2.6.0 |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 00003 2011,2012,2013 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 A special exception to the GPL can be applied should you wish to distribute 00023 a combined work that includes ChibiOS/RT, without being obliged to provide 00024 the source code for any proprietary components. See the file exception.txt 00025 for full details of how and when the exception can be applied. 00026 */ 00027 00028 /** 00029 * @file AVR/chcore.h 00030 * @brief AVR architecture port macros and structures. 00031 * 00032 * @addtogroup AVR_CORE 00033 * @{ 00034 */ 00035 00036 #ifndef _CHCORE_H_ 00037 #define _CHCORE_H_ 00038 00039 #include <avr/io.h> 00040 #include <avr/interrupt.h> 00041 00042 #if CH_DBG_ENABLE_STACK_CHECK 00043 #error "option CH_DBG_ENABLE_STACK_CHECK not supported by this port" 00044 #endif 00045 00046 /** 00047 * @brief If enabled allows the idle thread to enter a low power mode. 00048 */ 00049 #ifndef ENABLE_WFI_IDLE 00050 #define ENABLE_WFI_IDLE 0 00051 #endif 00052 00053 /** 00054 * @brief Macro defining the AVR architecture. 00055 */ 00056 #define CH_ARCHITECTURE_AVR 00057 00058 /** 00059 * @brief Name of the implemented architecture. 00060 */ 00061 #define CH_ARCHITECTURE_NAME "AVR" 00062 00063 /** 00064 * @brief Name of the architecture variant (optional). 00065 */ 00066 #define CH_CORE_VARIANT_NAME "MegaAVR" 00067 00068 /** 00069 * @brief Name of the compiler supported by this port. 00070 */ 00071 #define CH_COMPILER_NAME "GCC " __VERSION__ 00072 00073 /** 00074 * @brief Port-specific information string. 00075 */ 00076 #define CH_PORT_INFO "None" 00077 00078 /** 00079 * @brief 8 bits stack and memory alignment enforcement. 00080 */ 00081 typedef uint8_t stkalign_t; 00082 00083 /** 00084 * @brief Interrupt saved context. 00085 * @details This structure represents the stack frame saved during a 00086 * preemption-capable interrupt handler. 00087 * @note The field @p _next is not part of the context, it represents the 00088 * offset of the structure relative to the stack pointer. 00089 */ 00090 struct extctx { 00091 uint8_t _next; 00092 uint8_t r31; 00093 uint8_t r30; 00094 uint8_t r27; 00095 uint8_t r26; 00096 uint8_t r25; 00097 uint8_t r24; 00098 uint8_t r23; 00099 uint8_t r22; 00100 uint8_t r21; 00101 uint8_t r20; 00102 uint8_t r19; 00103 uint8_t r18; 00104 uint8_t sr; 00105 uint8_t r1; 00106 uint8_t r0; 00107 uint16_t pc; 00108 }; 00109 00110 /** 00111 * @brief System saved context. 00112 * @details This structure represents the inner stack frame during a context 00113 * switching. 00114 * @note The field @p _next is not part of the context, it represents the 00115 * offset of the structure relative to the stack pointer. 00116 */ 00117 struct intctx { 00118 uint8_t _next; 00119 uint8_t r29; 00120 uint8_t r28; 00121 uint8_t r17; 00122 uint8_t r16; 00123 uint8_t r15; 00124 uint8_t r14; 00125 uint8_t r13; 00126 uint8_t r12; 00127 uint8_t r11; 00128 uint8_t r10; 00129 uint8_t r9; 00130 uint8_t r8; 00131 uint8_t r7; 00132 uint8_t r6; 00133 uint8_t r5; 00134 uint8_t r4; 00135 uint8_t r3; 00136 uint8_t r2; 00137 uint8_t pcl; 00138 uint8_t pch; 00139 }; 00140 00141 /** 00142 * @brief Platform dependent part of the @p Thread structure. 00143 * @details In the AVR port this structure just holds a pointer to the 00144 * @p intctx structure representing the stack pointer at the time 00145 * of the context switch. 00146 */ 00147 struct context { 00148 struct intctx *sp; 00149 }; 00150 00151 /** 00152 * @brief Platform dependent part of the @p chThdCreateI() API. 00153 * @details This code usually setup the context switching frame represented 00154 * by an @p intctx structure. 00155 */ 00156 #define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ 00157 tp->p_ctx.sp = (struct intctx*)((uint8_t *)workspace + wsize - \ 00158 sizeof(struct intctx)); \ 00159 tp->p_ctx.sp->r2 = (int)pf; \ 00160 tp->p_ctx.sp->r3 = (int)pf >> 8; \ 00161 tp->p_ctx.sp->r4 = (int)arg; \ 00162 tp->p_ctx.sp->r5 = (int)arg >> 8; \ 00163 tp->p_ctx.sp->pcl = (int)_port_thread_start >> 8; \ 00164 tp->p_ctx.sp->pch = (int)_port_thread_start; \ 00165 } 00166 00167 /** 00168 * @brief Stack size for the system idle thread. 00169 * @details This size depends on the idle thread implementation, usually 00170 * the idle thread should take no more space than those reserved 00171 * by @p PORT_INT_REQUIRED_STACK. 00172 * @note In this port it is set to 8. 00173 */ 00174 #ifndef PORT_IDLE_THREAD_STACK_SIZE 00175 #define PORT_IDLE_THREAD_STACK_SIZE 8 00176 #endif 00177 00178 /** 00179 * @brief Per-thread stack overhead for interrupts servicing. 00180 * @details This constant is used in the calculation of the correct working 00181 * area size. 00182 * This value can be zero on those architecture where there is a 00183 * separate interrupt stack and the stack space between @p intctx and 00184 * @p extctx is known to be zero. 00185 * @note In this port the default is 32 bytes per thread. 00186 */ 00187 #ifndef PORT_INT_REQUIRED_STACK 00188 #define PORT_INT_REQUIRED_STACK 32 00189 #endif 00190 00191 /** 00192 * @brief Enforces a correct alignment for a stack area size value. 00193 */ 00194 #define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) 00195 00196 /** 00197 * @brief Computes the thread working area global size. 00198 */ 00199 #define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ 00200 (sizeof(struct intctx) - 1) + \ 00201 (sizeof(struct extctx) - 1) + \ 00202 (n) + (PORT_INT_REQUIRED_STACK)) 00203 00204 /** 00205 * @brief Static working area allocation. 00206 * @details This macro is used to allocate a static thread working area 00207 * aligned as both position and size. 00208 */ 00209 #define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] 00210 00211 /** 00212 * @brief IRQ prologue code. 00213 * @details This macro must be inserted at the start of all IRQ handlers 00214 * enabled to invoke system APIs. 00215 * @note This code tricks the compiler to save all the specified registers 00216 * by "touching" them. 00217 */ 00218 #define PORT_IRQ_PROLOGUE() { \ 00219 asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \ 00220 "r25", "r26", "r27", "r30", "r31"); \ 00221 } 00222 00223 /** 00224 * @brief IRQ epilogue code. 00225 * @details This macro must be inserted at the end of all IRQ handlers 00226 * enabled to invoke system APIs. 00227 */ 00228 #define PORT_IRQ_EPILOGUE() { \ 00229 dbg_check_lock(); \ 00230 if (chSchIsPreemptionRequired()) \ 00231 chSchDoReschedule(); \ 00232 dbg_check_unlock(); \ 00233 } 00234 00235 /** 00236 * @brief IRQ handler function declaration. 00237 * @note @p id can be a function name or a vector number depending on the 00238 * port implementation. 00239 */ 00240 #define PORT_IRQ_HANDLER(id) ISR(id) 00241 00242 /** 00243 * @brief Port-related initialization code. 00244 * @note This function is empty in this port. 00245 */ 00246 #define port_init() 00247 00248 /** 00249 * @brief Kernel-lock action. 00250 * @details Usually this function just disables interrupts but may perform more 00251 * actions. 00252 * @note Implemented as global interrupt disable. 00253 */ 00254 #define port_lock() asm volatile ("cli" : : : "memory") 00255 00256 /** 00257 * @brief Kernel-unlock action. 00258 * @details Usually this function just enables interrupts but may perform more 00259 * actions. 00260 * @note Implemented as global interrupt enable. 00261 */ 00262 #define port_unlock() asm volatile ("sei" : : : "memory") 00263 00264 /** 00265 * @brief Kernel-lock action from an interrupt handler. 00266 * @details This function is invoked before invoking I-class APIs from 00267 * interrupt handlers. The implementation is architecture dependent, 00268 * in its simplest form it is void. 00269 * @note This function is empty in this port. 00270 */ 00271 #define port_lock_from_isr() 00272 00273 /** 00274 * @brief Kernel-unlock action from an interrupt handler. 00275 * @details This function is invoked after invoking I-class APIs from interrupt 00276 * handlers. The implementation is architecture dependent, in its 00277 * simplest form it is void. 00278 * @note This function is empty in this port. 00279 */ 00280 #define port_unlock_from_isr() 00281 00282 /** 00283 * @brief Disables all the interrupt sources. 00284 * @note Of course non-maskable interrupt sources are not included. 00285 * @note Implemented as global interrupt disable. 00286 */ 00287 #define port_disable() asm volatile ("cli" : : : "memory") 00288 00289 /** 00290 * @brief Disables the interrupt sources below kernel-level priority. 00291 * @note Interrupt sources above kernel level remains enabled. 00292 * @note Same as @p port_disable() in this port, there is no difference 00293 * between the two states. 00294 */ 00295 #define port_suspend() asm volatile ("cli" : : : "memory") 00296 00297 /** 00298 * @brief Enables all the interrupt sources. 00299 * @note Implemented as global interrupt enable. 00300 */ 00301 #define port_enable() asm volatile ("sei" : : : "memory") 00302 00303 /** 00304 * @brief Enters an architecture-dependent IRQ-waiting mode. 00305 * @details The function is meant to return when an interrupt becomes pending. 00306 * The simplest implementation is an empty function or macro but this 00307 * would not take advantage of architecture-specific power saving 00308 * modes. 00309 * @note This port function is implemented as inlined code for performance 00310 * reasons. 00311 */ 00312 #if ENABLE_WFI_IDLE != 0 00313 #define port_wait_for_interrupt() { \ 00314 asm volatile ("sleep" : : : "memory"); \ 00315 } 00316 #else 00317 #define port_wait_for_interrupt() 00318 #endif 00319 00320 #ifdef __cplusplus 00321 extern "C" { 00322 #endif 00323 void port_switch(Thread *ntp, Thread *otp); 00324 void port_halt(void); 00325 void _port_thread_start(void); 00326 #ifdef __cplusplus 00327 } 00328 #endif 00329 00330 #endif /* _CHCORE_H_ */ 00331 00332 /** @} */