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]

Trouble with linker script for a paged silicon


Hi.

I am struggling with a new default linker script for AVR.

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.

My current attempt reads like that:

SECTIONS
{
  ...

  .text :
  {
    ...
    *(.text)
    *(.text.*)
     _etext = . ;
  }  > text

  .flash1 MAX (1 << 16, ADDR(.text) + SIZEOF(.text)) :
  {
     PROVIDE (__flash1_start = .) ;
    *(.progmem1)
    *(.progmem1.*)
  }  > text

...

  .flash3 MAX (3 << 16, ADDR (.flash2) + SIZEOF (.flash2)) :
  {
     PROVIDE (__flash3_start = .) ;
    *(.progmem3)
    *(.progmem3.*)
  }  > text

  .data : AT (ADDR(.flash3) + SIZEOF(.flash3))
  {
    ...
  }
  ...
} /* SECTIONS */


Questions:


1) Is it possible not to waste memory if .flashN is empty? What I tried is:

  .flash1 MAX (SIZEOF(.flash1) ? 1 << 16 : 0,
               ADDR(.text) + SIZEOF(.text)) :
  { ...

But it will evaluate as if SIZEOF(.flash1) was zero.

The docs read:

> SIZEOF(section)
>     Return the size in bytes of the named section, if that section
>     has been allocated. If the section has not been allocated when
>     this is evaluated, the linker will report an error.

As I don't get an error, the conclusion is that SIZEOF(.flash1) is known and brings a reasonable value. However, with the following linker script

  _sizeof_flash1  = SIZEOF(.flash1) ;
  _endof_text     = ADDR(.text) + SIZEOF(.text) ;
  _startof_flash1 = MAX (_sizeof_flash1 ? 1<<16 : 0, _endof_text) ;
  .flash1 _startof_flash1 :
  {
    ...
  }

and a non-empty .flash1 with 0xa bytes the map file reads:

0x0000212e _etext = .
0x0000000a _sizeof_flash1 = SIZEOF (.flash1)
0x0000212e _endof_text = (ADDR (.text) + SIZEOF (.text))
0x00010000 _startof_flash1 = MAX (_sizeof_flash1?0x10000:0x0, _endof_text)


.flash1         0x0000212e        0xa
                0x0000212e                PROVIDE (__flash1_start, .)
 *(.progmem1)
 *(.progmem1.*)
 .progmem1.data.foo1
                0x0000212e        0xa c:\Temp\ccMUm0N4.o
                0x0000212e                flash1_start

Obviously, the right values are calculated for _startof_flash1 but not transferred correctly to the section start.

Is this a bug (in the documentation, in the linker) or a feature?

Can this be fixed in the AVR part of ld?


2) How do I express this correctly? The requirement is to move the location (counter) forward only if the stuff that follows is non-empty.


What works is

. = MAX (. , 0x10000)

but that moves the location unconditionally and wasted memory because the location counted is moved (an thus data bumped to a high address) for no reason. What I need is something like

  . = MAX (. , __some_end == __some_start ? 0 : 0x10000)
  __some_start = .
  *(.some.stuff*)
  __some_end = .

i.e. there is no need to advance the location for nothing. ld will complain on the forward references.

Notice that neither ALIGN nor NEXT will do this.

Id there a way to pre-compute the difference? The different won't change its value, no matter where stuff is located in the end. as can handle label differences, maybe ld can, too?


3) The end of the script contains assertions:


/* Sanity check the progmem stuff: .progmemN must be located within the
   N-th 64Ki byte chunk.  The low end needs no checking because the MAX
   with .flashN sets the right start address if .flashN is non-empty.  */

__assert_flash2
  = ASSERT (!SIZEOF (.flash2)
            || ADDR (.flash2) + SIZEOF (.flash2) <= 3 << 16,
            "section overflow: .progmem2 (__flash2)");

This works correctly but gives no indication on how much the section overflowed. This means the user must trial-and-error juggle his data until he finds a working configuration. He can not infer from the message how much data he has to move away from flash1 in order to satisfy the assertion, which is quite annoying.

Is there a way to report numerical values / values of expressions in a diagnostic? Similar to GCC's error() or warning() that implement a printf-like interface? Something like a %d together with a varargs ASSERT?

I observed that there are neat messages that report overlapping memory regions. However, the pages mentioned above are not mutually exclusive because .text. and .progmemN may use and will use the same flash.

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].


Many thanks for your advice


Georg-Johann


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