diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-03-23 10:11:58 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-03-23 10:11:58 -0600 |
commit | d15a9cedd177e357a1b6bd8adbfbedd73448906e (patch) | |
tree | bee64cfdfeccf84acf54db0e1334de370648b700 /nuttx | |
parent | 9acd7deb2a7d40d8134706cc0f9434375475abe1 (diff) | |
download | px4-nuttx-d15a9cedd177e357a1b6bd8adbfbedd73448906e.tar.gz px4-nuttx-d15a9cedd177e357a1b6bd8adbfbedd73448906e.tar.bz2 px4-nuttx-d15a9cedd177e357a1b6bd8adbfbedd73448906e.zip |
Add logic to check interrupt stack usage
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/arch/arm/src/common/up_checkstack.c | 82 | ||||
-rw-r--r-- | nuttx/arch/arm/src/common/up_initialize.c | 30 | ||||
-rw-r--r-- | nuttx/arch/avr/src/avr/up_checkstack.c | 78 | ||||
-rw-r--r-- | nuttx/arch/avr/src/common/up_initialize.c | 30 | ||||
-rw-r--r-- | nuttx/include/nuttx/arch.h | 8 |
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 /**************************************************************************** |