8
\$\begingroup\$

Suppose I am using a 8051. I compiled a code which has a static variable. Where that Static Variable will be stored? In RAM? In Stack? On Heap?? In flash? Where?

Also, Correct me if I am wrong: CONST are stored in ROM. And global variables are stored in Flash.(What if I don't have Flash?)

I am expecting answers with respect to Embedded Programming. It's not like in Code Segment or in .bss, but exact where on my board?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ I expect static variables to be stored at the same place as global variables. After all, they are the same thing with different scope. (let me know if I'm wrong) \$\endgroup\$
    – user606723
    Commented Jun 18, 2012 at 16:08

6 Answers 6

7
\$\begingroup\$

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).

And global variables are stored in Flash.

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.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ "static variables" known at compilation time are not variables, but constants. Static variables are assigned and changed at run-time. The difference with other variables is their scope and lifetime: they exist as long as the program exists. \$\endgroup\$
    – stevenvh
    Commented Jun 18, 2012 at 13:06
  • \$\begingroup\$ @stevenvh: I can think of examples of static variables, which are certainly not constant. If you were right, would that not mean that the const keyword would be useless? \$\endgroup\$
    – 0x6d64
    Commented Jun 18, 2012 at 15:12
  • 1
    \$\begingroup\$ You've edited your answer, but the way it was worded it looked like being known at compile time was the basic criterion to call it static. You perfectly can define static variables whose value isn't known at compile time; you can declare them without assignment. \$\endgroup\$
    – stevenvh
    Commented Jun 18, 2012 at 15:17
11
\$\begingroup\$

Suppose I am using a 8051.

Then you are supposed to know about CODE, DATA, IDATA, XDATA and PDATA memory - 8051 is a multi Harvard architecture.

Where that Static Variable will be stored?

That is a good question. It will depend on the compiler settings - usually called "memory model"; But you can also explicitly say where the compiler will put it:

xdata unsigned int i;  // integer in XDATA memory

The compiler/linker should be able to crate a Map file, which will show you the addresses of your variables.

CONST are stored in ROM.

This probably depends on the compiler and needs to be checked against the Map file. I remember tagging those explicitly:

code const char fooStr[]="Foo";  // string constant in code = flash memory

And global variables are stored in Flash

Both true and false. They reside in one of the 8051's data memories, but the initial value will be loaded from Flash at startup time - unless the variable is initialised with zero.

\$\endgroup\$
2
\$\begingroup\$

On processors where the code store is in the same address space as all other variables, compilers will typically place "const"-qualified global or static variables into their own link section, and linkers will typically be configured to place that section in the system's code store (flash, OTP, or whatever). This will reduce the amount of RAM required by the program, and will reduce the amount of work the startup code has to do.

On processors where the code store is in a different address space (e.g. the PIC or 8051), some compilers will use a const qualifier to signal that they should place the variables into the code store and use different instructions to access them, while others will not. Such compilers will require that only pointers with a const qualifier may be used to access const-declared variables, since without that requirement the compilers wouldn't know that special instructions had to be used to access such pointers.

On the 8051 compilers I've seen (Archimedes and Keil), there are 8051-compiler-specific keywords __data, __idata, __code, __bdata, _pdata, and_xdata available to indicate that variables should be loaded in a particular address space. By default, the names can be used with or without underscores; the non-underscore versions are more convenient, but may be disabled if, e.g. one is porting a program which uses identifiers named code or data). If a pointer is declared without applying one of those keywords to its target, the compiler will allocate three bytes: one to indicate what memory space the target is in, and two to hold a 16-bit address if one is required. Declaring a variable const without also applying a code qualifier will cause the variable to be placed in the default RAM address space, and loaded with the default value at startup; a variable declared that way may be passed to code expecting a pointer in the default address space (but will use RAM). Adding a __code (or code, if enabled) declaration will cause the variable to be placed in code space. It's usually better to use the code declaration than not, but in some cases, especially if the item in question is small, the comparative ease of accessing things in idata RAM might make up for the loss of a few bytes of that space.

\$\endgroup\$
0
\$\begingroup\$

Partial Answer: "Also, Correct me if I am wrong: CONST are stored in ROM."

Incorrect. The keyword 'const' is a directive to help the compiler. When a variable is declared as 'const' then the compiler knows it cannot change, but it is still a variable that is allocated a memory location.

If you need/want to store it in ROM, then you will need to use another keyword for the compiler that tells it which memory type or location to use. I don't think there is a standardized keyword for this. Probably because C started life on a PC with all program space and variable space being RAM.

For a PIC, you would use the keyword 'rom' in declaring the variable.

e.g. "rom int const x = 42;'

\$\endgroup\$
1
  • \$\begingroup\$ The placement of a const variable is controlled by a non-standard keyword sometimes. Note that there is often a way to configure the linker to define where the const variables are stored. This, of course, varies with each tool chain. \$\endgroup\$
    – semaj
    Commented Jun 18, 2012 at 15:12
0
\$\begingroup\$

Static implies the variable is both isolated to that file/function/area of code. The place where it is defined it is both only visible there and when used on non-globals essentially turns that variable into a global from a storage perspective. A local variable with a static definition means I want to not lose that value from one call of this function to another, so it has to be stored globally for that function, normally a local variable is on the stack so the function can be re-entrant (a new copy of the local variables for every entry into the function). So static globals are global anyway, static locals are local but stored along with the globals. In what is often called .data but toolchains may have different names. This is basically the ram/memory (read/write) where your other globals are stored or where variables that are initialized when defined

int x = 7;

are stored. Global variables or static locals that are not initialized when defined

int y;

are in what is often called .bss. This is another chunk of read/write memory, but this memory before starting main() is zeroed for you so that per the spec or per assumption those variables are zero when your program starts.

const is a way of saying I am declaring this as a read only variable, I dont plan on every storing to it just reading from it. So the compiler may choose (actually it is the programmer as they ultimately dictate what the linker does, often letting the default linker script be used and not taking over that job) whether that goes to flash or ram, it can go either place and work just fine.

For microcontrollers and other places where you need to boot and start running from non-volatile memory (flash/rom/etc). First off the program itself has to be stored in something non-volatile. Next the .data stuff, things that you initialized in your code when defining the variable, stuff that at compile time can be determined. has to also be in non-volatile storage, but that data is read/write ultimately so the bootstrap code that runs before main() is called, does the job of copying the .data blocks to read/write memory. The .bss code or global or static local variables that are not initialized and assumed to be zero when you start, those do not need non-volatile storage, just the location and how much does, and from that the bootstrap can zero that read/write memory.

There are reasons why we communicate using terms like .text, .data, .bss, .rodata, etc. Because we see that the tools place elements of our program into those places and then we can see where those places have to live in non-volatile storage and then during runtime if that is different. .text although goofy, is our program, the machine code and other associated data. .data is variables from our program that are initilized before starting to be non-zero so they have to be stored in non-volatile storage then moved to read/write before using them. .bss is variables from our program that are assumed to be zero when we start, so the amount and location needs to be stored in non-volatile and the boostrap can do the zeroing (or sometimes they are just stored as a bunch of zeros in the flash/rom as well). .rodata is sometimes separate it is the consts sometimes the consts are found in .text, .text and .rodata are considered to be read-only so they can remain in flash if your product can handle that (newer flashes have read-disturb problems so outside the flash on a microcontroller you dont necessarily want to do that, you have to be careful) or they can be copied to ram as well.

Then there are the terms heap and stack, which often after your program if needed, .bss and .data consume some amount of ram, often from the lower addresses up. then the rest of that ram is divided up into heap and stack, sometimes without a solid line between them, ill behaved programs can have the heap and stack collide causing a crash. stack is often top down and heap is often bottom up, but these are not hard and fast rules.

Where are these on your board? well it depends both on the chip and the board as to what the options are then ultimately it is up to you the programmer to decide as you control the compile and linking process. Most folks get an example or a toolchain that knows about your system and you leave the default settings. But you are utimately responsible. For a microcontroller to boot you have to have a way to do that, usually that is a flash on or off chip depending on the mcu, and the above mentioned non-volatile stuff has to be stored there or in some other non-volatile place. Likewise you have some ram, you have to divide that up with the read/write things you need including stack and heap if you are brave enough to use it in such a system (not wise). Some processors the stack is part of the design and you dont have to worry about, others you do. If you have multiples of these things, non-volatile or read/write ram then great you can pick and choose where to put things.

if you use a toolchain from someone, or have access to different ones there is no reason to assume they will do the exact same thing with your program with their default linker script. usually toolchains provide map files or other ways to see where they have placed things for you.

it is certainly possible to have a microcontroller based system with no flash, every hear of a mouse or keyboard? Some of the along with many other products can work without such things. Some may for example have in the logic of the chip to manage the usb enumeration, then the operating system driver for that product contains the firmware, downloads the firmware to ram on the device, and starts the processor and perhaps re-enumerates the usb so that it is now a mouse or whatever. not everyone does it but it is done sometimes. Likewise you may have some other design where some other hardware or solution downloads the program into the chip/ram before starting the processor effectively making it feel like that processor has no flash. But you still have the same .text, .data, .bss concepts and the program you run be it ram only still was compiled down into program, zero init data, and non-zero init data and the linker had to be told where to place these things in the binary and patch up the code to know where the linker had placed the variables it needs to use.

\$\endgroup\$
-1
\$\begingroup\$

Though your question is related to 8051 and many right answers have been suggested,i would also like to include an answer for people who land up here by just reading your question and not the details. I would like to provide few links for the ARM architecture on the LPC Series of microcontrollers using Keil IDE. These are few important links that helped me understand the behaviour of where variables are placed:

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.