ChibiOS/RT
2.5.1
chcore_v6m.h
Go to the documentation of this file.
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 /** @} */