diff options
Diffstat (limited to 'nuttx/arch/arm/src/armv7-m')
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/exc_return.h | 51 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/nvic.h | 1 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_exception.S | 236 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_initialstate.c | 45 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_svcall.c | 10 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_vectors.c | 95 |
6 files changed, 416 insertions, 22 deletions
diff --git a/nuttx/arch/arm/src/armv7-m/exc_return.h b/nuttx/arch/arm/src/armv7-m/exc_return.h index f32fd7a06..cffbd3e2e 100644 --- a/nuttx/arch/arm/src/armv7-m/exc_return.h +++ b/nuttx/arch/arm/src/armv7-m/exc_return.h @@ -1,8 +1,8 @@ /************************************************************************************ * arch/arm/src/armv7-m/exc_return.h * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -48,38 +48,65 @@ /* The processor saves an EXC_RETURN value to the LR on exception entry. The * exception mechanism relies on this value to detect when the processor has - * completed an exception handler. Bits[31:4] of an EXC_RETURN value are - * 0xfffffffX. When the processor loads a value matching this pattern to the - * PC it detects that the operation is a not a normal branch operation and, - * instead, that the exception is complete. Therefore, it starts the exception - * return sequence. Bits[3:0] of the EXC_RETURN value indicate the required - * return stack and processor mode: + * completed an exception handler. + * + * Bits [31:28] of an EXC_RETURN value are always 1. When the processor loads a + * value matching this pattern to the PC it detects that the operation is a not + * a normal branch operation and instead, that the exception is complete. + * Therefore, it starts the exception return sequence. + * + * Bits[4:0] of the EXC_RETURN value indicate the required return stack and eventual + * processor mode. The remaining bits of the EXC_RETURN value should be set to 1. + */ + +/* EXC_RETURN_BASE: Bits that are always set in an EXC_RETURN value. */ + +#define EXC_RETURN_BASE 0xffffffe1 + +/* EXC_RETURN_PROCESS_STACK: The exception saved (and will restore) the hardware + * context using the process stack pointer (if not set, the context was saved + * using the main stack pointer) + */ + +#define EXC_RETURN_PROCESS_STACK (1 << 2) + +/* EXC_RETURN_THREAD_MODE: The exception will return to thread mode (if not set, + * return stays in handler mode) + */ + +#define EXC_RETURN_THREAD_MODE (1 << 3) + +/* EXC_RETURN_STD_CONTEXT: The state saved on the stack does not include the + * volatile FP registers and FPSCR. If this bit is clear, the state does include + * these registers. */ + +#define EXC_RETURN_STD_CONTEXT (1 << 4) /* EXC_RETURN_HANDLER: Return to handler mode. Exception return gets state from * the main stack. Execution uses MSP after return. */ -#define EXC_RETURN_HANDLER 0xfffffff1 +#define EXC_RETURN_HANDLER 0xfffffff1 /* EXC_RETURN_PRIVTHR: Return to privileged thread mode. Exception return gets * state from the main stack. Execution uses MSP after return. */ -#define EXC_RETURN_PRIVTHR 0xfffffff9 +#define EXC_RETURN_PRIVTHR 0xfffffff9 /* EXC_RETURN_UNPRIVTHR: Return to unprivileged thread mode. Exception return gets * state from the process stack. Execution uses PSP after return. */ -#define EXC_RETURN_UNPRIVTHR 0xfffffffd +#define EXC_RETURN_UNPRIVTHR 0xfffffffd /* In the kernel build is not selected, then all threads run in privileged thread * mode. */ #ifdef CONFIG_NUTTX_KERNEL -# define EXC_RETURN 0xfffffff9 +# define EXC_RETURN 0xfffffff9 #endif /************************Th************************************************************ diff --git a/nuttx/arch/arm/src/armv7-m/nvic.h b/nuttx/arch/arm/src/armv7-m/nvic.h index b0b08ddef..07d9cde6f 100644 --- a/nuttx/arch/arm/src/armv7-m/nvic.h +++ b/nuttx/arch/arm/src/armv7-m/nvic.h @@ -373,6 +373,7 @@ #define NVIC_ISAR4 (ARMV7M_NVIC_BASE + NVIC_ISAR4_OFFSET) #define NVIC_CPACR (ARMV7M_NVIC_BASE + NVIC_CPACR_OFFSET) #define NVIC_STIR (ARMV7M_NVIC_BASE + NVIC_STIR_OFFSET) +#define NVIC_FPCCR (ARMV7M_NVIC_BASE + NVIC_FPCCR_OFFSET) #define NVIC_PID4 (ARMV7M_NVIC_BASE + NVIC_PID4_OFFSET) #define NVIC_PID5 (ARMV7M_NVIC_BASE + NVIC_PID5_OFFSET) #define NVIC_PID6 (ARMV7M_NVIC_BASE + NVIC_PID6_OFFSET) diff --git a/nuttx/arch/arm/src/armv7-m/up_exception.S b/nuttx/arch/arm/src/armv7-m/up_exception.S new file mode 100644 index 000000000..091542ea3 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_exception.S @@ -0,0 +1,236 @@ +/************************************************************************************ + * arch/arm/src/stm32/up_exception.S + * arch/arm/src/chip/up_exception.S + * + * Copyright (C) 2009-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012 Michael Smith. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include <nuttx/config.h> + +#include <arch/irq.h> +#include "exc_return.h" + +#include "chip.h" + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .globl exception_common + + .syntax unified + .thumb + .file "up_exception.S" + +/************************************************************************************ + * .text + ************************************************************************************/ + +/* Common exception handling logic. On entry here, the return stack is on either + * the PSP or the MSP and looks like the following: + * + * REG_XPSR + * REG_R15 + * REG_R14 + * REG_R12 + * REG_R3 + * REG_R2 + * REG_R1 + * MSP->REG_R0 + * + * And + * IPSR contains the IRQ number + * R14 Contains the EXC_RETURN value + * We are in handler mode and the current SP is the MSP + * + * If CONFIG_ARCH_FPU is defined, the volatile FP registers and FPSCR are on the + * return stack immediately above REG_XPSR. + */ + + .text + .type exception_common, function + .thumb_func +exception_common: + + mrs r0, ipsr /* R0=exception number */ + + /* Complete the context save */ + + /* The EXC_RETURN value tells us whether the context is on the MSP or PSP */ + + tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ + ite eq /* next two instructions conditional */ + mrseq r1, msp /* R1=The main stack pointer */ + mrsne r1, psp /* R1=The process stack pointer */ + + mov r2, r1 /* R2=Copy of the main/process stack pointer */ + add r2, #HW_XCPT_SIZE /* R2=MSP/PSP before the interrupt was taken */ + /* (ignoring the xPSR[9] alignment bit) */ + mrs r3, primask /* R3=Current PRIMASK setting */ + +#ifdef CONFIG_ARCH_FPU + + /* Save the non-volatile FP registers here. + * + * This routine is the only point where we can save these registers; either before + * or after calling up_doirq. The compiler is free to use them at any time as long + * as they are restored before returning, so we can't assume that we can get at the + * true values of these registers in any routine called from here. + * + * XXX we could do all this saving lazily on the context switch side if we knew where to put + * the registers. + */ + + vstmdb r1!, {s16-s31} /* Save the non-volatile FP context */ + +#endif + + stmdb r1!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */ + + /* Disable interrupts, select the stack to use for interrupt handling + * and call up_doirq to handle the interrupt + */ + + cpsid i /* Disable further interrupts */ + + /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt + * stack pointer. The way that this is done here prohibits nested interrupts! + * Otherwise, we will use the stack that was current when the interrupt was taken. + */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + ldr sp, =g_intstackbase + push r1 /* Save the MSP on the interrupt stack */ + bl up_doirq /* R0=IRQ, R1=register save area on stack */ + pop r1 /* Recover R1=main stack pointer */ +#else + msr msp, r1 /* We are using the main stack pointer */ + bl up_doirq /* R0=IRQ, R1=register save area on stack */ + mrs r1, msp /* Recover R1=main stack pointer */ +#endif + + /* On return from up_doirq, R0 will hold a pointer to register context + * array to use for the interrupt return. If that return value is the same + * as current stack pointer, then things are relatively easy. + */ + + cmp r0, r1 /* Context switch? */ + beq 1f /* Branch if no context switch */ + + /* We are returning with a pending context switch. This case is different + * because in this case, the register save structure does not lie on the + * stack but, rather within a TCB structure. We'll have to copy some + * values to the stack. + */ + + /* Copy the hardware-saved context to the stack, and restore the software + * saved context directly. + * + * XXX In the normal case, it appears that this entire operation is unnecessary; + * context switch time would be improved if we could work out when the stack + * is dirty and avoid the work... + */ + add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */ + ldmia r1!, {r4-r11} /* Fetch eight registers in HW save area */ +#ifdef CONFIG_ARCH_FPU + vldmia r1!, {s0-s15} /* Fetch sixteen FP registers in HW save area */ + ldmia r1, {r2-r3} /* Fetch FPSCR and Reserved in HW save area */ +#endif + ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */ +#ifdef CONFIG_ARCH_FPU + stmdb r1!, {r2-r3} /* Store FPSCR and Reserved on the return stack */ + vstmdb r1!, {s0-s15} /* Store sixteen FP registers on the return stack */ +#endif + stmdb r1!, {r4-r11} /* Store eight registers on the return stack */ + ldmia r0!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#ifdef CONFIG_ARCH_FPU + vldmia r0, {s16-s31} /* Recover S16-S31 */ +#endif + + b 2f /* Re-join common logic */ + +1: + /* We are returning with no context switch. We simply need to "unwind" + * the same stack frame that we created at entry. + */ + + ldmia r1!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */ +#ifdef CONFIG_ARCH_FPU + vldmia r1!, {s16-s31} /* Recover S16-S31 */ +#endif + +2: + /* The EXC_RETURN value tells us whether we are returning on the MSP or PSP + */ + + tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */ + ite eq /* next two instructions conditional */ + msreq msp, r1 /* R1=The main stack pointer */ + msrne psp, r1 /* R1=The process stack pointer */ + + /* Restore the interrupt state */ + + msr primask, r3 /* Restore interrupts */ + + /* Always return with R14 containing the special value that will: (1) + * return to thread mode, and (2) select the correct stack. + */ + + bx r14 /* And return */ + + .size exception_common, .-exception_common + +/************************************************************************************ + * Name: up_interruptstack/g_intstackbase + * + * Description: + * Shouldn't happen + * + ************************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + .bss + .global g_intstackbase + .align 4 +up_interruptstack: + .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) +g_intstackbase: + .size up_interruptstack, .-up_interruptstack +#endif + + .end + diff --git a/nuttx/arch/arm/src/armv7-m/up_initialstate.c b/nuttx/arch/arm/src/armv7-m/up_initialstate.c index 6a13f038b..81a4dc9ea 100644 --- a/nuttx/arch/arm/src/armv7-m/up_initialstate.c +++ b/nuttx/arch/arm/src/armv7-m/up_initialstate.c @@ -1,8 +1,8 @@ /**************************************************************************** * arch/arm/src/armv7-m/up_initialstate.c * - * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2009, 2011-2 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -124,8 +124,43 @@ void up_initial_state(_TCB *tcb) #ifdef CONFIG_NXFLAT tcb->entry.main = (main_t)((uint32_t)tcb->entry.main | 1); #endif +#endif /* CONFIG_PIC */ + +#ifdef CONFIG_ARMV7M_CMNVECTOR + /* Set privileged- or unprivileged-mode, depending on how NuttX is + * configured and what kind of thread is being started. + * + * If the kernel build is not selected, then all threads run in + * privileged thread mode. + * + * If FPU support is not configured, set the bit that indicates that + * the context does not include the volatile FP registers. + */ + + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_BASE | EXC_RETURN_THREAD_MODE; + +#ifndef CONFIG_ARCH_FPU + + xcp->regs[REG_EXC_RETURN] |= EXC_RETURN_STD_CONTEXT; + +#else + + xcp->regs[REG_FPSCR] = 0; // XXX initial FPSCR should be configurable + xcp->regs[REG_FPReserved] = 0; + +#endif + +#ifdef CONFIG_NUTTX_KERNEL + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) + { + /* It is a normal task or a pthread. Set user mode */ + + xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PROCESS_STACK; + } #endif +#else /* CONFIG_ARMV7M_CMNVECTOR */ + /* Set privileged- or unprivileged-mode, depending on how NuttX is * configured and what kind of thread is being started. * @@ -147,11 +182,11 @@ void up_initial_state(_TCB *tcb) xcp->regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR; } #endif +#endif /* CONFIG_ARMV7M_CMNVECTOR */ /* Enable or disable interrupts, based on user configuration */ -# ifdef CONFIG_SUPPRESS_INTERRUPTS +#ifdef CONFIG_SUPPRESS_INTERRUPTS xcp->regs[REG_PRIMASK] = 1; -# endif +#endif } - diff --git a/nuttx/arch/arm/src/armv7-m/up_svcall.c b/nuttx/arch/arm/src/armv7-m/up_svcall.c index 85430c0ad..949efb1af 100644 --- a/nuttx/arch/arm/src/armv7-m/up_svcall.c +++ b/nuttx/arch/arm/src/armv7-m/up_svcall.c @@ -1,8 +1,8 @@ /**************************************************************************** * arch/arm/src/armv7-m/up_svcall.c * - * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -265,14 +265,14 @@ int up_svcall(int irq, FAR void *context) * R1 = saveregs * * In this case, we simply need to copy the current regsters to the - * save regiser space references in the saved R1 and return. + * save register space references in the saved R1 and return. */ case SYS_save_context: { DEBUGASSERT(regs[REG_R1] != 0); memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE); -#ifdef CONFIG_ARCH_FPU +#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_ARMV7M_CMNVECTOR) up_savefpu((uint32_t*)regs[REG_R1]); #endif } @@ -324,7 +324,7 @@ int up_svcall(int irq, FAR void *context) } break; - /* This is not an architecture-specify system call. If NuttX is built + /* This is not an architecture-specific system call. If NuttX is built * as a standalone kernel with a system call interface, then all of the * additional system calls must be handled as in the default case. */ diff --git a/nuttx/arch/arm/src/armv7-m/up_vectors.c b/nuttx/arch/arm/src/armv7-m/up_vectors.c new file mode 100644 index 000000000..b85ac9246 --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_vectors.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/up_vectors.c + * + * Copyright (C) 2012 Michael Smith. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include "chip.h" + +/************************************************************************************ + * Preprocessor Definitions + ************************************************************************************/ + +#define IDLE_STACK ((unsigned)&_ebss+CONFIG_IDLETHREAD_STACKSIZE-4) + +#ifndef ARMV7M_PERIPHERAL_INTERRUPTS +# error ARMV7M_PERIPHERAL_INTERRUPTS must be defined to the number of I/O interrupts to be supported +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Chip-specific entrypoint */ + +extern void __start(void); + +/* Common exception entrypoint */ + +extern void exception_common(void); + +/************************************************************************************ + * Public data + ************************************************************************************/ + +/* Provided by the linker script to indicate the end of the BSS */ + +extern char _ebss; + +/* The v7m vector table consists of an array of function pointers, with the first + * slot (vector zero) used to hold the initial stack pointer. + * + * As all exceptions (interrupts) are routed via exception_common, we just need to + * fill this array with pointers to it. + * + * Note that the [ ... ] desginated initialiser is a GCC extension. + */ + +unsigned _vectors[] __attribute__((section(".vectors"))) = + { + /* Initial stack */ + + IDLE_STACK, + + /* Reset exception handler */ + + (unsigned)&__start, + + /* Vectors 2 - n point directly at the generic handler */ + + [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common + }; |