• Announcements

    • bluehash

      Forum Upgrade   03/11/2017

      Hello Everyone, Thanks for being patient while the forums were being fixed and upgraded. Please see details and report issues in this thread. Thanks!
Sign in to follow this  
Followers 0
nickds1

Easy way to monitor peak stack usage...

1 post in this topic

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0