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
This commit is contained in:
patacongo 2011-11-11 14:06:10 +00:00
parent f7642cf1cd
commit 7ea157b328
5 changed files with 121 additions and 43 deletions

View File

@ -2194,4 +2194,7 @@
support a file system (such as NXFFS). (Contributed by Hal Glenn). support a file system (such as NXFFS). (Contributed by Hal Glenn).
* include/nuttx/rgbcolors.h: More fixes to RGB color conversion * include/nuttx/rgbcolors.h: More fixes to RGB color conversion
macros. 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.

View File

@ -5114,7 +5114,12 @@ build
some functions into RAM, either for better performance or for errata workarounds. some functions into RAM, either for better performance or for errata workarounds.
</li> </li>
<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>
<li> <li>
<code>CONFIG_IDLETHREAD_STACKSIZE</code>: The size of the initial stack. <code>CONFIG_IDLETHREAD_STACKSIZE</code>: The size of the initial stack.

View File

@ -51,6 +51,33 @@
#include "up_arch.h" #include "up_arch.h"
#include "up_internal.h" #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 * Private Types
****************************************************************************/ ****************************************************************************/
@ -110,54 +137,60 @@ int up_create_stack(_TCB *tcb, size_t stack_size)
tcb->stack_alloc_ptr = NULL; tcb->stack_alloc_ptr = NULL;
} }
if (!tcb->stack_alloc_ptr) if (!tcb->stack_alloc_ptr)
{ {
#ifdef CONFIG_DEBUG #ifdef CONFIG_DEBUG
tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size); tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size);
#else #else
tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size); tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size);
#endif #endif
} }
if (tcb->stack_alloc_ptr) if (tcb->stack_alloc_ptr)
{ {
size_t top_of_stack; size_t top_of_stack;
size_t size_of_stack; size_t size_of_stack;
/* The ARM uses a push-down stack: the stack grows /* The ARM uses a push-down stack: the stack grows toward lower
* toward loweraddresses in memory. The stack pointer * addresses in memory. The stack pointer register, points to
* register, points to the lowest, valid work address * the lowest, valid work address (the "top" of the stack). Items
* (the "top" of the stack). Items on the stack are * on the stack are referenced as positive word offsets from sp.
* 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 at word (4 byte) /* The ARM stack must be aligned; 4 byte alignment for OABI and
* boundaries. If necessary top_of_stack must be rounded * 8-byte alignment for EABI. If necessary top_of_stack must be
* down to the next boundary * rounded down to the next boundary
*/ */
top_of_stack &= ~3; top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
/* Save the adjusted stack values in the _TCB */ /* 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.
*/
tcb->adj_stack_ptr = (uint32_t*)top_of_stack; size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
tcb->adj_stack_size = size_of_stack;
/* If stack debug is enabled, then fill the stack with a /* Save the adjusted stack values in the _TCB */
* 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) #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 #endif
up_ledon(LED_STACKCREATED); up_ledon(LED_STACKCREATED);
return OK; return OK;
} }
return ERROR; return ERROR;
} }

View File

@ -49,6 +49,33 @@
#include "up_internal.h" #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 * Private Types
****************************************************************************/ ****************************************************************************/
@ -96,21 +123,27 @@ int up_use_stack(_TCB *tcb, void *stack, size_t stack_size)
tcb->stack_alloc_ptr = stack; tcb->stack_alloc_ptr = stack;
/* The ARM uses a push-down stack: the stack grows /* The ARM uses a push-down stack: the stack grows toward lower addresses
* toward loweraddresses in memory. The stack pointer * in memory. The stack pointer register, points to the lowest, valid
* register, points to the lowest, valid work address * work address (the "top" of the stack). Items on the stack are
* (the "top" of the stack). Items on the stack are
* referenced as positive word offsets from sp. * 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 at word (4 byte) /* The ARM stack must be aligned; 4 byte alignment for OABI and 8-byte
* boundaries. If necessary top_of_stack must be rounded * alignment for EABI. If necessary top_of_stack must be rounded down
* down to the next boundary * 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; size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
/* Save the adjusted stack values in the _TCB */ /* Save the adjusted stack values in the _TCB */

View File

@ -1148,7 +1148,11 @@ defconfig -- This is a configuration file similar to the Linux
but copy themselves entirely into RAM for better performance. but copy themselves entirely into RAM for better performance.
CONFIG_BOOT_RAMFUNCS - Other configurations may copy just some functions CONFIG_BOOT_RAMFUNCS - Other configurations may copy just some functions
into RAM, either for better performance or for errata workarounds. 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. CONFIG_IDLETHREAD_STACKSIZE - The size of the initial stack.
This is the thread that (1) performs the inital boot of the system up 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 to the point where user_start() is spawned, and (2) there after is the