|
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 IAR/ARMCMx/chcore_v6m.h 00023 * @brief ARMv6-M architecture port macros and structures. 00024 * 00025 * @addtogroup IAR_ARMCMx_V6M_CORE 00026 * @{ 00027 */ 00028 00029 #ifndef _CHCORE_V6M_H_ 00030 #define _CHCORE_V6M_H_ 00031 00032 /*===========================================================================*/ 00033 /* Port constants. */ 00034 /*===========================================================================*/ 00035 00036 /** 00037 * @brief PendSV priority level. 00038 * @note This priority is enforced to be equal to @p 0, 00039 * this handler always has the highest priority that cannot preempt 00040 * the kernel. 00041 */ 00042 #define CORTEX_PRIORITY_PENDSV 0 00043 00044 /*===========================================================================*/ 00045 /* Port macros. */ 00046 /*===========================================================================*/ 00047 00048 /*===========================================================================*/ 00049 /* Port configurable parameters. */ 00050 /*===========================================================================*/ 00051 00052 /** 00053 * @brief Stack size for the system idle thread. 00054 * @details This size depends on the idle thread implementation, usually 00055 * the idle thread should take no more space than those reserved 00056 * by @p PORT_INT_REQUIRED_STACK. 00057 * @note In this port it is set to 16 because the idle thread does have 00058 * a stack frame when compiling without optimizations. You may 00059 * reduce this value to zero when compiling with optimizations. 00060 */ 00061 #if !defined(PORT_IDLE_THREAD_STACK_SIZE) 00062 #define PORT_IDLE_THREAD_STACK_SIZE 16 00063 #endif 00064 00065 /** 00066 * @brief Per-thread stack overhead for interrupts servicing. 00067 * @details This constant is used in the calculation of the correct working 00068 * area size. 00069 * @note In this port this value is conservatively set to 32 because the 00070 * function @p chSchDoReschedule() can have a stack frame, especially 00071 * with compiler optimizations disabled. The value can be reduced 00072 * when compiler optimizations are enabled. 00073 */ 00074 #if !defined(PORT_INT_REQUIRED_STACK) 00075 #define PORT_INT_REQUIRED_STACK 32 00076 #endif 00077 00078 /** 00079 * @brief Enables the use of the WFI instruction in the idle thread loop. 00080 */ 00081 #if !defined(CORTEX_ENABLE_WFI_IDLE) 00082 #define CORTEX_ENABLE_WFI_IDLE FALSE 00083 #endif 00084 00085 /** 00086 * @brief SYSTICK handler priority. 00087 * @note The default SYSTICK handler priority is calculated as the priority 00088 * level in the middle of the numeric priorities range. 00089 */ 00090 #if !defined(CORTEX_PRIORITY_SYSTICK) 00091 #define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) 00092 #elif !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK) 00093 /* If it is externally redefined then better perform a validity check on it.*/ 00094 #error "invalid priority level specified for CORTEX_PRIORITY_SYSTICK" 00095 #endif 00096 00097 /** 00098 * @brief Alternate preemption method. 00099 * @details Activating this option will make the Kernel use the PendSV 00100 * handler for preemption instead of the NMI handler. 00101 */ 00102 #ifndef CORTEX_ALTERNATE_SWITCH 00103 #define CORTEX_ALTERNATE_SWITCH FALSE 00104 #endif 00105 00106 /*===========================================================================*/ 00107 /* Port derived parameters. */ 00108 /*===========================================================================*/ 00109 00110 /** 00111 * @brief Maximum usable priority for normal ISRs. 00112 */ 00113 #if CORTEX_ALTERNATE_SWITCH || defined(__DOXYGEN__) 00114 #define CORTEX_MAX_KERNEL_PRIORITY 1 00115 #else 00116 #define CORTEX_MAX_KERNEL_PRIORITY 0 00117 #endif 00118 00119 /*===========================================================================*/ 00120 /* Port exported info. */ 00121 /*===========================================================================*/ 00122 00123 /** 00124 * @brief Macro defining the specific ARM architecture. 00125 */ 00126 #define CH_ARCHITECTURE_ARM_v6M 00127 00128 /** 00129 * @brief Name of the implemented architecture. 00130 */ 00131 #define CH_ARCHITECTURE_NAME "ARMv6-M" 00132 00133 /** 00134 * @brief Name of the architecture variant. 00135 */ 00136 #if (CORTEX_MODEL == CORTEX_M0) || defined(__DOXYGEN__) 00137 #define CH_CORE_VARIANT_NAME "Cortex-M0" 00138 #elif (CORTEX_MODEL == CORTEX_M1) 00139 #define CH_CORE_VARIANT_NAME "Cortex-M1" 00140 #endif 00141 00142 /** 00143 * @brief Port-specific information string. 00144 */ 00145 #if !CORTEX_ALTERNATE_SWITCH || defined(__DOXYGEN__) 00146 #define CH_PORT_INFO "Preemption through NMI" 00147 #else 00148 #define CH_PORT_INFO "Preemption through PendSV" 00149 #endif 00150 00151 /*===========================================================================*/ 00152 /* Port implementation part. */ 00153 /*===========================================================================*/ 00154 00155 #if !defined(_FROM_ASM_) 00156 00157 /** 00158 * @brief Generic ARM register. 00159 */ 00160 typedef void *regarm_t; 00161 00162 /** 00163 * @brief Stack and memory alignment enforcement. 00164 * @note In this architecture the stack alignment is enforced to 64 bits, 00165 * 32 bits alignment is supported by hardware but deprecated by ARM, 00166 * the implementation choice is to not offer the option. 00167 */ 00168 typedef uint64_t stkalign_t; 00169 00170 /* The documentation of the following declarations is in chconf.h in order 00171 to not have duplicated structure names into the documentation.*/ 00172 #if !defined(__DOXYGEN__) 00173 00174 struct extctx { 00175 regarm_t r0; 00176 regarm_t r1; 00177 regarm_t r2; 00178 regarm_t r3; 00179 regarm_t r12; 00180 regarm_t lr_thd; 00181 regarm_t pc; 00182 regarm_t xpsr; 00183 }; 00184 00185 struct intctx { 00186 regarm_t r8; 00187 regarm_t r9; 00188 regarm_t r10; 00189 regarm_t r11; 00190 regarm_t r4; 00191 regarm_t r5; 00192 regarm_t r6; 00193 regarm_t r7; 00194 regarm_t lr; 00195 }; 00196 00197 #endif /* !defined(__DOXYGEN__) */ 00198 00199 /** 00200 * @brief Platform dependent part of the @p Thread structure. 00201 * @details In this port the structure just holds a pointer to the @p intctx 00202 * structure representing the stack pointer at context switch time. 00203 */ 00204 struct context { 00205 struct intctx *r13; 00206 }; 00207 00208 /** 00209 * @brief Platform dependent part of the @p chThdCreateI() API. 00210 * @details This code usually setup the context switching frame represented 00211 * by an @p intctx structure. 00212 */ 00213 #define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ 00214 tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \ 00215 wsize - \ 00216 sizeof(struct intctx)); \ 00217 tp->p_ctx.r13->r4 = (regarm_t)pf; \ 00218 tp->p_ctx.r13->r5 = (regarm_t)arg; \ 00219 tp->p_ctx.r13->lr = (regarm_t)_port_thread_start; \ 00220 } 00221 00222 /** 00223 * @brief Enforces a correct alignment for a stack area size value. 00224 */ 00225 #define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) 00226 00227 /** 00228 * @brief Computes the thread working area global size. 00229 */ 00230 #define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ 00231 sizeof(struct intctx) + \ 00232 sizeof(struct extctx) + \ 00233 (n) + (PORT_INT_REQUIRED_STACK)) 00234 00235 /** 00236 * @brief Static working area allocation. 00237 * @details This macro is used to allocate a static thread working area 00238 * aligned as both position and size. 00239 */ 00240 #define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] 00241 00242 /** 00243 * @brief IRQ prologue code. 00244 * @details This macro must be inserted at the start of all IRQ handlers 00245 * enabled to invoke system APIs. 00246 */ 00247 #define PORT_IRQ_PROLOGUE() regarm_t _saved_lr = (regarm_t)__get_LR() 00248 00249 /** 00250 * @brief IRQ epilogue code. 00251 * @details This macro must be inserted at the end of all IRQ handlers 00252 * enabled to invoke system APIs. 00253 */ 00254 #define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr) 00255 00256 /** 00257 * @brief IRQ handler function declaration. 00258 * @note @p id can be a function name or a vector number depending on the 00259 * port implementation. 00260 */ 00261 #define PORT_IRQ_HANDLER(id) void id(void) 00262 00263 /** 00264 * @brief Fast IRQ handler function declaration. 00265 * @note @p id can be a function name or a vector number depending on the 00266 * port implementation. 00267 */ 00268 #define PORT_FAST_IRQ_HANDLER(id) void id(void) 00269 00270 /** 00271 * @brief Port-related initialization code. 00272 */ 00273 #define port_init() { \ 00274 SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \ 00275 nvicSetSystemHandlerPriority(HANDLER_PENDSV, \ 00276 CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV)); \ 00277 nvicSetSystemHandlerPriority(HANDLER_SYSTICK, \ 00278 CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \ 00279 } 00280 00281 /** 00282 * @brief Kernel-lock action. 00283 * @details Usually this function just disables interrupts but may perform 00284 * more actions. 00285 */ 00286 #define port_lock() __disable_interrupt() 00287 00288 /** 00289 * @brief Kernel-unlock action. 00290 * @details Usually this function just enables interrupts but may perform 00291 * more actions. 00292 */ 00293 #define port_unlock() __enable_interrupt() 00294 00295 /** 00296 * @brief Kernel-lock action from an interrupt handler. 00297 * @details This function is invoked before invoking I-class APIs from 00298 * interrupt handlers. The implementation is architecture dependent, 00299 * in its simplest form it is void. 00300 * @note Same as @p port_lock() in this port. 00301 */ 00302 #define port_lock_from_isr() port_lock() 00303 00304 /** 00305 * @brief Kernel-unlock action from an interrupt handler. 00306 * @details This function is invoked after invoking I-class APIs from interrupt 00307 * handlers. The implementation is architecture dependent, in its 00308 * simplest form it is void. 00309 * @note Same as @p port_lock() in this port. 00310 */ 00311 #define port_unlock_from_isr() port_unlock() 00312 00313 /** 00314 * @brief Disables all the interrupt sources. 00315 */ 00316 #define port_disable() __disable_interrupt() 00317 00318 /** 00319 * @brief Disables the interrupt sources below kernel-level priority. 00320 */ 00321 #define port_suspend() __disable_interrupt() 00322 00323 /** 00324 * @brief Enables all the interrupt sources. 00325 */ 00326 #define port_enable() __enable_interrupt() 00327 00328 /** 00329 * @brief Enters an architecture-dependent IRQ-waiting mode. 00330 * @details The function is meant to return when an interrupt becomes pending. 00331 * The simplest implementation is an empty function or macro but this 00332 * would not take advantage of architecture-specific power saving 00333 * modes. 00334 * @note Implemented as an inlined @p WFI instruction. 00335 */ 00336 #if CORTEX_ENABLE_WFI_IDLE || defined(__DOXYGEN__) 00337 #define port_wait_for_interrupt() asm ("wfi") 00338 #else 00339 #define port_wait_for_interrupt() 00340 #endif 00341 00342 /** 00343 * @brief Performs a context switch between two threads. 00344 * @details This is the most critical code in any port, this function 00345 * is responsible for the context switch between 2 threads. 00346 * @note The implementation of this code affects <b>directly</b> the context 00347 * switch performance so optimize here as much as you can. 00348 * 00349 * @param[in] ntp the thread to be switched in 00350 * @param[in] otp the thread to be switched out 00351 */ 00352 #if !CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) 00353 #define port_switch(ntp, otp) _port_switch(ntp, otp) 00354 #else 00355 #define port_switch(ntp, otp) { \ 00356 if ((stkalign_t *)(__get_SP() - sizeof(struct intctx)) < otp->p_stklimit) \ 00357 chDbgPanic("stack overflow"); \ 00358 _port_switch(ntp, otp); \ 00359 } 00360 #endif 00361 00362 #ifdef __cplusplus 00363 extern "C" { 00364 #endif 00365 void port_halt(void); 00366 void _port_irq_epilogue(regarm_t lr); 00367 void _port_switch_from_isr(void); 00368 void _port_exit_from_isr(void); 00369 void _port_switch(Thread *ntp, Thread *otp); 00370 void _port_thread_start(void); 00371 #ifdef __cplusplus 00372 } 00373 #endif 00374 00375 #endif /* _FROM_ASM_ */ 00376 00377 #endif /* _CHCORE_V6M_H_ */ 00378 00379 /** @} */