diff options
Diffstat (limited to 'os/ports/IAR/ARMCMx')
-rw-r--r-- | os/ports/IAR/ARMCMx/chcore_v6m.c | 90 | ||||
-rw-r--r-- | os/ports/IAR/ARMCMx/chcore_v6m.h | 17 | ||||
-rw-r--r-- | os/ports/IAR/ARMCMx/chcore_v7m.h | 2 | ||||
-rw-r--r-- | os/ports/IAR/ARMCMx/chcoreasm_v6m.s | 134 |
4 files changed, 150 insertions, 93 deletions
diff --git a/os/ports/IAR/ARMCMx/chcore_v6m.c b/os/ports/IAR/ARMCMx/chcore_v6m.c index 4c8ab0646..25b360809 100644 --- a/os/ports/IAR/ARMCMx/chcore_v6m.c +++ b/os/ports/IAR/ARMCMx/chcore_v6m.c @@ -53,94 +53,4 @@ CH_IRQ_HANDLER(SysTickVector) { 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.
- */
-void _port_switch_from_irq(void) {
- /* Note, saves r4 to make space for the PC.*/
- asm ("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 ("pop {r0, r1, r2} \n\t"
- "mov r12, r1 \n\t"
- "msr APSR, r0 \n\t"
- "mov lr, r2 \n\t"
- "cpsie i \n\t"
- "pop {r0, r1, r2, r3, pc}");
-}
-
-#define PUSH_CONTEXT(sp) { \
- asm ("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 ("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}"); \
-}
-
-/**
- * @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
- */
-void port_switch(Thread *ntp, Thread *otp) {
-
- /* 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);
-
- asm ("str sp, [r1, #12] \n\t"
- "ldr sp, [r0, #12]");
-
- 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 ("mov r0, r5 \n\t"
- "blx r4 \n\t"
- "bl chThdExit");
-}
-
/** @} */
diff --git a/os/ports/IAR/ARMCMx/chcore_v6m.h b/os/ports/IAR/ARMCMx/chcore_v6m.h index 3c1189ce6..fe6c68a92 100644 --- a/os/ports/IAR/ARMCMx/chcore_v6m.h +++ b/os/ports/IAR/ARMCMx/chcore_v6m.h @@ -216,6 +216,18 @@ struct intctx { #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.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#define port_switch(ntp, otp) _port_switch(ntp, otp)
+
#if !defined(__DOXYGEN__)
extern regarm_t _port_saved_pc;
extern unsigned _port_irq_nesting;
@@ -225,8 +237,9 @@ extern unsigned _port_irq_nesting; extern "C" {
#endif
void port_halt(void);
- void port_switch(Thread *ntp, Thread *otp);
- void _port_switch_from_irq(void);
+ void _port_switch(Thread *ntp, Thread *otp);
+ void _port_irq_epilogue(void);
+ void _port_switch_from_isr(void);
void _port_thread_start(void);
#ifdef __cplusplus
}
diff --git a/os/ports/IAR/ARMCMx/chcore_v7m.h b/os/ports/IAR/ARMCMx/chcore_v7m.h index 7f7112d45..ba0c83f5a 100644 --- a/os/ports/IAR/ARMCMx/chcore_v7m.h +++ b/os/ports/IAR/ARMCMx/chcore_v7m.h @@ -225,7 +225,7 @@ struct intctx { * @param[in] ntp the thread to be switched in
* @param[in] otp the thread to be switched out
*/
-#define port_switch(ntp, otp) _port_switch(ntp, otp)
+#define port_switch(ntp, otp) _port_switch(ntp, otp)
#ifdef __cplusplus
extern "C" {
diff --git a/os/ports/IAR/ARMCMx/chcoreasm_v6m.s b/os/ports/IAR/ARMCMx/chcoreasm_v6m.s new file mode 100644 index 000000000..c9ee6a0c8 --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcoreasm_v6m.s @@ -0,0 +1,134 @@ +/*
+ 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/>.
+*/
+
+ MODULE ?chcoreasm_v6m
+
+ AAPCS INTERWORK, VFP_COMPATIBLE
+ PRESERVE8
+
+/*
+ * Imports the Cortex-Mx parameters header and performs the same calculations
+ * done in chcore.h.
+ */
+#include "cmparams.h"
+
+#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS))
+
+#ifndef CORTEX_PRIORITY_SVCALL
+#define CORTEX_PRIORITY_SVCALL 1
+#endif
+
+EXTCTX_SIZE SET 32
+CONTEXT_OFFSET SET 12
+
+ SECTION .text:CODE:NOROOT(2)
+
+ EXTERN chThdExit
+ EXTERN chSchIsRescRequiredExI
+ EXTERN chSchDoRescheduleI
+ EXTERN _port_saved_pc
+ EXTERN _port_irq_nesting
+
+ THUMB
+
+/*
+ * Performs a context switch between two threads.
+ */
+ PUBLIC _port_switch
+_port_switch:
+ push {r4, r5, r6, r7, lr}
+ mov r4, r8
+ mov r5, r9
+ mov r6, r10
+ mov r7, r11
+ push {r4, r5, r6, r7}
+ mov r3, sp
+ str r3, [r1, #CONTEXT_OFFSET]
+ ldr r3, [r0, #CONTEXT_OFFSET]
+ mov sp, r3
+ pop {r4, r5, r6, r7}
+ mov r8, r4
+ mov r9, r5
+ mov r10, r6
+ mov r11, r7
+ pop {r4, r5, r6, r7, pc}
+
+/*
+ * Start a thread by invoking its work function.
+ * If the work function returns @p chThdExit() is automatically invoked.
+ */
+ PUBLIC _port_thread_start
+_port_thread_start:
+ cpsie i
+ mov r0, r5
+ blx r4
+ bl chThdExit
+
+/*
+ * Post-IRQ switch code.
+ * Exception handlers return here for context switching.
+ */
+ PUBLIC _port_switch_from_isr
+_port_switch_from_isr:
+ /* Note, saves r4 to make space for the PC.*/
+ push {r0, r1, r2, r3, r4}
+ mrs r0, APSR
+ mov r1, r12
+ push {r0, r1, lr}
+ ldr r0, =_port_saved_pc
+ ldr r0, [r0]
+ adds r0, r0, #1
+ str r0, [sp, #28]
+ bl chSchDoRescheduleI
+ pop {r0, r1, r2}
+ mov r12, r1
+ msr APSR, r0
+ mov lr, r2
+ cpsie i
+ pop {r0, r1, r2, r3, pc}
+
+/*
+ * Reschedule verification and setup after an IRQ.
+ */
+ PUBLIC _port_irq_epilogue
+_port_irq_epilogue:
+ push {r4, lr}
+ cpsid i
+ ldr r2, =_port_irq_nesting
+ ldr r3, [r2]
+ subs r3, r3, #1
+ str r3, [r2]
+ cmp r3, #0
+ beq .L34
+ cpsie i
+ pop {r4, pc}
+.L34:
+ bl chSchIsRescRequiredExI
+ cmp r0, #0
+ beq .L31
+ mrs r1, PSP
+ ldr r2, =_port_saved_pc
+ ldr r3, [r1, #24]
+ str r3, [r2]
+ ldr r3, =_port_switch_from_isr
+ str r3, [r1, #24]
+.L31:
+ pop {r4, pc}
+
+ END
|