Question

I'm writing a customized linker script for a bare-metal ARM application. The application is stored in a flash memory, at the moment I have a bootup code copying the whole application in SDRAM, and continuing execution in SDRAM for speed purpose. I want to modify this script to run the whole code from flash directly, but I have problems understanding certain elements.

In the linker script below, the .ram_data section has an execution address in RAM and a load address in ROM (both sections in SDRAM). From what I understand the execution address is used by the linker to do the symbol resolution of all elements which are not PC relative, but what about the load address? In the context of a bare-metal ARM there is no such thing as a program loader, and there is no way the linker can have any influence on where I write the program in flash, so what is it actually used for?

In the same way, how can the linker have any influence on the SDRAM being (rx) or (rw) at run-time? Does it actually change anything when I modify those options in the memory regions?

MEMORY
{
  RAM(rw) : ORIGIN = 0x00001000, LENGTH = 12M-4K
  ROM(rx) : ORIGIN = 0x007f1000, LENGTH = 60K
}              

SECTIONS                                                                
{    
   .startup : 
   { ... } > VECTOR                

   .rom_text :   
   { ... } > ROM 

   .ram_data : 
   {   
      _data_start = .;                                                                 
      *(.data*)        
      _data_end = .;       
   } > RAM AT>ROM 

   .ram_bss :
   { ... } > RAM
}
Was it helpful?

Solution

Given your example linker script, these two questions are related.

From what I understand the execution address is used by the linker to do the symbol resolution of all elements which are not PC relative, but what about the load address?

In the same way, how can the linker have any influence on the SDRAM being (rx) or (rw) at run-time? Does it actually change anything when I modify those options in the memory regions?

The LOAD address is useful as everything must be programmed to FLASH. This is why .ram_data should have AT>ROM. It is telling the linker that the data will LOAD from the ROM/Flash. You have to make some assembler boot code that will copy it from flash to SDRAM in this case.

The 2nd question can be answered by putting >ROM for the .ram_data section. If you do this, the linker will complain that a write-able section is being placed in read-only memory. It is good to mark the MEMORY sections with read/write information as it can help to make sure you have the sections in the correct places. Ie, it is a cross check on the information you give the linker.

A mistake where >RAM AT>ROM is instead just >ROM makes the concepts/questions similar.

OTHER TIPS

From what I understand the execution address is used by the linker to do the symbol resolution of all elements which are not PC relative, but what about the load address? In the context of a bare-metal ARM there is no such thing as a program loader, and there is no way the linker can have any influence on where I write the program in flash, so what is it actually used for?

That information is stored in the ELF executable, and is used by tools like objcopy to determine how the binary file (e.g, .bin or .hex) is laid out. Ultimately, it ends up telling your programmer where to put the program.

In the same way, how can the linker have any influence on the SDRAM being (rx) or (rw) at run-time? Does it actually change anything when I modify those options in the memory regions?

In this particular use case, I believe those flags are informational only. They're primarily used for dynamic-loaded programs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top