We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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?