From 4bc04c7835daccf943dbe299a7f79f9c33e16032 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 31 Mar 2010 15:13:55 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1820 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ports/GCC/ARMCM3/port.dox | 1 - os/ports/GCC/ARMCMx/chcore.c | 25 ++++++---- os/ports/GCC/ARMCMx/chcore.h | 109 ++++++++++++++++++++++++++++++++++++------ os/ports/GCC/ARMCMx/chtypes.h | 7 ++- os/ports/GCC/ARMCMx/crt0.s | 4 +- os/ports/GCC/ARMCMx/nvic.c | 12 +++-- os/ports/GCC/ARMCMx/nvic.h | 23 ++++----- os/ports/GCC/ARMCMx/port.dox | 94 +++++++++++++++++++++++++----------- 8 files changed, 200 insertions(+), 75 deletions(-) (limited to 'os/ports') diff --git a/os/ports/GCC/ARMCM3/port.dox b/os/ports/GCC/ARMCM3/port.dox index fd18ae82d..caaabf24c 100644 --- a/os/ports/GCC/ARMCM3/port.dox +++ b/os/ports/GCC/ARMCM3/port.dox @@ -158,7 +158,6 @@ * - @p _bss_end BSS end location +1. * . * @ingroup ARMCM3 - * @file ARMCM3/crt0.s Startup code. */ /** diff --git a/os/ports/GCC/ARMCMx/chcore.c b/os/ports/GCC/ARMCMx/chcore.c index 348aedef7..78ed6d7ad 100644 --- a/os/ports/GCC/ARMCMx/chcore.c +++ b/os/ports/GCC/ARMCMx/chcore.c @@ -19,7 +19,7 @@ /** * @file ARMCMx/chcore.c - * @brief ARM Cortex-Mx architecture port code. + * @brief ARM Cortex-Mx port code. * * @addtogroup ARMCMx_CORE * @{ @@ -165,14 +165,21 @@ void _port_switch_from_irq(void) { __attribute__((naked)) #endif void port_switch(Thread *ntp, Thread *otp) { - register struct intctx *sp_thd asm ("sp"); + register struct intctx *r13 asm ("r13"); - PUSH_CONTEXT(sp_thd); + /* Stack overflow check, if enabled.*/ +#if CH_DBG_ENABLE_STACK_CHECK + if ((void *)(r13 - 1) < (void *)(otp + 1)) + asm volatile ("movs r0, #0 \n\t" + "b chDbgPanic"); +#endif /* CH_DBG_ENABLE_STACK_CHECK */ - otp->p_ctx.r13 = sp_thd; - sp_thd = ntp->p_ctx.r13; + PUSH_CONTEXT(r13); - POP_CONTEXT(sp_thd); + otp->p_ctx.r13 = r13; + r13 = ntp->p_ctx.r13; + + POP_CONTEXT(r13); } /** @@ -182,9 +189,9 @@ void port_switch(Thread *ntp, Thread *otp) { */ void _port_thread_start(void) { - asm volatile ("cpsie i \n\t" \ - "mov r0, r5 \n\t" \ - "blx r4 \n\t" \ + asm volatile ("cpsie i \n\t" \ + "mov r0, r5 \n\t" \ + "blx r4 \n\t" \ "bl chThdExit"); } diff --git a/os/ports/GCC/ARMCMx/chcore.h b/os/ports/GCC/ARMCMx/chcore.h index 57183e162..dd7d2897b 100644 --- a/os/ports/GCC/ARMCMx/chcore.h +++ b/os/ports/GCC/ARMCMx/chcore.h @@ -19,7 +19,7 @@ /** * @file ARMCMx/chcore.h - * @brief ARM Cortex-Mx architecture port macros and structures. + * @brief ARM Cortex-Mx port macros and structures. * * @addtogroup ARMCMx_CORE * @{ @@ -49,14 +49,16 @@ /* Inclusion of the Cortex-Mx implementation specific parameters.*/ #include "cmparams.h" -/* Cortex model check, only M0 and M3 right now.*/ +/* Cortex model check, only M0 and M3 supported right now.*/ #if (CORTEX_MODEL == CORTEX_M0) || (CORTEX_MODEL == CORTEX_M3) +#elif (CORTEX_MODEL == CORTEX_M1) || (CORTEX_MODEL == CORTEX_M4) +#warning "untested Cortex-M model" #else #error "unknown or unsupported Cortex-M model" #endif /*===========================================================================*/ -/* Port derived parameters. */ +/* Port statically derived parameters. */ /*===========================================================================*/ /** @@ -114,8 +116,8 @@ /** * @brief SYSTICK handler priority. - * @note The default is calculated as the priority level in the middle - * of the priority range. + * @note The default priority is calculated as the priority level in + * the middle of the numeric priorities range. */ #ifndef CORTEX_PRIORITY_SYSTICK #define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) @@ -126,13 +128,67 @@ #endif #endif +/** + * @brief Priority masking support. + * @details The ARMv7-M architecture is capable to mask only interrupt + * priorities below or equal to a certain specified priority + * mask. If this option is enabled all the priorities above + * @p CORTEX_BASEPRI_KERNEL (lower numeric values) are not + * affected by the kernel locks and can operate with minimum + * latency.
+ * This option makes the kernel code a bit larger and slower, if + * your application does not need fast interrups it is recommended + * to keep this option disabled. + */ +#if CORTEX_SUPPORTS_BASEPRI || defined(__DOXYGEN__) +#if !defined(CORTEX_USE_BASEPRI) || defined(__DOXYGEN__) +#define CORTEX_USE_BASEPRI FALSE +#endif /* !defined(CORTEX_USE_BASEPRI) */ +#else /* !CORTEX_SUPPORTS_BASEPRI */ +#if defined(CORTEX_USE_BASEPRI) && CORTEX_USE_BASEPRI +#error "BASEPRI priority masking register not supported in this architecture" +#endif +#define CORTEX_USE_BASEPRI FALSE +#endif /* !CORTEX_SUPPORTS_BASEPRI */ + +#if CORTEX_USE_BASEPRI || defined(__DOXYGEN__) +/** + * @brief BASEPRI user level. + * @note This constant is defined only if the @p CORTEX_USE_BASEPRI port + * option is enabled. + */ +#ifndef CORTEX_BASEPRI_USER +#define CORTEX_BASEPRI_USER CORTEX_PRIORITY_MASK(0) +#endif + +/** + * @brief BASEPRI level within kernel lock. + * @details Priority levels higher than this one (lower numeric values) are + * unaffected by kernel locks and can be classified as fast + * interrupt sources, see @ref interrupt_classes. + * @note This constant is defined only if the @p CORTEX_USE_BASEPRI port + * option is enabled. + * @note The default setting reserves just the highest priority level + * (@p CORTEX_MAXIMUM_PRIORITY) for fast interrupts, you may redefine + * this setting in order to reserve more levels. + */ +#ifndef CORTEX_BASEPRI_KERNEL +#define CORTEX_BASEPRI_KERNEL CORTEX_PRIORITY_MASK(CORTEX_MAXIMUM_PRIORITY+1) +#endif +#endif /* CORTEX_USE_BASEPRI */ + /*===========================================================================*/ /* Port exported info. */ /*===========================================================================*/ +/** + * @brief Macro defining a generic ARM architecture. + */ +#define CH_ARCHITECTURE_ARM + #if defined(__DOXYGEN__) /** - * @brief Macro defining the ARM architecture. + * @brief Macro defining the specific ARM architecture. */ #define CH_ARCHITECTURE_ARM_vxm @@ -147,7 +203,7 @@ #define CH_CORE_VARIANT_NAME "Cortex-Mx" #elif CORTEX_MODEL == CORTEX_M4 #define CH_ARCHITECTURE_ARM_v7M -#define CH_ARCHITECTURE_NAME "ARMv7-M" +#define CH_ARCHITECTURE_NAME "ARMv7-ME" #define CH_CORE_VARIANT_NAME "Cortex-M4" #elif CORTEX_MODEL == CORTEX_M3 #define CH_ARCHITECTURE_ARM_v7M @@ -364,17 +420,29 @@ struct context { * @brief Kernel-lock action. * @details Usually this function just disables interrupts but may perform * more actions. - * @note In this port it disables all the interrupt sources. */ +#if CORTEX_USE_BASEPRI +#define port_lock() { \ + register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL; \ + asm volatile ("msr BASEPRI, %0" : : "r" (tmp)); \ +} +#else /* !CORTEX_USE_BASEPRI */ #define port_lock() asm volatile ("cpsid i") +#endif /* !CORTEX_USE_BASEPRI */ /** * @brief Kernel-unlock action. * @details Usually this function just disables interrupts but may perform * more actions. - * @note In this port it enables all the interrupt sources. */ +#if CORTEX_USE_BASEPRI +#define port_unlock() { \ + register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_USER; \ + asm volatile ("msr BASEPRI, %0" : : "r" (tmp)); \ +} +#else /* !CORTEX_USE_BASEPRI */ #define port_unlock() asm volatile ("cpsie i") +#endif /* !CORTEX_USE_BASEPRI */ /** * @brief Kernel-lock action from an interrupt handler. @@ -390,29 +458,40 @@ struct context { * @details This function is invoked after invoking I-class APIs from interrupt * handlers. The implementation is architecture dependent, in its * simplest form it is void. - * @note Same as @p port_unlock() in this port. + * @note Same as @p port_lock() in this port. */ #define port_unlock_from_isr() port_unlock() /** * @brief Disables all the interrupt sources. - * @note Of course non maskable interrupt sources are not included. - * @note In this port it disables all the interrupt sources. */ #define port_disable() asm volatile ("cpsid i") /** * @brief Disables the interrupt sources below kernel-level priority. - * @note Interrupt sources above kernel level remains enabled. - * @note In this port it disables all the interrupt sources. */ +#if CORTEX_USE_BASEPRI +#define port_suspend() { \ + register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL; \ + asm volatile ("msr BASEPRI, %0 \n\t" \ + "cpsie i" : : "r" (tmp)); \ +} +#else /* !CORTEX_USE_BASEPRI */ #define port_suspend() asm volatile ("cpsid i") +#endif /* !CORTEX_USE_BASEPRI */ /** * @brief Enables all the interrupt sources. - * @note In this port it enables all the interrupt sources. */ +#if CORTEX_USE_BASEPRI +#define port_enable() { \ + register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_USER; \ + asm volatile ("msr BASEPRI, %0 \n\t" \ + "cpsie i" : : "r" (tmp)); \ +} +#else /* !CORTEX_USE_BASEPRI */ #define port_enable() asm volatile ("cpsie i") +#endif /* !CORTEX_USE_BASEPRI */ /** * @brief Enters an architecture-dependent IRQ-waiting mode. diff --git a/os/ports/GCC/ARMCMx/chtypes.h b/os/ports/GCC/ARMCMx/chtypes.h index be89b04bf..ef35d6324 100644 --- a/os/ports/GCC/ARMCMx/chtypes.h +++ b/os/ports/GCC/ARMCMx/chtypes.h @@ -18,8 +18,9 @@ */ /** - * @file ARMCMx/chtypes.h - * @brief ARM Cortex-M3 architecture port system types. + * @file ARMCMx/chtypes.h + * @brief ARM Cortex-Mx port system types. + * * @addtogroup ARMCMx_CORE * @{ */ @@ -32,9 +33,7 @@ #define __need_ptrdiff_t #include -#if !defined(_STDINT_H) && !defined(__STDINT_H_) #include -#endif typedef int32_t bool_t; /**< Fast boolean type. */ typedef uint8_t tmode_t; /**< Thread flags. */ diff --git a/os/ports/GCC/ARMCMx/crt0.s b/os/ports/GCC/ARMCMx/crt0.s index 15aed34a6..51739aa62 100644 --- a/os/ports/GCC/ARMCMx/crt0.s +++ b/os/ports/GCC/ARMCMx/crt0.s @@ -73,7 +73,7 @@ ResetHandler: ldr r3, =_edata dloop: cmp r2, r3 -#if CORTEX_MODEL == CORTEX_M0 +#if (CORTEX_MODEL == CORTEX_M0) || (CORTEX_MODEL == CORTEX_M1) bge enddloop ldr r0, [r1] str r0, [r2] @@ -96,7 +96,7 @@ enddloop: ldr r2, =_bss_end bloop: cmp r1, r2 -#if CORTEX_MODEL == CORTEX_M0 +#if (CORTEX_MODEL == CORTEX_M0) || (CORTEX_MODEL == CORTEX_M1) bge endbloop str r0, [r1] adds r1, r1, #4 diff --git a/os/ports/GCC/ARMCMx/nvic.c b/os/ports/GCC/ARMCMx/nvic.c index 67551ec1d..5b0dd9782 100644 --- a/os/ports/GCC/ARMCMx/nvic.c +++ b/os/ports/GCC/ARMCMx/nvic.c @@ -18,8 +18,9 @@ */ /** - * @file ARMCMx/nvic.c - * @brief Cortex-Mx NVIC support code. + * @file ARMCMx/nvic.c + * @brief Cortex-Mx NVIC support code. + * * @addtogroup ARMCMx_NVIC * @{ */ @@ -31,7 +32,7 @@ * @brief Sets the priority of an interrupt handler and enables it. * * @param n the interrupt number - * @param prio the interrupt priority + * @param prio the interrupt priority mask * * @note The parameters are not tested for correctness. */ @@ -61,13 +62,14 @@ void NVICDisableVector(uint32_t n) { * @brief Changes the priority of a system handler. * * @param handler the system handler number - * @param prio the system handler priority + * @param prio the system handler priority mask * @note The parameters are not tested for correctness. */ void NVICSetSystemHandlerPriority(uint32_t handler, uint32_t prio) { unsigned sh = (handler & 3) * 8; - SCB_SHPR(handler >> 2) = (SCB_SHPR(handler >> 2) & ~(0xFF << sh)) | (prio << sh); + SCB_SHPR(handler >> 2) = (SCB_SHPR(handler >> 2) & + ~(0xFF << sh)) | (prio << sh); } /** @} */ diff --git a/os/ports/GCC/ARMCMx/nvic.h b/os/ports/GCC/ARMCMx/nvic.h index 8a9950fcf..196b78fbd 100644 --- a/os/ports/GCC/ARMCMx/nvic.h +++ b/os/ports/GCC/ARMCMx/nvic.h @@ -18,8 +18,9 @@ */ /** - * @file ARMCMx/nvic.h - * @brief Cortex-Mx NVIC support macros and structures. + * @file ARMCMx/nvic.h + * @brief Cortex-Mx NVIC support macros and structures. + * * @addtogroup ARMCMx_NVIC * @{ */ @@ -30,21 +31,21 @@ /* * System vector constants for @p NVICSetSystemHandlerPriority(). */ -#define HANDLER_MEM_MANAGE 0 /**< MEM MANAGE vector id.*/ -#define HANDLER_BUS_FAULT 1 /**< BUS FAULT vector id.*/ -#define HANDLER_USAGE_FAULT 2 /**< USAGE FAULT vector id.*/ +#define HANDLER_MEM_MANAGE 0 /**< MEM MANAGE vector id. */ +#define HANDLER_BUS_FAULT 1 /**< BUS FAULT vector id. */ +#define HANDLER_USAGE_FAULT 2 /**< USAGE FAULT vector id. */ #define HANDLER_RESERVED_3 3 #define HANDLER_RESERVED_4 4 #define HANDLER_RESERVED_5 5 #define HANDLER_RESERVED_6 6 -#define HANDLER_SVCALL 7 /**< SVCALL vector id.*/ -#define HANDLER_DEBUG_MONITOR 8 /**< DEBUG MONITOR vector id.*/ +#define HANDLER_SVCALL 7 /**< SVCALL vector id. */ +#define HANDLER_DEBUG_MONITOR 8 /**< DEBUG MONITOR vector id. */ #define HANDLER_RESERVED_9 9 -#define HANDLER_PENDSV 10 /**< PENDSV vector id.*/ -#define HANDLER_SYSTICK 11 /**< SYS TCK vector id.*/ +#define HANDLER_PENDSV 10 /**< PENDSV vector id. */ +#define HANDLER_SYSTICK 11 /**< SYS TCK vector id. */ -typedef volatile unsigned char IOREG8; /**< 8 bits I/O register type.*/ -typedef volatile unsigned int IOREG32; /**< 32 bits I/O register type.*/ +typedef volatile uint8_t IOREG8; /**< 8 bits I/O register type. */ +typedef volatile uint32_t IOREG32; /**< 32 bits I/O register type. */ /** * @brief NVIC ITCR register. diff --git a/os/ports/GCC/ARMCMx/port.dox b/os/ports/GCC/ARMCMx/port.dox index 6ec32f56f..a47ba1ad5 100644 --- a/os/ports/GCC/ARMCMx/port.dox +++ b/os/ports/GCC/ARMCMx/port.dox @@ -19,17 +19,65 @@ /** * @defgroup ARMCMx ARM Cortex-Mx - * @details This port supports the ARM Cortex-Mx architectures, specifically - * the Cortex-M0 and the Cortex-M3. + * @details This port supports the ARMv6-M and ARMv7-M architectures (all the + * Cortex-Mx cores). * * @section ARMCMx_STATES Mapping of the System States in the ARM Cortex-Mx port + * This port supports two IRQ handling modes: + * - IRQ disabling. This is the simplest and most efficient way to + * implement kernel locks, this is done by globally disabling interrupts. + * This mode is available to both the ARMv6-M and ARMv7-M architectures. + * - IRQ priority masking. In this mode kernel locks are implemented by + * raising the priority mask to the @p CORTEX_BASEPRI_KERNEL level. Using + * priority masking it is possible to reserve one or more priority levels + * for use as fast interrupt handlers. This mode is slightly less efficient + * because the lock/unlock code requires two instructions instead of just + * one and is available to the ARMv7-M architecture only (Cortex-M3 and + * Cortex-M4). The advantage in this mode is the availability of very low + * latency priority levels unaffected by the RTOS activity. + * . + * The mapping of the @ref system_states changes depending on the chosen IRQ + * handling mode. + * + * @subsection ARMCMx_STATES_A System logical states in IRQ disabling 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 interrupts are enabled. The processor + * is running in thread-privileged mode. + * - Suspended. In this state the interrupt sources are globally + * disabled. The processor is running in thread-privileged mode. In this + * mode this state is not different from the Disabled state. + * - Disabled. In this state the interrupt sources are globally + * disabled. The processor is running in thread-privileged mode. In this + * mode this state is not different from the Suspended state. + * - Sleep. This state is entered with the execution of the specific + * instruction @p wfi. + * - S-Locked. In this state the interrupt sources are globally + * disabled. The processor is running in thread-privileged mode. + * - I-Locked. In this state the interrupt sources are globally + * disabled. The processor is running in exception-privileged mode. + * - Serving Regular Interrupt. In this state the interrupt sources are + * not globally masked but only interrupts with higher priority can preempt + * the current handler. The processor is running in exception-privileged + * mode. + * - Serving Fast Interrupt. This state is not implemented in this mode. + * - Serving Non-Maskable Interrupt. The Cortex-M3 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. + * + * @subsection ARMCMx_STATES_B System logical states in IRQ priority masking mode * The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM - * Cortex-Mx port: + * Cortex-M3 port: * - 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-Mx has the BASEPRI register + * @p chSysInit(). In this state the ARM Cortex-M3 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 @@ -50,13 +98,14 @@ * is running in exception-privileged mode. * - Serving Regular Interrupt. In this state the interrupt sources are * not globally masked but only interrupts with higher priority can preempt - * the current handler. The processor is running in exception-privileged mode. + * the current handler. The processor is running in exception-privileged + * mode. * - 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-Mx has a specific + * - Serving Non-Maskable Interrupt. The Cortex-M3 has a specific * asynchronous NMI vector and several synchronous fault vectors that can - * be considered to be in this category. + * 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. @@ -66,18 +115,8 @@ * - The @p main() function is invoked in thread-privileged mode. * - Each thread has a private process stack, the system has a single main * stack where all the interrupts and exceptions are processed. - * - Only the 4 MSb of the priority level are used, the 4 LSb are assumed - * to be zero. - * - The threads are started in thread-privileged mode with BASEPRI level - * 0x00 (disabled). - * - The kernel raises its BASEPRI level to @p CORTEX_BASEPRI_KERNEL in order - * to protect the kernel data structures. - * - Interrupt nesting and the other advanced NVIC features are supported. - * - The SVC instruction and vector, with parameter #0, is internally used - * for commanded context switching.
- * It is possible to share the SVC handler at the cost of slower context - * switching. - * - The PendSV vector is internally used for preemption context switching. + * - The threads are started in thread-privileged mode. + * - Interrupt nesting and the other advanced core/NVIC features are supported. * . * @ingroup ports */ @@ -85,7 +124,7 @@ /** * @defgroup ARMCMx_CONF Configuration Options * @brief ARM Cortex-Mx Configuration Options. - * @details The ARMCMx port allows some architecture-specific configurations + * @details The ARMCM3 port allows some architecture-specific configurations * settings that can be specified externally, as example on the compiler * command line: * - @p INT_REQUIRED_STACK, this value represent the amount of stack space used @@ -97,18 +136,18 @@ * - @p CORTEX_BASEPRI_USER, this is the @p BASEPRI value for the user threads. * The default value is @p 0 (disabled).
* Usually there is no need to change this value, please refer to the - * Cortex-Mx technical reference manual for a detailed description. + * Cortex-M3 technical reference manual for a detailed description. * - @p CORTEX_BASEPRI_KERNEL, this is the @p BASEPRI value for the kernel lock * code.
* Code running at higher priority levels must not invoke any OS API.
* Usually there is no need to change this value, please refer to the - * Cortex-Mx technical reference manual for a detailed description. - * - @p ENABLE_WFI_IDLE, if set to @p 1 enables the use of the @p wfi - * instruction from within the idle loop. This is defaulted to 0 because - * it can create problems with some debuggers. Setting this option to 1 - * reduces the system power requirements. + * Cortex-M3 technical reference manual for a detailed description. + * - @p CORTEX_ENABLE_WFI_IDLE, if set to @p 1 enables the use of the + * @p wfi instruction from within the idle loop. This is defaulted to + * 0 because it can create problems with some debuggers. Setting this option + * to 1 reduces the system power requirements. * . - * @ingroup ARMCMx + * @ingroup ARMCM3 */ /** @@ -159,7 +198,6 @@ * - @p _bss_end BSS end location +1. * . * @ingroup ARMCMx - * @file ARMCMx/crt0.s Startup code. */ /** -- cgit v1.2.3