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

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

Re: [avr-gcc-list] Allocating code to separate sections


From: Erik Christiansen
Subject: Re: [avr-gcc-list] Allocating code to separate sections
Date: Thu, 9 Oct 2014 22:14:10 +1100
User-agent: Mutt/1.5.21+145 (2a1c5d3dd72e) (2012-12-30)

On 09.10.14 08:49, Alistair Gadd wrote:
> I think I prefer your first option though because it would put everything in
> that module into the .sdlib section, but my problem is I don't know how to
> create and use the linker script.

To take a copy of the linker script used for the ATmega328p:

$ avr-gcc -mmcu=atmega328p -Wl,--verbose > ld.lnk

Then, in your favourite editor, delete the two long lines of
"============", and anything outside them, keeping only the linker
script in between. And add the

   .sdlib : 0x2000
   {
        file & input section specs here
   }

where it needs to go in relation to the existing output sections.

To use your custom linker script, add "-T ld.lnk" to CFLAGS in a
makefile, or add it directly to the avr-gcc command line if that is more
convenient.

N.B. The following question and suggestion may arise because the IDE
does something weird which I have not seen:

But can those addresses possibly work? Looking at
"26.8.16 ATmega328P Boot Loader Parameters" in the datasheet, the
available bootloader addresses are: 0x3F00, 0x3E00, 0x3C00, and 0x3800.
It shows the application code _ending_ at 0x37FF, in the latter case.

In any event, the bootloader area of flash is an entirely separate
memory segment, which is best made explicit in the MEMORY description in
the linker script. To set the scene, here is how I last did it for an
ATmega16, also with the bootloader at the top of memory:

MEMORY 
{
  text   (rx)   : ORIGIN = 0, LENGTH = 62K
  boot   (rx)   : ORIGIN = 62K, LENGTH = 2K
  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 4K
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 2K
}

Doing it that way for the ATmega328p would need adding of one line, and
modification of another, along the lines of:

MEMORY
{
  text      (rx)   : ORIGIN = 0, LENGTH = 30K
  boot      (rx)   : ORIGIN = 30K, LENGTH = 2K
  data      (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0
  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
}

That corresponds with "Table 26-13. Boot Size Configuration, ATmega328P"
in the datasheet, AIUI. Now all you have to do is add:

  .boot :
  {
    *(.boot_init)       /* You may have different input
                              section names */
    *(.boot)
  } > boot

between

   .text
   {
     ...
   }              <- After this closing brace.

and

   .data
   {
     ...

Alternatively, you could skip the then necessary e.g.

void boot(void) __attribute__ ((section (".boot")));

by using my_boot_filename(*.text), as Senthil describes.

But using also e.g. __attribute__ ((section (".boot_init"))) allows you
to specify link order within the output section explicitly in the
linker script as I have shown.

I'm not sure how digestible such a short description is, given that this
is your first encounter with linker scripts, but the basics are simpler
than they look. It is only adventurousness which finds the boggy
patches.

If it is essential to use the name ".sdl", because the IDE otherwise
can't cope, then by all means change it. But with your own linker
script, you should be fully in control.

Erik


-- 
Investment in infrastructure accounts for much of China's GDP - the country is
said to have built the equivalent of Rome every two months in the past decade.
And with such a large pool of labour, it is harder to put the brakes on when
growth slows and supply outstrips demand. - 
http://www.bbc.com/news/magazine-19049254



reply via email to

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