Reputation: 53
Are there conditional statements for the GNU LD linker command language?
Context: I am developing firmware for an arm cortex m0+, which consists of a bootloader and an application. Both are compiled and flashed to target in separate projects, but I use a framework with symbolic links to the drivers, makefile and loader scripts so that I can reuse those for every app I make without copying these files for each app. Currently I have two loader files, for bootloader and application (makefile automatically specifies the appropriate one), with memory assigment as follows:
bootloader
MEMORY {
flash (rx) : ORIGIN = 0x00000000, LENGTH = 16K
ram (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K
}
app
MEMORY {
flash (rx) : ORIGIN = 0x00004000, LENGTH = 112K
ram (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K
}
Like the makefile, I want to merge these to something like this (using C expressions to clarify)
MEMORY {
#ifdef(bootloaderSymbol)
flash (rx) : ORIGIN = 0x00000000, LENGTH = 16K
#else
flash (rx) : ORIGIN = 0x00004000, LENGTH = 112K
#endif
ram (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K
}
Upvotes: 5
Views: 13119
Reputation: 577
I think you can try "DEFINED(symbol)" according to https://sourceware.org/binutils/docs/ld/Builtin-Functions.html
Also, please don't forget to pass "--defsym=bootloaderSymbol=1" to ld.
MEMORY {
flash (rx) : ORIGIN = DEFINED(bootloaderSymbol) ? 0x00000000 : 0x00004000, LENGTH = DEFINED(bootloaderSymbol) ? 112K : 16K
ram (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K
}
Upvotes: 7
Reputation: 3335
Although its not its primary purpose, you can always run the C preprocessor (cpp) on your linker scripts:
#if defined(MACHINE1)
# define TARGET_ADDRESS 0x80000000
# define SDRAM_START xxx
# define SDRAM_SIZE yyy
# define ROMFLAGS rx
#elif defined(MACHINE2)
# define TARGET_ADDRESS 0x40000000
# define SDRAM_START zzz
# define SDRAM_SIZE aaa
# define ROMFLAGS rwx
#else
# error unknown machine
#endif
MEMORY
{
rom (ROMFLAGS) : ORIGIN = TARGET_ADDRESS, LENGTH = 0x00100000
ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00200000, LENGTH = 0x00100000
driver_ram (WX) : ORIGIN = SDRAM_START + SDRAM_SIZE - 0x00100000, LENGTH = 0x00100000
}
...
You just need to make sure your macros don't collide with linker script syntax. Then save your linker script as xxx.lk.in (instead of xxx.lk) and add a recipe to your Makefile:
xxx.lk: xxx.lk.in
$(CPP) -P $(INCLUDE) -D$(MACHINE) $< $@
All that's left to do is to add xxx.lk as dependency to your final executables build recipe. I'm using similar processes on many of my projects successfully.
Upvotes: 5
Reputation: 2403
I've gone down this same path before, and later found out there's an ld command line argument to specify segment origin, which alleviates the need to figure it out in the linker script. From man page:
-Tbss=org
-Tdata=org
-Ttext=org
Same as --section-start, with ".bss", ".data" or ".text" as the section name.
So in your case, you would have -Ttext=0 (bootloader) or -Ttext=0x00004000 (app)
Upvotes: 1