…sing C preprocessor
Background:
For cases where modifications to the linker script are required, pico-sdk only
provides the option to provide an entire linker script using
pico_set_linker_script. This patch adds a function pico_customize_linker_script
to create a linker script in the build process, based on a template provided by
pico-sdk and local settings provided by the user.
Use cases for linker script modification include:
- using the linker script as a rudimentary file system for binary blobs
- sharing WiFi firmware blobs between bootloader and application (picowota)
- reducing the number of code duplication in linker scripts (e.g.
memmap_blocked_ram.ld which differs in only one line from the default)
In such cases, deriving the linker script from a template may/should lead to
code that is easier to maintain.
Implementation:
The template is memmap.ld.in, the user input is provided by specifying a
customization file to be included, and the linker script is generated by the C
preprocessor.
The template exposes a few settings by #defining them before including the
customization file, and provides a few hooks to add elements to the template.
Examples and hints for use, based on a working example where cyw43 firmware
lives in a separate region in flash:
in CMakeLists.txt:
pico_customize_linker_script(my_target tweaks.h)
tweaks.h:
#undef MAIN_FLASH_LENGTH
#define MAIN_FLASH_LENGTH 256k
#undef ADDITIONAL_FLASH_REGIONS
#define ADDITIONAL_FLASH_REGIONS \
FLASH_CYWFW(rx): ORIGIN = 0x10040000, LENGTH = 256k
#undef ADDITIONAL_SECTIONS
#define ADDITIONAL_SECTIONS \
.fw_cyw43 : { \\
. = ALIGN(4k); \\
KEEP(*(.fw_cyw43.meta)) \\
. = ALIGN(512); \\
*(.fw_cyw43.blob) \\
} > FLASH_CYWFW
Details:
- The linker script will be a build product named ${TARGET}.ld
- When using \\ at the end of lines, newlines are inserted in the resulting
linker script in a postprocessing step. This is done to improve readability
of the resulting linker script.
- Lines starting with # need to be removed from the output; they are now turned
into /*comments*/
- Values that are to be overridden need to be #undeffed before redefining them,
which is a bit awkward; another option is to use #ifdef for each and every
variable in the template; yet another option (for integers) is to use linker
variables (i.e. simply setting MAIN_FLASH_LENGTH=256k).