summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-03-23 10:11:58 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-03-23 10:11:58 -0600
commitd15a9cedd177e357a1b6bd8adbfbedd73448906e (patch)
treebee64cfdfeccf84acf54db0e1334de370648b700
parent9acd7deb2a7d40d8134706cc0f9434375475abe1 (diff)
downloadpx4-nuttx-d15a9cedd177e357a1b6bd8adbfbedd73448906e.tar.gz
px4-nuttx-d15a9cedd177e357a1b6bd8adbfbedd73448906e.tar.bz2
px4-nuttx-d15a9cedd177e357a1b6bd8adbfbedd73448906e.zip
Add logic to check interrupt stack usage
-rw-r--r--nuttx/arch/arm/src/common/up_checkstack.c82
-rw-r--r--nuttx/arch/arm/src/common/up_initialize.c30
-rw-r--r--nuttx/arch/avr/src/avr/up_checkstack.c78
-rw-r--r--nuttx/arch/avr/src/common/up_initialize.c30
-rw-r--r--nuttx/include/nuttx/arch.h8
5 files changed, 194 insertions, 34 deletions
diff --git a/nuttx/arch/arm/src/common/up_checkstack.c b/nuttx/arch/arm/src/common/up_checkstack.c
index 9cf4c684f..02f95f7ba 100644
--- a/nuttx/arch/arm/src/common/up_checkstack.c
+++ b/nuttx/arch/arm/src/common/up_checkstack.c
@@ -44,27 +44,31 @@
#include <sched.h>
#include <debug.h>
-#include <nuttx/arch.h>
+#include <nuttx/arch.h>
#include "os_internal.h"
#include "up_internal.h"
-#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
-
/****************************************************************************
- * Private Types
+ * Pre-processor Definitions
****************************************************************************/
+#if !defined(CONFIG_DEBUG)
+# undef CONFIG_DEBUG_STACK
+#endif
+
+#if defined(CONFIG_DEBUG_STACK)
+
/****************************************************************************
- * Private Function Prototypes
+ * Public Data
****************************************************************************/
/****************************************************************************
- * Global Functions
+ * Private Function Prototypes
****************************************************************************/
/****************************************************************************
- * Name: up_check_stack
+ * Name: do_stackcheck
*
* Description:
* Determine (approximately) how much stack has been used be searching the
@@ -72,25 +76,34 @@
* stack that clobbered some recognizable marker in the stack memory.
*
* Input Parameters:
- * None
+ * alloc - Allocation base address of the stack
+ * size - The size of the stack in bytes
*
* Returned value:
* The estimated amount of stack space used.
*
****************************************************************************/
-size_t up_check_tcbstack(FAR struct tcb_s *tcb)
+size_t do_stackcheck(uintptr_t alloc, size_t size)
{
+ FAR uintptr_t start;
+ FAR uintptr_t end;
FAR uint32_t *ptr;
size_t mark;
+ /* Get aligned addresses and adjusted sizes */
+
+ start = alloc & ~3;
+ end = (alloc + size + 3) & ~3;
+ size = end - start;
+
/* The ARM uses a push-down stack: the stack grows toward lower addresses
* in memory. We need to start at the lowest address in the stack memory
* allocation and search to higher addresses. The first word we encounter
* that does not have the magic value is the high water mark.
*/
- for (ptr = (FAR uint32_t *)tcb->stack_alloc_ptr, mark = tcb->adj_stack_size/4;
+ for (ptr = (FAR uint32_t *)start, mark = (size >> 2);
*ptr == STACK_COLOR && mark > 0;
ptr++, mark--);
@@ -105,12 +118,12 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb)
*/
#if 0
- if (mark + 16 > tcb->adj_stack_size/4)
+ if (mark + 16 > nwords)
{
int i, j;
- ptr = (FAR uint32_t *)tcb->stack_alloc_ptr;
- for (i = 0; i < tcb->adj_stack_size; i += 4*64)
+ ptr = (FAR uint32_t *)start;
+ for (i = 0; i < size; i += 4*64)
{
for (j = 0; j < 64; j++)
{
@@ -123,8 +136,10 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb)
{
ch = 'X';
}
+
up_putc(ch);
}
+
up_putc('\n');
}
}
@@ -132,7 +147,32 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb)
/* Return our guess about how much stack space was used */
- return mark*4;
+ return mark << 2;
+}
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_check_stack and friends
+ *
+ * Description:
+ * Determine (approximately) how much stack has been used be searching the
+ * stack memory for a high water mark. That is, the deepest level of the
+ * stack that clobbered some recognizable marker in the stack memory.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned value:
+ * The estimated amount of stack space used.
+ *
+ ****************************************************************************/
+
+size_t up_check_tcbstack(FAR struct tcb_s *tcb)
+{
+ return do_stackcheck((uintptr_t)tcb->stack_alloc_ptr, tcb->adj_stack_size);
}
ssize_t up_check_tcbstack_remain(FAR struct tcb_s *tcb)
@@ -150,4 +190,16 @@ ssize_t up_check_stack_remain(void)
return up_check_tcbstack_remain((FAR struct tcb_s*)g_readytorun.head);
}
-#endif /* CONFIG_DEBUG && CONFIG_DEBUG_STACK */
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+size_t up_check_intstack(void)
+{
+ return do_stackcheck((uintptr_t)&g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3));
+}
+
+size_t up_check_intstack_remain(void)
+{
+ return (CONFIG_ARCH_INTERRUPTSTACK & ~3) - up_check_intstack();
+}
+#endif
+
+#endif /* CONFIG_DEBUG_STACK */
diff --git a/nuttx/arch/arm/src/common/up_initialize.c b/nuttx/arch/arm/src/common/up_initialize.c
index feb5011ce..2d9bb7988 100644
--- a/nuttx/arch/arm/src/common/up_initialize.c
+++ b/nuttx/arch/arm/src/common/up_initialize.c
@@ -88,6 +88,32 @@ static void up_calibratedelay(void)
#endif
/****************************************************************************
+ * Name: up_color_intstack
+ *
+ * Description:
+ * Set the interrupt stack to a value so that later we can determine how
+ * much stack space was used by interrupt handling logic
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG_STACK) && CONFIG_ARCH_INTERRUPTSTACK > 3
+static inline void up_color_intstack(void)
+{
+ uint32_t *ptr = (uint32_t *)&g_intstackalloc;
+ ssize_t size;
+
+ for (size = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
+ size > 0;
+ size -= sizeof(uint32_t))
+ {
+ *ptr++ = INTSTACK_COLOR;
+ }
+}
+#else
+# define up_color_intstack()
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -118,6 +144,10 @@ void up_initialize(void)
up_calibratedelay();
+ /* Colorize the interrupt stack */
+
+ up_color_intstack();
+
/* Add any extra memory fragments to the memory manager */
up_addregion();
diff --git a/nuttx/arch/avr/src/avr/up_checkstack.c b/nuttx/arch/avr/src/avr/up_checkstack.c
index 07b1f9d14..647b1c99b 100644
--- a/nuttx/arch/avr/src/avr/up_checkstack.c
+++ b/nuttx/arch/avr/src/avr/up_checkstack.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/avr/src/avr/up_checkstack.c
*
- * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -44,26 +44,31 @@
#include <sched.h>
#include <debug.h>
-#include <nuttx/arch.h>
+#include <nuttx/arch.h>
+#include "up_internal.h"
#include "os_internal.h"
-#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
-
/****************************************************************************
- * Private Types
+ * Pre-processor Definitions
****************************************************************************/
+#if !defined(CONFIG_DEBUG)
+# undef CONFIG_DEBUG_STACK
+#endif
+
+#if defined(CONFIG_DEBUG_STACK)
+
/****************************************************************************
- * Private Function Prototypes
+ * Public Data
****************************************************************************/
/****************************************************************************
- * Global Functions
+ * Private Functions
****************************************************************************/
/****************************************************************************
- * Name: up_check_stack
+ * Name: do_stackcheck
*
* Description:
* Determine (approximately) how much stack has been used be searching the
@@ -71,14 +76,15 @@
* stack that clobbered some recognizable marker in the stack memory.
*
* Input Parameters:
- * None
+ * alloc - Allocation base address of the stack
+ * size - The size of the stack in bytes
*
* Returned value:
* The estimated amount of stack space used.
*
****************************************************************************/
-size_t up_check_tcbstack(FAR struct tcb_s *tcb)
+size_t do_stackcheck(uintptr_t alloc, size_t size)
{
FAR uint8_t *ptr;
size_t mark;
@@ -93,8 +99,8 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb)
* that does not have the magic value is the high water mark.
*/
- for (ptr = (FAR uint8_t *)tcb->stack_alloc_ptr, mark = tcb->adj_stack_size;
- *ptr == 0xaa && mark > 0;
+ for (ptr = (FAR uint8_t *)alloc, mark = size;
+ *ptr == STACK_COLOR && mark > 0;
ptr++, mark--);
/* If the stack is completely used, then this might mean that the stack
@@ -108,15 +114,15 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb)
*/
#if 0
- if (mark + 16 > tcb->adj_stack_size)
+ if (mark + 16 > size)
{
- ptr = (FAR uint8_t *)tcb->stack_alloc_ptr;
- for (i = 0; i < tcb->adj_stack_size; i += 64)
+ ptr = (FAR uint8_t *)alloc;
+ for (i = 0; i < size; i += 64)
{
for (j = 0; j < 64; j++)
{
int ch;
- if (*ptr++ == 0xaa)
+ if (*ptr++ == STACK_COLOR)
{
ch = '.';
}
@@ -138,6 +144,31 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb)
return mark;
}
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_check_stack and friends
+ *
+ * Description:
+ * Determine (approximately) how much stack has been used be searching the
+ * stack memory for a high water mark. That is, the deepest level of the
+ * stack that clobbered some recognizable marker in the stack memory.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned value:
+ * The estimated amount of stack space used.
+ *
+ ****************************************************************************/
+
+size_t up_check_tcbstack(FAR struct tcb_s *tcb)
+{
+ return do_stackcheck((uintptr_t)tcb->stack_alloc_ptr, tcb->adj_stack_size);
+}
+
ssize_t up_check_tcbstack_remain(FAR struct tcb_s *tcb)
{
return (ssize_t)tcb->adj_stack_size - (ssize_t)up_check_tcbstack(tcb);
@@ -153,4 +184,17 @@ ssize_t up_check_stack_remain(void)
return up_check_tcbstack_remain((FAR struct tcb_s*)g_readytorun.head);
}
-#endif /* CONFIG_DEBUG && CONFIG_DEBUG_STACK */
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+size_t up_check_intstack(void)
+{
+ uintptr_t start = (uintptr_t)g_intstackbase - (CONFIG_ARCH_INTERRUPTSTACK & ~3);
+ return do_stackcheck(start, (CONFIG_ARCH_INTERRUPTSTACK & ~3));
+}
+
+size_t up_check_intstack_remain(void)
+{
+ return (CONFIG_ARCH_INTERRUPTSTACK & ~3) - up_check_intstack();
+}
+#endif
+
+#endif /* CONFIG_DEBUG_STACK */
diff --git a/nuttx/arch/avr/src/common/up_initialize.c b/nuttx/arch/avr/src/common/up_initialize.c
index 89840dfaf..69f58ec33 100644
--- a/nuttx/arch/avr/src/common/up_initialize.c
+++ b/nuttx/arch/avr/src/common/up_initialize.c
@@ -133,6 +133,32 @@ static void up_calibratedelay(void)
#endif
/****************************************************************************
+ * Name: up_color_intstack
+ *
+ * Description:
+ * Set the interrupt stack to a value so that later we can determine how
+ * much stack space was used by interrupt handling logic
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG_STACK) && CONFIG_ARCH_INTERRUPTSTACK > 3
+static inline void up_color_intstack(void)
+{
+ uint8_t *ptr = (uint8_t *)&g_intstackalloc;
+ ssize_t size;
+
+ for (size = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
+ size > 0;
+ size -= sizeof(uint8_t))
+ {
+ *ptr++ = INTSTACK_COLOR;
+ }
+}
+#else
+# define up_color_intstack()
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -163,6 +189,10 @@ void up_initialize(void)
up_calibratedelay();
+ /* Colorize the interrupt stack */
+
+ up_color_intstack();
+
/* Add any extra memory fragments to the memory manager */
up_addregion();
diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h
index 13336ae8b..dceee8ab1 100644
--- a/nuttx/include/nuttx/arch.h
+++ b/nuttx/include/nuttx/arch.h
@@ -1059,10 +1059,14 @@ void irq_dispatch(int irq, FAR void *context);
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
struct tcb_s;
-size_t up_check_tcbstack(FAR struct tcb_s *tcb);
+size_t up_check_tcbstack(FAR struct tcb_s *tcb);
ssize_t up_check_tcbstack_remain(FAR struct tcb_s *tcb);
-size_t up_check_stack(void);
+size_t up_check_stack(void);
ssize_t up_check_stack_remain(void);
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+size_t up_check_intstack(void);
+size_t up_check_intstack_remain(void);
+#endif
#endif
/****************************************************************************