diff --git a/ChangeLog b/ChangeLog index b752b8ec347..2f83184f639 100644 --- a/ChangeLog +++ b/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/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html index 7d190a14620..f4c699541f2 100644 --- a/Documentation/NuttxPortingGuide.html +++ b/Documentation/NuttxPortingGuide.html @@ -5114,7 +5114,12 @@ build 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.
diff --git a/arch/arm/src/common/up_createstack.c b/arch/arm/src/common/up_createstack.c
index 0d78d9ce9d9..068924b4b60 100644
--- a/arch/arm/src/common/up_createstack.c
+++ b/arch/arm/src/common/up_createstack.c
@@ -51,6 +51,33 @@
#include "up_arch.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
****************************************************************************/
@@ -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 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.
- */
+ /* 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;
+ 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 &= ~3;
- size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
+ top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
- /* 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;
- tcb->adj_stack_size = size_of_stack;
+ size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
- /* If stack debug is enabled, then fill the stack with a
- * recognizable value that we can use later to test for high
- * water marks.
- */
+ /* Save the adjusted stack values in the _TCB */
+
+ 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/arch/arm/src/common/up_usestack.c b/arch/arm/src/common/up_usestack.c
index 822f051689f..f46be0cc900 100644
--- a/arch/arm/src/common/up_usestack.c
+++ b/arch/arm/src/common/up_usestack.c
@@ -49,6 +49,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/configs/README.txt b/configs/README.txt
index f19fa28eea5..46b41d1aba7 100644
--- a/configs/README.txt
+++ b/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