diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-11-11 14:06:10 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-11-11 14:06:10 +0000 |
commit | b30b365353a28dc7cc06afe13e3d1ab3f5a3b2b2 (patch) | |
tree | 026ea8a64f4cf0143b897addc8083698d5898e3d /nuttx | |
parent | f0a1251a7b4c2e9dee486f95db2c6e87a06274bd (diff) | |
download | px4-nuttx-b30b365353a28dc7cc06afe13e3d1ab3f5a3b2b2.tar.gz px4-nuttx-b30b365353a28dc7cc06afe13e3d1ab3f5a3b2b2.tar.bz2 px4-nuttx-b30b365353a28dc7cc06afe13e3d1ab3f5a3b2b2.zip |
Fix stack alignment for EABI floating point
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4089 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/ChangeLog | 3 | ||||
-rw-r--r-- | nuttx/Documentation/NuttxPortingGuide.html | 7 | ||||
-rw-r--r-- | nuttx/arch/arm/src/common/up_createstack.c | 99 | ||||
-rw-r--r-- | nuttx/arch/arm/src/common/up_usestack.c | 49 | ||||
-rw-r--r-- | nuttx/configs/README.txt | 6 |
5 files changed, 121 insertions, 43 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index b752b8ec3..2f83184f6 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -2194,4 +2194,7 @@ support a file system (such as NXFFS). (Contributed by Hal Glenn). * include/nuttx/rgbcolors.h: More fixes to RGB color conversion macros. + * arch/arm/src/common/up_createstack.c and up_usestack.c: For ARM EABI + the stack must be aligned to 8-byte boundaries. This is necessary for + passing aligned floating point values under EABI. diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index 7d190a146..f4c699541 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -5114,7 +5114,12 @@ build some functions into RAM, either for better performance or for errata workarounds. </li> <li> - <code>CONFIG_STACK_POINTER</code>: The initial stack pointer + <code>CONFIG_STACK_POINTER</code>: The initial stack pointer (may not be supported + in all architectures). + </li> + <li> + <code>CONFIG_STACK_ALIGNMENT</code>: Set if the your application has specific + stack alignment requirements (may not be supported in all architectures). </li> <li> <code>CONFIG_IDLETHREAD_STACKSIZE</code>: The size of the initial stack. diff --git a/nuttx/arch/arm/src/common/up_createstack.c b/nuttx/arch/arm/src/common/up_createstack.c index 0d78d9ce9..068924b4b 100644 --- a/nuttx/arch/arm/src/common/up_createstack.c +++ b/nuttx/arch/arm/src/common/up_createstack.c @@ -52,6 +52,33 @@ #include "up_internal.h" /**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* 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 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** * Private Types ****************************************************************************/ @@ -110,54 +137,60 @@ int up_create_stack(_TCB *tcb, size_t stack_size) tcb->stack_alloc_ptr = NULL; } - if (!tcb->stack_alloc_ptr) - { + if (!tcb->stack_alloc_ptr) + { #ifdef CONFIG_DEBUG - tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size); #endif - } + } - if (tcb->stack_alloc_ptr) - { - size_t top_of_stack; - size_t size_of_stack; + if (tcb->stack_alloc_ptr) + { + size_t top_of_stack; + size_t size_of_stack; + + /* The ARM uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to + * the lowest, valid work address (the "top" of the stack). Items + * on the stack are referenced as positive word offsets from sp. + */ - /* The ARM uses a push-down stack: the stack grows - * toward loweraddresses in memory. The stack pointer - * register, points to the lowest, valid work address - * (the "top" of the stack). Items on the stack are - * referenced as positive word offsets from sp. - */ + top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; - top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; + /* The ARM stack must be aligned; 4 byte alignment for OABI and + * 8-byte alignment for EABI. If necessary top_of_stack must be + * rounded down to the next boundary + */ - /* The ARM stack must be aligned at word (4 byte) - * boundaries. If necessary top_of_stack must be rounded - * down to the next boundary - */ + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); - top_of_stack &= ~3; - size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; + /* The size of the stack in bytes is then the difference between + * the top and the bottom of the stack (+4 because if the top + * is the same as the bottom, then the size is one 32-bit element). + * The size need not be aligned. + */ - /* Save the adjusted stack values in the _TCB */ + size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; - tcb->adj_stack_ptr = (uint32_t*)top_of_stack; - tcb->adj_stack_size = size_of_stack; + /* Save the adjusted stack values in the _TCB */ - /* If stack debug is enabled, then fill the stack with a - * recognizable value that we can use later to test for high - * water marks. - */ + tcb->adj_stack_ptr = (uint32_t*)top_of_stack; + tcb->adj_stack_size = size_of_stack; + + /* If stack debug is enabled, then fill the stack with a + * recognizable value that we can use later to test for high + * water marks. + */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) - memset32(tcb->stack_alloc_ptr, 0xDEADBEEF, tcb->adj_stack_size/4); + memset32(tcb->stack_alloc_ptr, 0xDEADBEEF, tcb->adj_stack_size/4); #endif - up_ledon(LED_STACKCREATED); - return OK; - } + up_ledon(LED_STACKCREATED); + return OK; + } return ERROR; } diff --git a/nuttx/arch/arm/src/common/up_usestack.c b/nuttx/arch/arm/src/common/up_usestack.c index 822f05168..f46be0cc9 100644 --- a/nuttx/arch/arm/src/common/up_usestack.c +++ b/nuttx/arch/arm/src/common/up_usestack.c @@ -50,6 +50,33 @@ #include "up_internal.h" /**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* 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 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (CONFIG_STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** * Private Types ****************************************************************************/ @@ -96,21 +123,27 @@ int up_use_stack(_TCB *tcb, void *stack, size_t stack_size) tcb->stack_alloc_ptr = stack; - /* The ARM uses a push-down stack: the stack grows - * toward loweraddresses in memory. The stack pointer - * register, points to the lowest, valid work address - * (the "top" of the stack). Items on the stack are + /* The ARM uses a push-down stack: the stack grows toward lower addresses + * in memory. The stack pointer register, points to the lowest, valid + * work address (the "top" of the stack). Items on the stack are * referenced as positive word offsets from sp. */ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; - /* The ARM stack must be aligned at word (4 byte) - * boundaries. If necessary top_of_stack must be rounded - * down to the next boundary + /* The ARM stack must be aligned; 4 byte alignment for OABI and 8-byte + * alignment for EABI. If necessary top_of_stack must be rounded down + * to the next boundary + */ + + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); + + /* The size of the stack in bytes is then the difference between + * the top and the bottom of the stack (+4 because if the top + * is the same as the bottom, then the size is one 32-bit element). + * The size need not be aligned. */ - top_of_stack &= ~3; size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; /* Save the adjusted stack values in the _TCB */ diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt index f19fa28ee..46b41d1ab 100644 --- a/nuttx/configs/README.txt +++ b/nuttx/configs/README.txt @@ -1148,7 +1148,11 @@ defconfig -- This is a configuration file similar to the Linux but copy themselves entirely into RAM for better performance. CONFIG_BOOT_RAMFUNCS - Other configurations may copy just some functions into RAM, either for better performance or for errata workarounds. - CONFIG_STACK_POINTER - The initial stack pointer + CONFIG_STACK_POINTER - The initial stack pointer (may not be supported + in all architectures). + CONFIG_STACK_ALIGNMENT - Set if the your application has specific + stack alignment requirements (may not be supported + in all architectures). CONFIG_IDLETHREAD_STACKSIZE - The size of the initial stack. This is the thread that (1) performs the inital boot of the system up to the point where user_start() is spawned, and (2) there after is the |