Hello,
I'm currently working on a rather large project for a SAM4E16C (128Kb RAM). In order to get a rough idea on how much stack my program is using I am using a small stack painter. Therefor, I have included the following symbols from the linker-script into my program and extracted the section addresses:
// Linker-Symbols extern uint32_t _srelocate; extern uint32_t _erelocate; extern uint32_t _sbss; extern uint32_t _ebss; extern uint32_t _sstack; extern uint32_t _estack; extern uint32_t __ram_end__; // Linker-Section-Addresses: #define DATA_START_ADDR (&_srelocate) #define DATA_END_ADDR (&erelocate) #define BSS_START_ADDR (&_sbss) #define BSS_END_ADDR (&_ebss) #define STACK_START_ADDR (&_sstack) #define STACK_END_ADDR (&_estack) #define RAM_END_ADDR (&__ram_end__)
Based on this stumbled across the following questions:
1. In the build output Atmel Studio prints 3584 Bytes as the size of the data-section and 75344 Bytes as the size of the bss-section. However, if I subtract the start and end address coming from the linker symbols, I only get 2872 Bytes for data and 42572 Bytes for bss. Why is there such a huge difference?
2. From the linker symbols I can see that the stack is placed directly after the bss-section in RAM (BSS_END_ADDR = STACK_START_ADDR + 1), leaving space after the stack. I would prefer to place the stack at the end of the RAM. Is this possible and, if yes, how can I do this?
3. In the linker script that I'm currently using (see below, I think it’s the default script for this chip), there is no section for the heap. However, my code does not fail even though it does some dynamic memory allocation. Is the heap section added somewhere else or is the free memory automatically reserved for the heap? Would it make sense to add a heap section to the linker script or is it okay the way it is? Would it still be okay if I move the stack at the end of the RAM?
4. In the following you can see my stack painter and stack counter functions (it is based on the AVR version from here: https://www.avrfreaks.net/forum/soft-c-avrgcc-monitoring-stack-usage). Do you see any problems with the implementation or do you have any improvement suggestions?
#define STACK_CANARY 0xc5 uint32_t StackPaint() { // Read the current stack pointer. uint32_t currentstackPointer = __get_MSP(); // Create a pointer. volatile uint8_t *p = currentstackPointer; // Calculate the current stack size. uint32_t initStackSize = (uint32_t)(&_estack) - currentstackPointer; // Paint the stack. while(p >= &_sstack) { *p = STACK_CANARY; p--; } // Return current stack size. return initStackSize; } uint32_t StackCount(){ // Create a pointer. volatile const uint8_t *p = &_sstack; uint32_t c = 0; // Count remaining canaries. while(*p == STACK_CANARY && p <= &_estack) { p++; c++; } // Return remaining canaries. return c; }
Thank you in advance!
Marc