Jump to content
nickds1

Easy way to monitor peak stack usage...

Recommended Posts

Hi,

I needed a way to see how much of my C++ stack was being consumed in my MSP application - the traditional way is to "poison" the stack with a known pattern, and then to see how much of it gets burnt away.

So I wrote the following - hope folk find it useful:

The following code allows you to simply do this and to check at any point how much of the pre-allocated stack was consumed during peak usage, i.e. how close your app got to the bottom of the stack, or indeed, whether it over-ran. The TI CCS documentation is completely wrong in the names it gives for the global symbols that define the size and start of the stack - needs to be updated,

Stick this code (or similar) wherever you want to report on/check stack usage <smallest number of byes left free on the stack since initialisation>/<configured size of the stack>.

#if defined(STACK_CHECK)
	std::printf( "Stack: %d/%d\n", stackMinFreeCount(), stackMaxSize() );
#endif
and then, in your main code you need to poison the stack as early as possible and then define the reporting routines:
// Define STACK_CHECK to include stack usage diagnostics
#define STACK_CHECK

#if defined(STACK_CHECK)
#define STACK_INIT  0xBEEF				// Pattern to use to initially poison the stack
extern uint16_t  _stack;                // Start of stack (low address)

uint16_t stackMinFreeCount(void);
uint16_t stackMaxSize(void);
#endif

#if defined(__cplusplus)
extern "C"
{
#endif
#if defined(__TI_COMPILER_VERSION__) || \
	defined(__GNUC__)
int _system_pre_init( void )
#elif defined(__IAR_SYSTEMS_ICC__)
int __low_level_init( void )
#endif
{
	//... stuff...

#if defined(STACK_CHECK)
	//
	// Poison the stack, word by word, with a defined pattern
	//
	// Note that _system_pre_init is the earliest that we can
	// do this and that it may not be possible in TI-RTOS
	//
	// When we call the __get_SP_register intrinsic (same on IAR & CCS), it will return the address
	// of the RET address for the caller of this routine. Make sure that we don't trash it!!
	//
	register uint16_t *stack = &_stack; // Address of lowest address in .stack section
	register uint16_t *stack_top = reinterpret_cast<uint16_t *>(__get_SP_register());

	do {
		*stack++ = STACK_INIT;			// Poison stack addresses
	} while (stack < stack_top);		// Stop before top of stack to leave RET address
#endif

	return 1;
}
#if defined(__cplusplus)
}
#endif

#if defined(STACK_CHECK)
/**
 * Check how deep the stack usage has been
 *
 * \return	\c uint16_t		Minimum number of bytes to bottom of stack
 */

extern uint16_t	__STACK_END;		// End of data
extern uint16_t	__STACK_SIZE;		// Linker-set size of stack 

uint16_t stackMinFreeCount(void)
{
	const uint16_t *stack = &_stack;
	uint16_t freeCount = 0;

	while (*stack == STACK_INIT && stack++ <= &__STACK_END)
	{
		freeCount++;
	}
	return freeCount << 1;
}

/**
 * Return size of C++ stack
 *
 * Set by the linker --stack_size option
 *
 * \return	\c uint16_t		Configued maximum size of the stack in bytes
 */
uint16_t stackMaxSize(void)
{
	return static_cast<uint16_t>( _symval(&__STACK_SIZE) );
}
#endif


int main(void)
{
... stuff
#if defined(STACK_CHECK)
	std::printf( "Stack: %d/%d\n", stackMinFreeCount(), stackMaxSize() );
#endif
...stuff
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...