avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] Where to find linker script examples? (was "Howto put


From: Erik Christiansen
Subject: Re: [avr-gcc-list] Where to find linker script examples? (was "Howto put constants on fixed address")
Date: Mon, 14 Jan 2008 17:18:48 +1100
User-agent: Mutt/1.5.9i

On Wed, Jan 02, 2008 at 09:05:07PM +0100, Jan Fristedt wrote:
> I think many of us could use a linker script tutorial or faq or collection of 
> examples. Does anyone know of anything like that, less complicated than the 
> manual?

There are so many things that can be done with ld, but it's hard to
find examples of a fraction of them. I've found that experimentation,
with heavy use of objdump, to verify results, has usually allowed the
desired result to be achieved.

IIUC last december's question, then something I did recently might
illuminate some simple options. (It was a V850 project, so any absolute
addresses will look unfamiliar, but it's ld's script syntax and
behaviour that interests us here.)

My memory region naming may also look weird, but it is an example of the
freedom afforded. My preference is to lay out the target board's memory
map here, including any small blocks of hardware registers, DSPs,
time-domain switches, etc. (And bury _no_ magic addresses in line 20479
of file inconspicuous_subterfuge.c :-)

MEMORY
{
  sram       : ORIGIN = 0x0200000, LENGTH = 0x0100000  /*   1M    */
  falcreg    : ORIGIN = 0x0100000, LENGTH = 0x100      /* Chip1   */
  program    : ORIGIN = 0x0400000, LENGTH = 0x0100000  /*  .text  */
  dspreg     : ORIGIN = 0x0800000, LENGTH = 0x0800000  /* Chip2   */
  cgareg     : ORIGIN = 0x3C00000, LENGTH = 0x30       /* Chip3   */
  cgareg1    : ORIGIN = 0x3D00000, LENGTH = 0x30       /* Chip4   */
  fpgareg    : ORIGIN = 0x3E00000, LENGTH = 0x3004     /* FPGA    */
  tdsreg     : ORIGIN = 0x3F00000, LENGTH = 0x40       /* TDSW    */
  os_stack   : ORIGIN = 0x3FFE000, LENGTH = 0x1000     /* On-Chip RAM */
  mpureg     : ORIGIN = 0x3FFF000, LENGTH = 0x1000     /* CPU SPR */
}

OK, putting stuff at a fixed address within a region is easy. Here's how
that project went:

SECTIONS
{
   .check 0x0400000 :      /* Magic values at 0x0400000 are checked, */
   { *(.check) }           /* by a bootloader. */
   > program

   .jump  0x0401000 :      /* Fixed location jumptable. There are two */
   {                       /* entirely separate applications on this  */
     *(.jump)              /* board. We need to reach either.         */
   }  > program

   .fpgadata 0x0402000 :   /* CPU loads the fpga with this binary     */
   {                       /* soup. (Location fixed, so we can        */
     *(.fpgadata)          /* "be nice" to the other application.)    */
   }  > program

   .text  0x0430000 :      /* That's our part of flash, so use it.    */
   {
      *(.text)
      PROVIDE(__ctbp = .);
      *(.call_table_data)
      *(.call_table_text)
      *(.rodata) *(.rodata.*) *(.gnu.linkonce.r*)
      _etext = . ;
   }  > program

   ...

The addresses being fixed, above, are VMA (i.e. the run address) but
ld defaults the LMA (i.e. the load address) to the same, as shown by
running "objdump -h" on any ELF file to hand. If the code is not to be
moved at run-time, then VMA = LMA. On the AVR, with code in flash, the
distinction can safely be left far at the back of the mind, I think.

We don't then need ld's "AT" syntax much. It sets the LMA. But it's not
good to clutter an example with gumpf that won't be used.

It is difficult to provide useful examples of some linker script tweaks,
such as simply moving two input sections closer together in the output,
to make the object file megabytes smaller, and quicker to download.

Anyway, if the above makes it to your example collection, then the
bandwidth isn't wasted.

Erik




reply via email to

[Prev in Thread] Current Thread [Next in Thread]