This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Trouble with linker script for a paged silicon


On 16.12.12 12:24, Georg-Johann Lay wrote:
> This device has its flash layout in 64Ki byte chunks, and in order to
> put non-volatile data there, avr-gcc 4.7 and newer supports address
> spaces __flash1, __flash2, etc. according to ISO/IEC 18037 (Embedded
> C).
> 
> avr-gcc will drop data for __flash1 at input section .progmem1,
> similar for other __flashN spaces.
> 
> This input section must be located in such a way that it is a subset
> of [0x10000, 0x1ffff].  Notice this is trivially true for the empty
> set. This means that if .progmem1 is empty, it may be placed anywhere
> in order to minimize memory cutoff.

It does not need to be "placed anywhere ...". When empty, it becomes
essentially invisible to the location process, as shown by test results
at the end of this post. (Check the last test, where .hightext "snugs
down" _without_ a wasted byte, and other similar results.)

Please try the appended linker script. It provides the paged memory
model which you require. The tests and results appended after the script
show that it does NOT waste memory, because the empty output sections do
not affect the location counter, so everything butts up. (Except where
the user specifies a hole by asking for a modulo 2^16 page start,
obviously)

> If, for example, .text extends at [0, 0x2a000] and the user puts 10
> bytes into .flash2, we can locate them at [0x2a001, 0x2a00a] and there
> is no need to throw an error because .text overlaps [0x20000, 0x2ffff].

It should be noted that the .text input section is _above_ __flashN, and
therefore occupies unused __flashN from _above_, _not_ from below. For
this reason, ld's default behaviour of butting up to the preceding
section solves this imagined problem. I think you will find that, if you
read through and repeat the tests already done. Please try it.

Johann, the nifty sourcecode used to test the linker script is your own.
Please run any test you like on the appended script, and report what
might be improved. AFAICT, it satisfies all the requirements which have
recently appeared on avr-gcc-list.

If any tweaks are required, please post your test results, or just state
what extra the tested working script should do. (Soon, please. I'm
incommunicado for several weeks from Wednesday.)

Reporting the size of a page overflow is the one new minor requirement
that I detect, and yes, the ability to include variables in an ASSERT
message would be brilliant for that.

It is after 1 a.m. here, but if you take the trouble to check out what
has been developed, I can reply to any questions in the morning.

Best Regards,

Erik

file: avr6.x
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:6)
MEMORY
{
  text   (rx)   : ORIGIN = 0, LENGTH = 1024K
  data   (rw!x) : ORIGIN = 0x800200, LENGTH = 0xfe00
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
  fuse      (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
  lock      (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
  signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
}
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  .hash          : { *(.hash)		}
  .dynsym        : { *(.dynsym)		}
  .dynstr        : { *(.dynstr)		}
  .gnu.version   : { *(.gnu.version)	}
  .gnu.version_d   : { *(.gnu.version_d)	}
  .gnu.version_r   : { *(.gnu.version_r)	}
  .rel.init      : { *(.rel.init)		}
  .rela.init     : { *(.rela.init)	}
  .rel.text      :
    {
      *(.rel.text)
      *(.rel.text.*)
      *(.rel.gnu.linkonce.t*)
    }
  .rela.text     :
    {
      *(.rela.text)
      *(.rela.text.*)
      *(.rela.gnu.linkonce.t*)
    }
  .rel.fini      : { *(.rel.fini)		}
  .rela.fini     : { *(.rela.fini)	}
  .rel.rodata    :
    {
      *(.rel.rodata)
      *(.rel.rodata.*)
      *(.rel.gnu.linkonce.r*)
    }
  .rela.rodata   :
    {
      *(.rela.rodata)
      *(.rela.rodata.*)
      *(.rela.gnu.linkonce.r*)
    }
  .rel.data      :
    {
      *(.rel.data)
      *(.rel.data.*)
      *(.rel.gnu.linkonce.d*)
    }
  .rela.data     :
    {
      *(.rela.data)
      *(.rela.data.*)
      *(.rela.gnu.linkonce.d*)
    }
  .rel.ctors     : { *(.rel.ctors)	}
  .rela.ctors    : { *(.rela.ctors)	}
  .rel.dtors     : { *(.rel.dtors)	}
  .rela.dtors    : { *(.rela.dtors)	}
  .rel.got       : { *(.rel.got)		}
  .rela.got      : { *(.rela.got)		}
  .rel.bss       : { *(.rel.bss)		}
  .rela.bss      : { *(.rela.bss)		}
  .rel.plt       : { *(.rel.plt)		}
  .rela.plt      : { *(.rela.plt)		}
  /* Internal text space or external memory.  */
  .lowtext :
  {
    *(.vectors)
    KEEP(*(.vectors))
    /* For data that needs to reside in the lower 64k of progmem.  */
    *(.progmem.gcc*)
    . = ALIGN(2);
     __trampolines_start = . ;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = . ;
    /* For future tablejump instruction arrays for 3 byte pc devices.
       We don't relax jump/call instructions within these sections.  */
    *(.jumptables)
    *(.jumptables*)
    /* For code that needs to reside in the lower 128k progmem.  */
    *(.lowtext)
    *(.lowtext*)
     __ctors_start = . ;
     *(.ctors)
     __ctors_end = . ;
     __dtors_start = . ;
     *(.dtors)
     __dtors_end = . ;
    KEEP(SORT(*)(.ctors))
    KEEP(SORT(*)(.dtors))
    *(.progmem.data*)    /* Explicitly page 0 input sections */
    _elowtext = . ;
    x = ASSERT (. <= 0x20000, "Error: .lowtext (128KiB limit) overflow. Try shrinking .progmem?") ;
  } > text

  .flash1 0x10000 :
  { *(.progmem1.data*)    /* Page 1 */
  } > text

  .flash2 0x20000 :
  { *(.progmem2.data*)    /* Page 2 */
  } > text

  .flash3 0x30000 :
  { *(.progmem3.data*)    /* Page 3 */
  } > text

  .flash4 0x40000 :
  { *(.progmem4.data*)    /* Page 4 */
  } > text

  .flash5 0x50000 :
  { *(.progmem5.data*)    /* Page 5 */
  } > text

  .hightext :
  {
    /* The following is OK to follow preceding sections
       at any even byte address, on any page. */

    . = ALIGN(2) ;
    *(.init0)  /* Start here after reset.  */
    KEEP (*(.init0))
    *(.init1)
    KEEP (*(.init1))
    *(.init2)  /* Clear __zero_reg__, set up stack pointer.  */
    KEEP (*(.init2))
    *(.init3)
    KEEP (*(.init3))
    *(.init4)  /* Initialize data and BSS.  */
    KEEP (*(.init4))
    *(.init5)
    KEEP (*(.init5))
    *(.init6)  /* C++ constructors.  */
    KEEP (*(.init6))
    *(.init7)
    KEEP (*(.init7))
    *(.init8)
    KEEP (*(.init8))
    *(.init9)  /* Call main().  */
    KEEP (*(.init9))
    *(.text)
    . = ALIGN(2);
    *(.text.*)
    . = ALIGN(2);
    *(.fini9)  /* _exit() starts here.  */
    KEEP (*(.fini9))
    *(.fini8)
    KEEP (*(.fini8))
    *(.fini7)
    KEEP (*(.fini7))
    *(.fini6)  /* C++ destructors.  */
    KEEP (*(.fini6))
    *(.fini5)
    KEEP (*(.fini5))
    *(.fini4)
    KEEP (*(.fini4))
    *(.fini3)
    KEEP (*(.fini3))
    *(.fini2)
    KEEP (*(.fini2))
    *(.fini1)
    KEEP (*(.fini1))
    *(.fini0)  /* Infinite loop after program termination.  */
    KEEP (*(.fini0))
     _etext = . ;
  }  > text

  .data	  : AT (_etext)
  {
     PROVIDE (__data_start = .) ;
    /* --gc-sections will delete empty .data. This leads to wrong start
       addresses for subsequent sections because -Tdata= from the command
       line will have no effect, see PR13697.  Thus, keep .data  */
    KEEP (*(.data))
    *(.data*)
    *(.rodata)  /* We need to include .rodata here if gcc is used */
    *(.rodata*) /* with -fdata-sections.  */
    *(.gnu.linkonce.d*)
    . = ALIGN(2);
     _edata = . ;
     PROVIDE (__data_end = .) ;
  }  > data
  .bss   : AT (ADDR (.bss))
  {
     PROVIDE (__bss_start = .) ;
    *(.bss)
    *(.bss*)
    *(COMMON)
     PROVIDE (__bss_end = .) ;
  }  > data
   __data_load_start = LOADADDR(.data);
   __data_load_end = __data_load_start + SIZEOF(.data);
  /* Global data not cleared after reset.  */
  .noinit  :
  {
     PROVIDE (__noinit_start = .) ;
    *(.noinit*)
     PROVIDE (__noinit_end = .) ;
     _end = . ;
     PROVIDE (__heap_start = .) ;
  }  > data
  .eeprom  :
  {
    *(.eeprom*)
     __eeprom_end = . ;
  }  > eeprom
  .fuse  :
  {
    KEEP(*(.fuse))
    KEEP(*(.lfuse))
    KEEP(*(.hfuse))
    KEEP(*(.efuse))
  }  > fuse
  .lock  :
  {
    KEEP(*(.lock*))
  }  > lock
  .signature  :
  {
    KEEP(*(.signature*))
  }  > signature

    x = ASSERT (SIZEOF(.flash1) <= 0x10000, "Error: __flash1 (64KiB limit) overflow. Need to shrink it.") ;
    x = ASSERT (SIZEOF(.flash2) <= 0x10000, "Error: __flash2 (64KiB limit) overflow. Need to shrink it.") ;
    x = ASSERT (SIZEOF(.flash3) <= 0x10000, "Error: __flash3 (64KiB limit) overflow. Need to shrink it.") ;
    x = ASSERT (SIZEOF(.flash4) <= 0x10000, "Error: __flash4 (64KiB limit) overflow. Need to shrink it.") ;
    x = ASSERT (SIZEOF(.flash5) <= 0x10000, "Error: __flash5 (64KiB limit) overflow. Need to shrink it.") ;

  /* Stabs debugging sections.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
}

end avr6.x

file: script_tests
                           Tests and Expected Results
                           --------------------------
Trampolines, etc., must be in lower 128 KiB:
   Just fits in:
   $ avr-gcc -T avr6.x-new -Wl,-Map,flash.map -o flash.elf -DSTUBS=10 \
     -DP0=0x1f000 -DTEXT=0x20000 -mmcu=atmega2560 flash.sx

   Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800200  0003f16e  0003f1e2  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .lowtext      0001f10c  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .hightext     00020062  0001f10c  0001f10c  0001f180  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE

   .data LMA butts up to .hightext, which butts up to .lowtext.

   Overflows:
   $ avr-gcc -T avr6.x-new -Wl,-Map,flash.map -o flash.elf -DSTUBS=10 \
     -DP0=0x20000 -DTEXT=0x20000 -mmcu=atmega2560 flash.sx

   Error: .lowtext (128KiB limit) overflow. Try shrinking .progmem?

Locate __flashN at 0xN0000:
   Just fits in:
   $ avr-gcc -T avr6.x-new -Wl,-Map,flash.map -o flash.elf -DSTUBS=10 \
     -DP1=0x10000 -DP3=0x87ff -DTEXT=0x20000 -mmcu=atmega2560 flash.sx

   Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800200  00058862  00038a22  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .lowtext      0000010c  00000000  00000000  000000b4  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .flash1       00010000  00010000  00010000  000001c0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .flash3       000087ff  00030000  00030000  000101c0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .hightext     00020063  000387ff  000387ff  000189bf  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE

   Note: .hightext (where input section .text goes) butts up to 000387ff, using
         all spare .flash3. (From the next even byte address, inside .hightext.)
         .data in flash does the same with .hightext, at 00058862.

   Overflows:
   $ avr-gcc -T avr6.x-new -Wl,-Map,flash.map -o flash.elf -DSTUBS=10 \
     -DP1=0x10001 -DP3=0x10001 -DTEXT=0x20000 -mmcu=atmega2560 flash.sx

   Error: __flash1 (64KiB limit) overflow. Need to shrink it
   Error: __flash3 (64KiB limit) overflow. Need to shrink it.

   Overlaps prior section:
   $ avr-gcc -T avr6.x-new -Wl,-Map,flash.map -o flash.elf -DSTUBS=10 \
     -DP0=0x10000 -DP1=0x87ff -DTEXT=0x20000 -mmcu=atmega2560 flash.sx

   section .flash1 loaded at [00010000,000187fe] overlaps section .lowtext
   loaded at [00000000,0001010b]
   flash.elf: section .flash1 vma 0x10000 overlaps previous sections

   but ld also says this, which isn't helpful:

   section .hightext vma 0x187ff overlaps previous sections

   Overlaps following section:
   $ avr-gcc -T avr6.x-new -Wl,-Map,flash.map -o flash.elf -DSTUBS=10 \
     -DP1=0x10001 -DP2=0x87ff -DTEXT=0x20000 -mmcu=atmega2560 flash.sx

   Error: __flash1 (64KiB limit) overflow. Need to shrink it.
   section .flash2 loaded at [00020000,000287fe] overlaps section .flash1 loaded
   at [00010000,00020000]
   flash.elf: section .flash2 vma 0x20000 overlaps previous sections

   and again:
   flash.elf: section .hightext vma 0x287ff overlaps previous sections

The bulk of code (.text -> .hightext) snugs down if there are no __flashN:
   $ avr-gcc -T avr6.x-new -Wl,-Map,flash.map -o flash.elf -DSTUBS=10 \
     -DTEXT=0x20000 -mmcu=atmega2560 flash.sx

   Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800200  0002016e  000201e2  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .lowtext      0000010c  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .hightext     00020062  0000010c  0000010c  00000180  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE


   .hightext now follows imediately from .lowtext.

   

-- 
A computer is like an air conditioner, it works poorly when you open Windows.


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