EmbDev.net

Forum: ARM programming with GCC/GNU tools Specifying load addresses


von Andy K. (andykunz)


Rate this post
useful
not useful
I would like to specify that certain data be located in Flash at a
particular address.  For functions, I see that I can use the
_attribute_ capabilities to do this.  It doesn't work for constants.

I have been trying to accomplish this primarily using the linker, but
the linker needs to see my data items in a distinct section (so far as I
can tell).

I started with the atmel-rom.ld file available in the lwIP demos, as my
application is based on them.  I changed the top of the file to:

MEMORY
{
  flash  : ORIGIN = 0x00100000, LENGTH = 0x3F000
  fixed  : ORIGIN = 0x0013F000, LENGTH = 0x1000
  ram  : ORIGIN = 0x00200000, LENGTH = 64K
}

However, in order to make this work, I have to tell the linker which
modules go into the "fixed" section.

A standard declaration such as

   const unsigned char  ieee_mac[6] = {
    0x00, 0x30, 0x86,  // Our IEEE OUI number
    OUI_MINE,    // This product's code
    0xFF, 0xFF};    // Assigned by chip burner

is always going into .rodata, even though I may put an asm (" .section
fixed") before it.

I realize I could accomplish this brute-force using the same method as
the declarations found in at91sam7x256.h (i.e,  #define AT91C_PIOB_MDER
((AT91_REG *)   0xFFFFF650)  ) but I would prefer something slightly
more elegant.

Any ideas?

Thanks.

Andy

von Andy K. (andykunz)


Rate this post
useful
not useful
A solution came to mind on the way to work.  It takes several steps to
explain, but in summary what I did was use inline assembly code for the
particular constant instead of using just C.

First, I added a line to my compiler flags to cause them to generate the
assembly .lst file:

-Wa,-adhlns=$(subst $(suffix $<),.lst,$<) \

(tacked onto the CFLAGS definition).

Next, I did a make.  This created .lst files for everything.  The ones I
needed I kept, the others I deleted.

I edited those lst files to produce true ASM code.  I could have put
these into the makefile as assembly source, but I chose instead to embed
them into the appropriate .C files.

For instance, the declaration above

>   const unsigned char  ieee_mac[6] = {
>    0x00, 0x30, 0x86,  // Our IEEE OUI number
>    OUI_MINE,    // This product's code
>    0xFF, 0xFF};    // Assigned by chip burner

is now commented out, and the comparable assembly is inserted as a
series of C asm() statements as shown below:

//  const unsigned char  ieee_mac[6] = {
//    0x00, 0x30, 0x86,  // Our IEEE OUI number
//    OUI_MINE,    // This product's code
//    0xFF, 0xFF};    // Assigned by chip burner

asm ("  .global  ieee_mac");
asm ("  .section  .fixed");
asm ("ieee_mac:");
asm ("  .byte  0");
asm ("  .byte  48");
asm ("  .byte  -122");
asm ("  .byte  16");
asm ("  .byte  -1");
asm ("  .byte  -1");

Next, I had to update the linker file.  I did it by inserting the .fixed
section as the first one, then allowing it to work its regular stuff
from there.

MEMORY
{
  flash  : ORIGIN = 0x00100000, LENGTH = 0x3F000
  fixed  : ORIGIN = 0x0013F000, LENGTH = 0x1000
  ram  : ORIGIN = 0x00200000, LENGTH = 64K
}

_stack_end_ = 0x00200000 + 64K - 4;

SECTIONS
{
  . = 0x0013F000;
  .fixed :
  {
    _fixed_beg_ = .;
    *(.fixed)
    _fixed_end_ = .;
  } >fixed

  . = 0;
  startup : { *(.startup)} >flash
...

I hope this helps others.

Andy

von Martin Thomas (Guest)


Rate this post
useful
not useful
Just an additional suggestion: Did you check the gcc variable-attribute
section (see gcc-manual)? The (inline-)assembler-code can be avoided by
assigning a inititialized constant C-structure/array to a
"linker"-section using the section-attribute.

I have just done some AVR-code with avr-gcc which uses this method. I
have not tried the method on an ARM with arm-elf-gcc so far but it
should work with every "GNU-toolchain".

The basic idea:
unsigned char data_table_fixed[] _attribute_ ((section
(".fixed_table"))) =
   { 0xaa, 0x55, 0xff, 0x00 };

For AVR I have used the default linker-scripts (provided by the
toolchain/avr-libc) and just passed the section-address as parameter to
the linker:
LDFLAGS += -Wl,--section-start=.fixed_table=0x2000
But of cause you could use a "DIY" linker-script the way you have
already implemented it.

I checked the locations and contents in a disassembly created with this
target in the makefile:
%.lss: %.elf
[TAB]  $(OBJDUMP) -D -h -S -C $< > $@

Remark on your linker-script: If you declare an extra MEMORY area for
"fixed" the line . = 0x0013F000; should not be needed. Did you try to
link without this line in the linker-script?

Martin Thomas

von Andy K. (andykunz)


Rate this post
useful
not useful
Thanks for the reply, Martin.

> Just an additional suggestion: Did you check the gcc variable-attribute
> section (see gcc-manual)? The (inline-)assembler-code can be avoided by

At the time I did this, I had not found the attributes for variables
section yet.  Use of the attribute on the variable would have been much
more elegant.

> Remark on your linker-script: If you declare an extra MEMORY area for
> "fixed" the line . = 0x0013F000; should not be needed. Did you try to
> link without this line in the linker-script?

The reason for the separate section is because we will be putting a
bootloader into the same area eventually.  I do not want the possibility
of application code being in the same region - I would prefer to have
the linker tell me I ran out of memory first.

I appreciate all you've done with this work.  Your examples have been
very helpful in understanding how to approach solutions to problems in
several areas.

Andy

von Andy K. (andykunz)


Rate this post
useful
not useful
Martin,

I just implemented the code according to your example and it works fine.

The extra MEMORY line is to force a specific load address for the data.
It will be in a protected portion of memory shared with the bootloader.
I didn't see another way to force it to the exact address I wanted.

Thanks.

Andy

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.