nickds1 11 Posted March 28, 2017 Share Posted March 28, 2017 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 } bluehash, tripwire and stirlingboy1426459970 3 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.