From eb665ad2407a28c57a6d5802b3bcfa474b8c6e3f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 8 Jan 2011 12:09:18 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2615 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ports/IAR/ARMCMx/chcore_v6m.c | 90 ------------------------ os/ports/IAR/ARMCMx/chcore_v6m.h | 17 ++++- os/ports/IAR/ARMCMx/chcore_v7m.h | 2 +- os/ports/IAR/ARMCMx/chcoreasm_v6m.s | 134 ++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 93 deletions(-) create mode 100644 os/ports/IAR/ARMCMx/chcoreasm_v6m.s (limited to 'os/ports') 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 directly 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 directly 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 . +*/ + + 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 -- cgit v1.2.3