Electronic – Memory allocation in Microcontrollers

cmicrocontroller

I know I'm asking a basic Question. But it will be very useful for me to continue my Micro-controller Experience. Consider I am using a controller with 256 KB Flash and 8 KB Ram. My Questions are

  1. I know about memory mapping like code, Data, Stack and Heap Segment, which variable will store in which segment. But are these allocated in RAM or Flash

  2. If I am declaring a buffer, I know it is allocating in RAM. Whether it will deallocate after the function ends (if that Buffer is Locally declared)

  3. Where the Register Variable will allocate the memory.

Best Answer

Everything is done in "sections". Where a section goes depends on its use. What gets put into a section, again, depends on its use.

In general you get two "data" sections - .data and .rodata. .data is stored in RAM and is read-write. .rodata is stored in Flash and is read-only.

Things that are "const" generally end up in .rodata. Literals (string, numeric, etc) also end up in .rodata.

For instance, these would normally be stored in Flash:

const char *foo = "foo";
const int bar = 234;

"baz" (string literal)

These will be stored in RAM:

char foo[10];
int bar;

But then of course, it can be more MCU specific, especially when you get into Harvard (split RAM / Flash address spaces) architecture, where accessing data stored in Flash can be more of a special task and not done as normal variables. For instance, the const char *foo="foo"; would be copied into RAM for easy access during the initialization of the program.

When you allocate a variable of any size within a function, such as:

void func() {
    char mybuf[100];
}

the variable will be allocated as part of the stack (or an emulated stack-like system using static variables on MCUs with a limited hardware stack, such as low-end 8-bit PICs). As soon as you return from the function all the stack space is reclaimed.

However, if you allocate it using malloc():

void func() {
    char *mybuf = malloc(100);
}

it will be allocated on the heap, and it is your responsibility to reclaim that space using free().

The register keyword, as in:

int register foo;

will, if a register can be allocated, store the data purely within that allocated register. It will never touch RAM, and consequently it will run faster. However, if a register cannot be allocated (they're all in use in the code) then the register keyword will be ignored and the variable allocated in RAM as per normal. One thing to note:

char register *foo;

That will only hold the pointer to the data in a register, not the data itself. The data itself will still be in RAM.

In general, though, the use of the register keyword is frowned upon since the compiler's optimizer usually does a better job, and using register can in fact cause other parts of your code to not be optimized as well and end up more complex than they would otherwise be.