summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/armv7-m
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/arch/arm/src/armv7-m')
-rw-r--r--nuttx/arch/arm/src/armv7-m/exc_return.h51
-rw-r--r--nuttx/arch/arm/src/armv7-m/nvic.h1
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_exception.S236
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_initialstate.c45
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_svcall.c10
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_vectors.c95
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
+ };