2
votes

I'm trying to create an extra ram section (in my GNU linker script) for initialized data, in my ARM MCU. The section will have to be placed at a known address, so that I can set specific attributes for it in the MPU. I'm having some trouble with all the linker magic.

The memory is divided as follows:

/* Memory Spaces Definitions */
MEMORY
{
  rom (rx)  :         ORIGIN = 0x00420200, LENGTH = 0x001DFE00
  ram (rwx) :         ORIGIN = 0x20400000, LENGTH = 0x0005e000
  ram_nocache_section (rwx) : ORIGIN = 0x2045e000, LENGTH = 0x00002000
  sdram(rwx):         ORIGIN = 0x70000000, LENGTH = 0x00200000
}

It's the "ram_nocache_section" that I'm trying to handle.

I can define an appropriate section as follows:

/* no cache section */
.ram_nocache :
{
   . = ALIGN(8);
   *(.ram_nocache)
} > ram_nocache_section

This works, but the resulting binary is gigantic. 0.5 GB. This is because the ram address space is 0.5 GB apart from the flash address space. The way to deal with this, is to 'relocate' the initialized ram data. The script performs this like so:

.text :
{
    ...
} > rom

. = ALIGN(4);
_etext = .;

.relocate : AT (_etext)
{
    . = ALIGN(4);
    _srelocate = .;
    *(.ramfunc .ramfunc.*);
    *(.data .data.*);
    . = ALIGN(4);
    _erelocate = .;
} > ram

This will magically allocate initialized data (and ram functions) both in flash and in ram. So this would be easy just to copy, right? Like so:

. = ALIGN(4);
_etext = .;

.relocate : AT (_etext)
{
    . = ALIGN(4);
    _srelocate = .;
    *(.ramfunc .ramfunc.*);
    *(.data .data.*);
    . = ALIGN(4);
    _erelocate = .;
} > ram

. = ALIGN(4);
_eramdata = .;

.relocate2 : AT ( _eramdata )
{
    . = ALIGN(4);
    _srelocate2 = .;
    . = ALIGN(8);
    *(.ram_nocache)
    . = ALIGN(4);
    _erelocate2 = .;
} > ram_nocache_section

This will compile, but the resulting binary is still gigantic. This is because the _eramdata symbol is somehow placed in ram and not in flash like the _etext.

Well then... According to this document, I should be able to do something like this instead:

.relocate2 : AT ( _etext + SIZEOF(.data) + SIZEOF(.ramfunc) )
{
    . = ALIGN(4);
    _srelocate2 = .;
    . = ALIGN(8);
    *(.ram_nocache)
    . = ALIGN(4);
    _erelocate2 = .;
} > ram_nocache_section

This wont compile though. Instead I can create the desired result like so:

.relocate2 : AT ( _etext + 10k )
{
    . = ALIGN(4);
    _srelocate2 = .;
    . = ALIGN(8);
    *(.ram_nocache)
    . = ALIGN(4);
    _erelocate2 = .;
} > ram_nocache_section

However, this is a rather fragile and wasteful solution.

How do I do this properly? I want to place the 'relocate2' section right next to the regular 'relocate' section. Without any excess waste or predefined code limits.

2
Read about the NOINIT attribute.too honest for this site
I'm guessing that NOINIT is similar to NOLOAD. Which will prevent any initialization of variables. This will solve the issue (I've checked) but it'll also break the program. (I'm using initialized data.)Illishar
Not clear what you want then. Why not use the standard .data section then? And you don't have a load memory specified.too honest for this site
I want to create a section different from .data at a specified address (so that I can remove some cache attributes etc.)Illishar

2 Answers

2
votes

I like this construct better:

. = ALIGN(4);
_etext = .;

.relocate : 
{
    . = ALIGN(4);
    _srelocate = .;
    *(.ramfunc .ramfunc.*);
    *(.data .data.*);
    . = ALIGN(4);
    _erelocate = .;
} > ram AT>rom

.relocate2 :
{
    . = ALIGN(4);
    _srelocate2 = .;
    . = ALIGN(8);
    *(.ram_nocache)
    . = ALIGN(4);
    _erelocate2 = .;
} > ram_nocache_section AT>rom

Both sections have to changed to AT>rom. (No mixing.)

0
votes

I might have found the solution myself:

.relocate2 : AT ( _etext + SIZEOF(.relocate) )
{
    . = ALIGN(4);
    _srelocate2 = .;
    . = ALIGN(8);
    *(.ram_nocache)
    . = ALIGN(4);
    _erelocate2 = .;
} > ram_nocache_section

I was sure that I'd already tried something like that. But this seems to be what I'd wanted. Still not the most elegant solution though.