I know that .data
will be in the RAM, but I came across article that says during boot of an micro-controller the initial value of variables is stored in the ROM and then the boot-loader copy the initial values of variables from ROM to RAM, Is this true!?
Microcontroller Memory Allocation – Linker Script and Data Allocation
bootloadermemorymicrocontrollerrom;
Related Solutions
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.
Ok, let's first define some terms and the differences between them.
- Bootloader
This is a small program coded into the chip's Flash or PROM. Its purpose is to allow you to install a program from outside into the Flash or other internal storage. Apart from that it is usually completely passive and doesn't affect your running program in any way.
- Loader
This is a small program coded into the chip's Flash or PROM. It is usually installed using the bootloader originally if one exists, or it can take the place of a bootloader and also perform the functions associated with that. It's main function is to load a program from some storage medium - be that flash, SD card, or whatever - and execute it. It often also provides some IO facilities, such as routines for accessing the console. Loaders also often provide a configuration environment with NVRAM (often just a block of Flash) for storing system settings.
As you can see a loader is far more complex than a bootloader.
So they are just both concerned with getting your program into the right place, be that into Flash or RAM, depending on a) how your program is written, and b) what your system is designed to do. That is the "loading" phase of the program. With the bootloader the "loading" is done once by you when you burn your program into the chip. With the loader it is done every time at reset (if needed).
Then control is transferred to your program - be that in RAM (with the loader) or Flash (with either the loader or the bootloader). From then on everything else that happens is purely down to what your program does.
If you happened to write your program in C, then you will have certain C conventions and C library code in place. One of those conventions is the concept of the .data, .bss, etc. C library code manages those sections for you, copying data from .rodata into .data (or wherever for your system) if you are executing from Flash, blanking .bss, etc. That routine is called "crt0", or C Run-Time stage 0, and is responsible for the initialization of your program and passing control to the main() function.
If you didn't write your program in C - say you wrote it in Assembly, then what happens when control is passed to your program is entirely up to you. You might decide to have some block of RAM set aside for global variables. You may not. It's entirely up to you.
So in general, once control has been passed to your program, what happens then is entirely down to your program.
As for setting things like clocks and such, well, that depends entirely on the chip. Most of them have the basic clock settings stored in flash and are loaded up at power-on before anything else happens. On some chips they form part of the bootloader, on some they are separate, etc. Some chips provide a way of adjusting the clock from software, some don't. If they do, then when that would happen is anyone's guess. The bootloader may set the clock, or maybe a loader, or even your own program might set a specific clock speed.
For the stack pointer, each environment in the boot sequence is a separate system in its own right. Typically the bootloader or loader would set the stack pointer for its own usage. Then when control is passed to your program the stack pointer will be re-initialized by your program to suit its own needs. Once your program executes the bootloader or loader as good as doesn't exist any more. Yes, there may be the ability to call functions based in the loader (like a PC'S BIOS calls) but the loader is no longer running as such.
Related Topic
- Electronic – How to access the data from RAM and ROM(Flash)
- Electronic – Which is faster, Executing a program from ROM or RAM
- Electronic – Is a boot-loader needed to dump the flash memory to RAM? Why
- Electronic – How does a microcontroller boot and startup, step by step
- Electronic – the difference between EEPROM Data Memory and RAM
Best Answer
Ask yourself how could the system work if it isn't true?
In most implementations, the
.data
segment is for initialized data, where.bss
is for data that is set to zero. You can't count on RAM being set to anything at all on power-up, so the processor has to zero out the.bss
segment and initialize.data
.Usually this is done by storing an image of the start-up value of the
.data
segment in ROM, and copying it to the correct location in RAM on startup.