EmbDev.net

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


Author: Andy Kunz (andykunz)
Posted on:

Rate this post
0 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

Author: Andy Kunz (andykunz)
Posted on:

Rate this post
0 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

Author: Martin Thomas (Guest)
Posted on:

Rate this post
0 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

Author: Andy Kunz (andykunz)
Posted on:

Rate this post
0 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

Author: Andy Kunz (andykunz)
Posted on:

Rate this post
0 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

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.