diff options
author | px4dev <px4@purgatory.org> | 2013-01-23 18:58:19 -0800 |
---|---|---|
committer | px4dev <px4@purgatory.org> | 2013-01-23 18:58:19 -0800 |
commit | dc88dd0abb440b070e87337a7da6fd7a4c39311c (patch) | |
tree | 00260c9b8b5d6f20983f1ffbe211c39c87bd2b85 /nuttx/arch | |
parent | d8a013f8720e81afb637b8206fbe521ccb43ac8f (diff) | |
parent | 1ce1d4460b1c7884490118ea356bf61ffbd31163 (diff) | |
download | px4-firmware-dc88dd0abb440b070e87337a7da6fd7a4c39311c.tar.gz px4-firmware-dc88dd0abb440b070e87337a7da6fd7a4c39311c.tar.bz2 px4-firmware-dc88dd0abb440b070e87337a7da6fd7a4c39311c.zip |
Merge branch 'master' into px4io-i2c
Diffstat (limited to 'nuttx/arch')
-rw-r--r-- | nuttx/arch/Kconfig | 23 | ||||
-rw-r--r-- | nuttx/arch/README.txt | 12 | ||||
-rw-r--r-- | nuttx/arch/arm/Kconfig | 11 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/Kconfig | 8 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/Toolchain.defs | 19 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/up_doirq.c | 8 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-m/vfork.S | 142 | ||||
-rw-r--r-- | nuttx/arch/arm/src/common/up_internal.h | 4 | ||||
-rw-r--r-- | nuttx/arch/arm/src/common/up_vfork.c | 233 | ||||
-rw-r--r-- | nuttx/arch/arm/src/common/up_vfork.h | 88 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/Make.defs | 9 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_flash.c | 37 |
12 files changed, 551 insertions, 43 deletions
diff --git a/nuttx/arch/Kconfig b/nuttx/arch/Kconfig index f19228143..d43137adb 100644 --- a/nuttx/arch/Kconfig +++ b/nuttx/arch/Kconfig @@ -16,6 +16,7 @@ config ARCH_8051 config ARCH_ARM bool "ARM" select ARCH_HAVE_INTERRUPTSTACK + select ARCH_HAVE_VFORK ---help--- The ARM architectures @@ -108,6 +109,10 @@ config ARCH_NOINTC bool default n +config ARCH_VECNOTIRQ + bool + default n + config ARCH_DMA bool default n @@ -124,6 +129,10 @@ config ADDRENV bool default n +config ARCH_HAVE_VFORK + bool + default n + config ARCH_STACKDUMP bool "Dump stack on assertions" default n @@ -136,6 +145,20 @@ config ENDIAN_BIG ---help--- Select if architecture operates using big-endian byte ordering. +config ARCH_HAVE_RAMFUNCS + bool + default n + +config ARCH_RAMFUNCS + bool "Copy functions to RAM on startup" + default n + depends on ARCH_HAVE_RAMFUNCS + ---help--- + Copy some functions to RAM at boot time. This is done in some + architectures to improve performance. In other cases, it is done + so that FLASH can be reconfigured while the MCU executes out of + SRAM. + comment "Board Settings" config BOARD_LOOPSPERMSEC diff --git a/nuttx/arch/README.txt b/nuttx/arch/README.txt index 67b99b255..14704aa76 100644 --- a/nuttx/arch/README.txt +++ b/nuttx/arch/README.txt @@ -170,12 +170,12 @@ arch/arm - ARM-based micro-controllers STATUS: This port has stalled because of development tool issues. Coding is complete on the basic port (timer, serial console, SPI). - arch/arm/include/lm3s and arch/arm/src/lm3s - These directories contain support for the Luminary LMS family, particularly - for the LM3S6918. The initial, release of this port was included in NuttX version - 0.4.6. The current port includes timer, serial console, Ethernet, SSI, and microSD - support. There are working configurations the NuttX OS test, to run the NuttShell - (NSH), the NuttX networking test, and the uIP web server. + arch/arm/include/lm and arch/arm/src/lm + These directories contain support for the Luminary LM3S/4F family. The + initial, release of this port was included in NuttX version 0.4.6. The + current port includes timer, serial console, Ethernet, SSI, and microSD + support. There are working configurations the NuttX OS test, to run the + NuttShell (NSH), the NuttX networking test, and the uIP web server. arch/arm/include/lpc214x and arch/arm/src/lpc214x These directories provide support for NXP LPC214x family of diff --git a/nuttx/arch/arm/Kconfig b/nuttx/arch/arm/Kconfig index 4fce8efbf..36343e319 100644 --- a/nuttx/arch/arm/Kconfig +++ b/nuttx/arch/arm/Kconfig @@ -47,12 +47,13 @@ config ARCH_CHIP_KINETIS select ARCH_CORTEXM4 select ARCH_HAVE_MPU select ARCH_IRQPRIO + select ARCH_HAVE_RAMFUNCS + select ARCH_RAMFUNCS ---help--- Freescale Kinetis Architectures (ARM Cortex-M4) -config ARCH_CHIP_LM3S +config ARCH_CHIP_LM bool "TI Stellaris" - select ARCH_CORTEXM3 select ARCH_HAVE_MPU select ARCH_IRQPRIO ---help--- @@ -151,7 +152,7 @@ config ARCH_CHIP default "dm320" if ARCH_CHIP_DM320 default "imx" if ARCH_CHIP_IMX default "kinetis" if ARCH_CHIP_KINETIS - default "lm3s" if ARCH_CHIP_LM3S + default "lm" if ARCH_CHIP_LM default "lpc17xx" if ARCH_CHIP_LPC17XX default "lpc214x" if ARCH_CHIP_LPC214X default "lpc2378" if ARCH_CHIP_LPC2378 @@ -274,8 +275,8 @@ endif if ARCH_CHIP_KINETIS source arch/arm/src/kinetis/Kconfig endif -if ARCH_CHIP_LM3S -source arch/arm/src/lm3s/Kconfig +if ARCH_CHIP_LM +source arch/arm/src/lm/Kconfig endif if ARCH_CHIP_LPC17XX source arch/arm/src/lpc17xx/Kconfig diff --git a/nuttx/arch/arm/src/armv7-m/Kconfig b/nuttx/arch/arm/src/armv7-m/Kconfig index dc5aa3915..a154a4c5c 100644 --- a/nuttx/arch/arm/src/armv7-m/Kconfig +++ b/nuttx/arch/arm/src/armv7-m/Kconfig @@ -49,3 +49,11 @@ config ARMV7M_TOOLCHAIN_RAISONANCE depends on HOST_WINDOWS endchoice + +config ARMV7M_OABI_TOOLCHAIN + bool "OABI (vs EABI)" + default y + depends on ARMV7M_TOOLCHAIN_BUILDROOT + ---help--- + Most of the older buildroot toolchains are OABI and are named arm-nuttx-elf- vs. arm-nuttx-eabi- + diff --git a/nuttx/arch/arm/src/armv7-m/Toolchain.defs b/nuttx/arch/arm/src/armv7-m/Toolchain.defs index e214ce8bd..45ee9e36c 100644 --- a/nuttx/arch/arm/src/armv7-m/Toolchain.defs +++ b/nuttx/arch/arm/src/armv7-m/Toolchain.defs @@ -53,7 +53,7 @@ ifeq ($(filter y, \ endif ifeq ($(filter y, \ $(CONFIG_KINETIS_BUILDROOT) \ - $(CONFIG_LM3S_BUILDROOT) \ + $(CONFIG_LM_BUILDROOT) \ $(CONFIG_LPC17_BUILDROOT) \ $(CONFIG_LPC43_BUILDROOT) \ $(CONFIG_SAM3U_BUILDROOT) \ @@ -77,7 +77,7 @@ ifeq ($(filter y, \ endif ifeq ($(filter y, \ $(CONFIG_KINETIS_CODESOURCERYL) \ - $(CONFIG_LM3S_CODESOURCERYL) \ + $(CONFIG_LM_CODESOURCERYL) \ $(CONFIG_LPC17_CODESOURCERYL) \ $(CONFIG_LPC43_CODESOURCERYL) \ $(CONFIG_SAM3U_CODESOURCERYL) \ @@ -88,7 +88,7 @@ ifeq ($(filter y, \ endif ifeq ($(filter y, \ $(CONFIG_KINETIS_CODESOURCERYW) \ - $(CONFIG_LM3S_CODESOURCERYW) \ + $(CONFIG_LM_CODESOURCERYW) \ $(CONFIG_LPC17_CODESOURCERYW) \ $(CONFIG_LPC43_CODESOURCERYW) \ $(CONFIG_SAM3U_CODESOURCERYW) \ @@ -99,7 +99,7 @@ ifeq ($(filter y, \ endif ifeq ($(filter y, \ $(CONFIG_KINETIS_DEVKITARM) \ - $(CONFIG_LM3S_DEVKITARM) \ + $(CONFIG_LM_DEVKITARM) \ $(CONFIG_LPC17_DEVKITARM) \ $(CONFIG_LPC43_DEVKITARM) \ $(CONFIG_SAM3U_DEVKITARM) \ @@ -160,14 +160,15 @@ endif # NuttX buildroot under Linux or Cygwin ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),BUILDROOT) - # OABI - # CROSSDEV = arm-nuttx-elf- - # ARCROSSDEV = arm-nuttx-elf- - # ARCHCPUFLAGS = -mtune=cortex-m3 -march=armv7-m -mfloat-abi=soft - # EABI +ifeq ($(CONFIG_ARMV7M_OABI_TOOLCHAIN),y) + CROSSDEV = arm-nuttx-elf- + ARCROSSDEV = arm-nuttx-elf- + ARCHCPUFLAGS = -mtune=cortex-m3 -march=armv7-m -mfloat-abi=soft +else CROSSDEV = arm-nuttx-eabi- ARCROSSDEV = arm-nuttx-eabi- ARCHCPUFLAGS = -mcpu=cortex-m3 -mthumb -mfloat-abi=soft +endif MAXOPTIMIZATION = -Os endif diff --git a/nuttx/arch/arm/src/armv7-m/up_doirq.c b/nuttx/arch/arm/src/armv7-m/up_doirq.c index 375054fba..6063f9ca1 100644 --- a/nuttx/arch/arm/src/armv7-m/up_doirq.c +++ b/nuttx/arch/arm/src/armv7-m/up_doirq.c @@ -79,9 +79,11 @@ uint32_t *up_doirq(int irq, uint32_t *regs) uint32_t *savestate; /* Nested interrupts are not supported in this implementation. If you want - * implemented nested interrupts, you would have to (1) change the way that - * current regs is handled and (2) the design associated with - * CONFIG_ARCH_INTERRUPTSTACK. + * to implement nested interrupts, you would have to (1) change the way that + * current_regs is handled and (2) the design associated with + * CONFIG_ARCH_INTERRUPTSTACK. The savestate variable will not work for + * that purpose as implemented here because only the outermost nested + * interrupt can result in a context switch (it can probably be deleted). */ /* Current regs non-zero indicates that we are processing an interrupt; diff --git a/nuttx/arch/arm/src/armv7-m/vfork.S b/nuttx/arch/arm/src/armv7-m/vfork.S new file mode 100644 index 000000000..f36ff23aa --- /dev/null +++ b/nuttx/arch/arm/src/armv7-m/vfork.S @@ -0,0 +1,142 @@ +/************************************************************************************ + * arch/arm/src/armv7-m/vfork.S + * + * Copyright (C) 2013 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 + * 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 "up_vfork.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Global Symbols + ************************************************************************************/ + + .syntax unified + .thumb + .file "vfork.S" + .globl up_vfork + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: vfork + * + * Description: + * The vfork() function has the same effect as fork(), except that the behavior is + * undefined if the process created by vfork() either modifies any data other than + * a variable of type pid_t used to store the return value from vfork(), or returns + * from the function in which vfork() was called, or calls any other function before + * successfully calling _exit() or one of the exec family of functions. + * + * This thin layer implements vfork by simply calling up_vfork() with the vfork() + * context as an argument. The overall sequence is: + * + * 1) User code calls vfork(). vfork() collects context information and + * transfers control up up_vfork(). + * 2) up_vfork()and calls task_vforksetup(). + * 3) task_vforksetup() allocates and configures the child task's TCB. This + * consists of: + * - Allocation of the child task's TCB. + * - Initialization of file descriptors and streams + * - Configuration of environment variables + * - Setup the intput parameters for the task. + * - Initialization of the TCB (including call to up_initial_state() + * 4) up_vfork() provides any additional operating context. up_vfork must: + * - Allocate and initialize the stack + * - Initialize special values in any CPU registers that were not + * already configured by up_initial_state() + * 5) up_vfork() then calls task_vforkstart() + * 6) task_vforkstart() then executes the child thread. + * + * Input Paremeters: + * None + * + * Return: + * Upon successful completion, vfork() returns 0 to the child process and returns + * the process ID of the child process to the parent process. Otherwise, -1 is + * returned to the parent, no child process is created, and errno is set to + * indicate the error. + * + ************************************************************************************/ + + .thumb_func + .globl vfork + .type vfork, function +vfork: + /* Create a stack frame */ + + mov r0, sp /* Save the value of the stack on entry */ + sub sp, sp, #VFORK_SIZEOF /* Allocate the structure on the stack */ + + /* CPU registers */ + /* Save the volatile registers */ + + str r4, [sp, #VFORK_R4_OFFSET] + str r5, [sp, #VFORK_R5_OFFSET] + str r6, [sp, #VFORK_R6_OFFSET] + str r7, [sp, #VFORK_R7_OFFSET] + str r8, [sp, #VFORK_R8_OFFSET] + str r9, [sp, #VFORK_R9_OFFSET] + str r10, [sp, #VFORK_R10_OFFSET] + + /* Save the frame pointer, stack pointer, and return address */ + + str fp, [sp, #VFORK_FP_OFFSET] + str r0, [sp, #VFORK_SP_OFFSET] + str lr, [sp, #VFORK_LR_OFFSET] + + /* Floating point registers (not yet) */ + + /* Then, call up_vfork(), passing it a pointer to the stack structure */ + + mov r0, sp + bl up_vfork + + /* Release the stack data and return the value returned by up_vfork */ + + ldr lr, [sp, #VFORK_LR_OFFSET] + add sp, sp, #VFORK_SIZEOF + bx lr + .size vfork, .-vfork + .end + diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h index 0d3c5b1f2..55071345f 100644 --- a/nuttx/arch/arm/src/common/up_internal.h +++ b/nuttx/arch/arm/src/common/up_internal.h @@ -188,7 +188,7 @@ extern uint32_t _ebss; /* End+1 of .bss */ * will create a function named foo that will execute from RAM. */ -#ifdef CONFIG_BOOT_RAMFUNCS +#ifdef CONFIG_ARCH_RAMFUNCS # define __ramfunc__ __attribute__ ((section(".ramfunc"))) @@ -204,7 +204,7 @@ extern const uint32_t _framfuncs; /* Copy source address in FLASH */ extern uint32_t _sramfuncs; /* Copy destination start address in RAM */ extern uint32_t _eramfuncs; /* Copy destination start address in RAM */ -#endif /* CONFIG_BOOT_RAMFUNCS */ +#endif /* CONFIG_ARCH_RAMFUNCS */ #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/nuttx/arch/arm/src/common/up_vfork.c b/nuttx/arch/arm/src/common/up_vfork.c new file mode 100644 index 000000000..3b653e317 --- /dev/null +++ b/nuttx/arch/arm/src/common/up_vfork.c @@ -0,0 +1,233 @@ +/**************************************************************************** + * arch/arm/src/common/up_vfork.c + * + * Copyright (C) 2013 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 + * 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 <stdint.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#include <debug.h> + +#include <nuttx/sched.h> +#include <nuttx/arch.h> +#include <arch/irq.h> + +#include "up_vfork.h" +#include "os_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ARM requires at least a 4-byte stack alignment. For use with EABI and + * floating point, the stack must be aligned to 8-byte addresses. + */ + +#ifndef CONFIG_STACK_ALIGNMENT + +/* The symbol __ARM_EABI__ is defined by GCC if EABI is being used. If you + * are not using GCC, make sure that CONFIG_STACK_ALIGNMENT is set correctly! + */ + +# ifdef __ARM_EABI__ +# define CONFIG_STACK_ALIGNMENT 8 +# else +# define CONFIG_STACK_ALIGNMENT 4 +# endif +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_vfork + * + * Description: + * The vfork() function has the same effect as fork(), except that the + * behavior is undefined if the process created by vfork() either modifies + * any data other than a variable of type pid_t used to store the return + * value from vfork(), or returns from the function in which vfork() was + * called, or calls any other function before successfully calling _exit() + * or one of the exec family of functions. + * + * The overall sequence is: + * + * 1) User code calls vfork(). vfork() collects context information and + * transfers control up up_vfork(). + * 2) up_vfork()and calls task_vforksetup(). + * 3) task_vforksetup() allocates and configures the child task's TCB. This + * consists of: + * - Allocation of the child task's TCB. + * - Initialization of file descriptors and streams + * - Configuration of environment variables + * - Setup the intput parameters for the task. + * - Initialization of the TCB (including call to up_initial_state() + * 4) up_vfork() provides any additional operating context. up_vfork must: + * - Allocate and initialize the stack + * - Initialize special values in any CPU registers that were not + * already configured by up_initial_state() + * 5) up_vfork() then calls task_vforkstart() + * 6) task_vforkstart() then executes the child thread. + * + * task_vforkabort() may be called if an error occurs between steps 3 and 6. + * + * Input Paremeters: + * context - Caller context information saved by vfork() + * + * Return: + * Upon successful completion, vfork() returns 0 to the child process and + * returns the process ID of the child process to the parent process. + * Otherwise, -1 is returned to the parent, no child process is created, + * and errno is set to indicate the error. + * + ****************************************************************************/ + +pid_t up_vfork(const struct vfork_s *context) +{ + _TCB *parent = (FAR _TCB *)g_readytorun.head; + _TCB *child; + size_t stacksize; + uint32_t newsp; + uint32_t newfp; + uint32_t stackutil; + int ret; + + svdbg("r4:%08x r5:%08x r6:%08x r7:%08x\n", + context->r4, context->r5, context->r6, context->r7); + svdbg("r8:%08x r9:%08x r10:%08x\n", + context->r8, context->r9, context->r10); + svdbg("fp:%08x sp:%08x lr:%08x\n", + context->fp, context->sp, context->lr); + + /* Allocate and initialize a TCB for the child task. */ + + child = task_vforksetup((start_t)(context->lr & ~1)); + if (!child) + { + sdbg("task_vforksetup failed\n"); + return (pid_t)ERROR; + } + + svdbg("Parent=%p Child=%p\n", parent, child); + + /* Get the size of the parent task's stack. Due to alignment operations, + * the adjusted stack size may be smaller than the stack size originally + * requrested. + */ + + stacksize = parent->adj_stack_size + CONFIG_STACK_ALIGNMENT - 1; + + /* Allocate the stack for the TCB */ + + ret = up_create_stack(child, stacksize); + if (ret != OK) + { + sdbg("up_create_stack failed: %d\n", ret); + task_vforkabort(child, -ret); + return (pid_t)ERROR; + } + + /* How much of the parent's stack was utilized? The ARM uses + * a push-down stack so that the current stack pointer should + * be lower than the initial, adjusted stack pointer. The + * stack usage should be the difference between those two. + */ + + DEBUGASSERT((uint32_t)parent->adj_stack_ptr > context->sp); + stackutil = (uint32_t)parent->adj_stack_ptr - context->sp; + + svdbg("stacksize:%d stackutil:%d\n", stacksize, stackutil); + + /* Make some feeble effort to perserve the stack contents. This is + * feeble because the stack surely contains invalid pointers and other + * content that will not work in the child context. However, if the + * user follows all of the caveats of vfor() usage, even this feeble + * effort is overkill. + */ + + newsp = (uint32_t)child->adj_stack_ptr - stackutil; + memcpy((void *)newsp, (const void *)context->sp, stackutil); + + /* Was there a frame pointer in place before? */ + + if (context->fp <= (uint32_t)parent->adj_stack_ptr && + context->fp >= (uint32_t)parent->adj_stack_ptr - stacksize) + { + uint32_t frameutil = (uint32_t)parent->adj_stack_ptr - context->fp; + newfp = (uint32_t)child->adj_stack_ptr - frameutil; + } + else + { + newfp = context->fp; + } + + svdbg("Old stack base:%08x SP:%08x FP:%08x\n", + parent->adj_stack_ptr, context->sp, context->fp); + svdbg("New stack base:%08x SP:%08x FP:%08x\n", + child->adj_stack_ptr, newsp, newfp); + + /* Update the stack pointer, frame pointer, and volatile registers. When + * the child TCB was initialized, all of the values were set to zero. + * up_initial_state() altered a few values, but the return value in R0 + * should be cleared to zero, providing the indication to the newly started + * child thread. + */ + + child->xcp.regs[REG_R4] = context->r4; /* Volatile register r4 */ + child->xcp.regs[REG_R5] = context->r5; /* Volatile register r5 */ + child->xcp.regs[REG_R6] = context->r6; /* Volatile register r6 */ + child->xcp.regs[REG_R7] = context->r7; /* Volatile register r7 */ + child->xcp.regs[REG_R8] = context->r8; /* Volatile register r8 */ + child->xcp.regs[REG_R9] = context->r9; /* Volatile register r9 */ + child->xcp.regs[REG_R10] = context->r10; /* Volatile register r10 */ + child->xcp.regs[REG_FP] = newfp; /* Frame pointer */ + child->xcp.regs[REG_SP] = newsp; /* Stack pointer */ + + /* And, finally, start the child task. On a failure, task_vforkstart() + * will discard the TCB by calling task_vforkabort(). + */ + + return task_vforkstart(child); +} diff --git a/nuttx/arch/arm/src/common/up_vfork.h b/nuttx/arch/arm/src/common/up_vfork.h new file mode 100644 index 000000000..97edf9aaa --- /dev/null +++ b/nuttx/arch/arm/src/common/up_vfork.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * arch/arm/src/common/up_vfork.h + * + * Copyright (C) 2013 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 + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_ARM_VFORK_H +#define __ARCH_ARM_SRC_ARM_VFORK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define VFORK_R4_OFFSET (0*4) /* Volatile register r4 */ +#define VFORK_R5_OFFSET (1*4) /* Volatile register r5 */ +#define VFORK_R6_OFFSET (2*4) /* Volatile register r6 */ +#define VFORK_R7_OFFSET (3*4) /* Volatile register r7 */ +#define VFORK_R8_OFFSET (4*4) /* Volatile register r8 */ +#define VFORK_R9_OFFSET (5*4) /* Volatile register r9 */ +#define VFORK_R10_OFFSET (6*4) /* Volatile register r10 */ + +#define VFORK_FP_OFFSET (7*4) /* Frame pointer */ +#define VFORK_SP_OFFSET (8*4) /* Stack pointer*/ +#define VFORK_LR_OFFSET (9*4) /* Return address*/ + +#define VFORK_SIZEOF (10*4) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +struct vfork_s +{ + /* CPU registers */ + + uint32_t r4; /* Volatile register r4 */ + uint32_t r5; /* Volatile register r5 */ + uint32_t r6; /* Volatile register r6 */ + uint32_t r7; /* Volatile register r7 */ + uint32_t r8; /* Volatile register r8 */ + uint32_t r9; /* Volatile register r9 */ + uint32_t r10; /* Volatile register r10 */ + + uint32_t fp; /* Frame pointer */ + uint32_t sp; /* Stack pointer*/ + uint32_t lr; /* Return address*/ + + /* Floating point registers (not yet) */ +}; +#endif + +#endif /* __ARCH_ARM_SRC_ARM_VFORK_H */ diff --git a/nuttx/arch/arm/src/stm32/Make.defs b/nuttx/arch/arm/src/stm32/Make.defs index baa751c7d..940ff6517 100644 --- a/nuttx/arch/arm/src/stm32/Make.defs +++ b/nuttx/arch/arm/src/stm32/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # arch/arm/src/stm32/Make.defs # -# Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved. +# Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved. # Author: Gregory Nutt <gnutt@nuttx.org> # # Redistribution and use in source and binary forms, with or without @@ -39,15 +39,16 @@ else HEAD_ASRC = stm32_vectors.S endif -CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S +CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S \ + vfork.S CMN_CSRCS = up_assert.c up_blocktask.c up_copystate.c \ up_createstack.c up_mdelay.c up_udelay.c up_exit.c \ up_initialize.c up_initialstate.c up_interruptcontext.c \ up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c \ up_releasepending.c up_releasestack.c up_reprioritizertr.c \ up_schedulesigaction.c up_sigdeliver.c up_systemreset.c \ - up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c up_svcall.c \ - up_stackcheck.c + up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c \ + up_svcall.c up_stackcheck.c up_vfork.c ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y) CMN_ASRCS += up_exception.S diff --git a/nuttx/arch/arm/src/stm32/stm32_flash.c b/nuttx/arch/arm/src/stm32/stm32_flash.c index 83fcc6172..20b0cfe10 100644 --- a/nuttx/arch/arm/src/stm32/stm32_flash.c +++ b/nuttx/arch/arm/src/stm32/stm32_flash.c @@ -35,7 +35,7 @@ /* Provides standard flash access functions, to be used by the flash mtd driver. * The interface is defined in the include/nuttx/progmem.h - * + * * Requirements during write/erase operations on FLASH: * - HSI must be ON. * - Low Power Modes are not permitted during write/erase @@ -80,7 +80,7 @@ void stm32_flash_unlock(void) if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK) { /* Unlock sequence */ - + putreg32(FLASH_KEY1, STM32_FLASH_KEYR); putreg32(FLASH_KEY2, STM32_FLASH_KEYR); } @@ -112,6 +112,11 @@ uint16_t up_progmem_pagesize(uint16_t page) int up_progmem_getpage(uint32_t addr) { + if (addr >= STM32_FLASH_BASE) + { + addr -= STM32_FLASH_BASE; + } + if (addr >= STM32_FLASH_SIZE) { return -EFAULT; @@ -131,14 +136,14 @@ int up_progmem_erasepage(uint16_t page) } /* Get flash ready and begin erasing single page */ - + if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION)) { return -EPERM; } - + stm32_flash_unlock(); - + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER); putreg32(page * STM32_FLASH_PAGESIZE, STM32_FLASH_AR); modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT); @@ -146,10 +151,10 @@ int up_progmem_erasepage(uint16_t page) while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste(); modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0); - + /* Verify */ - - for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; + + for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; count; count-=4, addr += 4) { if (getreg32(addr) != 0xffffffff) @@ -173,8 +178,8 @@ int up_progmem_ispageerased(uint16_t page) } /* Verify */ - - for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; + + for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; count; count--, addr++) { if (getreg8(addr) != 0xff) @@ -200,6 +205,11 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count) /* Check for valid address range */ + if (addr >= STM32_FLASH_BASE) + { + addr -= STM32_FLASH_BASE; + } + if ((addr+count) >= STM32_FLASH_SIZE) { return -EFAULT; @@ -213,10 +223,10 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count) } stm32_flash_unlock(); - + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG); - - for (addr += STM32_FLASH_BASE; count; count--, hword++, addr+=2) + + for (addr += STM32_FLASH_BASE; count; count-=2, hword++, addr+=2) { /* Write half-word and wait to complete */ @@ -237,7 +247,6 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count) modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); return -EIO; } - } modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); |