How is memory used on the AVR?

nobody wrote on Monday, June 20, 2005:

HI I would like to know how RAM memory is used on the AVR using WinAVR.

I have a task that makes a function call. but for some strange reason the the function does not return properly. The compiler generates some internal functions and performs a "call" and "ret" as required to access these codes.
Using VMLab to simulate the code, i find that where the function was to return, there is this compilers internally generated function call that continues to remain on the call stack.

Everything goes haywire from here on and VMLab reports error trying to access illegal memory locations. I initially thought that this was an error due to small stack sizes. I then doubled tribled and quadraupled the stack size of the 3 tasks that i run. Still no use.

Trying to understand the problem better, i wanted to know how memory is managed with FreeRTOS and WinAVR as i am new to both of these tools.

rtel wrote on Monday, June 20, 2005:

FreeRTOS RAM usage is very simple.  Every time the kernel requires memory it makes a call to pvPortMalloc(), which is just a C function and will not result in any unexpected code being inserted into the binary.  Take a look at the memory management page on the site for more details:

If there are memory corruption problems then the most likely scenario is that you are running out of stack space within your task.  Try creating the tasks with larger stacks.

I am not a GCC expert, but there are a couple of cases that I know of where unexpected function calls may be inserted into the code.  The first is if you are using floating point variables, where functions can get inserted for multiplication, divides, etc.  The second is with some optimisations turned on  especially space (code size) optimisations which can result in common code sections being grouped into functions.

Can you provide a sample very small project that exhibits such behaviour?  One with just a couple of functions.


nobody wrote on Monday, June 20, 2005:

I my case the point of error is right where i use double precision floating point math. The same used to be working until recently. I have made plenty of changes since and am unable to get back. The simulator however, shows no error until soon after this function call. It is here that the call stack gets suspicious. I have tried increasing the stack size for all of the 3 tasks created. I have raised the stack size upto 800!!!! on the mega128 but the problem persists.

I will try to regenerate the problem with the smallest piece of code and mail it to you.

I was assuming that all local variables, context etc are placed in stack which grows downwards from RAM end. All dynamically requested memory such as by queue create etc. (calls to pvPortMalloc()) are allocated on the heap which grows from lower address to upper similar to malloc().

Does the TaskCreate function also allocate memory on the heap? If so, then there is nothing that is using the absolute RAM end? and the heap size declared in the configuration file can be as big as the available RAM minus the global and static variable requirement?

rtel wrote on Monday, June 20, 2005:

Your last paragraph here is correct.

The kernel maintains its own heap - the size of which is set in the configuration file FreeRTOSConfig.h.  All the kernels memory requirements come from that memory pool.  If your application does not use any calls to malloc() (as opposed to pvPortMalloc()) then no other heap is required.

When a task is created the stack for the task is obtained from this memory pool.  Therefore once the scheduler has started the original stack (that used by main()) is no longer used.

Some floating point libraries can be very stack intensive but 800 is huge.  You also have to be careful that the libraries are reenterant (I think this is the case with GCC, but check the compiler options).


nobody wrote on Monday, June 27, 2005:

Thanks. This problem is solved. The issue seems to be with that of optimisation used by GCC. The function not returning was a caused by such an optimisation.

The memory problem was due to bad programming on my side in an other task. Seeing that the function continued to stay it stack even after it is supposed to have completed that step confused me.

Compiler optimisation reorders the code we write and it is debugged too with this optimisation and hence got confusing.