Hello to all:
How does Linker or Compiler determine that which source file should be located first in base address of device memory? For example we have a project with a startup file.s (stm32f10x_startup.s) and a main.c. We expect that, the object of startup file.s be located in initial address of execute memory (typically ROM) and main.c object, be located after; because, typically, the microcontrollers read address 0x0 after rest to receive MSP base address and then 0x4 to receive Reset handler address, which these information are in startup file corresponding to that microcontroller. So if main.c contents, be located from address 0x0, then the execution encounters with error. Also there maybe another (another.s) file, in this case, how does linker decide which (startup file.s) or (another.s) shouldbe located first?
Thank for your answer:
OK; your explanation is correct, but I mean that how linker or compiler knows, it has to put the contents related to vector table (in startup.s file), from address 0x0 to end of table. For example; Why does not it put machine codes related to lines 10 to 20 of main.c rather than them!!? Is this franchise done with specific command?
I hope that I have expressed my meaning well!
It's all down to the linker script passed to the linker, either implicitly or explictly. I use the arm-none-eabi toolchain, so use the -T foo.ld option.
The linker is passed a list of .o and .a files on its command line too. The linker is building output sections, for the image, from input sections (each function or global data is tagged with a section name in its .o file). The linker keeps a 'cursor' of where it is in composing the output, and the cursor starts at 0.
When the linker processes this directive from the .ld file:
KEEP(*(.vectors))
it searches ALL .o and .a files on its command line (the * matches ANY file) for any sections called .vectors. It will find just one. In my case, this is in startup_efm32gg.c (I use SiiiconLabs efm32gg MCUs) and is a const array that is of course the interrupt vector table. Since the cursor is currently 0, the vec table goes at the start of the image. The output cursor is then incremented by the size of the vector table.
Since a Cortex M3 always starts life by loading SP from image address 0 and PC from image address 4, the vector table MUST be placed at 0 in the image. If my .ld file said
*(.text*)
BEFORE the line above, the linker would find all the sections named .text* in all .o files on its cmd line, relegating the .vectors section, and thus the vector table, to some arbitrary location in the image, and that image wouldn't boot once flashed.
Am I making any sense?
Oops, I just realized this is the Keil forum (I normally just scan it for RTX posts), but Keil's scatter files work on the same principle (I think) as GNU's .ld scripts.
Thank Tobermory; I almost understood your explanation, but if anyone has any other explanation, pleas post it here!
Mahdi Masoudi said:how linker or compiler knows
It has command-line options which tell it what type of chip the Target is.
There are also settings in the Keil project - which tell it memory sizes, etc.
If you look in the startup file, you will see where the vector table is created:
MODULE ?cstartup ;; Forward declaration of sections. SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start EXTERN SystemInit PUBLIC __vector_table DATA __vector_table DCD sfe(CSTACK) DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler