From 3e2d87c22ade20620724b7696e763a800e320cdc Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 7 Dec 2011 18:58:21 +0000 Subject: Add support for the Cortex-M4 floating pointing git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4144 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/include/armv7-m/irq.h | 4 +- nuttx/arch/arm/src/armv7-m/mpu.h | 2 +- nuttx/arch/arm/src/armv7-m/up_fpu.S | 236 +++++++++++++++++++++ nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S | 2 +- nuttx/arch/arm/src/armv7-m/up_svcall.c | 3 + nuttx/arch/arm/src/common/up_internal.h | 25 ++- nuttx/arch/arm/src/stm32/Make.defs | 4 + nuttx/arch/arm/src/stm32/stm32_start.c | 2 +- nuttx/arch/arm/src/stm32/stm32_vectors.S | 15 +- 9 files changed, 283 insertions(+), 10 deletions(-) create mode 100644 nuttx/arch/arm/src/armv7-m/up_fpu.S (limited to 'nuttx/arch/arm') diff --git a/nuttx/arch/arm/include/armv7-m/irq.h b/nuttx/arch/arm/include/armv7-m/irq.h index 226101cd9..87647ee2d 100644 --- a/nuttx/arch/arm/include/armv7-m/irq.h +++ b/nuttx/arch/arm/include/armv7-m/irq.h @@ -2,7 +2,7 @@ * arch/arm/include/armv7-m/irq.h * * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -143,7 +143,7 @@ # define REG_D15 (SW_INT_REGS+30) /* D15 */ # define REG_S30 (SW_INT_REGS+30) /* S30 */ # define REG_S31 (SW_INT_REGS+31) /* S31 */ -# DEFINE REG_FPSCR (SW_INT_REGS+32) /* Floating point status and control */ +# define REG_FPSCR (SW_INT_REGS+32) /* Floating point status and control */ # define SW_FPU_REGS (33) #else # define SW_FPU_REGS (0) diff --git a/nuttx/arch/arm/src/armv7-m/mpu.h b/nuttx/arch/arm/src/armv7-m/mpu.h index 43746b507..8d4cd1829 100644 --- a/nuttx/arch/arm/src/armv7-m/mpu.h +++ b/nuttx/arch/arm/src/armv7-m/mpu.h @@ -2,7 +2,7 @@ * arch/arm/src/armv7-m/mpu.h * * Copyright (C) 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/arch/arm/src/armv7-m/up_fpu.S b/nuttx/arch/arm/src/armv7-m/up_fpu.S new file mode 100644 index 000000000..c301f793e --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/up_fpu.S @@ -0,0 +1,236 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/stm32_fpu.S + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ************************************************************************************/ +/* + * When this file is assembled, it will require the following GCC options: + * + * -mcpu=cortex-m3 -mfloat-abi=hard -mfpu=vfp -meabi=5 + */ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include + +#ifdef CONFIG_ARCH_FPU + +/************************************************************************************ + * Preprocessor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .globl up_savefpu + .globl up_restorefpu + + .syntax unified + .thumb + .file "up_fpu.S" + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_restorefpu + * + * Description: + * Given the pointer to a register save area (in R0), save the state of the + * floating point registers. + * + * C Function Prototype: + * void up_savefpu(uint32_t *regs); + * + * Input Parameters: + * regs - A pointer to the register save area in which to save the floating point + * registers + * + * Returned Value: + * None + * + ************************************************************************************/ + + .thumb_func + .type up_savefpu, function +up_savefpu: + + add r1, r0, #(4*REG_S0) /* R1=Address of FP register storage */ + vmov r2, r3, d0 /* r2, r3 = d0 */ + str r2, [r1], #4 /* Save S0 and S1 values */ + str r3, [r1], #4 + vmov r2, r3, d1 /* r2, r3 = d1 */ + str r2, [r1], #4 /* Save S2 and S3 values */ + str r3, [r1], #4 + vmov r2, r3, d2 /* r2, r3 = d2 */ + str r2, [r1], #4 /* Save S4 and S5 values */ + str r3, [r1], #4 + vmov r2, r3, d3 /* r2, r3 = d3 */ + str r2, [r1], #4 /* Save S6 and S7 values */ + str r3, [r1], #4 + vmov r2, r3, d4 /* r2, r3 = d4 */ + str r2, [r1], #4 /* Save S8 and S9 values */ + str r3, [r1], #4 + vmov r2, r3, d5 /* r2, r3 = d5 */ + str r2, [r1], #4 /* Save S10 and S11 values */ + str r3, [r1], #4 + vmov r2, r3, d6 /* r2, r3 = d6 */ + str r2, [r1], #4 /* Save S12 and S13 values */ + str r3, [r1], #4 + vmov r2, r3, d7 /* r2, r3 = d7 */ + str r2, [r1], #4 /* Save S14 and S15 values */ + str r3, [r1], #4 + vmov r2, r3, d8 /* r2, r3 = d8 */ + str r2, [r1], #4 /* Save S16 and S17 values */ + str r3, [r1], #4 + vmov r2, r3, d9 /* r2, r3 = d9 */ + str r2, [r1], #4 /* Save S18 and S19 values */ + str r3, [r1], #4 + vmov r2, r3, d10 /* r2, r3 = d10 */ + str r2, [r1], #4 /* Save S20 and S21 values */ + str r3, [r1], #4 + vmov r2, r3, d11 /* r2, r3 = d11 */ + str r2, [r1], #4 /* Save S22 and S23 values */ + str r3, [r1], #4 + vmov r2, r3, d12 /* r2, r3 = d12 */ + str r2, [r1], #4 /* Save S24 and S25 values */ + str r3, [r1], #4 + vmov r2, r3, d13 /* r2, r3 = d13 */ + str r2, [r1], #4 /* Save S26 and S27 values */ + str r3, [r1], #4 + vmov r2, r3, d14 /* r2, r3 = d14 */ + str r2, [r1], #4 /* Save S28 and S29 values */ + str r3, [r1], #4 + vmov r2, r3, d15 /* r2, r3 = d15 */ + str r2, [r1], #4 /* Save S30 and S31 values */ + str r3, [r1], #4 + + /* The gnu assembler doesn't support all the new UAL mnemonics. + * Use the old FMRX and FMXR names instead of 'vmrx r2, fpscr' + */ + + fmrx r2, fpscr, /* Fetch the FPCSR */ + str r2, [r1], #4 /* Save the floating point control and status register */ + bx lr + + .size up_savefpu, .-up_savefpu + +/************************************************************************************ + * Name: up_restorefpu + * + * Description: + * Given the pointer to a register save area (in R0), restore the state of the + * floating point registers. + * + * C Function Prototype: + * void up_restorefpu(const uint32_t *regs); + * + * Input Parameters: + * regs - A pointer to the register save area containing the floating point + * registers + * + * Returned Value: + * None + * + ************************************************************************************/ + + .thumb_func + .type up_restorefpu, function +up_restorefpu: + + add r1, r0, #(4*REG_S0) /* R1=Address of FP register storage */ + ldr r2, [r1], #4 /* Fetch S0 and S1 values */ + ldr r3, [r1], #4 + vmov d0, r2, r3 /* Save as d0 */ + ldr r2, [r1], #4 /* Fetch S2 and S3 values */ + ldr r3, [r1], #4 + vmov d1, r2, r3 /* Save as d1 */ + ldr r2, [r1], #4 /* Fetch S4 and S5 values */ + ldr r3, [r1], #4 + vmov d2, r2, r3 /* Save as d2 */ + ldr r2, [r1], #4 /* Fetch S6 and S7 values */ + ldr r3, [r1], #4 + vmov d3, r2, r3 /* Save as d3 */ + ldr r2, [r1], #4 /* Fetch S8 and S9 values */ + ldr r3, [r1], #4 + vmov d4, r2, r3 /* Save as d4 */ + ldr r2, [r1], #4 /* Fetch S10 and S11 values */ + ldr r3, [r1], #4 + vmov d5, r2, r3 /* Save as d5 */ + ldr r2, [r1], #4 /* Fetch S12 and S13 values */ + ldr r3, [r1], #4 + vmov d6, r2, r3 /* Save as d6 */ + ldr r2, [r1], #4 /* Fetch S14 and S15 values */ + ldr r3, [r1], #4 + vmov d7, r2, r3 /* Save as d7 */ + ldr r2, [r1], #4 /* Fetch S16 and S17 values */ + ldr r3, [r1], #4 + vmov d8, r2, r3 /* Save as d8 */ + ldr r2, [r1], #4 /* Fetch S18 and S19 values */ + ldr r3, [r1], #4 + vmov d9, r2, r3 /* Save as d9 */ + ldr r2, [r1], #4 /* Fetch S20 and S21 values */ + ldr r3, [r1], #4 + vmov d10, r2, r3 /* Save as d10 */ + ldr r2, [r1], #4 /* Fetch S22 and S23 values */ + ldr r3, [r1], #4 + vmov d11, r2, r3 /* Save as d11 */ + ldr r2, [r1], #4 /* Fetch S24 and S25 values */ + ldr r3, [r1], #4 + vmov d12, r2, r3 /* Save as d12 */ + ldr r2, [r1], #4 /* Fetch S26 and S27 values */ + ldr r3, [r1], #4 + vmov d13, r2, r3 /* Save as d13 */ + ldr r2, [r1], #4 /* Fetch S28 and S29 values */ + ldr r3, [r1], #4 + vmov d14, r2, r3 /* Save as d14 */ + ldr r2, [r1], #4 /* Fetch S30 and S31 values */ + ldr r3, [r1], #4 + vmov d15, r2, r3 /* Save as d15 */ + + /* The gnu assembler doesn't support all the new UAL mnemonics. + * Use the old FMRX and FMXR names instead of 'vmsr fpscr, r2' + */ + + ldr r2, [r1], #4 /* Fetch the floating point control and status register */ + fmxr fpscr, r2 /* Restore the FPCSR */ + bx lr + + .size up_restorefpu, .-up_restorefpu + .end + diff --git a/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S b/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S index 7795cd23d..3ce51c9cd 100755 --- a/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S +++ b/nuttx/arch/arm/src/armv7-m/up_fullcontextrestore.S @@ -2,7 +2,7 @@ * arch/arm/src/armv7-m/up_fullcontextrestore.S * * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/arch/arm/src/armv7-m/up_svcall.c b/nuttx/arch/arm/src/armv7-m/up_svcall.c index 248f1fb48..85430c0ad 100644 --- a/nuttx/arch/arm/src/armv7-m/up_svcall.c +++ b/nuttx/arch/arm/src/armv7-m/up_svcall.c @@ -272,6 +272,9 @@ int up_svcall(int irq, FAR void *context) { DEBUGASSERT(regs[REG_R1] != 0); memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE); +#ifdef CONFIG_ARCH_FPU + up_savefpu((uint32_t*)regs[REG_R1]); +#endif } break; diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h index a22855ba7..c90f49a3d 100644 --- a/nuttx/arch/arm/src/common/up_internal.h +++ b/nuttx/arch/arm/src/common/up_internal.h @@ -2,7 +2,7 @@ * common/up_internal.h * * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -76,14 +76,23 @@ # define CONFIG_ARCH_INTERRUPTSTACK 0 #endif -/* Macros to handle saving and restore interrupt state. In the current ARM +/* Macros to handle saving and restoring interrupt state. In the current ARM * model, the state is always copied to and from the stack and TCB. In the * Cortex-M3 model, the state is copied from the stack to the TCB, but only * a referenced is passed to get the state from the TCB. */ #if defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4) -# define up_savestate(regs) up_copystate(regs, (uint32_t*)current_regs) +# ifdef CONFIG_ARCH_FPU +# define up_savestate(regs) \ + do { \ + up_copystate(regs, (uint32_t*)current_regs); \ + up_savefpu(regs); \ + } \ + while (0) +# else +# define up_savestate(regs) up_copystate(regs, (uint32_t*)current_regs) +# endif # define up_restorestate(regs) (current_regs = regs) #else # define up_savestate(regs) up_copystate(regs, (uint32_t*)current_regs) @@ -240,6 +249,16 @@ extern void up_vectoraddrexcptn(void); extern void up_vectorirq(void); extern void up_vectorfiq(void); +/* Floating point unit ******************************************************/ + +#ifdef CONFIG_ARCH_FPU +extern void up_savefpu(uint32_t *regs); +extern void up_restorefpu(const uint32_t *regs); +#else +# define up_savefpu(regs) +# define up_restorefpu(regs) +#endif + /* System timer *************************************************************/ extern void up_timerinit(void); diff --git a/nuttx/arch/arm/src/stm32/Make.defs b/nuttx/arch/arm/src/stm32/Make.defs index b09ffd519..824d2fbfc 100644 --- a/nuttx/arch/arm/src/stm32/Make.defs +++ b/nuttx/arch/arm/src/stm32/Make.defs @@ -48,6 +48,10 @@ ifeq ($(CONFIG_DEBUG_STACK),y) CMN_CSRCS += up_checkstack.c endif +ifeq ($(CONFIG_ARCH_FPU),y) +CMN_ASRCS += up_fpu.S +endif + CHIP_ASRCS = CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c \ stm32_gpio.c stm32_exti.c stm32_flash.c stm32_irq.c \ diff --git a/nuttx/arch/arm/src/stm32/stm32_start.c b/nuttx/arch/arm/src/stm32/stm32_start.c index 7209d3cb9..7ac7ac1f9 100644 --- a/nuttx/arch/arm/src/stm32/stm32_start.c +++ b/nuttx/arch/arm/src/stm32/stm32_start.c @@ -3,7 +3,7 @@ * arch/arm/src/chip/stm32_start.c * * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/arch/arm/src/stm32/stm32_vectors.S b/nuttx/arch/arm/src/stm32/stm32_vectors.S index 714244686..ee4220ccc 100644 --- a/nuttx/arch/arm/src/stm32/stm32_vectors.S +++ b/nuttx/arch/arm/src/stm32/stm32_vectors.S @@ -3,7 +3,7 @@ * arch/arm/src/chip/stm32_vectors.S * * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -254,7 +254,7 @@ stm32_common: * values to the stack. */ - add r1, r0, #SW_XCPT_SIZE /* R1=Address of HW save area in reg array */ + 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 */ ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */ stmdb r1!, {r4-r11} /* Store eight registers in HW save area */ @@ -263,6 +263,17 @@ stm32_common: #else ldmia r0, {r2-r11} /* Recover R4-R11 + 2 temp values */ #endif + + /* We may also need to restore FPU registers. This is not done in + * normal interrupt save/restore because the cost is prohibitive. This + * is only done when switching contexts. A consequence of this is that + * floating point operations may not be performed in interrupt handling + * logic. + */ + +#ifdef CONFIG_ARCH_FPU + bl up_restorefpu /* Restore the FPU registers */ +#endif b 2f /* Re-join common logic */ /* We are returning with no context switch. We simply need to "unwind" -- cgit v1.2.3