Hi guys,
This is my first comment so, if I'm doing something wrong please point me in the right direction!Well,I'm currently working on a project using Nordic's Dev Kit PCA10040 which has an nRF52832 SoC (arm cortex-M4). I've been working with GNU toolchain (arm-none-eabi-gcc) for a while now and I'm just playing around with some ld (linker) features. While reading the manual I saw a cool command from the linker which is the INSERT (AFTER | BEFORE) command described in the manual as follows:
SECTIONS
So, basically this command allow us to add some output sections after a specified output section found in the default linker script right? Got it!
Now let's take a look at what the manual says about the -T option:
ld
MEMORY
As you can read, the -T option will replace the default linker script (rather than adding to it) but the INSERT command "...and also causes ‘-T’ to not override the default linker script." Here is where I start being a bit confused! So I ran a small example using the following linker script:
SECTIONS { . = ALIGN(4); .mem_section_dummy_ram : { } .cli_sorted_cmd_ptrs : { PROVIDE(__start_cli_sorted_cmd_ptrs = .); KEEP(*(.cli_sorted_cmd_ptrs)) PROVIDE(__stop_cli_sorted_cmd_ptrs = .); } > RAM .fs_data : { PROVIDE(__start_fs_data = .); KEEP(*(.fs_data)) PROVIDE(__stop_fs_data = .); } > RAM .log_dynamic_data : { PROVIDE(__start_log_dynamic_data = .); KEEP(*(SORT(.log_dynamic_data*))) PROVIDE(__stop_log_dynamic_data = .); } > RAM .log_filter_data : { PROVIDE(__start_log_filter_data = .); KEEP(*(SORT(.log_filter_data*))) PROVIDE(__stop_log_filter_data = .); } > RAM } INSERT AFTER .data; SECTIONS { .nrf_queue : { PROVIDE(__start_nrf_queue = .); KEEP(*(.nrf_queue)) PROVIDE(__stop_nrf_queue = .); } > FLASH .nrf_balloc : { PROVIDE(__start_nrf_balloc = .); KEEP(*(.nrf_balloc)) PROVIDE(__stop_nrf_balloc = .); } > FLASH .cli_command : { PROVIDE(__start_cli_command = .); KEEP(*(.cli_command)) PROVIDE(__stop_cli_command = .); } > FLASH .crypto_data : { PROVIDE(__start_crypto_data = .); KEEP(*(SORT(.crypto_data*))) PROVIDE(__stop_crypto_data = .); } > FLASH .log_const_data : { PROVIDE(__start_log_const_data = .); KEEP(*(SORT(.log_const_data*))) PROVIDE(__stop_log_const_data = .); } > FLASH .log_backends : { PROVIDE(__start_log_backends = .); KEEP(*(SORT(.log_backends*))) PROVIDE(__stop_log_backends = .); } > FLASH } INSERT AFTER .text /*------------------------------------- dummy/empty ld file */ INCLUDE dummy.ld OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") ENTRY(Reset_Handler) SECTIONS { .text : { KEEP(*(.isr_vector)) *(.text*) KEEP(*(.init)) KEEP(*(.fini)) /* .ctors */ *crtbegin.o(.ctors) *crtbegin?.o(.ctors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) *(SORT(.ctors.*)) *(.ctors) /* .dtors */ *crtbegin.o(.dtors) *crtbegin?.o(.dtors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) *(SORT(.dtors.*)) *(.dtors) *(.rodata*) KEEP(*(.eh_frame*)) } > FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > FLASH __exidx_end = .; . = ALIGN(4); __etext = .; .data : AT (__etext) { __data_start__ = .; *(vtable) *(.data*) . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); KEEP(*(.jcr*)) . = ALIGN(4); . = ALIGN(4); __fdtini_early_start = .; KEEP(*(.fdtini.early*)) __fdtini_early_end = .; __fdtini_devices_start = .; KEEP(*(.fdtini.devices*)) __fdtini_devices_end = .; __fdtini_drivers_start = .; KEEP(*(.fdtini.drivers*)) __fdtini_drivers_end = .; __fdtini_tasks_start = .; KEEP(*(.fdtini.tasks*)) __fdtini_tasks_end = .; /* All data end */ __data_end__ = .; } > RAM .bss : { . = ALIGN(4); __bss_start__ = .; *(.bss*) *(COMMON) . = ALIGN(4); __bss_end__ = .; } > RAM .heap (COPY): { __HeapBase = .; __end__ = .; PROVIDE(end = .); KEEP(*(.heap*)) __HeapLimit = .; } > RAM /* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign * values to stack symbols later */ .stack_dummy (COPY): { KEEP(*(.stack*)) } > RAM /* Set stack top to end of RAM, and stack limit move down by * size of stack_dummy section */ __StackTop = ORIGIN(RAM) + LENGTH(RAM); __StackLimit = __StackTop - SIZEOF(.stack_dummy); PROVIDE(__stack = __StackTop); /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") /* Check if text sections + data exceeds FLASH limit */ DataInitFlashUsed = __bss_start__ - __data_start__; CodeFlashUsed = __etext - ORIGIN(FLASH); TotalFlashUsed = CodeFlashUsed + DataInitFlashUsed; ASSERT(TotalFlashUsed <= LENGTH(FLASH), "region FLASH overflowed with .data and user data") }
Now is where this becomes really strange: the generated code (.hex) only runs is I insert the dummy file dummy.ld (see the code above). If I comment on that line I'll get no errors from the linker but, the code won't run!
There is no info about this in the manual or other place. I bet that it is not a bug but I would like to know why it happens.
Any idea guys?
Thanks a lot!
Hi Mr Bit
Are you still looking for help with this, or did you find the answer you were looking for?