We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi, I am a beginner level developer and until now I have been working on PIC18 & PIC16 using MikroC compiler. But now I am working on a project with LPC2138, an ARM7 based MCU from NXP, using Keil uVision. The project includes GSM module interfacing, EEPROM, SD card, different digital (with I2C and SPI interface) and analog sensors etc. This may later include USB and Ethernet interfacing too (for which I intend to shift to LPC2378). Well ... In case of MikroC, the compiler allocates all required memory ONLY at compile-time (a negative aspect of which is that the functions are non-reentrant) so I never had to worry about the concepts like dynamic memory allocation and heap etc.
Now with Keil, I started developing without giving much thought to memory management. Once I created an array of 4000 elements inside a function (local variable) and after compilation there was no significant change in used RAM space. This made me start wondering about compiler's memory management. According to my current knowledge about PC high-level programming: 1. local variables: values are stored on stack and references are stored on heap 2. dynamically allocated variables (using malloc etc) are stored on heap if above two points are correct and these concepts apply to MCU's as well, then my array would be created on stack and if there's not enough stack, there will be stack-overflow. Am I correct? I used this syntax to create my array: [syntax=c]char arr[4000] = "";[/syntax] my second question is: Who Pushes and Pops the data to and from stack as there is no OS in my case. Does compiler include some house-keeping code during compilation/linking?
P.S. I would also like to discuss the concepts like function reentrancy and dynamic memory allocation in some detail but first let's clear my concepts about above two questions. P.P.S. if you think that this question is possible duplicate, please overlook my laziness although I did try (a bit) to find my answers through google. please provide me some pointers where i could have learned these things.
Thanks in advance. I'd really appreciate your response.
It isn't the "PC" that is special.
It is your MicroC compiler (and some other compilers too, like the Keil C51 compiler for 8051 chips) that is special in converting auto data into static data as a work-around to processors with limited stack or with limited stack-operating instructions.
For "normal" processors, the compilers just make use of a base pointer that points at the current stack frame. So moving this stack pointer 20 bytes either allocates or releases 20 bytes for auto variables. And the compilers also generate code where they decide if parameters can be sent in registers, or if they need to be pushed on the stack - and later popped from the stack.
On a PC, you normally have access to huge stack space - processes/threads are normally setup with multiple megabytes of stack space for each process/thread unless they explicitly inform that they need less.
On a microcontroller, you have to specify the stack size. In the startup file, the initial stack is initialized. If you use an RTOS,then that has some own mechanics for specifying the stack size of the individual tasks.
Avoid large objects on the stack, unless you have a big advantage of keeping them there. Like multiple different functions never called at the same time that each needs a larger chunk of memory that can be released directly when they return. Then they can reuse the same memory, making it meaningful with a larger stack.
For things that needs to live a longer time, it's better to either make them global (potentially static to keep them from the global name space) or implement some logic to allocate/release memory as needed. Embedded programs can often avoid the use of the heap because they have very good control of the lifetime of the program. And a standard heap implementation can suffer from fragmentation of memory if different-sized blocks are regularly allocated/released in random order.
Anyway - placing auto variables on the stack is what the C language standard intended. Your old compiler created non-standard code just because the cost was too high to try to follow the C standard.
Hi Per Westermark, Thank you very much for your well explained response. I guess using MikroC for some time limited my understanding but your starting line "It isn't the "PC" that is special." helped me shift my perspective :) Also thanks for your suggestion about heap usage. I'll keep that in mind.