aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-04-02 08:11:05 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-04-02 08:11:05 +0000
commitc047b2198006076a00ebfe9cff9e8537aeb8ca96 (patch)
tree27f4f75da18a4e2da34fc4ae6a37eeb24b21fcdb /os
parent3bc41906b36968c2a2e7a753e572e7067fa737a3 (diff)
downloadChibiOS-c047b2198006076a00ebfe9cff9e8537aeb8ca96.tar.gz
ChibiOS-c047b2198006076a00ebfe9cff9e8537aeb8ca96.tar.bz2
ChibiOS-c047b2198006076a00ebfe9cff9e8537aeb8ca96.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1825 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/ports/GCC/ARMCM3/chcore.h8
-rw-r--r--os/ports/GCC/ARMCMx/LPC11xx/port.mk5
-rw-r--r--os/ports/GCC/ARMCMx/STM32F10x/port.mk1
-rw-r--r--os/ports/GCC/ARMCMx/chcore.c155
-rw-r--r--os/ports/GCC/ARMCMx/chcore.h375
-rw-r--r--os/ports/GCC/ARMCMx/chcore_v6m.c152
-rw-r--r--os/ports/GCC/ARMCMx/chcore_v6m.h271
-rw-r--r--os/ports/GCC/ARMCMx/chcore_v7m.c178
-rw-r--r--os/ports/GCC/ARMCMx/chcore_v7m.h313
9 files changed, 965 insertions, 493 deletions
diff --git a/os/ports/GCC/ARMCM3/chcore.h b/os/ports/GCC/ARMCM3/chcore.h
index b844fbffb..ac8ab021b 100644
--- a/os/ports/GCC/ARMCM3/chcore.h
+++ b/os/ports/GCC/ARMCM3/chcore.h
@@ -34,13 +34,6 @@
/* Port constants. */
/*===========================================================================*/
-/**
- * @brief Port implementing a exception mode context switching.
- * @details This macro can be used to differentiate this port from the other
- * Cortex-Mx port which defines @p CORTEX_PORT_MODE_EXOSWITCH.
- */
-#define CORTEX_PORT_MODE_ENDOSWITCH
-
#define CORTEX_M0 0 /**< @brief Cortex-M0 variant. */
#define CORTEX_M1 1 /**< @brief Cortex-M1 variant. */
#define CORTEX_M3 3 /**< @brief Cortex-M3 variant. */
@@ -55,7 +48,6 @@
#error "unknown or unsupported Cortex-M model"
#endif
-
/*===========================================================================*/
/* Port derived parameters. */
/*===========================================================================*/
diff --git a/os/ports/GCC/ARMCMx/LPC11xx/port.mk b/os/ports/GCC/ARMCMx/LPC11xx/port.mk
index dfbb01b16..3935b9195 100644
--- a/os/ports/GCC/ARMCMx/LPC11xx/port.mk
+++ b/os/ports/GCC/ARMCMx/LPC11xx/port.mk
@@ -1,7 +1,8 @@
# List of the ChibiOS/RT Cortex-M0 LPC111x port files.
PORTSRC = ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore.c \
- ${CHIBIOS}/os/ports/GCC/ARMCMx/nvic.c
-# ${CHIBIOS}/os/ports/GCC/ARMCMx/cmsis/core_cm0.c
+ ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore_v6m.c \
+ ${CHIBIOS}/os/ports/GCC/ARMCMx/nvic.c \
+ ${CHIBIOS}/os/ports/GCC/ARMCMx/cmsis/core_cm0.c
PORTASM = ${CHIBIOS}/os/ports/GCC/ARMCMx/crt0.s
diff --git a/os/ports/GCC/ARMCMx/STM32F10x/port.mk b/os/ports/GCC/ARMCMx/STM32F10x/port.mk
index 739f031f8..02cbe871a 100644
--- a/os/ports/GCC/ARMCMx/STM32F10x/port.mk
+++ b/os/ports/GCC/ARMCMx/STM32F10x/port.mk
@@ -1,5 +1,6 @@
# List of the ChibiOS/RT Cortex-M3 STM32 port files.
PORTSRC = ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore.c \
+ ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore_v7m.c \
${CHIBIOS}/os/ports/GCC/ARMCMx/nvic.c \
${CHIBIOS}/os/ports/GCC/ARMCMx/cmsis/core_cm3.c
diff --git a/os/ports/GCC/ARMCMx/chcore.c b/os/ports/GCC/ARMCMx/chcore.c
index 908f0b5a6..24a9d7f7a 100644
--- a/os/ports/GCC/ARMCMx/chcore.c
+++ b/os/ports/GCC/ARMCMx/chcore.c
@@ -26,17 +26,6 @@
*/
#include "ch.h"
-#include "nvic.h"
-
-/**
- * @brief PC register temporary storage.
- */
-regarm_t _port_saved_pc;
-
-/**
- * @brief IRQ nesting counter.
- */
-unsigned _port_irq_nesting;
/**
* @brief Halts the system.
@@ -53,148 +42,4 @@ void port_halt(void) {
}
}
-/**
- * @brief System Timer vector.
- * @details This interrupt is used as system tick.
- * @note The timer must be initialized in the startup code.
- */
-CH_IRQ_HANDLER(SysTickVector) {
-
- CH_IRQ_PROLOGUE();
-
- chSysLockFromIsr();
- chSysTimerHandlerI();
- chSysUnlockFromIsr();
-
- CH_IRQ_EPILOGUE();
-}
-
-/**
- * @brief Post-IRQ switch code.
- * @details On entry the stack and the registers are restored by the exception
- * return, the PC value is stored in @p _port_saved_pc, the interrupts
- * are disabled.
- */
-#if !defined(__DOXYGEN__)
-__attribute__((naked))
-#endif
-void _port_switch_from_irq(void) {
- /* Note, saves r4 to make space for the PC.*/
-#if defined(CH_ARCHITECTURE_ARM_v6M)
- asm volatile ("push {r0, r1, r2, r3, r4} \n\t" \
- "mrs r0, APSR \n\t" \
- "mov r1, r12 \n\t" \
- "push {r0, r1, lr} \n\t" \
- "ldr r0, =_port_saved_pc \n\t" \
- "ldr r0, [r0] \n\t" \
- "add r0, r0, #1 \n\t" \
- "str r0, [sp, #28]");
-#elif defined(CH_ARCHITECTURE_ARM_v7M)
- asm volatile ("push {r0, r1, r2, r3, r4} \n\t" \
- "mrs r0, APSR \n\t" \
- "push {r0, r12, lr} \n\t" \
- "ldr r0, =_port_saved_pc \n\t" \
- "ldr r0, [r0] \n\t" \
- "add r0, r0, #1 \n\t" \
- "str r0, [sp, #28]");
-#endif
-
- chSchDoRescheduleI();
-
- /* Note, the last registers are restored alone after re-enabling the
- interrupts in order to minimize the (very remote and unlikely)
- possibility that the stack is filled by continuous and saturating
- interrupts that would not allow that last words to be pulled out of
- the stack.*/
-#if defined(CH_ARCHITECTURE_ARM_v6M)
- asm volatile ("pop {r0, r1, r2} \n\t" \
- "mov r12, r1 \n\t" \
- "msr APSR, r0 \n\t" \
- "mov lr, r2");
-#elif defined(CH_ARCHITECTURE_ARM_v7M)
- asm volatile ("pop {r0, r12, lr} \n\t" \
- "msr APSR, r0");
-#endif
-#if CORTEX_USE_BASEPRI
- asm volatile ("mov r0, #0 \n\t" \
- "msr BASEPRI, r0");
-#else /* !CORTEX_USE_BASEPRI */
- asm volatile ("cpsie i");
-#endif /* !CORTEX_USE_BASEPRI */
- asm volatile ("pop {r0, r1, r2, r3, pc}");
-}
-
-#if defined(CH_ARCHITECTURE_ARM_v6M)
-#define PUSH_CONTEXT(sp) { \
- asm volatile ("push {r4, r5, r6, r7, lr} \n\t" \
- "mov r4, r8 \n\t" \
- "mov r5, r9 \n\t" \
- "mov r6, r10 \n\t" \
- "mov r7, r11 \n\t" \
- "push {r4, r5, r6, r7}"); \
-}
-
-#define POP_CONTEXT(sp) { \
- asm volatile ("pop {r4, r5, r6, r7} \n\t" \
- "mov r8, r4 \n\t" \
- "mov r9, r5 \n\t" \
- "mov r10, r6 \n\t" \
- "mov r11, r7 \n\t" \
- "pop {r4, r5, r6, r7, pc}" : : "r" (sp)); \
-}
-#elif defined(CH_ARCHITECTURE_ARM_v7M)
-#define PUSH_CONTEXT(sp) { \
- asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t"); \
-}
-
-#define POP_CONTEXT(sp) { \
- asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} \n\t" \
- : : "r" (sp)); \
-}
-#endif
-
-/**
- * @brief Performs a context switch between two threads.
- * @details This is the most critical code in any port, this function
- * is responsible for the context switch between 2 threads.
- * @note The implementation of this code affects <b>directly</b> the context
- * switch performance so optimize here as much as you can.
- *
- * @param[in] ntp the thread to be switched in
- * @param[in] otp the thread to be switched out
- */
-#if !defined(__DOXYGEN__)
-__attribute__((naked))
-#endif
-void port_switch(Thread *ntp, Thread *otp) {
- register struct intctx *r13 asm ("r13");
-
- /* 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 */
-
- PUSH_CONTEXT(r13);
-
- otp->p_ctx.r13 = r13;
- r13 = ntp->p_ctx.r13;
-
- POP_CONTEXT(r13);
-}
-
-/**
- * @brief Start a thread by invoking its work function.
- * @details If the work function returns @p chThdExit() is automatically
- * invoked.
- */
-void _port_thread_start(void) {
-
- port_unlock();
- asm volatile ("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 e627fcf8f..5d45b00fd 100644
--- a/os/ports/GCC/ARMCMx/chcore.h
+++ b/os/ports/GCC/ARMCMx/chcore.h
@@ -34,13 +34,6 @@
/* Port constants. */
/*===========================================================================*/
-/**
- * @brief Port implementing a process mode context switching.
- * @details This macro can be used to differentiate this port from the other
- * Cortex-Mx port which defines @p CORTEX_PORT_MODE_ENDOSWITCH.
- */
-#define CORTEX_PORT_MODE_EXOSWITCH
-
#define CORTEX_M0 0 /**< @brief Cortex-M0 variant. */
#define CORTEX_M1 1 /**< @brief Cortex-M1 variant. */
#define CORTEX_M3 3 /**< @brief Cortex-M3 variant. */
@@ -62,16 +55,6 @@
/*===========================================================================*/
/**
- * @brief Priority masking support.
- */
-#if (CORTEX_MODEL == CORTEX_M3) || (CORTEX_MODEL == CORTEX_M4) || \
- defined(__DOXYGEN__)
-#define CORTEX_SUPPORTS_BASEPRI TRUE
-#else
-#define CORTEX_SUPPORTS_BASEPRI FALSE
-#endif
-
-/**
* @brief Total priority levels.
*/
#define CORTEX_PRIORITY_LEVELS (1 << CORTEX_PRIORITY_BITS)
@@ -89,6 +72,11 @@
*/
#define CORTEX_MAXIMUM_PRIORITY 0
+/**
+ * @brief Disabled value for BASEPRI register.
+ */
+#define CORTEX_BASEPRI_DISABLED 0
+
/*===========================================================================*/
/* Port macros. */
/*===========================================================================*/
@@ -117,8 +105,8 @@
/**
* @brief SYSTICK handler priority.
- * @note The default priority is calculated as the priority level in
- * the middle of the numeric priorities range.
+ * @note The default SYSTICK handler 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)
@@ -130,44 +118,48 @@
#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.<br>
- * 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.
+ * @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.
*/
-#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"
+#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 In the ARMv7-M port this value should be not changed from the
+ * minimum priority level.
+ * @note The PENDSV vector is only used in the ARMv7-M port, it is available
+ * to user in the ARMv6-M port.
+ */
+#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
-#define CORTEX_USE_BASEPRI FALSE
-#endif /* !CORTEX_SUPPORTS_BASEPRI */
-#if CORTEX_USE_BASEPRI || defined(__DOXYGEN__)
/**
* @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.
+ * @note This value must not mask the SVCALL priority level.
*/
#ifndef CORTEX_BASEPRI_KERNEL
-#define CORTEX_BASEPRI_KERNEL CORTEX_PRIORITY_MASK(CORTEX_MAXIMUM_PRIORITY+1)
+#define CORTEX_BASEPRI_KERNEL CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL+1)
#endif
-#endif /* CORTEX_USE_BASEPRI */
/*===========================================================================*/
/* Port exported info. */
@@ -225,294 +217,21 @@ typedef uint32_t stkalign_t;
*/
typedef void *regarm_t;
-/**
- * @brief Cortex-Mx exception context.
- */
-struct cmxctx {
- regarm_t r0;
- regarm_t r1;
- regarm_t r2;
- regarm_t r3;
- regarm_t r12;
- regarm_t lr_thd;
- regarm_t pc;
- regarm_t xpsr;
-};
-
-#if !defined(__DOXYGEN__)
-/**
- * @brief Interrupt saved context.
- * @details This structure represents the stack frame saved during a
- * preemption-capable interrupt handler.
- */
-struct extctx {
- regarm_t xpsr;
- regarm_t r12;
- regarm_t lr;
- regarm_t r0;
- regarm_t r1;
- regarm_t r2;
- regarm_t r3;
- regarm_t pc;
-};
-#endif
-
-#if !defined(__DOXYGEN__)
-/**
- * @brief System saved context.
- * @details This structure represents the inner stack frame during a context
- * switching.
- */
-#if defined(CH_ARCHITECTURE_ARM_v6M)
-struct intctx {
- regarm_t r8;
- regarm_t r9;
- regarm_t r10;
- regarm_t r11;
- regarm_t r4;
- regarm_t r5;
- regarm_t r6;
- regarm_t r7;
- regarm_t lr;
-};
-#elif defined(CH_ARCHITECTURE_ARM_v7M)
-struct intctx {
- regarm_t r4;
- regarm_t r5;
- regarm_t r6;
- regarm_t r7;
- regarm_t r8;
- regarm_t r9;
- regarm_t r10;
- regarm_t r11;
- regarm_t lr;
-};
-#endif
-#endif
-
#if !defined(__DOXYGEN__)
/**
* @brief Platform dependent part of the @p Thread structure.
- * @details In the Cortex-Mx port this structure just holds a pointer to the
- * @p intctx structure representing the stack pointer at the time
- * of the context switch.
+ * @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;
};
#endif
-/**
- * @brief Platform dependent part of the @p chThdInit() 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 4 because the idle thread does have
- * a stack frame when compiling without optimizations.
- */
-#ifndef IDLE_THREAD_STACK_SIZE
-#define IDLE_THREAD_STACK_SIZE 4
-#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 This port requires some extra stack space for interrupt handling
- * representing the frame of the function @p chSchDoRescheduleI().
- */
-#ifndef INT_REQUIRED_STACK
-#define INT_REQUIRED_STACK 8
-#endif
-
-/**
- * @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) + (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.
- * @details This macro must be inserted at the start of all IRQ handlers
- * enabled to invoke system APIs.
- */
-#define PORT_IRQ_PROLOGUE() { \
- chSysLockFromIsr(); \
- _port_irq_nesting++; \
- chSysUnlockFromIsr(); \
-}
-
-/**
- * @brief IRQ epilogue code.
- * @details This macro must be inserted at the end of all IRQ handlers
- * enabled to invoke system APIs.
- */
-#define PORT_IRQ_EPILOGUE() { \
- chSysLockFromIsr(); \
- if ((--_port_irq_nesting == 0) && chSchIsRescRequiredExI()) { \
- register struct cmxctx *ctxp; \
- \
- asm volatile ("mrs %0, PSP" : "=r" (ctxp) : ); \
- _port_saved_pc = ctxp->pc; \
- ctxp->pc = _port_switch_from_irq; \
- return; \
- } \
- chSysUnlockFromIsr(); \
-}
-
-/**
- * @brief IRQ handler function declaration.
- * @note @p id can be a function name or a vector number depending on the
- * port implementation.
- */
-#define PORT_IRQ_HANDLER(id) void id(void)
-
-/**
- * @brief Port-related initialization code.
- */
-#define port_init() { \
- _port_irq_nesting = 0; \
- SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \
- NVICSetSystemHandlerPriority(HANDLER_SYSTICK, \
- CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \
-}
-
-/**
- * @brief Kernel-lock action.
- * @details Usually this function just disables interrupts but may perform
- * more actions.
- */
-#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.
- */
-#if CORTEX_USE_BASEPRI
-#define port_unlock() { \
- register uint32_t tmp asm ("r3") = 0; \
- 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.
- * @details This function is invoked before invoking I-class APIs from
- * interrupt handlers. The implementation is architecture dependent,
- * in its simplest form it is void.
- * @note Same as @p port_lock() in this port.
- */
-#define port_lock_from_isr() port_lock()
-
-/**
- * @brief Kernel-unlock action from an interrupt handler.
- * @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_lock() in this port.
- */
-#define port_unlock_from_isr() port_unlock()
-
-/**
- * @brief Disables all the interrupt sources.
- */
-#define port_disable() asm volatile ("cpsid i")
-
-/**
- * @brief Disables the interrupt sources below kernel-level priority.
- */
-#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.
- */
-#if CORTEX_USE_BASEPRI
-#define port_enable() { \
- register uint32_t tmp asm ("r3") = 0; \
- 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.
- * @details The function is meant to return when an interrupt becomes pending.
- * The simplest implementation is an empty function or macro but this
- * would not take advantage of architecture-specific power saving
- * modes.
- * @note Implemented as an inlined @p WFI instruction.
- */
-#if CORTEX_ENABLE_WFI_IDLE || defined(__DOXYGEN__)
-#define port_wait_for_interrupt() asm volatile ("wfi")
-#else
-#define port_wait_for_interrupt()
-#endif
-
-#if !defined(__DOXYGEN__)
-extern regarm_t _port_saved_pc;
-extern unsigned _port_irq_nesting;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- void port_halt(void);
- void port_switch(Thread *ntp, Thread *otp);
- void _port_switch_from_irq(void);
- void _port_thread_start(void);
-#ifdef __cplusplus
-}
+#if defined(CH_ARCHITECTURE_ARM_v6M)
+#include "chcore_v6m.h"
+#elif defined(CH_ARCHITECTURE_ARM_v7M)
+#include "chcore_v7m.h"
#endif
#endif /* _CHCORE_H_ */
diff --git a/os/ports/GCC/ARMCMx/chcore_v6m.c b/os/ports/GCC/ARMCMx/chcore_v6m.c
new file mode 100644
index 000000000..8f8a0a100
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/chcore_v6m.c
@@ -0,0 +1,152 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ARMCMx/chcore_v6m.c
+ * @brief ARMv6-M architecture port code.
+ *
+ * @addtogroup ARMCMx_V6M_CORE
+ * @{
+ */
+
+#include "ch.h"
+
+/**
+ * @brief PC register temporary storage.
+ */
+regarm_t _port_saved_pc;
+
+/**
+ * @brief IRQ nesting counter.
+ */
+unsigned _port_irq_nesting;
+
+/**
+ * @brief System Timer vector.
+ * @details This interrupt is used as system tick.
+ * @note The timer must be initialized in the startup code.
+ */
+CH_IRQ_HANDLER(SysTickVector) {
+
+ CH_IRQ_PROLOGUE();
+
+ chSysLockFromIsr();
+ chSysTimerHandlerI();
+ chSysUnlockFromIsr();
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief Post-IRQ switch code.
+ * @details On entry the stack and the registers are restored by the exception
+ * return, the PC value is stored in @p _port_saved_pc, the interrupts
+ * are disabled.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((naked))
+#endif
+void _port_switch_from_irq(void) {
+ /* Note, saves r4 to make space for the PC.*/
+ asm volatile ("push {r0, r1, r2, r3, r4} \n\t" \
+ "mrs r0, APSR \n\t" \
+ "mov r1, r12 \n\t" \
+ "push {r0, r1, lr} \n\t" \
+ "ldr r0, =_port_saved_pc \n\t" \
+ "ldr r0, [r0] \n\t" \
+ "add r0, r0, #1 \n\t" \
+ "str r0, [sp, #28]");
+
+ chSchDoRescheduleI();
+
+ /* Note, the last registers are restored alone after re-enabling the
+ interrupts in order to minimize the (very remote and unlikely)
+ possibility that the stack is filled by continuous and saturating
+ interrupts that would not allow that last words to be pulled out of
+ the stack.*/
+ asm volatile ("pop {r0, r1, r2} \n\t" \
+ "mov r12, r1 \n\t" \
+ "msr APSR, r0 \n\t" \
+ "mov lr, r2 \n\t" \
+ "pop {r0, r1, r2, r3, pc}");
+}
+
+#define PUSH_CONTEXT(sp) { \
+ asm volatile ("push {r4, r5, r6, r7, lr} \n\t" \
+ "mov r4, r8 \n\t" \
+ "mov r5, r9 \n\t" \
+ "mov r6, r10 \n\t" \
+ "mov r7, r11 \n\t" \
+ "push {r4, r5, r6, r7}"); \
+}
+
+#define POP_CONTEXT(sp) { \
+ asm volatile ("pop {r4, r5, r6, r7} \n\t" \
+ "mov r8, r4 \n\t" \
+ "mov r9, r5 \n\t" \
+ "mov r10, r6 \n\t" \
+ "mov r11, r7 \n\t" \
+ "pop {r4, r5, r6, r7, pc}" : : "r" (sp)); \
+}
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects <b>directly</b> the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((naked))
+#endif
+void port_switch(Thread *ntp, Thread *otp) {
+ register struct intctx *r13 asm ("r13");
+
+ /* 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 */
+
+ PUSH_CONTEXT(r13);
+
+ otp->p_ctx.r13 = r13;
+ r13 = ntp->p_ctx.r13;
+
+ POP_CONTEXT(r13);
+}
+
+/**
+ * @brief Start a thread by invoking its work function.
+ * @details If the work function returns @p chThdExit() is automatically
+ * invoked.
+ */
+void _port_thread_start(void) {
+
+ port_unlock();
+ asm volatile ("mov r0, r5 \n\t" \
+ "blx r4 \n\t" \
+ "bl chThdExit");
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARMCMx/chcore_v6m.h b/os/ports/GCC/ARMCMx/chcore_v6m.h
new file mode 100644
index 000000000..7aff774bc
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/chcore_v6m.h
@@ -0,0 +1,271 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ARMCMx/chcore_v6m.h
+ * @brief ARMv6-M architecture port macros and structures.
+ *
+ * @addtogroup ARMCMx_V6M_CORE
+ * @{
+ */
+
+#ifndef _CHCORE_V6M_H_
+#define _CHCORE_V6M_H_
+
+/*===========================================================================*/
+/* Port implementation part. */
+/*===========================================================================*/
+
+/**
+ * @brief Cortex-Mx exception context.
+ */
+struct cmxctx {
+ regarm_t r0;
+ regarm_t r1;
+ regarm_t r2;
+ regarm_t r3;
+ regarm_t r12;
+ regarm_t lr_thd;
+ regarm_t pc;
+ regarm_t xpsr;
+};
+
+#if !defined(__DOXYGEN__)
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ */
+struct extctx {
+ regarm_t xpsr;
+ regarm_t r12;
+ regarm_t lr;
+ regarm_t r0;
+ regarm_t r1;
+ regarm_t r2;
+ regarm_t r3;
+ regarm_t pc;
+};
+#endif
+
+#if !defined(__DOXYGEN__)
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switching.
+ */
+struct intctx {
+ regarm_t r8;
+ regarm_t r9;
+ regarm_t r10;
+ regarm_t r11;
+ regarm_t r4;
+ regarm_t r5;
+ regarm_t r6;
+ regarm_t r7;
+ regarm_t lr;
+};
+#endif
+
+/**
+ * @brief Platform dependent part of the @p chThdInit() 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 4 because the idle thread does have
+ * a stack frame when compiling without optimizations.
+ */
+#ifndef IDLE_THREAD_STACK_SIZE
+#define IDLE_THREAD_STACK_SIZE 4
+#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 This port requires some extra stack space for interrupt handling
+ * representing the frame of the function @p chSchDoRescheduleI().
+ */
+#ifndef INT_REQUIRED_STACK
+#define INT_REQUIRED_STACK 8
+#endif
+
+/**
+ * @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) + (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.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_PROLOGUE() { \
+ chSysLockFromIsr(); \
+ _port_irq_nesting++; \
+ chSysUnlockFromIsr(); \
+}
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE() { \
+ chSysLockFromIsr(); \
+ if ((--_port_irq_nesting == 0) && chSchIsRescRequiredExI()) { \
+ register struct cmxctx *ctxp; \
+ \
+ asm volatile ("mrs %0, PSP" : "=r" (ctxp) : ); \
+ _port_saved_pc = ctxp->pc; \
+ ctxp->pc = _port_switch_from_irq; \
+ return; \
+ } \
+ chSysUnlockFromIsr(); \
+}
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#define PORT_IRQ_HANDLER(id) void id(void)
+
+/**
+ * @brief Port-related initialization code.
+ */
+#define port_init() { \
+ _port_irq_nesting = 0; \
+ SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \
+ NVICSetSystemHandlerPriority(HANDLER_SYSTICK, \
+ CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ */
+#define port_lock() asm volatile ("cpsid i")
+
+/**
+ * @brief Kernel-unlock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ */
+#define port_unlock() asm volatile ("cpsie i")
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details This function is invoked before invoking I-class APIs from
+ * interrupt handlers. The implementation is architecture dependent,
+ * in its simplest form it is void.
+ * @note Same as @p port_lock() in this port.
+ */
+#define port_lock_from_isr() port_lock()
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @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_lock() in this port.
+ */
+#define port_unlock_from_isr() port_unlock()
+
+/**
+ * @brief Disables all the interrupt sources.
+ */
+#define port_disable() asm volatile ("cpsid i")
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ */
+#define port_suspend() asm volatile ("cpsid i")
+
+/**
+ * @brief Enables all the interrupt sources.
+ */
+#define port_enable() asm volatile ("cpsie i")
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p WFI instruction.
+ */
+#if CORTEX_ENABLE_WFI_IDLE || defined(__DOXYGEN__)
+#define port_wait_for_interrupt() asm volatile ("wfi")
+#else
+#define port_wait_for_interrupt()
+#endif
+
+#if !defined(__DOXYGEN__)
+extern regarm_t _port_saved_pc;
+extern unsigned _port_irq_nesting;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void port_halt(void);
+ void port_switch(Thread *ntp, Thread *otp);
+ void _port_switch_from_irq(void);
+ void _port_thread_start(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CHCORE_V6M_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARMCMx/chcore_v7m.c b/os/ports/GCC/ARMCMx/chcore_v7m.c
new file mode 100644
index 000000000..e5df0d296
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/chcore_v7m.c
@@ -0,0 +1,178 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ARMCMx/chcore_v7m.c
+ * @brief ARMv7-M architecture port code.
+ *
+ * @addtogroup ARMCMx_V7M_CORE
+ * @{
+ */
+
+#include "ch.h"
+
+#if !CH_OPTIMIZE_SPEED
+void _port_lock(void) {
+ register uint32_t tmp asm ("r3") = BASEPRI_KERNEL;
+ asm volatile ("msr BASEPRI, %0" : : "r" (tmp));
+}
+
+void _port_unlock(void) {
+ register uint32_t tmp asm ("r3") = BASEPRI_USER;
+ asm volatile ("msr BASEPRI, %0" : : "r" (tmp));
+}
+#endif
+
+/**
+ * @brief System Timer vector.
+ * @details This interrupt is used as system tick.
+ * @note The timer must be initialized in the startup code.
+ */
+void SysTickVector(void) {
+
+ chSysLockFromIsr();
+ chSysTimerHandlerI();
+ if (chSchIsRescRequiredExI())
+ SCB_ICSR = ICSR_PENDSVSET;
+ chSysUnlockFromIsr();
+}
+
+#if CORTEX_MODEL == CORTEX_M0
+#define PUSH_CONTEXT(sp, prio) { \
+ asm volatile ("mrs %0, PSP \n\t" \
+ "sub %0, %0, #40 \n\t" \
+ "stmia %0!, {r3-r7} \n\t" \
+ "sub %0, %0, #20 \n\t" \
+ "mov r3, r8 \n\t" \
+ "str r3, [%0, #20] \n\t" \
+ "mov r3, r9 \n\t" \
+ "str r3, [%0, #24] \n\t" \
+ "mov r3, r10 \n\t" \
+ "str r3, [%0, #28] \n\t" \
+ "mov r3, r11 \n\t" \
+ "str r3, [%0, #32] \n\t" \
+ "mov r3, lr \n\t" \
+ "str r3, [%0, #36] \n\t" \
+ : "=r" (sp) : "r" (sp), "r" (prio)); \
+}
+
+#define POP_CONTEXT(sp) { \
+ asm volatile ("ldr r3, [%0, #20] \n\t" \
+ "mov r8, r3 \n\t" \
+ "ldr r3, [%0, #24] \n\t" \
+ "mov r9, r3 \n\t" \
+ "ldr r3, [%0, #28] \n\t" \
+ "mov r10, r3 \n\t" \
+ "ldr r3, [%0, #32] \n\t" \
+ "mov r11, r3 \n\t" \
+ "ldr r3, [%0, #36] \n\t" \
+ "mov lr, r3 \n\t" \
+ "ldmia %0!, {r3-r7} \n\t" \
+ "add %0, %0, #20 \n\t" \
+ "msr PSP, %0 \n\t" \
+ "msr BASEPRI, r3 \n\t" \
+ "bx lr" : "=r" (sp) : "r" (sp)); \
+}
+#else /* CORTEX_MODEL != CORTEX_M0 */
+#if !defined(CH_CURRP_REGISTER_CACHE)
+#define PUSH_CONTEXT(sp, prio) { \
+ asm volatile ("mrs %0, PSP \n\t" \
+ "stmdb %0!, {r3-r11,lr}" : \
+ "=r" (sp) : "r" (sp), "r" (prio)); \
+}
+
+#define POP_CONTEXT(sp) { \
+ asm volatile ("ldmia %0!, {r3-r11, lr} \n\t" \
+ "msr PSP, %0 \n\t" \
+ "msr BASEPRI, r3 \n\t" \
+ "bx lr" : "=r" (sp) : "r" (sp)); \
+}
+#else /* defined(CH_CURRP_REGISTER_CACHE) */
+#define PUSH_CONTEXT(sp, prio) { \
+ asm volatile ("mrs %0, PSP \n\t" \
+ "stmdb %0!, {r3-r6,r8-r11, lr}" : \
+ "=r" (sp) : "r" (sp), "r" (prio)); \
+}
+
+#define POP_CONTEXT(sp) { \
+ asm volatile ("ldmia %0!, {r3-r6,r8-r11, lr} \n\t" \
+ "msr PSP, %0 \n\t" \
+ "msr BASEPRI, r3 \n\t" \
+ "bx lr" : "=r" (sp) : "r" (sp)); \
+}
+#endif /* defined(CH_CURRP_REGISTER_CACHE) */
+#endif /* CORTEX_MODEL != CORTEX_M0 */
+
+/**
+ * @brief SVC vector.
+ * @details The SVC vector is used for commanded context switch. Structures
+ * @p intctx are saved and restored from the process stacks of the
+ * switched threads.
+ *
+ * @param[in] ntp the thread to be switched it
+ * @param[in] otp the thread to be switched out
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((naked))
+#endif
+void SVCallVector(Thread *ntp, Thread *otp) {
+ register struct intctx *sp_thd asm("r2");
+ register uint32_t prio asm ("r3");
+
+ asm volatile ("mrs r3, BASEPRI" : "=r" (prio) : );
+ PUSH_CONTEXT(sp_thd, prio)
+
+ otp->p_ctx.r13 = sp_thd;
+ sp_thd = ntp->p_ctx.r13;
+
+ POP_CONTEXT(sp_thd)
+}
+
+/**
+ * @brief Preemption code.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((naked))
+#endif
+void PendSVVector(void) {
+ register struct intctx *sp_thd asm("r2");
+ register uint32_t prio asm ("r3");
+ Thread *otp, *ntp;
+
+ chSysLockFromIsr();
+
+ prio = CORTEX_BASEPRI_DISABLED;
+ PUSH_CONTEXT(sp_thd, prio)
+
+ (otp = currp)->p_ctx.r13 = sp_thd;
+ ntp = fifo_remove(&rlist.r_queue);
+ setcurrp(ntp);
+ ntp->p_state = THD_STATE_CURRENT;
+ chSchReadyI(otp);
+#if CH_TIME_QUANTUM > 0
+ /* Set the round-robin time quantum.*/
+ rlist.r_preempt = CH_TIME_QUANTUM;
+#endif
+ chDbgTrace(otp);
+ sp_thd = ntp->p_ctx.r13;
+
+ POP_CONTEXT(sp_thd)
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARMCMx/chcore_v7m.h b/os/ports/GCC/ARMCMx/chcore_v7m.h
new file mode 100644
index 000000000..804f6357e
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/chcore_v7m.h
@@ -0,0 +1,313 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ARMCMx/chcore_v7m.h
+ * @brief ARMv7-M architecture port macros and structures.
+ *
+ * @addtogroup ARMCMx_V7M_CORE
+ * @{
+ */
+
+#ifndef _CHCORE_V7M_H_
+#define _CHCORE_V7M_H_
+
+/*===========================================================================*/
+/* Port implementation part. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ * @note This structure is empty in this port.
+ */
+struct extctx {
+};
+#endif
+
+#if !defined(__DOXYGEN__)
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switching.
+ */
+struct intctx {
+ regarm_t basepri;
+ 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;
+ regarm_t r11;
+ regarm_t lr_exc;
+ /* Start of the hardware saved frame.*/
+ regarm_t r0;
+ regarm_t r1;
+ regarm_t r2;
+ regarm_t r3;
+ regarm_t r12;
+ regarm_t lr_thd;
+ regarm_t pc;
+ regarm_t xpsr;
+};
+#endif
+
+/**
+ * @brief Platform dependent part of the @p chThdInit() 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->basepri = CORTEX_BASEPRI_DISABLED; \
+ tp->p_ctx.r13->lr_exc = (regarm_t)0xFFFFFFFD; \
+ tp->p_ctx.r13->r0 = arg; \
+ tp->p_ctx.r13->lr_thd = chThdExit; \
+ tp->p_ctx.r13->pc = pf; \
+ tp->p_ctx.r13->xpsr = (regarm_t)0x01000000; \
+}
+
+/**
+ * @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 4 because the idle thread does have
+ * a stack frame when compiling without optimizations.
+ */
+#ifndef IDLE_THREAD_STACK_SIZE
+#define IDLE_THREAD_STACK_SIZE 4
+#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 This port requires no extra stack space for interrupt handling.
+ */
+#ifndef INT_REQUIRED_STACK
+#define INT_REQUIRED_STACK 0
+#endif
+
+/**
+ * @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) + (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.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE() { \
+ chSysLockFromIsr(); \
+ if (chSchIsRescRequiredI()) \
+ SCB_ICSR = ICSR_PENDSVSET; \
+ chSysUnlockFromIsr(); \
+}
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#define PORT_IRQ_HANDLER(id) void id(void)
+
+/**
+ * @brief Port-related initialization code.
+ */
+#define port_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)); \
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ * @note In this port this it raises the base priority to kernel level.
+ */
+#if CH_OPTIMIZE_SPEED
+#define port_lock() { \
+ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL; \
+ asm volatile ("msr BASEPRI, %0" : : "r" (tmp)); \
+}
+#else
+#define port_lock() { \
+ asm volatile ("bl _port_lock" : : : "r3", "lr"); \
+}
+#endif
+
+/**
+ * @brief Kernel-unlock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ * @note In this port this it lowers the base priority to kernel level.
+ */
+#if CH_OPTIMIZE_SPEED
+#define port_unlock() { \
+ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_DISABLED; \
+ asm volatile ("msr BASEPRI, %0" : : "r" (tmp)); \
+}
+#else
+#define port_unlock() { \
+ asm volatile ("bl _port_unlock" : : : "r3", "lr"); \
+}
+#endif
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details This function is invoked before invoking I-class APIs from
+ * interrupt handlers. The implementation is architecture dependent,
+ * in its simplest form it is void.
+ * @note Same as @p port_lock() in this port.
+ */
+#define port_lock_from_isr() port_lock()
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @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.
+ */
+#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 by raising
+ * the priority mask to level 0.
+ */
+#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 raises/lowers the base priority to kernel level.
+ */
+#define port_suspend() { \
+ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL; \
+ asm volatile ("msr BASEPRI, %0 \n\t" \
+ "cpsie i" : : "r" (tmp)); \
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ * @note In this port it lowers the base priority to user level.
+ */
+#define port_enable() { \
+ register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_DISABLED; \
+ asm volatile ("msr BASEPRI, %0 \n\t" \
+ "cpsie i" : : "r" (tmp)); \
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p WFI instruction.
+ */
+#if CORTEX_ENABLE_WFI_IDLE || defined(__DOXYGEN__)
+#define port_wait_for_interrupt() { \
+ asm volatile ("wfi"); \
+}
+#else
+#define port_wait_for_interrupt()
+#endif
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects <b>directly</b> the context
+ * switch performance so optimize here as much as you can.
+ * @note Implemented as inlined code for performance reasons.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+static INLINE Thread *port_switch(Thread *ntp, Thread *otp) {
+ register Thread *_ntp asm ("r0") = (ntp);
+ register Thread *_otp asm ("r1") = (otp);
+#if CH_DBG_ENABLE_STACK_CHECK
+ register char *sp asm ("sp");
+ if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp)
+ asm volatile ("movs r0, #0 \n\t"
+ "b chDbgPanic");
+#endif /* CH_DBG_ENABLE_STACK_CHECK */
+ asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp) : "memory");
+ return _otp;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void port_halt(void);
+#if !CH_OPTIMIZE_SPEED
+ void _port_lock(void);
+ void _port_unlock(void);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CHCORE_V7M_H_ */
+
+/** @} */