Question

So I am reading from MicroC/OS-II book, but in the section for task stacks I couldn't find exactly what the stack is and most importantly - what is it used for. I know it is not something long and difficult, but I kinda' have to understand it. The book only says how to set the stack size and some other things like this. So, can somebody explain me in short and simple words what is the task stack and what is it used for, in uC/OS-II ?

Was it helpful?

Solution

In general in the context of a procedural programming language, the stack is where a function/procedure/sub-routine's local variables and return address are stored (in a "stack frame") - the greater the call depth, the more stack frames are stored - one for each function that has not yet returned. That part is true regardless of whether you are using an RTOS such as MicroC/OS-II or not.

In a single threaded environment, only one stack is required, and this is normally provided for you as part of the C runtime environment set-up for example. In a multi-threaded environment, you need a stack for each separate thread of execution, and it is typically up to you to allocate stack space for each thread, or at least to specify its length.

OTHER TIPS

I don't know MicroC/OS-II, but the stack of a task is nearly always the same:
During the execution of a task, it stores data that are required in the current context. This means when a subroutine (method, etc.) is called, a "stack frame" is stored on top of the stack. This stack frame stores local variables of the called subroutine, the return address used when the subroutine is finished, and some other info. When the subroutine returns, the stack frame is deleted. If the subroutine calls another one (or itself recursively), another stack frame is stored on top of the current one.
In contrast to a stack where stored data are deleted in reverse order as the have been stored, a heap stores data a long as their memory is not freed, which can be done in an arbitrary order.

Many processors have a stack pointer, and most of those have instructions that specifically use that stack pointer. The stack pointer is a register that holds an address, not unlike the program counter. The stack is simply memory pointed to by the stack pointer, at a higher level you or the operating system or someone divides the available memory space up for different uses, a little for data a little for program a little for heap (mallocs and frees) and some for the stack. The stack pointer and associated instructions allow code to temporarily allocate some memory. A global variable for example is at least for the life of your program stuck at one memory location. A local variable though only needs a memory location while the function is being executed, when the function returns you dont need that local variable memory (statically defined locals are allocated like globals but only available during that function, so not temporary). You could do a malloc and free in the function to allocate this local memory, or you could simply use the stack. And many/most compilers simply use the stack. In addition to local variables you might need to store the return address, if function a() calls function b() to get from b back to where you were in a you need to return to the next instruction after the call to b(). if B calls c then within the context of b() you need to save the return to a() and now within c() you need to know how to return to b(). And so on. This is architecture and calling convention dependent, some architectures always use the stack for returns, some lean toward using a specific register. When nesting calls though all architectures are going to need to eventually use the stack for the return address, so the stack is used here as well. If function a() calls itself 10 times and has one local integer and the return address lets say it needs 8 bytes of stack per call, so first call moves the stack pointer 8 bytes allocating 8 bytes, the second call another 8 and so on. when you start to hit returns, the the stack pointer moves back 8 bytes, another return another 8 bytes back on the stack pointer.

Now translate that from a single application to multiple applications with the illusion if executing simultaneously (an operating system) for each application/task/procedure/thread/whatever you probably want each of them to have their own stack. This is often quite easy as you just need to save the stack pointer from the prior task and set the stack pointer to the last value from the next task when it was switched out. You can of course get much more complicated and have protection mechanisms so each application can only live within its memory space including stack and heap. and mmus can make it even more complicated by having physical memory chopped up into many pieces and the mmu makes it look like separate pieces are linear within the applications virtual address space. etc.

as nurd_droid pointed out some processors have different stack pointers depending on the mode of the processor. you might have one for user/application mode, then when a system call happens a system/superuser stack pointer, and an interrupt happens an interrupt stack pointer. Some architectures simply have one stack pointer...Some architectures the stack is not in the main memory space the stack and stack pointer are buried in the logic and you dont really see it (often in this case the stack size is quite limited and can roll around on itself or other bad things if you dont manage your stack usage).

Stack is a data structure of type last in first out (LIFO) which is used by procedural languages to do push/pop local variable, CPU registers, return addresses before making a function call or when an interrupt occurs or for preparation of context switches.

Variables, registers are popped out in exactly reverse order when compared to order they are pushed on stack.

Stack can grow upwards or downwards in memory. This is something that will depend upon the micro-controller.

Also, many micro-controllers have multiple stacks. 1) User stack 2) Exception stack or Interrupt stack

If RTOS is used then each process/thread/task will have its own stack. In this case user SP micro-controller register will be reassigned by context switch routine to point to stack for currently active process/thread/task.

Exception stack or Interrupt stack is shared across the system.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top