This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/tms320c6713b: Stack, Stack Frame and Max Stack Calculation

Part Number: TMS320C6713B


Tool/software: TI C/C++ Compiler

Hi,

I am working on an application on TMS320c6713 dsk board. I have few question:

1) I know that when a function is called, its return address, parameters, and local auto variables are pushed to stack in a frame called stack frame. consider the following function:

void foo () {

int x,y, z,;

}

stack:

|   z     |

---------

|   y     |

---------

|   x     |

---------

Now if x,y, and z is pushed to stack as shown above, how they are randomly accessed even stack follow LIFO mechanism. I mean i can access any variable in random order, but on stack only the variable that is pushed last, should be accessible or on each random use of variable, the stack should pop all the entries until it reaches that variable which i think may not be the case. So again, how variables are randomly accessed after they are pushed to stack???

2) How can i calculate the max stack used in application and at which point??? what are the common methods used in embedded systems for stack calculation?? i think there is an option in CCS but i asking for platform independent methods.

  • This is not that kind of stack. You are thinking of an RPN stack like an HP calculator or Forth.

    You do not push and pop on the C stack, it just grows by a certain amount and the variables are accessed by their address like any area of RAM.

    It is called a "stack" because as you continue to call functions from inside functions, the various stack frames are "stacked" on top of each other.
  • x,y, and z are "local" variables. They are stored in the function's "frame," also known as an "activation record." Variables (as well as temporary variables) are accessed relative to the stack pointer (SP, which is B15 on C6x). That is, values in the frame are accessed with *SP+(imm) addressing. The compiler can and does reorder local variables, so you can't count on x,y, and z to be adjacent in the frame, or in any particular order. The optimizer might in fact optimize them away entirely.
  • Fortunately I couldn't understand your answer. I know that the variables are accessed relative to stack pointer but then why stack pointer is incremented/decremented if we have to access variables relatively, why not just store variable with respect to a fixed memory location and access it relatively???. And why even then it is called stack memory if we can access any memory in stack relative to stack pointer.... can't we only access the element that is pointed by the stack????
  • if it is so, as you stated Keith Barkley, then why would be need stack pointer??? isn't to to point to top element. If we can access variables just like any area in RAM the we could have called it ARRAY or LINKED LIST not stack, and would not need to put a REGISTER in hardware to be used as STACK POINTER!!!! all we need to declare then (as per your statement) an array with size (instead of stack size) and put variables in that array and we would have just random access RELATIVE to array base address!!!

    Also if we can treat variables just as an area in ram, then why can't you access local variable from one function in another???? it means unless you pop the current frame out of stack, return to original function, and then you can access its variables. It is actually stack, not in any sense but actual stack memory.
  • Also can you please suggest, the methods used in calculating stack size used by application??
  • Because it makes it easier for the compiler to keep track of it. Look at this fragment:

    void foo(void) {int x, y,z; return}

    .....

    if (getGPIOPinValue() == true) foo()

    ...

    The compiler has no idea whether foo() will ever be called. It would be extremely wasteful - especially on a RAM limited embedded processor - to allocate RAM space for the auto variables for every function. So, the compiler uses a stack, a relative area in memory to store the auto variables and uses the stack pointer + an offset to refer to them.

    It also allows for recursion so beloved by the computer scientists that write compilers. If the compiler sets aside specific areas in memory for the auto variables, if foo calls itself it will overwrite those variables.

    You can of course, defeat this by making all the variables static instead of auto.
  • Another aspect of the stack that is LIFO is the order that destructors are called is the reverse order that they were constructed.  You can design constructors/destructors and object creation such that actions will be performed in a certain order, and those actions would be correct if performed in a LIFO manner.  I believe the compiler's optimizer should respect such a dependency should it exist, but there may be limitations on this.  Also there may be some known corner cases (like temporaries).

  • aimal khan said:
    Also can you please suggest, the methods used in calculating stack size used by application??

    TI provides the cg_xml package which has several utilities that operate on object files, including one that calculates the worst case stack size.  See

    processors.wiki.ti.com/.../Stack_and_Heap_size_requirements and

    processors.wiki.ti.com/.../Stack_issues

  • Isn't this like solving the halting problem? How does it handle recursion?
  • It punts, of course. It tells you the function is recursive, and you need to figure it out by hand. Indirect function calls must be specified by the user, as well.