The GNU Linker (ld) is very, very powerful. This time I wanted to put all my Processor Expert generated code into its own dedicated section. This is useful for example to have a bootloader or a library inside a special area in FLASH. It was not obvious to me how to do this with the linker, with some search on the internet and some trial and errors, I finally managed that. And as always with exploring things, I have learnt something :-). So here is how I’m able to put the code of arbitrary files into its own dedicated section.
For this, I need to change the linker file. As in my setup Processor Expert is generating it, I need to disable it so it does not change it anymore. This is a setting in the CPU component, under Build Options:
Next, I’m modifying the linker file, and creating a new section (m_text2) where I want to put my dedicated code:
Next, I’m extending the linker file with my placement. For example to place the Cpu.o into my dedicated section, I use a new placement .generatedCode just before the .text placement:
.generatedCode : { . = ALIGN(4); *Cpu.o (.text .text*) . = ALIGN(4); } > m_text2 /* new section for my special code files */ /* The program code and other data goes into INTERNAL_FLASH */ .text : { ...
Note that I’m using ‘*Cpu.o’, that means that any object file matching this will end up in this section. So if I want to have all the object files from the Processor Expert Generated_Code folder, I simply can use this:
.generatedCode : { . = ALIGN(4); *Generated_Code/*.o (.text .text*) . = ALIGN(4); } > m_text2 /* new section for my special code files */
So this might be already all what you need.
However, if you get linker errors about duplicated symbols, then it means that the linker is pulling in things twice. To avoid that objects get linked twice, I use the EXCLUDE_FILE directive, with a modified original .text and .text* placement:
.generatedCode : { . = ALIGN(4); *Generated_Code/*.o (.text .text*) . = ALIGN(4); } > m_text2 /* new section for my special code files */ /* The program code and other data goes into INTERNAL_FLASH */ .text : { . = ALIGN(4); /* original placement: */ /* *(.text) */ /* .text sections (code) */ /* *(.text*) */ /* .text* sections (code) */ /* modified placement: need to exclude the ones I have in .generatedCode above */ *(EXCLUDE_FILE(*Generated_Code/*.o).text .text*) /* .text and .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } > m_text
And in the linker .map file I can verify that things worked:
Happy Linking 🙂
Thanks Erick. Have you used the Kinetis Bootloader at all?
http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=KBOOT
LikeLike
No, I have not looked at that bootloader yet, because it does not not support the KL25Z. I have developed my own bootloader for my use case: https://mcuoneclipse.com/2013/04/28/serial-bootloader-for-the-freedom-board-with-processor-expert/
LikeLike
great as always!
Have you try relocate just variable, like table of uint8_t or any?
LikeLike
Hi Greg,
no, I have not tried that, but the same thing should work for data too. Instead of specifing the code sections, use the data sections.
LikeLike
Please forgive my ignorance. I understand the concept you describe here, and it is interesting.
What I don’t understand is under what conditions would it be preferable to do things this way. What problems does it solve for the programmer?
Thank you.
LikeLike
Say if you envision that you very likely might need to patch some code from some source files in our device later on, it is not a bad idea to have that ‘preliminary’ code in a certain section of the memory together, so you only will need to patch that area of memory.
The other use case is if you have special code which e.g. needs to be protected or dealt in a special way in your device, you can place it into that special area. I agree that you can do this with section attributes in your code, but doing it on a file by file base is a nice other way to achieve this.
LikeLike
Thank you.
LikeLike
Is it possible to place shared ARM GCC library objects into a custom memory section?
When I open my project’s map file, I see the linker automatically place math lib functions (__aeabi_frsub, __mulsf3, etc_) at the start of .txt section. Then toward end of the same section after placement of my own app code, the linker places standard libray ojects such as libc.a. I want to move those objects to a special defined memory section which I specified in the linker script (.ld) file.
LikeLike
I would think that should be possible, but I have not done that myself. The easiest way to get control over this is if you would re-build the library yourself, then you can have them the way you want it.
LikeLike
You can use commands like these in your linker file at the start of the text section:
*libc.a:(.text*)
*libm.a:(.text*)
(note the colon after the library file name)
LikeLike
Hi Henry,
thanks for that hint, that’s very useful! Where did you find this documented? Somehow I have not spotted this in the linker/linker file documentation?
LikeLike
Hi Erich,
That’s the syntax for matching files within archives, it’s documented here: https://sourceware.org/binutils/docs-2.24/ld/Input-Section-Basics.html#Input-Section-Basics
In the case I mentioned, an archive file name with nothing after the colon matches the whole archive.
LikeLike
Thanks for the clarification!
LikeLike
Hi Erich,
I can’t understanding of this operation by follow you step.
This is my question on the nxp community.
I have tried to follow you step, but it didn’t work.
Could you give me some help?
https://community.nxp.com/thread/475729
LikeLike
In that article you are using a powerPC compiler? The error message indicates that it cannot find the object file. Have you added that path to the object file to the search path (libraries/etc) for the linker?
LikeLike
Pingback: Execute-Only-Code with GNU and gcc | MCU on Eclipse
Hi,
does this work for STM32F7xx? I tried this and ended up in MemManage_Handler.
LikeLike
Yes, I have used it with STM32F304, but STM32F7xx should not be different. I think you might have placed it in the linker file into areas which are not mapped to RAM or FLASH?
LikeLike