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