From bbc58e4f6055c24d8633a90fa2026a7db1d3184a Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 27 Dec 2011 19:12:33 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3664 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ports/IAR/ARMCMx/chcore.h | 89 +++------------- os/ports/IAR/ARMCMx/chcore_v6m.c | 66 ++++++++++++ os/ports/IAR/ARMCMx/chcore_v6m.h | 127 ++++++++++++++++++++++- os/ports/IAR/ARMCMx/chcore_v7m.c | 154 +++++++++++++++++++++++++++ os/ports/IAR/ARMCMx/chcore_v7m.h | 201 +++++++++++++++++++++++++++++++++--- os/ports/IAR/ARMCMx/chcoreasm_v6m.s | 49 --------- os/ports/IAR/ARMCMx/chcoreasm_v7m.s | 75 ++------------ 7 files changed, 553 insertions(+), 208 deletions(-) (limited to 'os/ports') diff --git a/os/ports/IAR/ARMCMx/chcore.h b/os/ports/IAR/ARMCMx/chcore.h index 9572a48c8..9b3f466c0 100644 --- a/os/ports/IAR/ARMCMx/chcore.h +++ b/os/ports/IAR/ARMCMx/chcore.h @@ -105,7 +105,7 @@ * a stack frame when compiling without optimizations. You may * reduce this value to zero when compiling with optimizations. */ -#ifndef PORT_IDLE_THREAD_STACK_SIZE +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) #define PORT_IDLE_THREAD_STACK_SIZE 16 #endif @@ -120,14 +120,14 @@ * @p chSchDoReschedule() can have a stack frame, expecially with * compiler optimizations disabled. */ -#ifndef PORT_INT_REQUIRED_STACK +#if !defined(PORT_INT_REQUIRED_STACK) #define PORT_INT_REQUIRED_STACK 16 #endif /** * @brief Enables the use of the WFI instruction in the idle thread loop. */ -#ifndef CORTEX_ENABLE_WFI_IDLE +#if !defined(CORTEX_ENABLE_WFI_IDLE) #define CORTEX_ENABLE_WFI_IDLE FALSE #endif @@ -136,25 +136,12 @@ * @note The default SYSTICK handler priority is calculated as the priority * level in the middle of the numeric priorities range. */ -#ifndef CORTEX_PRIORITY_SYSTICK +#if !defined(CORTEX_PRIORITY_SYSTICK) #define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) -#else +#elif !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK) /* If it is externally redefined then better perform a validity check on it.*/ -#if !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK) #error "invalid priority level specified for CORTEX_PRIORITY_SYSTICK" #endif -#endif - -/** - * @brief Stack alignment enforcement. - * @note The default value is 64 in order to comply with EABI, reducing - * the value to 32 can save some RAM space if you don't care about - * binary compatibility with EABI compiled libraries. - * @note Allowed values are 32 or 64. - */ -#ifndef CORTEX_STACK_ALIGNMENT -#define CORTEX_STACK_ALIGNMENT 64 -#endif /*===========================================================================*/ /* Port derived parameters (common). */ @@ -190,80 +177,34 @@ #include #include "nvic.h" +/* The following declarations are there just for Doxygen documentation, the + real declarations are inside the sub-headers.*/ +#if defined(__DOXYGEN__) + /** * @brief Stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 64 bits, + * 32 bits alignment is supported by hardware but deprecated by ARM, + * the implementation choice is to not offer the option. */ -#if (CORTEX_STACK_ALIGNMENT == 64) || defined(__DOXYGEN__) typedef uint64_t stkalign_t; -#elif CORTEX_STACK_ALIGNMENT == 32 -typedef uint32_t stkalign_t; -#else -#error "invalid stack alignment selected" -#endif -#if defined(__DOXYGEN__) /** * @brief Interrupt saved context. * @details This structure represents the stack frame saved during a * preemption-capable interrupt handler. * @note It is implemented to match the Cortex-Mx exception context. */ -struct extctx { - /* Dummy definition, just for Doxygen.*/ -}; +struct extctx {}; /** * @brief System saved context. * @details This structure represents the inner stack frame during a context * switching. */ -struct intctx { - /* Dummy definition, just for Doxygen.*/ -}; -#endif - -/** - * @brief Platform dependent part of the @p Thread structure. - * @details In this port the structure just holds a pointer to the @p intctx - * structure representing the stack pointer at context switch time. - */ -struct context { - struct intctx *r13; -}; +struct intctx {}; -/** - * @brief Platform dependent part of the @p chThdCreateI() API. - * @details This code usually setup the context switching frame represented - * by an @p intctx structure. - */ -#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ - tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \ - wsize - \ - sizeof(struct intctx)); \ - tp->p_ctx.r13->r4 = (void *)pf; \ - tp->p_ctx.r13->r5 = (void *)arg; \ - tp->p_ctx.r13->lr = (void *)_port_thread_start; \ -} - -/** - * @brief Enforces a correct alignment for a stack area size value. - */ -#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) - -/** - * @brief Computes the thread working area global size. - */ -#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ - sizeof(struct intctx) + \ - sizeof(struct extctx) + \ - (n) + (PORT_INT_REQUIRED_STACK)) - -/** - * @brief Static working area allocation. - * @details This macro is used to allocate a static thread working area - * aligned as both position and size. - */ -#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] +#endif /* defined(__DOXYGEN__) */ #endif /* _FROM_ASM_ */ diff --git a/os/ports/IAR/ARMCMx/chcore_v6m.c b/os/ports/IAR/ARMCMx/chcore_v6m.c index f04ff96d1..bee25350a 100644 --- a/os/ports/IAR/ARMCMx/chcore_v6m.c +++ b/os/ports/IAR/ARMCMx/chcore_v6m.c @@ -28,6 +28,10 @@ #include "ch.h" +/*===========================================================================*/ +/* Port interrupt handlers. */ +/*===========================================================================*/ + /** * @brief System Timer vector. * @details This interrupt is used as system tick. @@ -44,4 +48,66 @@ CH_IRQ_HANDLER(SysTickVector) { CH_IRQ_EPILOGUE(); } +#if !CORTEX_ALTERNATE_SWITCH || defined(__DOXYGEN__) +/** + * @brief NMI vector. + * @details The NMI vector is used for exception mode re-entering after a + * context switch. + */ +void NMIVector(void) { + register struct extctx *ctxp; + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp = (struct extctx *)__get_PSP(); + ctxp++; + __set_PSP((unsigned long)ctxp); + port_unlock_from_isr(); +} +#endif /* !CORTEX_ALTERNATE_SWITCH */ + +#if CORTEX_ALTERNATE_SWITCH || defined(__DOXYGEN__) +/** + * @brief PendSV vector. + * @details The PendSV vector is used for exception mode re-entering after a + * context switch. + */ +void PendSVVector(void) { + register struct extctx *ctxp; + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp = (struct extctx *)__get_PSP(); + ctxp++; + __set_PSP((unsigned long)ctxp); +} +#endif /* CORTEX_ALTERNATE_SWITCH */ + +/*===========================================================================*/ +/* Port exported functions. */ +/*===========================================================================*/ + +/** + * @brief IRQ epilogue code. + * + * @param[in] lr value of the @p LR register on ISR entry + */ +void _port_irq_epilogue(regarm_t lr) { + + if (lr != (regarm_t)0xFFFFFFF1) { + register struct extctx *ctxp; + + port_lock_from_isr(); + /* Adding an artificial exception return context, there is no need to + populate it fully.*/ + ctxp = (struct extctx *)__get_PSP(); + ctxp--; + __set_PSP((unsigned long)ctxp); + ctxp->pc = (regarm_t)_port_switch_from_isr; + ctxp->xpsr = (regarm_t)0x01000000; + /* Note, returning without unlocking is intentional, this is done in + order to keep the rest of the context switching atomic.*/ + } +} + /** @} */ diff --git a/os/ports/IAR/ARMCMx/chcore_v6m.h b/os/ports/IAR/ARMCMx/chcore_v6m.h index 9c7f77203..75f6c84da 100644 --- a/os/ports/IAR/ARMCMx/chcore_v6m.h +++ b/os/ports/IAR/ARMCMx/chcore_v6m.h @@ -41,10 +41,61 @@ */ #define CORTEX_PRIORITY_PENDSV 0 +/*===========================================================================*/ +/* Port macros. */ +/*===========================================================================*/ + /*===========================================================================*/ /* Port configurable parameters. */ /*===========================================================================*/ +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 16 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) +#define PORT_IDLE_THREAD_STACK_SIZE 16 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * This value can be zero on those architecture where there is a + * separate interrupt stack and the stack space between @p intctx and + * @p extctx is known to be zero. + * @note In this port it is conservatively set to 16 because the function + * @p chSchDoReschedule() can have a stack frame, expecially with + * compiler optimizations disabled. + */ +#if !defined(PORT_INT_REQUIRED_STACK) +#define PORT_INT_REQUIRED_STACK 16 +#endif + +/** + * @brief Enables the use of the WFI instruction in the idle thread loop. + */ +#if !defined(CORTEX_ENABLE_WFI_IDLE) +#define CORTEX_ENABLE_WFI_IDLE FALSE +#endif + +/** + * @brief SYSTICK handler priority. + * @note The default SYSTICK handler priority is calculated as the priority + * level in the middle of the numeric priorities range. + */ +#if !defined(CORTEX_PRIORITY_SYSTICK) +#define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) +#elif !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK) +/* If it is externally redefined then better perform a validity check on it.*/ +#error "invalid priority level specified for CORTEX_PRIORITY_SYSTICK" +#endif + /** * @brief Alternate preemption method. * @details Activating this option will make the Kernel use the PendSV @@ -101,7 +152,18 @@ */ typedef void *regarm_t; +/** + * @brief Stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 64 bits, + * 32 bits alignment is supported by hardware but deprecated by ARM, + * the implementation choice is to not offer the option. + */ +typedef uint64_t stkalign_t; + + /* The documentation of the following declarations is in chconf.h in order + to not have duplicated structure names into the documentation.*/ #if !defined(__DOXYGEN__) + struct extctx { regarm_t r0; regarm_t r1; @@ -124,7 +186,51 @@ struct intctx { regarm_t r7; regarm_t lr; }; -#endif + +#endif /* !defined(__DOXYGEN__) */ + +/** + * @brief Platform dependent part of the @p Thread structure. + * @details In this port the structure just holds a pointer to the @p intctx + * structure representing the stack pointer at context switch time. + */ +struct context { + struct intctx *r13; +}; + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p intctx structure. + */ +#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ + tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \ + wsize - \ + sizeof(struct intctx)); \ + tp->p_ctx.r13->r4 = (regarm_t)pf; \ + tp->p_ctx.r13->r5 = (regarm_t)arg; \ + tp->p_ctx.r13->lr = (regarm_t)_port_thread_start; \ +} + +/** + * @brief Enforces a correct alignment for a stack area size value. + */ +#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) + +/** + * @brief Computes the thread working area global size. + */ +#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ + sizeof(struct intctx) + \ + sizeof(struct extctx) + \ + (n) + (PORT_INT_REQUIRED_STACK)) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + */ +#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] /** * @brief IRQ prologue code. @@ -246,6 +352,25 @@ struct intctx { } #endif +#if 0 +/** + * @brief Excludes the default @p chSchIsPreemptionRequired()implementation. + */ +#define PORT_OPTIMIZED_ISPREEMPTIONREQUIRED + +#if (CH_TIME_QUANTUM > 0) || defined(__DOXYGEN__) +/** + * @brief Inlineable version of this kernel function. + */ +#define chSchIsPreemptionRequired() \ + (rlist.r_preempt ? firstprio(&rlist.r_queue) > currp->p_prio : \ + firstprio(&rlist.r_queue) >= currp->p_prio) +#else /* CH_TIME_QUANTUM == 0 */ +#define chSchIsPreemptionRequired() \ + (firstprio(&rlist.r_queue) > currp->p_prio) +#endif /* CH_TIME_QUANTUM == 0 */ +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/ports/IAR/ARMCMx/chcore_v7m.c b/os/ports/IAR/ARMCMx/chcore_v7m.c index cef8b59a0..ee6e41360 100644 --- a/os/ports/IAR/ARMCMx/chcore_v7m.c +++ b/os/ports/IAR/ARMCMx/chcore_v7m.c @@ -28,6 +28,10 @@ #include "ch.h" +/*===========================================================================*/ +/* Port interrupt handlers. */ +/*===========================================================================*/ + /** * @brief System Timer vector. * @details This interrupt is used as system tick. @@ -44,4 +48,154 @@ CH_IRQ_HANDLER(SysTickVector) { CH_IRQ_EPILOGUE(); } +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) +/** + * @brief SVC vector. + * @details The SVC vector is used for exception mode re-entering after a + * context switch. + * @note The PendSV vector is only used in advanced kernel mode. + */ +void SVCallVector(void) { + struct extctx *ctxp; + + /* Current PSP value.*/ + ctxp = (struct extctx *)__get_PSP(); + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp++; + +#if CORTEX_USE_FPU + /* Restoring the special register SCB_FPCCR.*/ + SCB_FPCCR = (uint32_t)ctxp->fpccr; + SCB_FPCAR = SCB_FPCAR + sizeof (struct extctx); +#endif + __set_PSP((unsigned long)ctxp); + port_unlock_from_isr(); +} +#endif /* !CORTEX_SIMPLIFIED_PRIORITY */ + +#if CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) +/** + * @brief PendSV vector. + * @details The PendSV vector is used for exception mode re-entering after a + * context switch. + * @note The PendSV vector is only used in compact kernel mode. + */ +void PendSVVector(void) { + struct extctx *ctxp; + + /* Current PSP value.*/ + ctxp = (struct extctx *)__get_PSP(); + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp++; + +#if CORTEX_USE_FPU + /* Restoring the special register SCB_FPCCR.*/ + SCB_FPCCR = (uint32_t)ctxp->fpccr; + SCB_FPCAR = SCB_FPCAR + sizeof (struct extctx); +#endif + __set_PSP((unsigned long)ctxp); +} +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ + +/*===========================================================================*/ +/* Port exported functions. */ +/*===========================================================================*/ + +/** + * @brief Port-related initialization code. + */ +void _port_init(void) { + + /* Initialization of the vector table and priority related settings.*/ + SCB_VTOR = CORTEX_VTOR_INIT; + SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); + +#if CORTEX_USE_FPU + { + uint32_t reg; + + /* Initializing the FPU context save in lazy mode.*/ + SCB_FPCCR = FPCCR_ASPEN | FPCCR_LSPEN; + + /* CP10 and CP11 set to full access.*/ + SCB_CPACR |= 0x00F00000; + + /* Enables FPU context save/restore on exception entry/exit (FPCA bit).*/ + __set_control(__get_control() | 4); + + /* FPSCR and FPDSCR initially zero.*/ + __set_FPSCR(0); + SCB_FPDSCR = 0; + } +#endif + + /* Initialization of the system vectors used by the port.*/ + nvicSetSystemHandlerPriority(HANDLER_SVCALL, + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL)); + nvicSetSystemHandlerPriority(HANDLER_PENDSV, + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV)); + nvicSetSystemHandlerPriority(HANDLER_SYSTICK, + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); +} + +/** + * @brief Exception exit redirection to _port_switch_from_isr(). + */ +void _port_irq_epilogue(void) { + + port_lock_from_isr(); + if ((SCB_ICSR & ICSR_RETTOBASE) != 0) { + struct extctx *ctxp; + + /* Current PSP value.*/ + ctxp = (struct extctx *)__get_PSP(); + + /* Adding an artificial exception return context, there is no need to + populate it fully.*/ + ctxp--; + __set_PSP((unsigned long)ctxp); + ctxp->xpsr = (regarm_t)0x01000000; + + /* The exit sequence is different depending on if a preemption is + required or not.*/ + if (chSchIsPreemptionRequired()) { + /* Preemption is required we need to enforce a context switch.*/ + ctxp->pc = (regarm_t)_port_switch_from_isr; +#if CORTEX_USE_FPU + /* Triggering a lazy FPU state save.*/ + (void)__get_FPSCR(); +#endif + } + else { + /* Preemption not required, we just need to exit the exception + atomically.*/ + void _port_exit_from_isr(void); + ctxp->pc = (regarm_t)_port_exit_from_isr; + } + +#if CORTEX_USE_FPU + { + uint32_t fpccr; + + /* Saving the special register SCB_FPCCR into the reserved offset of + the Cortex-M4 exception frame.*/ + (ctxp + 1)->fpccr = (regarm_t)(fpccr = SCB_FPCCR); + + /* Now the FPCCR is modified in order to not restore the FPU status + from the artificial return context.*/ + SCB_FPCCR = fpccr | FPCCR_LSPACT; + } +#endif + + /* Note, returning without unlocking is intentional, this is done in + order to keep the rest of the context switching atomic.*/ + return; + } + port_unlock_from_isr(); +} + /** @} */ diff --git a/os/ports/IAR/ARMCMx/chcore_v7m.h b/os/ports/IAR/ARMCMx/chcore_v7m.h index 38f77b7eb..b6c44d4ea 100644 --- a/os/ports/IAR/ARMCMx/chcore_v7m.h +++ b/os/ports/IAR/ARMCMx/chcore_v7m.h @@ -38,15 +38,78 @@ */ #define CORTEX_BASEPRI_DISABLED 0 +/*===========================================================================*/ +/* Port macros. */ +/*===========================================================================*/ + /*===========================================================================*/ /* Port configurable parameters. */ /*===========================================================================*/ +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 16 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) +#define PORT_IDLE_THREAD_STACK_SIZE 16 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * This value can be zero on those architecture where there is a + * separate interrupt stack and the stack space between @p intctx and + * @p extctx is known to be zero. + * @note In this port it is conservatively set to 16 because the function + * @p chSchDoReschedule() can have a stack frame, expecially with + * compiler optimizations disabled. + */ +#if !defined(PORT_INT_REQUIRED_STACK) +#define PORT_INT_REQUIRED_STACK 16 +#endif + +/** + * @brief Enables the use of the WFI instruction in the idle thread loop. + */ +#if !defined(CORTEX_ENABLE_WFI_IDLE) +#define CORTEX_ENABLE_WFI_IDLE FALSE +#endif + +/** + * @brief SYSTICK handler priority. + * @note The default SYSTICK handler priority is calculated as the priority + * level in the middle of the numeric priorities range. + */ +#if !defined(CORTEX_PRIORITY_SYSTICK) +#define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) +#elif !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK) +/* If it is externally redefined then better perform a validity check on it.*/ +#error "invalid priority level specified for CORTEX_PRIORITY_SYSTICK" +#endif + +/** + * @brief FPU support in context switch. + * @details Activating this option activates the FPU support in the kernel. + */ +#if !defined(CORTEX_USE_FPU) +#define CORTEX_USE_FPU CORTEX_HAS_FPU +#elif CORTEX_USE_FPU && !CORTEX_HAS_FPU +/* This setting requires an FPU presence check in case it is externally + redefined.*/ +#error "the selected core does not have an FPU" +#endif + /** * @brief Simplified priority handling flag. - * @details Activating this option will make the Kernel work in compact mode. + * @details Activating this option makes the Kernel work in compact mode. */ -#ifndef CORTEX_SIMPLIFIED_PRIORITY +#if !defined(CORTEX_SIMPLIFIED_PRIORITY) #define CORTEX_SIMPLIFIED_PRIORITY FALSE #endif @@ -57,14 +120,12 @@ * @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts * priority level. */ -#ifndef CORTEX_PRIORITY_SVCALL +#if !defined(CORTEX_PRIORITY_SVCALL) #define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1) -#else +#elif !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SVCALL) /* If it is externally redefined then better perform a validity check on it.*/ -#if !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SVCALL) #error "invalid priority level specified for CORTEX_PRIORITY_SVCALL" #endif -#endif /** * @brief NVIC VTOR initialization expression. @@ -119,8 +180,12 @@ #elif (CORTEX_MODEL == CORTEX_M4) #define CH_ARCHITECTURE_ARM_v7ME #define CH_ARCHITECTURE_NAME "ARMv7-ME" +#if CORTEX_USE_FPU +#define CH_CORE_VARIANT_NAME "Cortex-M4F" +#else #define CH_CORE_VARIANT_NAME "Cortex-M4" #endif +#endif /** * @brief Port-specific information string. @@ -142,7 +207,18 @@ */ typedef void *regarm_t; +/** + * @brief Stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 64 bits, + * 32 bits alignment is supported by hardware but deprecated by ARM, + * the implementation choice is to not offer the option. + */ +typedef uint64_t stkalign_t; + +/* The documentation of the following declarations is in chconf.h in order + to not have duplicated structure names into the documentation.*/ #if !defined(__DOXYGEN__) + struct extctx { regarm_t r0; regarm_t r1; @@ -152,9 +228,47 @@ struct extctx { regarm_t lr_thd; regarm_t pc; regarm_t xpsr; +#if CORTEX_USE_FPU + regarm_t s0; + regarm_t s1; + regarm_t s2; + regarm_t s3; + regarm_t s4; + regarm_t s5; + regarm_t s6; + regarm_t s7; + regarm_t s8; + regarm_t s9; + regarm_t s10; + regarm_t s11; + regarm_t s12; + regarm_t s13; + regarm_t s14; + regarm_t s15; + regarm_t fpscr; + regarm_t fpccr; +#endif /* CORTEX_USE_FPU */ }; struct intctx { +#if CORTEX_USE_FPU + regarm_t s16; + regarm_t s17; + regarm_t s18; + regarm_t s19; + regarm_t s20; + regarm_t s21; + regarm_t s22; + regarm_t s23; + regarm_t s24; + regarm_t s25; + regarm_t s26; + regarm_t s27; + regarm_t s28; + regarm_t s29; + regarm_t s30; + regarm_t s31; +#endif /* CORTEX_USE_FPU */ regarm_t r4; regarm_t r5; regarm_t r6; @@ -165,7 +279,51 @@ struct intctx { regarm_t r11; regarm_t lr; }; -#endif + +#endif /* !defined(__DOXYGEN__) */ + +/** + * @brief Platform dependent part of the @p Thread structure. + * @details In this port the structure just holds a pointer to the @p intctx + * structure representing the stack pointer at context switch time. + */ +struct context { + struct intctx *r13; +}; + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p intctx structure. + */ +#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ + tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \ + wsize - \ + sizeof(struct intctx)); \ + tp->p_ctx.r13->r4 = (regarm_t)pf; \ + tp->p_ctx.r13->r5 = (regarm_t)arg; \ + tp->p_ctx.r13->lr = (regarm_t)_port_thread_start; \ +} + +/** + * @brief Enforces a correct alignment for a stack area size value. + */ +#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) + +/** + * @brief Computes the thread working area global size. + */ +#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ + sizeof(struct intctx) + \ + sizeof(struct extctx) + \ + (n) + (PORT_INT_REQUIRED_STACK)) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + */ +#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] /** * @brief IRQ prologue code. @@ -198,16 +356,7 @@ struct intctx { /** * @brief Port-related initialization code. */ -#define port_init() { \ - SCB_VTOR = CORTEX_VTOR_INIT; \ - SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \ - nvicSetSystemHandlerPriority(HANDLER_SVCALL, \ - CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL)); \ - nvicSetSystemHandlerPriority(HANDLER_PENDSV, \ - CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV)); \ - nvicSetSystemHandlerPriority(HANDLER_SYSTICK, \ - CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \ -} +#define port_init() _port_init() /** * @brief Kernel-lock action. @@ -320,10 +469,28 @@ struct intctx { } #endif +/** + * @brief Excludes the default @p chSchIsPreemptionRequired()implementation. + */ +#define PORT_OPTIMIZED_ISPREEMPTIONREQUIRED + +#if (CH_TIME_QUANTUM > 0) || defined(__DOXYGEN__) +/** + * @brief Inlineable version of this kernel function. + */ +#define chSchIsPreemptionRequired() \ + (rlist.r_preempt ? firstprio(&rlist.r_queue) > currp->p_prio : \ + firstprio(&rlist.r_queue) >= currp->p_prio) +#else /* CH_TIME_QUANTUM == 0 */ +#define chSchIsPreemptionRequired() \ + (firstprio(&rlist.r_queue) > currp->p_prio) +#endif /* CH_TIME_QUANTUM == 0 */ + #ifdef __cplusplus extern "C" { #endif void port_halt(void); + void _port_init(void); void _port_switch(Thread *ntp, Thread *otp); void _port_irq_epilogue(void); void _port_switch_from_isr(void); diff --git a/os/ports/IAR/ARMCMx/chcoreasm_v6m.s b/os/ports/IAR/ARMCMx/chcoreasm_v6m.s index 56e62d16f..fb1cb0fb7 100644 --- a/os/ports/IAR/ARMCMx/chcoreasm_v6m.s +++ b/os/ports/IAR/ARMCMx/chcoreasm_v6m.s @@ -82,35 +82,6 @@ _port_thread_start: blx r4 bl chThdExit -/* - * NMI vector. - * The NMI vector is used for exception mode re-entering after a context - * switch. - */ -#if !CORTEX_ALTERNATE_SWITCH - PUBLIC NMIVector -NMIVector: - mrs r3, PSP - adds r3, r3, #32 - msr PSP, r3 - cpsie i - bx lr -#endif - -/* - * PendSV vector. - * The PendSV vector is used for exception mode re-entering after a context - * switch. - */ -#if CORTEX_ALTERNATE_SWITCH - PUBLIC PendSVVector -PendSVVector: - mrs r3, PSP - adds r3, r3, #32 - msr PSP, r3 - bx lr -#endif - /* * Post-IRQ switch code. * Exception handlers return here for context switching. @@ -141,24 +112,4 @@ noresch: waithere: b waithere -/* - * Reschedule verification and setup after an IRQ. - */ - PUBLIC _port_irq_epilogue -_port_irq_epilogue: - push {lr} - adds r0, r0, #15 - beq skipexit - cpsid i - mrs r3, PSP - subs r3, r3, #32 - msr PSP, r3 - ldr r2, =_port_switch_from_isr - str r2, [r3, #24] - movs r2, #128 - lsls r2, r2, #17 - str r2, [r3, #28] -skipexit: - pop {pc} - END diff --git a/os/ports/IAR/ARMCMx/chcoreasm_v7m.s b/os/ports/IAR/ARMCMx/chcoreasm_v7m.s index 4c40babc5..6c858c52b 100644 --- a/os/ports/IAR/ARMCMx/chcoreasm_v7m.s +++ b/os/ports/IAR/ARMCMx/chcoreasm_v7m.s @@ -39,7 +39,6 @@ ICSR_PENDSVSET SET 0x10000000 SECTION .text:CODE:NOROOT(2) EXTERN chThdExit - EXTERN chSchIsPreemptionRequired EXTERN chSchDoReschedule #if CH_DBG_SYSTEM_STATE_CHECK EXTERN dbg_check_unlock @@ -54,8 +53,14 @@ ICSR_PENDSVSET SET 0x10000000 PUBLIC _port_switch _port_switch: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} +#if CORTEX_USE_FPU + vpush {s16-s31} +#endif str sp, [r1, #CONTEXT_OFFSET] ldr sp, [r0, #CONTEXT_OFFSET] +#if CORTEX_USE_FPU + vpop {s16-s31} +#endif pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} /* @@ -82,17 +87,16 @@ _port_thread_start: * Exception handlers return here for context switching. */ PUBLIC _port_switch_from_isr + PUBLIC _port_exit_from_isr _port_switch_from_isr: #if CH_DBG_SYSTEM_STATE_CHECK bl dbg_check_lock #endif - bl chSchIsPreemptionRequired - cbz r0, .L2 bl chSchDoReschedule -.L2: #if CH_DBG_SYSTEM_STATE_CHECK bl dbg_check_unlock #endif +_port_exit_from_isr: #if CORTEX_SIMPLIFIED_PRIORITY mov r3, #LWRD SCB_ICSR movt r3, #HWRD SCB_ICSR @@ -104,67 +108,4 @@ _port_switch_from_isr: svc #0 #endif -/* - * Reschedule verification and setup after an IRQ. - */ - PUBLIC _port_irq_epilogue -_port_irq_epilogue: -#if CORTEX_SIMPLIFIED_PRIORITY - cpsid i -#else - movs r3, #CORTEX_BASEPRI_KERNEL - msr BASEPRI, r3 -#endif - mov r3, #LWRD SCB_ICSR - movt r3, #HWRD SCB_ICSR - ldr r3, [r3, #0] - ands r3, r3, #ICSR_RETTOBASE - bne .L8 -#if CORTEX_SIMPLIFIED_PRIORITY - cpsie i -#else - /* Note, R3 is already zero.*/ - msr BASEPRI, r3 -#endif - bx lr -.L8: - mrs r3, PSP - subs r3, r3, #EXTCTX_SIZE - msr PSP, r3 - ldr r2, =_port_switch_from_isr - str r2, [r3, #24] - mov r2, #0x01000000 - str r2, [r3, #28] - bx lr - -/* - * SVC vector. - * Discarding the current exception context and positioning the stack to - * point to the real one. - */ -#if !CORTEX_SIMPLIFIED_PRIORITY - PUBLIC SVCallVector -SVCallVector: - mrs r3, PSP - adds r3, r3, #EXTCTX_SIZE - msr PSP, r3 - movs r3, #CORTEX_BASEPRI_DISABLED - msr BASEPRI, r3 - bx lr -#endif - -/* - * PendSV vector. - * Discarding the current exception context and positioning the stack to - * point to the real one. - */ -#if CORTEX_SIMPLIFIED_PRIORITY - PUBLIC PendSVVector -PendSVVector: - mrs r3, PSP - adds r3, r3, #EXTCTX_SIZE - msr PSP, r3 - bx lr -#endif - END -- cgit v1.2.3