Maybe i'm missing something here (paragraphs would help) but with the C18 compiler local variables within a function are generally allocated on the software stack so i have no idea what the following means:
but the reality is you have a finite
amount of space to allocate all local
function vars that exist in an entire
project
By moving all your variables to globals within a module you are requiring there is space for all of them at the same time.
buffers and have to access that memory
via pointers so I can avoid the
semantics of memory banking.
What compiler are you using?
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.
Best Answer
The following answer is based on my experience looking at mapfiles, if I'm wrong about sth. please correct me!
Static vars are definitely not stored on the heap, since this is only for variables allocated during run time (and static vars are allocated during compile time).
Static variables are stored in RAM, just like your global variables. The scope of a certain variable matters only to the compiler, at the machine code level nobody prevents you from reading a local variable outside of a function (as long as your controller doesn't have some fancy features to protect memory areas from being accessed).
No. Think about it: To write a single bit of flash, you have to erase a whole block of data an then rewrite the whole thing with the modified data. And these steps do not execute in a single cycle like a simple store into RAM does. Global variables are stored in RAM, just like mentioned before. This solves also your confusion about flash-less systems.