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