From f8b3dbaa61aba8e2cb0745bdede6d1f76ff72eaa Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 1 Nov 2013 11:16:51 -0600 Subject: [PATCH] Extend stack debug logic to include IDLE and interrupt stacks. Also color the heap as well. Based on suggestions from David Sidrane --- ChangeLog | 3 ++ Kconfig | 11 +++++ arch/arm/Kconfig | 1 + arch/arm/src/arm/up_assert.c | 4 +- arch/arm/src/arm/up_vectors.S | 19 ++++---- arch/arm/src/armv6-m/up_exception.S | 9 ++-- arch/arm/src/armv7-a/arm_assert.c | 4 +- arch/arm/src/armv7-a/arm_vectors.S | 19 ++++---- arch/arm/src/armv7-m/up_exception.S | 7 +-- arch/arm/src/c5471/c5471_vectors.S | 17 +++---- arch/arm/src/common/up_checkstack.c | 5 +- arch/arm/src/common/up_createstack.c | 47 ++++++++++-------- arch/arm/src/common/up_internal.h | 19 +++++++- arch/arm/src/kinetis/kinetis_vectors.S | 6 +-- arch/arm/src/lm/lm_vectors.S | 6 +-- arch/arm/src/lpc17xx/lpc17_vectors.S | 6 +-- arch/arm/src/sam34/sam_vectors.S | 6 +-- arch/arm/src/stm32/stm32_allocateheap.c | 37 +++++++++++++- arch/arm/src/stm32/stm32_irq.c | 10 ++++ arch/arm/src/stm32/stm32_start.c | 65 ++++++++++++++++++++++++- arch/arm/src/stm32/stm32_vectors.S | 10 ++-- arch/hc/src/common/up_internal.h | 2 +- arch/hc/src/m9s12/m9s12_assert.c | 4 +- arch/hc/src/m9s12/m9s12_vectors.S | 2 +- arch/mips/src/mips32/up_dumpstate.c | 4 +- arch/sh/src/m16c/chip.h | 2 +- arch/sh/src/sh1/chip.h | 2 +- arch/sh/src/sh1/sh1_dumpstate.c | 4 +- arch/sh/src/sh1/sh1_vector.S | 19 ++++---- arch/x86/src/common/up_assert.c | 4 +- arch/x86/src/common/up_internal.h | 2 +- include/nuttx/init.h | 20 ++++---- tools/mkconfig.c | 1 + 33 files changed, 263 insertions(+), 114 deletions(-) diff --git a/ChangeLog b/ChangeLog index 474c696d24..bf6efd399b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5930,3 +5930,6 @@ media that is wrapped as an MTD device. From Ken Pettit (2013-11-1). * configs/mikroe-stm32f4: Now uses /dev/config for configuration data storage. From Ken Pettit (2013-11-1). + * arch/ stack management functions: Extension and standardization of + stack debug logic. Now includes coloration of the IDLE and interrupt + stacks as well as the heap. Suggested by David Sidrane (2013-11-1). diff --git a/Kconfig b/Kconfig index 06cddace3e..164324bb08 100644 --- a/Kconfig +++ b/Kconfig @@ -316,6 +316,10 @@ config ARCH_HAVE_STACKCHECK bool default n +config ARCH_HAVE_HEAPCHECK + bool + default n + if DEBUG config DEBUG_VERBOSE bool "Enable Debug Verbose Output" @@ -413,6 +417,13 @@ config DEBUG_STACK ---help--- Enable hooks to check stack usage. Only supported by a few architectures. +config DEBUG_HEAP + bool "Heap usage debug hooks" + default n + depends on ARCH_HAVE_HEAPCHECK + ---help--- + Enable hooks to check heap usage. Only supported by a few architectures. + comment "Driver Debug Options" config DEBUG_LCD diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 483f9bd924..1a5f494e3a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -129,6 +129,7 @@ config ARCH_CHIP_STM32 select ARCH_HAVE_CMNVECTOR select ARCH_HAVE_MPU select ARCH_HAVE_I2CRESET + select ARCH_HAVE_HEAPCHECK ---help--- STMicro STM32 architectures (ARM Cortex-M3/4). diff --git a/arch/arm/src/arm/up_assert.c b/arch/arm/src/arm/up_assert.c index 03f6e4d8fa..99be452ab5 100644 --- a/arch/arm/src/arm/up_assert.c +++ b/arch/arm/src/arm/up_assert.c @@ -186,7 +186,7 @@ static void up_dumpstate(void) /* Get the limits on the interrupt stack memory */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 - istackbase = (uint32_t)&g_userstack; + istackbase = (uint32_t)&g_intstackbase; istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; /* Show interrupt stack info */ @@ -210,7 +210,7 @@ static void up_dumpstate(void) * at the base of the interrupt stack. */ - sp = g_userstack; + sp = g_intstackbase; lldbg("sp: %08x\n", sp); } diff --git a/arch/arm/src/arm/up_vectors.S b/arch/arm/src/arm/up_vectors.S index 043516a50d..1dfdf623c0 100644 --- a/arch/arm/src/arm/up_vectors.S +++ b/arch/arm/src/arm/up_vectors.S @@ -149,7 +149,7 @@ up_vectorirq: .word g_irqtmp #if CONFIG_ARCH_INTERRUPTSTACK > 3 .Lirqstackbase: - .word up_stackbase + .word g_intstackbase #endif .size up_vectorirq, . - up_vectorirq .align 5 @@ -427,20 +427,21 @@ up_vectorfiq: .size up_vectorfiq, . - up_vectorfiq /************************************************************************************ - * Name: up_interruptstack/g_userstack + * Name: g_intstackalloc/g_intstackbase ************************************************************************************/ #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss .align 4 - .globl g_userstack - .type g_userstack, object -up_interruptstack: + .globl g_intstackalloc + .type g_intstackalloc, object + .globl g_intstackbase + .type g_intstackbase, object +g_intstackalloc: .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) -g_userstack: -up_stackbase: +g_intstackbase: .skip 4 - .size g_userstack, 4 - .size up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3) + .size g_intstackbase, 4 + .size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3) #endif .end diff --git a/arch/arm/src/armv6-m/up_exception.S b/arch/arm/src/armv6-m/up_exception.S index 249fb9e542..1a04cfe278 100644 --- a/arch/arm/src/armv6-m/up_exception.S +++ b/arch/arm/src/armv6-m/up_exception.S @@ -258,7 +258,7 @@ exception_common: .size exception_common, .-exception_common /************************************************************************************ - * Name: up_interruptstack/g_intstackbase + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -267,12 +267,13 @@ exception_common: #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss - .global g_intstackbase + .global g_intstackalloc + .global g_intstackbase .align 4 -up_interruptstack: +g_intstackalloc: .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) g_intstackbase: - .size up_interruptstack, .-up_interruptstack + .size g_intstackalloc, .-g_intstackalloc #endif .end diff --git a/arch/arm/src/armv7-a/arm_assert.c b/arch/arm/src/armv7-a/arm_assert.c index eab0e3252d..4bd04d1d96 100644 --- a/arch/arm/src/armv7-a/arm_assert.c +++ b/arch/arm/src/armv7-a/arm_assert.c @@ -186,7 +186,7 @@ static void up_dumpstate(void) /* Get the limits on the interrupt stack memory */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 - istackbase = (uint32_t)&g_userstack; + istackbase = (uint32_t)&g_intstackbase; istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; /* Show interrupt stack info */ @@ -217,7 +217,7 @@ static void up_dumpstate(void) * at the base of the interrupt stack. */ - sp = g_userstack; + sp = g_intstackbase; lldbg("sp: %08x\n", sp); } diff --git a/arch/arm/src/armv7-a/arm_vectors.S b/arch/arm/src/armv7-a/arm_vectors.S index b1ff40f25b..073bad4d6f 100644 --- a/arch/arm/src/armv7-a/arm_vectors.S +++ b/arch/arm/src/armv7-a/arm_vectors.S @@ -162,7 +162,7 @@ arm_vectorirq: .word g_irqtmp #if CONFIG_ARCH_INTERRUPTSTACK > 3 .Lirqstackbase: - .word up_stackbase + .word g_intstackbase #endif .size arm_vectorirq, . - arm_vectorirq .align 5 @@ -481,20 +481,21 @@ arm_vectorfiq: .size arm_vectorfiq, . - arm_vectorfiq /************************************************************************************ - * Name: up_interruptstack/g_userstack + * Name: g_intstackalloc/g_intstackbase ************************************************************************************/ #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss .align 4 - .globl g_userstack - .type g_userstack, object -up_interruptstack: + .globl g_intstackalloc + .type g_intstackalloc, object + .globl g_intstackbase + .type g_intstackbase, object +g_intstackalloc: .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) -g_userstack: -up_stackbase: +g_intstackbase: .skip 4 - .size g_userstack, 4 - .size up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3) + .size g_intstackbase, 4 + .size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3) #endif .end diff --git a/arch/arm/src/armv7-m/up_exception.S b/arch/arm/src/armv7-m/up_exception.S index df7a7ad299..ec2ed4dd7a 100644 --- a/arch/arm/src/armv7-m/up_exception.S +++ b/arch/arm/src/armv7-m/up_exception.S @@ -244,7 +244,7 @@ exception_common: .size exception_common, .-exception_common /************************************************************************************ - * Name: up_interruptstack/g_intstackbase + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -253,12 +253,13 @@ exception_common: #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss + .global g_intstackalloc .global g_intstackbase .align 4 -up_interruptstack: +g_intstackalloc: .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) g_intstackbase: - .size up_interruptstack, .-up_interruptstack + .size g_intstackalloc, .-g_intstackalloc #endif .end diff --git a/arch/arm/src/c5471/c5471_vectors.S b/arch/arm/src/c5471/c5471_vectors.S index aa514b03fa..a553f72198 100644 --- a/arch/arm/src/c5471/c5471_vectors.S +++ b/arch/arm/src/c5471/c5471_vectors.S @@ -179,7 +179,7 @@ up_vectorirq: .word g_irqtmp #if CONFIG_ARCH_INTERRUPTSTACK > 3 .Lirqstackbase: - .word up_stackbase + .word g_intstackbase #endif .align 5 @@ -462,7 +462,7 @@ up_vectoraddrexcptn: b up_vectoraddrexcptn /************************************************************************************ - * Name: up_interruptstack/g_userstack + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -472,14 +472,13 @@ up_vectoraddrexcptn: #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss .align 4 - .globl g_userstack - .type g_userstack, object -up_interruptstack: + .globl g_intstackbase + .type g_intstackbase, object +g_intstackalloc: .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) -g_userstack: -up_stackbase: +g_intstackbase: .skip 4 - .size g_userstack, 4 - .size up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3) + .size g_intstackbase, 4 + .size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3) #endif .end diff --git a/arch/arm/src/common/up_checkstack.c b/arch/arm/src/common/up_checkstack.c index 2bcd5c5561..9cf4c684f0 100644 --- a/arch/arm/src/common/up_checkstack.c +++ b/arch/arm/src/common/up_checkstack.c @@ -47,6 +47,7 @@ #include #include "os_internal.h" +#include "up_internal.h" #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) @@ -90,7 +91,7 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb) */ for (ptr = (FAR uint32_t *)tcb->stack_alloc_ptr, mark = tcb->adj_stack_size/4; - *ptr == 0xDEADBEEF && mark > 0; + *ptr == STACK_COLOR && mark > 0; ptr++, mark--); /* If the stack is completely used, then this might mean that the stack @@ -114,7 +115,7 @@ size_t up_check_tcbstack(FAR struct tcb_s *tcb) for (j = 0; j < 64; j++) { int ch; - if (*ptr++ == 0xDEADBEEF) + if (*ptr++ == STACK_COLOR) { ch = '.'; } diff --git a/arch/arm/src/common/up_createstack.c b/arch/arm/src/common/up_createstack.c index 46bf153586..e14142700a 100644 --- a/arch/arm/src/common/up_createstack.c +++ b/arch/arm/src/common/up_createstack.c @@ -82,23 +82,6 @@ * Private Types ****************************************************************************/ -/**************************************************************************** - * Name: memset32 - * - * On most larger than 8 bit archs this will need to be word aligned so - * so maybe some checks should be put in place? - * - ****************************************************************************/ - -#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) -static void *memset32(void *s, uint32_t c, size_t n) -{ - uint32_t *p = (uint32_t *)s; - while (n-- > 0) *p++ = c; - return s; -} -#endif - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -159,7 +142,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) } /* Do we need to allocate a new stack? */ - + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), @@ -240,7 +223,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) - memset32(tcb->stack_alloc_ptr, 0xdeadbeef, tcb->adj_stack_size/4); + up_stack_color(tcb->stack_alloc_ptr, tcb->adj_stack_size); #endif up_ledon(LED_STACKCREATED); @@ -249,3 +232,29 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) return ERROR; } + +/**************************************************************************** + * Name: up_stack_color + * + * Description: + * Write a well know value into the stack + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) +void up_stack_color(FAR void *stackbase, size_t nbytes) +{ + /* Take extra care that we do not write outsize the stack boundaries */ + + uint32_t *stkptr = (uint32_t *)(((uintptr_t)stackbase + 3) & ~3); + uintptr_t stkend = (((uintptr_t)stackbase + nbytes) & ~3); + size_t nwords = (stkend - (uintptr_t)stackbase) >> 2; + + /* Set the entire stack to the coloration value */ + + while (nwords-- > 0) + { + *stkptr++ = STACK_COLOR; + } +} +#endif diff --git a/arch/arm/src/common/up_internal.h b/arch/arm/src/common/up_internal.h index 448735e493..eb3ca896ae 100644 --- a/arch/arm/src/common/up_internal.h +++ b/arch/arm/src/common/up_internal.h @@ -171,6 +171,14 @@ #endif +/* This is the value used to mark the stack for subsequent stack monitoring + * logic. + */ + +#define STACK_COLOR 0xdeadbeef +#define INTSTACK_COLOR 0xdeadbeef +#define HEAP_COLOR 'h' + /**************************************************************************** * Public Types ****************************************************************************/ @@ -204,9 +212,10 @@ extern const uint32_t g_idle_topstack; #if CONFIG_ARCH_INTERRUPTSTACK > 3 #if defined(CONFIG_ARCH_CORTEXM0) || defined(CONFIG_ARCH_CORTEXM3) || \ defined(CONFIG_ARCH_CORTEXM4) -extern uint32_t g_intstackbase; +extern uint32_t g_intstackalloc; /* Allocated stack base */ +extern uint32_t g_intstackbase; /* Initial top of interrupt stack */ # else -extern uint32_t g_userstack; +extern uint32_t g_intstackbase; # endif #endif @@ -484,6 +493,12 @@ void up_usbuninitialize(void); void up_rnginitialize(void); #endif +/* Debug ********************************************************************/ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) +void up_stack_color(FAR void *stackbase, size_t nbytes); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_COMMON_UP_INTERNAL_H */ diff --git a/arch/arm/src/kinetis/kinetis_vectors.S b/arch/arm/src/kinetis/kinetis_vectors.S index 8394ff9166..e10b7604a2 100644 --- a/arch/arm/src/kinetis/kinetis_vectors.S +++ b/arch/arm/src/kinetis/kinetis_vectors.S @@ -779,7 +779,7 @@ kinetis_common: .size handlers, .-handlers /************************************************************************************************ - * Name: up_interruptstack/g_intstackbase + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -790,10 +790,10 @@ kinetis_common: .bss .global g_intstackbase .align 4 -up_interruptstack: +g_intstackalloc: .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) g_intstackbase: - .size up_interruptstack, .-up_interruptstack + .size g_intstackalloc, .-g_intstackalloc #endif #endif /* CONFIG_ARMV7M_CMNVECTOR */ diff --git a/arch/arm/src/lm/lm_vectors.S b/arch/arm/src/lm/lm_vectors.S index 0a146d6911..17cc34719a 100644 --- a/arch/arm/src/lm/lm_vectors.S +++ b/arch/arm/src/lm/lm_vectors.S @@ -382,7 +382,7 @@ lm_irqcommon: .size handlers, .-handlers /************************************************************************************ - * Name: up_interruptstack/g_intstackbase + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -393,10 +393,10 @@ lm_irqcommon: .bss .global g_intstackbase .align 4 -up_interruptstack: +g_intstackalloc: .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) g_intstackbase: - .size up_interruptstack, .-up_interruptstack + .size g_intstackalloc, .-g_intstackalloc #endif #endif /* CONFIG_ARMV7M_CMNVECTOR */ diff --git a/arch/arm/src/lpc17xx/lpc17_vectors.S b/arch/arm/src/lpc17xx/lpc17_vectors.S index 66e76932db..b36f331387 100644 --- a/arch/arm/src/lpc17xx/lpc17_vectors.S +++ b/arch/arm/src/lpc17xx/lpc17_vectors.S @@ -391,7 +391,7 @@ lpc17_common: .size handlers, .-handlers /************************************************************************************************ - * Name: up_interruptstack/g_intstackbase + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -402,10 +402,10 @@ lpc17_common: .bss .global g_intstackbase .align 4 -up_interruptstack: +g_intstackalloc: .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) g_intstackbase: - .size up_interruptstack, .-up_interruptstack + .size g_intstackalloc, .-g_intstackalloc #endif #endif /* CONFIG_ARMV7M_CMNVECTOR */ diff --git a/arch/arm/src/sam34/sam_vectors.S b/arch/arm/src/sam34/sam_vectors.S index fde817be4c..abf373bf18 100644 --- a/arch/arm/src/sam34/sam_vectors.S +++ b/arch/arm/src/sam34/sam_vectors.S @@ -397,7 +397,7 @@ sam_common: .size handlers, .-handlers /************************************************************************************************ - * Name: up_interruptstack/g_intstackbase + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -408,10 +408,10 @@ sam_common: .bss .global g_intstackbase .align 4 -up_interruptstack: +g_intstackalloc: .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) g_intstackbase: - .size up_interruptstack, .-up_interruptstack + .size g_intstackalloc, .-g_intstackalloc #endif #endif /* CONFIG_ARMV7M_CMNVECTOR */ diff --git a/arch/arm/src/stm32/stm32_allocateheap.c b/arch/arm/src/stm32/stm32_allocateheap.c index b44840ea64..9876ff8280 100644 --- a/arch/arm/src/stm32/stm32_allocateheap.c +++ b/arch/arm/src/stm32/stm32_allocateheap.c @@ -393,6 +393,23 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_heap_color + * + * Description: + * Set heap memory to a known, non-zero state to checking heap usage. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_HEAP +static inline void up_heap_color(FAR void *start, size_t size) +{ + memset(start, HEAP_COLOR, size); +} +#else +# define up_heap_color(start,size) +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -461,6 +478,10 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size) *heap_start = (FAR void*)ubase; *heap_size = usize; + /* Colorize the heap for debug */ + + up_heap_color((FAR void*)ubase, usize); + /* Allow user-mode access to the user heap memory */ stm32_mpu_uheap((uintptr_t)ubase, usize); @@ -471,6 +492,10 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size) up_ledon(LED_HEAPALLOCATE); *heap_start = (FAR void*)g_idle_topstack; *heap_size = SRAM1_END - g_idle_topstack; + + /* Colorize the heap for debug */ + + up_heap_color(*heap_start, *heap_size); #endif } @@ -539,6 +564,10 @@ void up_addregion(void) #endif + /* Colorize the heap for debug */ + + up_heap_color((FAR void*)SRAM2_START, SRAM2_END-SRAM2_START); + /* Add the STM32F20xxx/STM32F40xxx CCM SRAM user heap region. */ kumm_addregion((FAR void*)SRAM2_START, SRAM2_END-SRAM2_START); @@ -553,9 +582,13 @@ void up_addregion(void) #endif - /* Add the external FSMC SRAM user heap region. */ + /* Colorize the heap for debug */ - kumm_addregion((FAR void*)CONFIG_HEAP2_BASE, CONFIG_HEAP2_SIZE); + up_heap_color((FAR void*)CONFIG_HEAP2_BASE, CONFIG_HEAP2_SIZE); + + /* Add the external FSMC SRAM user heap region. */ + + kumm_addregion((FAR void*)CONFIG_HEAP2_BASE, CONFIG_HEAP2_SIZE); #endif } #endif diff --git a/arch/arm/src/stm32/stm32_irq.c b/arch/arm/src/stm32/stm32_irq.c index 6c05cedbde..ce931afa74 100644 --- a/arch/arm/src/stm32/stm32_irq.c +++ b/arch/arm/src/stm32/stm32_irq.c @@ -299,6 +299,16 @@ void up_irqinitialize(void) putreg32(0, NVIC_IRQ0_31_ENABLE); putreg32(0, NVIC_IRQ32_63_ENABLE); + /* Colorize the interrupt stack for debug purposes */ + +#if defined(CONFIG_DEBUG_STACK) && CONFIG_ARCH_INTERRUPTSTACK > 3 + { + size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~3); + up_stack_color((FAR void *)((uintptr_t)&g_intstackbase - intstack_size), + intstack_size); + } +#endif + /* The standard location for the vector table is at the beginning of FLASH * at address 0x0800:0000. If we are using the STMicro DFU bootloader, then * the vector table will be offset to a different location in FLASH and we diff --git a/arch/arm/src/stm32/stm32_start.c b/arch/arm/src/stm32/stm32_start.c index a2f82f7b2b..5a8fc3bb3d 100644 --- a/arch/arm/src/stm32/stm32_start.c +++ b/arch/arm/src/stm32/stm32_start.c @@ -58,6 +58,18 @@ # include "nvic.h" #endif +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FPU +static inline void stm32_fpuconfig(void); +#endif +#ifdef CONFIG_DEBUG_STACK +static void go_os_start(void *pv, unsigned int nbytes) + __attribute__ ((naked,no_instrument_function,noreturn)); +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -110,7 +122,7 @@ static inline void stm32_fpuconfig(void) * with the volatile FP registers stacked above the basic context. */ - regval = getcontrol(); + regval = getcontrol(); regval |= (1 << 2); setcontrol(regval); @@ -140,7 +152,7 @@ static inline void stm32_fpuconfig(void) * with the volatile FP registers stacked in the saved context. */ - regval = getcontrol(); + regval = getcontrol(); regval &= ~(1 << 2); setcontrol(regval); @@ -166,6 +178,46 @@ static inline void stm32_fpuconfig(void) # define stm32_fpuconfig() #endif +/**************************************************************************** + * Name: go_os_start + * + * Description: + * Set the IDLE stack to the + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_STACK +static void go_os_start(void *pv, unsigned int nbytes) +{ + /* Set the IDLE stack to the stack coloration value then jump to + * os_start(). We take extreme care here because were currently + * executing on this stack. + * + * We want to avoid sneak stack access generated by the compiler. + */ + + __asm__ __volatile__ + ( + "\tmov r1, r1, lsr #2\n" /* R1 = nwords = nbytes >> 2 */ + "\tbeq 2f\n" /* (should not happen) */ + + "\tbic r0, r0, #3\n" /* R0 = Aligned stackptr */ + "\tmovw r2, #0xbeef\n" /* R2 = STACK_COLOR = 0xdeadbeef */ + "\tmovt r2, #0xdead\n" + + "1:\n" /* Top of the loop */ + "\tsub r1, r1, #1\n" /* R1 nwords-- */ + "\tcmp r1, #0\n" /* Check (nwords == 0) */ + "\tstr r2, [r0], #4\n" /* Save stack color word, increment stackptr */ + "\tbne 1b\n" /* Bottom of the loop */ + + "2:\n" /* Top of the loop */ + "\tmov r14, #0\n" /* LR = return address (none) */ + "\tb os_start\n" /* Branch to os_start */ + ); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -242,9 +294,18 @@ void __start(void) showprogress('\r'); showprogress('\n'); + +#ifdef CONFIG_DEBUG_STACK + /* Set the IDLE stack to the coloration value and jump into os_start() */ + + go_os_start((FAR void *)_ebss, CONFIG_ARCH_INTERRUPTSTACK); +#else + /* Call os_start() */ + os_start(); /* Shoulnd't get here */ for(;;); +#endif } diff --git a/arch/arm/src/stm32/stm32_vectors.S b/arch/arm/src/stm32/stm32_vectors.S index a49729de3d..e1dbb5662e 100644 --- a/arch/arm/src/stm32/stm32_vectors.S +++ b/arch/arm/src/stm32/stm32_vectors.S @@ -404,7 +404,7 @@ stm32_common: .size handlers, .-handlers /************************************************************************************ - * Name: up_interruptstack/g_intstackbase + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -413,13 +413,15 @@ stm32_common: #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss - .global g_intstackbase + .global g_intstackalloc + .global g_intstackbase .align 4 -up_interruptstack: +g_intstackalloc: .skip (CONFIG_ARCH_INTERRUPTSTACK & ~3) g_intstackbase: - .size up_interruptstack, .-up_interruptstack + .size g_intstackalloc, .-g_intstackalloc #endif + #endif /* CONFIG_ARMV7M_CMNVECTOR */ /************************************************************************************ diff --git a/arch/hc/src/common/up_internal.h b/arch/hc/src/common/up_internal.h index 44847107e4..faf15c0e33 100644 --- a/arch/hc/src/common/up_internal.h +++ b/arch/hc/src/common/up_internal.h @@ -146,7 +146,7 @@ extern uint16_t g_idle_topstack; /* Address of the saved user stack pointer */ #if CONFIG_ARCH_INTERRUPTSTACK > 1 -extern uint32_t g_userstack; +extern uint32_t g_intstackbase; #endif /**************************************************************************** diff --git a/arch/hc/src/m9s12/m9s12_assert.c b/arch/hc/src/m9s12/m9s12_assert.c index 69d5e3c738..4a6292c3e6 100644 --- a/arch/hc/src/m9s12/m9s12_assert.c +++ b/arch/hc/src/m9s12/m9s12_assert.c @@ -181,7 +181,7 @@ static void up_dumpstate(void) /* Get the limits on the interrupt stack memory */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 - istackbase = (uint16_t)&g_userstack; + istackbase = (uint16_t)&g_intstackbase; istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; /* Show interrupt stack info */ @@ -205,7 +205,7 @@ static void up_dumpstate(void) * at the base of the interrupt stack. */ - sp = g_userstack; + sp = g_intstackbase; lldbg("sp: %04x\n", sp); } diff --git a/arch/hc/src/m9s12/m9s12_vectors.S b/arch/hc/src/m9s12/m9s12_vectors.S index dc57bf8b3b..4b10ed62af 100755 --- a/arch/hc/src/m9s12/m9s12_vectors.S +++ b/arch/hc/src/m9s12/m9s12_vectors.S @@ -433,7 +433,7 @@ up_fullcontextrestore: .comm .Lspsave, 2, 1 /************************************************************************************ - * Name: up_interruptstack/g_userstack + * Name: up_interruptstack/g_intstackbase * * Description: * If CONFIG_ARCH_INTERRUPTSTACK is defined, this sets aside memory for the diff --git a/arch/mips/src/mips32/up_dumpstate.c b/arch/mips/src/mips32/up_dumpstate.c index bdd21726b9..dc2a50d29c 100644 --- a/arch/mips/src/mips32/up_dumpstate.c +++ b/arch/mips/src/mips32/up_dumpstate.c @@ -179,7 +179,7 @@ void up_dumpstate(void) /* Get the limits on the interrupt stack memory */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 - istackbase = (uint32_t)&g_userstack; + istackbase = (uint32_t)&g_intstackbase; istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; /* Show interrupt stack info */ @@ -203,7 +203,7 @@ void up_dumpstate(void) * at the base of the interrupt stack. */ - sp = g_userstack; + sp = g_intstackbase; lldbg("sp: %08x\n", sp); } diff --git a/arch/sh/src/m16c/chip.h b/arch/sh/src/m16c/chip.h index 02140df790..83c0da2c93 100644 --- a/arch/sh/src/m16c/chip.h +++ b/arch/sh/src/m16c/chip.h @@ -272,7 +272,7 @@ extern uint32_t g_idle_topstack; /* Start of the heap */ #ifndef __ASSEMBLY__ # if CONFIG_ARCH_INTERRUPTSTACK > 3 - extern uint16_t g_userstack; + extern uint16_t g_intstackbase; # endif #endif diff --git a/arch/sh/src/sh1/chip.h b/arch/sh/src/sh1/chip.h index b679fe8661..331c1b0556 100644 --- a/arch/sh/src/sh1/chip.h +++ b/arch/sh/src/sh1/chip.h @@ -63,7 +63,7 @@ #ifndef __ASSEMBLY__ # if CONFIG_ARCH_INTERRUPTSTACK > 3 - extern uint32_t g_userstack; + extern uint32_t g_intstackbase; # endif #endif diff --git a/arch/sh/src/sh1/sh1_dumpstate.c b/arch/sh/src/sh1/sh1_dumpstate.c index 8990f66158..e9ffc4caac 100644 --- a/arch/sh/src/sh1/sh1_dumpstate.c +++ b/arch/sh/src/sh1/sh1_dumpstate.c @@ -172,7 +172,7 @@ void up_dumpstate(void) /* Get the limits on the interrupt stack memory */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 - istackbase = (uint32_t)&g_userstack; + istackbase = (uint32_t)&g_intstackbase; istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; /* Show interrupt stack info */ @@ -196,7 +196,7 @@ void up_dumpstate(void) * at the base of the interrupt stack. */ - sp = g_userstack; + sp = g_intstackbase; lldbg("sp: %08x\n", sp); } diff --git a/arch/sh/src/sh1/sh1_vector.S b/arch/sh/src/sh1/sh1_vector.S index 1655a782dc..a16fb8f0bc 100644 --- a/arch/sh/src/sh1/sh1_vector.S +++ b/arch/sh/src/sh1/sh1_vector.S @@ -411,7 +411,7 @@ _up_vector: .align 2 #if CONFIG_ARCH_INTERRUPTSTACK > 3 .Lintstack: - .long _up_stackbase + .long _g_intstackbase #endif .Ldoirq: .long _up_doirq @@ -501,7 +501,7 @@ _up_fullcontextrestore: .size _up_fullcontextrestore, .-_up_fullcontextrestore /************************************************************************************ - * Name: up_interruptstack/g_userstack + * Name: g_intstackalloc/g_intstackbase * * Description: * Shouldn't happen @@ -511,15 +511,16 @@ _up_fullcontextrestore: #if CONFIG_ARCH_INTERRUPTSTACK > 3 .bss .align 2 - .globl _g_userstack - .type _g_userstack, object -_up_interruptstack: + .globl _g_intstackalloc + .type _g_intstackalloc, object + .globl _g_intstackbase + .type _g_intstackbase, object +_g_intstackalloc: .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) -_g_userstack: -_up_stackbase: +_g_intstackbase: .skip 2 - .size _g_userstack, 4 - .size _up_interruptstack, (CONFIG_ARCH_INTERRUPTSTACK & ~3) + .size _g_intstackbase, 4 + .size _g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3) #endif .end diff --git a/arch/x86/src/common/up_assert.c b/arch/x86/src/common/up_assert.c index f9a36dc536..7db69d8843 100644 --- a/arch/x86/src/common/up_assert.c +++ b/arch/x86/src/common/up_assert.c @@ -140,7 +140,7 @@ static void up_dumpstate(void) /* Get the limits on the interrupt stack memory */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 - istackbase = (uint32_t)&g_userstack; + istackbase = (uint32_t)&g_intstackbase; istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; /* Show interrupt stack info */ @@ -164,7 +164,7 @@ static void up_dumpstate(void) * at the base of the interrupt stack. */ - sp = g_userstack; + sp = g_intstackbase; lldbg("sp: %08x\n", sp); } diff --git a/arch/x86/src/common/up_internal.h b/arch/x86/src/common/up_internal.h index 2e3ad33ea1..1738832803 100644 --- a/arch/x86/src/common/up_internal.h +++ b/arch/x86/src/common/up_internal.h @@ -145,7 +145,7 @@ extern uint32_t g_idle_topstack; /* Address of the saved user stack pointer */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 -extern uint32_t g_userstack; +extern uint32_t g_intstackbase; #endif /* These 'addresses' of these values are setup by the linker script. They are diff --git a/include/nuttx/init.h b/include/nuttx/init.h index 2d1b3c693c..72520a4c18 100644 --- a/include/nuttx/init.h +++ b/include/nuttx/init.h @@ -51,28 +51,26 @@ * Global Data ****************************************************************************/ -/**************************************************************************** - * Global Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Global Function Prototypes - ****************************************************************************/ - #ifdef __cplusplus #define EXTERN extern "C" -extern "C" { +extern "C" +{ #else #define EXTERN extern #endif +/**************************************************************************** + * Global Function Prototypes + ****************************************************************************/ + /* This entry point must be supplied by the application */ -EXTERN int CONFIG_USER_ENTRYPOINT(int argc, char *argv[]); +int CONFIG_USER_ENTRYPOINT(int argc, char *argv[]); /* Functions contained in os_task.c *****************************************/ +/* OS entry point called by boot logic */ -EXTERN void os_start(void); /* OS entry point called by boot logic */ +void os_start(void) noreturn_function; #undef EXTERN #ifdef __cplusplus diff --git a/tools/mkconfig.c b/tools/mkconfig.c index 92fb04a688..87389f04ed 100644 --- a/tools/mkconfig.c +++ b/tools/mkconfig.c @@ -270,6 +270,7 @@ int main(int argc, char **argv, char **envp) printf("# undef CONFIG_DEBUG_GPIO\n"); printf("# undef CONFIG_DEBUG_SPI\n"); printf("# undef CONFIG_DEBUG_STACK\n"); + printf("# undef CONFIG_DEBUG_HEAP\n"); printf("#endif\n\n"); printf("/* User entry point. This is provided as a fall-back to keep compatibility\n"); printf(" * with existing code, for builds which do not define CONFIG_USER_ENTRYPOINT.\n");