This is the mail archive of the crossgcc@sourceware.cygnus.com mailing list for the crossgcc project.

See the CrossGCC FAQ for lots more infromation.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: possible to have some C variables uninitiialized?


Everyone:

Thanks for the help on this one.  With it I was able to implement what I
wanted.  To remind ya, here is the bulk of my original inquiry:

"I'd like to know if there is a way to have the gcc compiler/linker not
initialize certain C variables that will be located in a battery-backed
RAM area.  I'd like these global variables to be declared normally (if
possible), for example, "int IAmANonVolatileInt;", but I don't want them
lumped in with the normal global variables that will get initialized to 0
on powerup of the embedded system."

Attached is a file containing all of the individual responses (with the
names deleted to protect the guilty).  

Here's what I ended up doing:

------------

In a master header file:

#define NON_VOLATILE __attribute__ ((section (".uninit"))) = { 0 };

/*
note:  the gnu compiler will place variables declared NON_VOLATILE in the
zero (.bss) data section instead of the desired .uninit section) UNLESS
the variables are initialized to zero in the c code (i.e., = 0), so we
force that to be the case here; braces are for zeroing arrays
*/

------------

In .c file(s) that want to use this feature:

int foo NON_VOLATILE;

------------

In the linker command (.ld) file:

MEMORY
{
  <snipped>
  uninitvar_ram (W) : ORIGIN = 0x110000, LENGTH = 4K
}
SECTIONS
{
  <snipped>

  .uninit (NOLOAD) :
  {
    *(.uninit)
  } > uninitvar_ram
} 

------------
------------------------------------------------------------------------------

I'm using gcc on a 68000-based embedded system that has some normal RAM and
some battery-backed RAM.  I'd like to know if there is a way to have the gcc
compiler/linker not initialize certain C variables that will be located in the
battery-backed RAM area.

I'd like these global variables to be declared normally, for example,

int IAmANonVolatileInt = 3;

but I don't want them lumped in with the normal global variables that will get
initialized to either 0 or to a certain value on powerup of the embedded
system.

I could cheat and do the following:

#define BATTERY_BACKED_RAM_ADDRESS (0x800000)
#define IAmANonVolatileInt (*(int *)BATTERY_BACKED_RAM_ADDRESS)

but I'd rather not.

Any ideas on how to accomplish this?  An example would be great, too!

------------------------------------------------------------------------------

Ooo, I know this one.

There's a GCC extension to place data items in sections other than data and
bss. You can declare a data item like this:

    int foo __attribute__ ((section ("BATTERY"))) = 23;

The section BATTERY needs to be put someplace at link time so you write your
own ld script, which isn't hard, I learned how to do it last week.  A couple
of hours of fiddling after reading 'info ld' and you'll know the whole deal.
Depending on how the battery backed up memory gets initialized the first time
you might need to use the "AT" command in the ld script to store the
initialized data in ROM but locate the addresses in the special memory.

------------------------------------------------------------------------------

This is how I would do it:

Step 1:
Make a structure that contains all of the variables you want to be in battery
backed RAM.

struct MyRamStruct
{
/*Stuff goes here */
};

Step 2:
Declare the struct extern:

extern struct MyRamStruct foo;

Step 3 in the linking step define the location of foo;

So

foo= 0x8000000;

That is how I would do it. There are other ways, you could define a new
section type and then assign that to the RAM space in the linker file.

------------------------------------------------------------------------------

Does anyone know why the section attribute only works on initialised
variables? The manual says it's because of the way the linker works but the
explanation is a bit lost on me...

------------------------------------------------------------------------------

gcc normally declares uninitialized variables as common variables. This means
that you can do

    int i;

in one file and

    int i = 4;

in another file, and have i in the first file refer to the same variable as i
in the second file.  This is a common Unix extension to the ISO C standard.

A common symbol can not be in a section.  If it were, it would be a defined
symbol, not a common symbol.

Even when gcc does not use common symbols, as with the -fno-common option, it
still puts uninitialized variables in the BSS section. This means that the
variables do not take up any space in the executable, which means that the
executable is smaller and loads faster.  Space for these variables is
automatically allocated by the loader.  Again, a variable can not be both in
the BSS section and in some section which you name.

gcc could certainly support the section attribute on an uninitialized variable
by simply treating the variable as having been implicitly initialized to 0.
So far the gcc maintainers have chosen to treat the section attribute as not
modifying the usual treatment of uninitialized variables.

------------------------------------------------------------------------------

The manual appears to be misleading. I have found that it works with
uninitialised variables as well.  However, if you mix uninitialised and
initialised in the same section, you end up with zero initialisers for the
uninitialised variables. This is the same as for normal unitiliased variables
that go in the .bss section, but that section is normal not loaded into PROM,
it is just cleared.

------------------------------------------------------------------------------

One way that I can think of is to put those variables in a separate section,
say ".uninit", and then put the '(NOLOAD)' option for this section in your
linker script. By doing this, the linker will compute the correct relocation
address without loading the section into the battery-backed RAM.

The following template of linker script may help you:

...

MEMORY {
   NormalRAM: ORIGIN = ....., LENGTH = ....
   BattRAM  : ORIGIN = ....., LENGTH = ....
}

SECTIONS {
  ... other sections [.text, .data. ,bss, ....] here

   .uninit (NOLOAD) : { ...... } >BattRAM
}

....

------------------------------------------------------------------------------

If you do not want them initialized, then why specify an initial value (the =3
in your example)?

------------------------------------------------------------------------------

Good eyes.  I should have just said:

int IAmANonVolatileInt;

------------------------------------------------------------------------------
------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]