From e0b53350156cef01da9b83e46127f7322e967909 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 17 May 2011 14:49:51 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2966 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/include/ch.h | 2 +- os/kernel/src/chsys.c | 2 +- os/kernel/templates/chcore.h | 82 ++++++++++---- os/ports/GCC/ARMCMx/chcore.h | 182 +++++++++++-------------------- os/ports/GCC/ARMCMx/chcore_v6m.h | 95 +++++++++------- os/ports/GCC/ARMCMx/chcore_v7m.c | 40 +++++-- os/ports/GCC/ARMCMx/chcore_v7m.h | 161 ++++++++++++++++++--------- os/ports/GCC/ARMCMx/port.dox | 37 +++++-- readme.txt | 9 ++ test/test.c | 10 +- test/testbmk.c | 8 +- 11 files changed, 366 insertions(+), 262 deletions(-) diff --git a/os/kernel/include/ch.h b/os/kernel/include/ch.h index 7d33e2397..db96d4338 100644 --- a/os/kernel/include/ch.h +++ b/os/kernel/include/ch.h @@ -95,7 +95,7 @@ #include "chdebug.h" #if !defined(__DOXYGEN__) -extern WORKING_AREA(_idle_thread_wa, IDLE_THREAD_STACK_SIZE); +extern WORKING_AREA(_idle_thread_wa, PORT_IDLE_THREAD_STACK_SIZE); #endif #ifdef __cplusplus diff --git a/os/kernel/src/chsys.c b/os/kernel/src/chsys.c index 5d3c0bcf4..13a1a53fa 100644 --- a/os/kernel/src/chsys.c +++ b/os/kernel/src/chsys.c @@ -40,7 +40,7 @@ * @brief Idle thread working area. * @see IDLE_THREAD_STACK_SIZE */ -WORKING_AREA(_idle_thread_wa, IDLE_THREAD_STACK_SIZE); +WORKING_AREA(_idle_thread_wa, PORT_IDLE_THREAD_STACK_SIZE); /** * @brief This function implements the idle thread infinite loop. diff --git a/os/kernel/templates/chcore.h b/os/kernel/templates/chcore.h index f190dfbe3..2c69362b2 100644 --- a/os/kernel/templates/chcore.h +++ b/os/kernel/templates/chcore.h @@ -31,6 +31,48 @@ #ifndef _CHCORE_H_ #define _CHCORE_H_ +/*===========================================================================*/ +/* Port constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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 INT_REQUIRED_STACK. + */ +#ifndef PORT_IDLE_THREAD_STACK_SIZE +#define PORT_IDLE_THREAD_STACK_SIZE 0 +#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. + */ +#ifndef PORT_INT_REQUIRED_STACK +#define PORT_INT_REQUIRED_STACK 0 +#endif + +/*===========================================================================*/ +/* Port derived parameters. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Port exported info. */ +/*===========================================================================*/ + /** * @brief Unique macro for the implemented architecture. */ @@ -39,12 +81,26 @@ /** * @brief Name of the implemented architecture. */ -#define CH_ARCHITECTURE_NAME "" +#define CH_ARCHITECTURE_NAME "" /** * @brief Name of the architecture variant (optional). */ -#define CH_ARCHITECTURE_VARIANT_NAME "" +#define CH_ARCHITECTURE_VARIANT_NAME "" + +/** + * @brief Name of the compiler supported by this port. + */ +#define CH_COMPILER_NAME "GCC" + +/** + * @brief Port-specific information string. + */ +#define CH_PORT_INFO "" + +/*===========================================================================*/ +/* Port implementation part. */ +/*===========================================================================*/ /** * @brief Base type for stack and memory alignment. @@ -84,28 +140,6 @@ struct context { #define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ } -/** - * @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 INT_REQUIRED_STACK. - */ -#ifndef IDLE_THREAD_STACK_SIZE -#define IDLE_THREAD_STACK_SIZE 0 -#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. - */ -#ifndef INT_REQUIRED_STACK -#define INT_REQUIRED_STACK 0 -#endif - /** * @brief Enforces a correct alignment for a stack area size value. */ diff --git a/os/ports/GCC/ARMCMx/chcore.h b/os/ports/GCC/ARMCMx/chcore.h index c58b7bb3a..42df48a09 100644 --- a/os/ports/GCC/ARMCMx/chcore.h +++ b/os/ports/GCC/ARMCMx/chcore.h @@ -35,10 +35,10 @@ /* Port constants. */ /*===========================================================================*/ -#define CORTEX_M0 0 /**< @brief Cortex-M0 variant. */ -#define CORTEX_M1 1 /**< @brief Cortex-M1 variant. */ -#define CORTEX_M3 3 /**< @brief Cortex-M3 variant. */ -#define CORTEX_M4 4 /**< @brief Cortex-M4 variant. */ +#define CORTEX_M0 0 /**< @brief Cortex-M0 variant. */ +#define CORTEX_M1 1 /**< @brief Cortex-M1 variant. */ +#define CORTEX_M3 3 /**< @brief Cortex-M3 variant. */ +#define CORTEX_M4 4 /**< @brief Cortex-M4 variant. */ /* Inclusion of the Cortex-Mx implementation specific parameters.*/ #include "cmparams.h" @@ -51,33 +51,29 @@ #error "unknown or unsupported Cortex-M model" #endif -/*===========================================================================*/ -/* Port statically derived parameters. */ -/*===========================================================================*/ - /** * @brief Total priority levels. */ -#define CORTEX_PRIORITY_LEVELS (1 << CORTEX_PRIORITY_BITS) +#define CORTEX_PRIORITY_LEVELS (1 << CORTEX_PRIORITY_BITS) /** * @brief Minimum priority level. * @details This minimum priority level is calculated from the number of * priority bits supported by the specific Cortex-Mx implementation. */ -#define CORTEX_MINIMUM_PRIORITY (CORTEX_PRIORITY_LEVELS - 1) +#define CORTEX_MINIMUM_PRIORITY (CORTEX_PRIORITY_LEVELS - 1) /** * @brief Maximum priority level. * @details The maximum allowed priority level is always zero. */ -#define CORTEX_MAXIMUM_PRIORITY 0 +#define CORTEX_MAXIMUM_PRIORITY 0 /** * @brief Disabled value for BASEPRI register. * @note ARMv7-M architecture only. */ -#define CORTEX_BASEPRI_DISABLED 0 +#define CORTEX_BASEPRI_DISABLED 0 /*===========================================================================*/ /* Port macros. */ @@ -99,11 +95,39 @@ /* 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. + */ +#ifndef 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 chSchDoRescheduleI() can have a stack frame, expecially with + * compiler optimizations disabled. + */ +#ifndef 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 -#define CORTEX_ENABLE_WFI_IDLE FALSE +#define CORTEX_ENABLE_WFI_IDLE FALSE #endif /** @@ -112,7 +136,7 @@ * level in the middle of the numeric priorities range. */ #ifndef CORTEX_PRIORITY_SYSTICK -#define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) +#define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) #else /* If it is externally redefined then better perform a validity check on it.*/ #if !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK) @@ -120,53 +144,6 @@ #endif #endif -/** - * @brief SVCALL handler priority. - * @note The default SVCALL handler priority is calculated as - * @p CORTEX_MAXIMUM_PRIORITY+1, in the ARMv7-M port this reserves - * the @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts - * priority level. - * @note The SVCALL vector is only used in the ARMv7-M port, it is available - * to user in the ARMv6-M port. - */ -#ifndef CORTEX_PRIORITY_SVCALL -#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1) -#else -/* 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 PENDSV handler priority. - * @note The default PENDSV handler priority is set at the - * @p CORTEX_MINIMUM_PRIORITY priority level. - * @note The PENDSV vector is only used in the ARMv7-M legacy port, it is - * available to user in the ARMv6-M and ARMv7-M ports. - * @note In the ARMv7-M legacy port this value should be not changed from - * the minimum priority level. - */ -#ifndef CORTEX_PRIORITY_PENDSV -#define CORTEX_PRIORITY_PENDSV CORTEX_MINIMUM_PRIORITY -#else -/* If it is externally redefined then better perform a validity check on it.*/ -#if !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_PENDSV) -#error "invalid priority level specified for CORTEX_PRIORITY_PENDSV" -#endif -#endif - -/** - * @brief BASEPRI level within kernel lock. - * @note This value must not mask the SVCALL priority level or the - * kernel would hard fault. - * @note ARMv7-M architecture only. - */ -#ifndef CORTEX_BASEPRI_KERNEL -#define CORTEX_BASEPRI_KERNEL \ - CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL+1) -#endif - /** * @brief Stack alignment enforcement. * @note The default value is 64 in order to comply with EABI, reducing @@ -175,9 +152,13 @@ * @note Allowed values are 32 or 64. */ #ifndef CORTEX_STACK_ALIGNMENT -#define CORTEX_STACK_ALIGNMENT 64 +#define CORTEX_STACK_ALIGNMENT 64 #endif +/*===========================================================================*/ +/* Port derived parameters. */ +/*===========================================================================*/ + /*===========================================================================*/ /* Port exported info. */ /*===========================================================================*/ @@ -187,57 +168,10 @@ */ #define CH_ARCHITECTURE_ARM -#if defined(__DOXYGEN__) /** - * @brief Macro defining the specific ARM architecture. - * @note This macro is for documentation only, the real name changes - * depending on the selected architecture, the possible names are: - * - CH_ARCHITECTURE_ARM_v6M. - * - CH_ARCHITECTURE_ARM_v7M. - * . + * @brief Name of the compiler supported by this port. */ -#define CH_ARCHITECTURE_ARM_vxm - -/** - * @brief Name of the implemented architecture. - * @note The value is for documentation only, the real value changes - * depending on the selected architecture, the possible values are: - * - "ARMv6-M". - * - "ARMv7-M". - * - "ARMv7-ME". - * . - */ -#define CH_ARCHITECTURE_NAME "ARMvx-M" - -/** - * @brief Name of the architecture variant (optional). - * @note The value is for documentation only, the real value changes - * depending on the selected architecture, the possible values are: - * - "Cortex-M0" - * - "Cortex-M1" - * - "Cortex-M3" - * - "Cortex-M4" - * . - */ -#define CH_CORE_VARIANT_NAME "Cortex-Mx" - -#elif CORTEX_MODEL == CORTEX_M4 -#define CH_ARCHITECTURE_ARM_v7M -#define CH_ARCHITECTURE_NAME "ARMv7-ME" -#define CH_CORE_VARIANT_NAME "Cortex-M4" -#elif CORTEX_MODEL == CORTEX_M3 -#define CH_ARCHITECTURE_ARM_v7M -#define CH_ARCHITECTURE_NAME "ARMv7-M" -#define CH_CORE_VARIANT_NAME "Cortex-M3" -#elif CORTEX_MODEL == CORTEX_M1 -#define CH_ARCHITECTURE_ARM_v6M -#define CH_ARCHITECTURE_NAME "ARMv6-M" -#define CH_CORE_VARIANT_NAME "Cortex-M1" -#elif CORTEX_MODEL == CORTEX_M0 -#define CH_ARCHITECTURE_ARM_v6M -#define CH_ARCHITECTURE_NAME "ARMv6-M" -#define CH_CORE_VARIANT_NAME "Cortex-M0" -#endif +#define CH_COMPILER_NAME "GCC "__VERSION__ /*===========================================================================*/ /* Port implementation part (common). */ @@ -294,6 +228,20 @@ 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 = pf; \ + tp->p_ctx.r13->r5 = arg; \ + tp->p_ctx.r13->lr = _port_thread_start; \ +} + /** * @brief Enforces a correct alignment for a stack area size value. */ @@ -302,10 +250,10 @@ struct context { /** * @brief Computes the thread working area global size. */ -#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ - sizeof(struct intctx) + \ - sizeof(struct extctx) + \ - (n) + (INT_REQUIRED_STACK)) +#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. @@ -315,9 +263,9 @@ struct context { #define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] /* Includes the architecture-specific implementation part.*/ -#if defined(CH_ARCHITECTURE_ARM_v6M) +#if (CORTEX_MODEL == CORTEX_M0) || (CORTEX_MODEL == CORTEX_M1) #include "chcore_v6m.h" -#elif defined(CH_ARCHITECTURE_ARM_v7M) +#elif (CORTEX_MODEL == CORTEX_M3) || (CORTEX_MODEL == CORTEX_M4) #include "chcore_v7m.h" #endif diff --git a/os/ports/GCC/ARMCMx/chcore_v6m.h b/os/ports/GCC/ARMCMx/chcore_v6m.h index 0212fe6b3..3154bde56 100644 --- a/os/ports/GCC/ARMCMx/chcore_v6m.h +++ b/os/ports/GCC/ARMCMx/chcore_v6m.h @@ -29,6 +29,57 @@ #ifndef _CHCORE_V6M_H_ #define _CHCORE_V6M_H_ +/*===========================================================================*/ +/* Port constants. */ +/*===========================================================================*/ + +/** + * @brief BASEPRI level within kernel lock. + * @note The ARMv6-M architecture does not implement the BASEPRI register + * so the kernel always masks the whole priority range during + * a kernel lock. + */ +#define CORTEX_BASEPRI_KERNEL 0 + +/** + * @brief PendSV priority level. + * @note This priority is enforced to be equal to @p CORTEX_BASEPRI_KERNEL, + * this handler always have the highest priority that cannot preempt + * the kernel. + */ +#define CORTEX_PRIORITY_PENDSV CORTEX_BASEPRI_KERNEL + +/*===========================================================================*/ +/* Port configurable parameters. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Port derived parameters. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Port exported info. */ +/*===========================================================================*/ + +/** + * @brief Macro defining the specific ARM architecture. + */ +#define CH_ARCHITECTURE_ARM_v7M + +/** + * @brief Name of the implemented architecture. + */ +#define CH_ARCHITECTURE_NAME "ARMv6-M" + +/** + * @brief Name of the architecture variant. + */ +#if (CORTEX_MODEL == CORTEX_M0) || defined(__DOXYGEN__) +#define CH_CORE_VARIANT_NAME "Cortex-M0" +#elif (CORTEX_MODEL == CORTEX_M1) +#define CH_CORE_VARIANT_NAME "Cortex-M1" +#endif + /*===========================================================================*/ /* Port implementation part. */ /*===========================================================================*/ @@ -58,48 +109,6 @@ struct intctx { }; #endif -/** - * @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 = pf; \ - tp->p_ctx.r13->r5 = arg; \ - tp->p_ctx.r13->lr = _port_thread_start; \ -} - -/** - * @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 INT_REQUIRED_STACK. - * @note In this port it is set to 8 because the idle thread does have - * a stack frame when compiling without optimizations. You may - * reduce this value to zero when compiling with optimizations. - */ -#ifndef IDLE_THREAD_STACK_SIZE -#define 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 chSchDoRescheduleI() can have a stack frame, expecially with - * compiler optimizations disabled. - */ -#ifndef INT_REQUIRED_STACK -#define INT_REQUIRED_STACK 16 -#endif - /** * @brief IRQ prologue code. * @details This macro must be inserted at the start of all IRQ handlers @@ -135,6 +144,8 @@ struct intctx { */ #define port_init() { \ SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \ + NVICSetSystemHandlerPriority(HANDLER_PENDSV, \ + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV)); \ NVICSetSystemHandlerPriority(HANDLER_SYSTICK, \ CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \ } diff --git a/os/ports/GCC/ARMCMx/chcore_v7m.c b/os/ports/GCC/ARMCMx/chcore_v7m.c index c71102127..da3f7b956 100644 --- a/os/ports/GCC/ARMCMx/chcore_v7m.c +++ b/os/ports/GCC/ARMCMx/chcore_v7m.c @@ -28,7 +28,6 @@ #include "ch.h" -#if !defined(CH_CURRP_REGISTER_CACHE) || defined(__DOXXYGEN__) /** * @brief Internal context stacking. */ @@ -44,17 +43,6 @@ asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" \ : : : "memory"); \ } -#else /* defined(CH_CURRP_REGISTER_CACHE) */ -#define PUSH_CONTEXT() { \ - asm volatile ("push {r4, r5, r6, r8, r9, r10, r11, lr}" \ - : : : "memory"); \ -} - -#define POP_CONTEXT() { \ - asm volatile ("pop {r4, r5, r6, r8, r9, r10, r11, pc}" \ - : : : "memory"); \ -} -#endif /* defined(CH_CURRP_REGISTER_CACHE) */ #if !CH_OPTIMIZE_SPEED void _port_lock(void) { @@ -84,10 +72,12 @@ 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) { register struct extctx *ctxp; @@ -99,6 +89,25 @@ void SVCallVector(void) { asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory"); 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 normal kernel mode. + */ +void PendSVVector(void) { + register struct extctx *ctxp; + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory"); + ctxp++; + asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory"); +} +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ /** * @brief Reschedule verification and setup after an IRQ. @@ -134,7 +143,14 @@ __attribute__((naked)) void _port_switch_from_isr(void) { chSchDoRescheduleI(); +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) asm volatile ("svc #0"); +#else /* CORTEX_SIMPLIFIED_PRIORITY */ + SCB_ICSR = ICSR_PENDSVSET; + port_unlock(); + while (TRUE) + ; +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ } /** diff --git a/os/ports/GCC/ARMCMx/chcore_v7m.h b/os/ports/GCC/ARMCMx/chcore_v7m.h index a7f02aece..ef7860b87 100644 --- a/os/ports/GCC/ARMCMx/chcore_v7m.h +++ b/os/ports/GCC/ARMCMx/chcore_v7m.h @@ -29,6 +29,93 @@ #ifndef _CHCORE_V7M_H_ #define _CHCORE_V7M_H_ +/*===========================================================================*/ +/* Port constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Port configurable parameters. */ +/*===========================================================================*/ + +/** + * @brief Simplified priority handling flag. + * @details Activating this option will make the Kernel work in normal mode. + */ +#ifndef CORTEX_SIMPLIFIED_PRIORITY +#define CORTEX_SIMPLIFIED_PRIORITY FALSE +#endif + +/** + * @brief SVCALL handler priority. + * @note The default SVCALL handler priority is defaulted to + * @p CORTEX_MAXIMUM_PRIORITY+1, this reserves the + * @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts + * priority level. + */ +#ifndef CORTEX_PRIORITY_SVCALL +#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1) +#else +/* 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 + +/*===========================================================================*/ +/* Port derived parameters. */ +/*===========================================================================*/ + +/** + * @brief BASEPRI level within kernel lock. + * @note In normal kernel mode this constant value is enforced to zero. + */ +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) +#define CORTEX_BASEPRI_KERNEL \ + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL+1) +#else +#define CORTEX_BASEPRI_KERNEL 0 +#endif + +/** + * @brief PendSV priority level. + * @note This priority is enforced to be equal to @p CORTEX_BASEPRI_KERNEL, + * this handler always have the highest priority that cannot preempt + * the kernel. + */ +#define CORTEX_PRIORITY_PENDSV CORTEX_BASEPRI_KERNEL + +/*===========================================================================*/ +/* Port exported info. */ +/*===========================================================================*/ + +/** + * @brief Macro defining the specific ARM architecture. + */ +#define CH_ARCHITECTURE_ARM_v7M + +/** + * @brief Name of the implemented architecture. + */ +#define CH_ARCHITECTURE_NAME "ARMv7-M" + +/** + * @brief Name of the architecture variant. + */ +#if (CORTEX_MODEL == CORTEX_M3) || defined(__DOXYGEN__) +#define CH_CORE_VARIANT_NAME "Cortex-M3" +#elif (CORTEX_MODEL == CORTEX_M4) +#define CH_CORE_VARIANT_NAME "Cortex-M4" +#endif + +/** + * @brief Port-specific information string. + */ +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) +#define CH_PORT_INFO "Advanced kernel mode" +#else +#define CH_PORT_INFO "Normal kernel mode" +#endif + /*===========================================================================*/ /* Port implementation part. */ /*===========================================================================*/ @@ -49,9 +136,7 @@ struct intctx { regarm_t r4; regarm_t r5; regarm_t r6; -#ifndef CH_CURRP_REGISTER_CACHE regarm_t r7; -#endif regarm_t r8; regarm_t r9; regarm_t r10; @@ -60,48 +145,6 @@ struct intctx { }; #endif -/** - * @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 = pf; \ - tp->p_ctx.r13->r5 = arg; \ - tp->p_ctx.r13->lr = _port_thread_start; \ -} - -/** - * @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 INT_REQUIRED_STACK. - * @note In this port it is set to 8 because the idle thread does have - * a stack frame when compiling without optimizations. You may - * reduce this value to zero when compiling with optimizations. - */ -#ifndef IDLE_THREAD_STACK_SIZE -#define IDLE_THREAD_STACK_SIZE 8 -#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 chSchDoRescheduleI() can have a stack frame, expecially with - * compiler optimizations disabled. - */ -#ifndef INT_REQUIRED_STACK -#define INT_REQUIRED_STACK 16 -#endif - /** * @brief IRQ prologue code. * @details This macro must be inserted at the start of all IRQ handlers @@ -137,6 +180,8 @@ struct intctx { 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)); \ } @@ -147,16 +192,20 @@ struct intctx { * more actions. * @note In this port this it raises the base priority to kernel level. */ -#if CH_OPTIMIZE_SPEED +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) +#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__) #define port_lock() { \ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL; \ asm volatile ("msr BASEPRI, %0" : : "r" (tmp) : "memory"); \ } -#else +#else /* !CH_OPTIMIZE_SPEED */ #define port_lock() { \ asm volatile ("bl _port_lock" : : : "r3", "lr", "memory"); \ } -#endif +#endif /* !CH_OPTIMIZE_SPEED */ +#else /* CORTEX_SIMPLIFIED_PRIORITY */ +#define port_lock() asm volatile ("cpsid i" : : : "memory") +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ /** * @brief Kernel-unlock action. @@ -164,16 +213,20 @@ struct intctx { * more actions. * @note In this port this it lowers the base priority to user level. */ -#if CH_OPTIMIZE_SPEED +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) +#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__) #define port_unlock() { \ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_DISABLED; \ asm volatile ("msr BASEPRI, %0" : : "r" (tmp) : "memory"); \ } -#else +#else /* !CH_OPTIMIZE_SPEED */ #define port_unlock() { \ asm volatile ("bl _port_unlock" : : : "r3", "lr", "memory"); \ } -#endif +#endif /* !CH_OPTIMIZE_SPEED */ +#else /* CORTEX_SIMPLIFIED_PRIORITY */ +#define port_unlock() asm volatile ("cpsie i" : : : "memory") +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ /** * @brief Kernel-lock action from an interrupt handler. @@ -206,21 +259,29 @@ struct intctx { * @note Interrupt sources above kernel level remains enabled. * @note In this port it raises/lowers the base priority to kernel level. */ +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) #define port_suspend() { \ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL; \ asm volatile ("msr BASEPRI, %0 \n\t" \ "cpsie i" : : "r" (tmp) : "memory"); \ } +#else /* CORTEX_SIMPLIFIED_PRIORITY */ +#define port_suspend() asm volatile ("cpsid i" : : : "memory") +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ /** * @brief Enables all the interrupt sources. * @note In this port it lowers the base priority to user level. */ +#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__) #define port_enable() { \ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_DISABLED; \ asm volatile ("msr BASEPRI, %0 \n\t" \ "cpsie i" : : "r" (tmp) : "memory"); \ } +#else /* CORTEX_SIMPLIFIED_PRIORITY */ +#define port_enable() asm volatile ("cpsie i" : : : "memory") +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ /** * @brief Enters an architecture-dependent IRQ-waiting mode. diff --git a/os/ports/GCC/ARMCMx/port.dox b/os/ports/GCC/ARMCMx/port.dox index 27e321f21..8f4a9bd51 100644 --- a/os/ports/GCC/ARMCMx/port.dox +++ b/os/ports/GCC/ARMCMx/port.dox @@ -26,9 +26,28 @@ * This port supports all the cores implementing the ARMv6-M and ARMv7-M * architectures. * - * @section ARMCMx_STATES_A System logical states in ARMv6-M mode - * The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM - * Cortex-M0 port: + * @section ARMCMx_MODES Kernel Modes + * The Cortex-Mx port supports two distinct kernel modes: + * - Normal Kernel mode. In this mode the kernel handles IRQ priorities + * in a simplified way, all interrupt sources are disabled when the kernel + * enters into a critical zone and re-enabled on exit. This is simple and + * adequate for most applications, this mode results in a more compact and + * faster kernel. + * - Advanced Kernel mode. In this mode the kernel only masks + * interrupt sources with priorities below or equal to the + * @p CORTEX_BASEPRI_KERNEL level. Higher priorities are not affected by + * the kernel critical sections and can be used for fast interrupts. + * This mode is not available in the ARMv6-M architecture which does not + * support priority masking. + * . + * The selection of the mode is performed using the port configuration option + * @p CORTEX_SIMPLIFIED_PRIORITY. Apart from the different handling of + * interrupts there are no other differences between the two modes. The + * kernel API is exactly the same. + * + * @section ARMCMx_STATES_A System logical states in Normal Kernel mode + * The ChibiOS/RT logical @ref system_states are mapped as follow in Normal + * Kernel mode: * - Init. This state is represented by the startup code and the * initialization code before @p chSysInit() is executed. It has not a * special hardware state associated. @@ -53,21 +72,21 @@ * mode. * - Serving Fast Interrupt. This state is not implemented in the * ARMv6-M implementation. - * - Serving Non-Maskable Interrupt. The Cortex-M3 has a specific + * - Serving Non-Maskable Interrupt. The Cortex-Mx has a specific * asynchronous NMI vector and several synchronous fault vectors that can * be considered belonging to this category. * - Halted. Implemented as an infinite loop after globally masking all * the maskable interrupt sources. The ARM state is whatever the processor * was running when @p chSysHalt() was invoked. * - * @section ARMCMx_STATES_B System logical states in ARMv7-M mode - * The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM - * Cortex-M3 port: + * @section ARMCMx_STATES_B System logical states in Advanced Kernel mode + * The ChibiOS/RT logical @ref system_states are mapped as follow in the + * Advanced Kernel mode: * - Init. This state is represented by the startup code and the * initialization code before @p chSysInit() is executed. It has not a * special hardware state associated. * - Normal. This is the state the system has after executing - * @p chSysInit(). In this state the ARM Cortex-M3 has the BASEPRI register + * @p chSysInit(). In this state the ARM Cortex-Mx has the BASEPRI register * set at @p CORTEX_BASEPRI_USER level, interrupts are not masked. The * processor is running in thread-privileged mode. * - Suspended. In this state the interrupt sources are not globally @@ -93,7 +112,7 @@ * - Serving Fast Interrupt. It is basically the same of the SRI state * but it is not possible to switch to the I-Locked state because fast * interrupts can preempt the kernel critical zone. - * - Serving Non-Maskable Interrupt. The Cortex-M3 has a specific + * - Serving Non-Maskable Interrupt. The Cortex-Mx has a specific * asynchronous NMI vector and several synchronous fault vectors that can * be considered belonging to this category. * - Halted. Implemented as an infinite loop after globally masking all diff --git a/readme.txt b/readme.txt index c294fbad2..91b369749 100644 --- a/readme.txt +++ b/readme.txt @@ -73,6 +73,15 @@ *** 2.3.3 *** - FIX: Fixed timeout problem in the lwIP interface layer (bug 3302420) (backported to 2.2.4). +- NEW: Reorganization of the Cortex-Mx ports in order to reduced code and + comments duplication in the various headers. +- CHANGE: Renamed the macros IDLE_THREAD_STACK_SIZE and INT_REQUIRED_STACK + to PORT_IDLE_THREAD_STACK_SIZE and PORT_INT_REQUIRED_STACK for consistency. +- CHANGE: Removed the "old" Cortex-M3 port from the code, the current port + has no drawbacks and the old port is now just a maintenance cost. +- CHANGE: Removed the CH_CURRP_REGISTER_CACHE option, it is GCC-specific so + it does not belong to the kernel options. The feature will be eventually + reimplemented as a port-specific option. *** 2.3.2 *** - FIX: Fixed invalid BRR() macro in AVR serial driver (bug 3299306)(backported diff --git a/test/test.c b/test/test.c index f1df08390..41662308c 100644 --- a/test/test.c +++ b/test/test.c @@ -328,9 +328,9 @@ msg_t TestThread(void *p) { test_println("***"); test_print("*** Kernel: "); test_println(CH_KERNEL_VERSION); -#ifdef __GNUC__ - test_print("*** GCC Version: "); - test_println(__VERSION__); +#ifdef CH_COMPILER_NAME + test_print("*** Compiler: "); + test_println(CH_COMPILER_NAME); #endif test_print("*** Architecture: "); test_println(CH_ARCHITECTURE_NAME); @@ -338,6 +338,10 @@ msg_t TestThread(void *p) { test_print("*** Core Variant: "); test_println(CH_CORE_VARIANT_NAME); #endif +#ifdef CH_PORT_INFO + test_print("*** Port Info: "); + test_println(CH_PORT_INFO); +#endif #ifdef PLATFORM_NAME test_print("*** Platform: "); test_println(PLATFORM_NAME); diff --git a/test/testbmk.c b/test/testbmk.c index 6c878f557..54da81fd8 100644 --- a/test/testbmk.c +++ b/test/testbmk.c @@ -635,9 +635,11 @@ ROMCONST struct testcase testbmk12 = { static void bmk13_execute(void) { test_print("--- System: "); - test_printn(sizeof(ReadyList) + sizeof(VTList) + IDLE_THREAD_STACK_SIZE + - (sizeof(Thread) + sizeof(struct intctx) + sizeof(struct extctx) + - INT_REQUIRED_STACK) * 2); + test_printn(sizeof(ReadyList) + sizeof(VTList) + + PORT_IDLE_THREAD_STACK_SIZE + + (sizeof(Thread) + sizeof(struct intctx) + + sizeof(struct extctx) + + PORT_INT_REQUIRED_STACK) * 2); test_println(" bytes"); test_print("--- Thread: "); test_printn(sizeof(Thread));