I decided to write this up as bootloaders have pretty much become ubiquitous for 32-bit projects, yet I was unable to find any good information on the web about how to use linker scripts with XC32 and MPLAB-X.
When you need to control where the linker will place what part of your code, you need to create a linker script which will instruct the linker where to place each section of the program.
Before we get started you should download the MPLAB XC32 C/C++ Linker and Utilities Users Guide. There is also some useful information in the MPLAB XC32 C/C++ Compiler User’s Guide for PIC32M MCUs, the appropriate version for your compiler should be in the XC32 installation folder under "docs".
This business of linker scripts is quite different from processor to processor. I have recently been working quite a bit with the PIC32MZ2048EFM100, so I will target this to this device using the latest XC32 V2.15.
This post will focus on what you need to to do to get the tools to use your linker script. Since XC32 is basically a variant of the GNU C compiler you can find a lot of information on the web about how to write linker scripts, here is a couple.
Adding a linker script
The default linker script for the PIC32MZ2048EFM100 can be found in the compiler folder at /xc32/v2.15/pic32mx/lib/proc/32MZ2048EFM100/p32MZ2048EFM100.ld. If you need a starting point that would be a good place.
For MPLAB-X and XC32 the extention of the linker script does not have any meaning.
The linker script itself is not compiled, it is passed into the linker at the final step of building your program. The command line should look something like this for a simple program:
"/Applications/microchip/xc32/v2.15/bin/xc32-gcc" -mprocessor=32MZ2048EFM100 -o dist/default/production/mine.X.production.elf build/default/production/main.o -DXPRJ_default=default -legacy-libc -Wl,--defsym=__MPLAB_BUILD=1,--script="myscript.ld",--no-code-in-dinit,--no-dinit-in-serial-mem,-Map="dist/default/production/mine.X.production.map",--memorysummary,dist/default/production/memoryfile.xml"
The linker script should be listed on the command line as "--script="name"
When you create a new project MPLAB will create a couple of "Logical Fodlers" for you. These folders are not actual folders on your file system, but files in these are sometimes treated differently, and Linker Files is a particular case of this. My best advice is not to ever rename of in any other way mess with these folders created for you by MPLAB. If you did edit configurations.xml or renamed any of these I suggest you just create new project file as there are so many ways this could go wrong fixing it will probably take you longer than just re-creating it. I have seen cases where it all looks 100% but the IDE simply does not use the linker script, just ignoring it.
The normal way to add files to a MPLAB-X project is to right-click on the Logical folder you wanted the file to appear in and select which kind of file under the "New" menu. In this menu files that you use often are shown as a shortcut, to see the entire list of possible files you need to select "Other..." at the bottom of the list. Unfortunatley Microchip has not placed "Linker Script" in this list, so there is no way to discover using the IDE how to add a linker script.
When it all goes according to plan (the happy path) you can simply right-click on "Linker Files" and add your script. This is also what the manual says to do of course. When you have added the file it should look like this (pay careful attention to the icon of the linker script file, it should NOT have a source code icon. It should just be a white block like this, and if this is the case the program should compile just fine using the linker script, you can confirm that the script is being passed in by inspecting the linker command line.
Adding a linker script - Problems - when it all goes wrong!
I noticed in the IDE that the icon for the script was actually that of a .C source file.
When this happens something has gone very wrong, and the compiler will attempt to compiler your linker script as a C source file. You will end up getting an error similar to this, stating that there is "No rule to make target":
CLEAN SUCCESSFUL (total time: 51ms) make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf make: *** No rule to make target 'build/default/production/newfile.o', needed by 'dist/default/production/aaa.X.production.hex'. Stop. make: Entering directory '/Users/cobusve/MPLABXProjects/aaa.X' make: *** Waiting for unfinished jobs.... make -f nbproject/Makefile-default.mk dist/default/production/aaa.X.production.hex make: Entering directory '/Users/cobusve/MPLABXProjects/aaa.X' make: *** [.build-conf] Error 2 "/Applications/microchip/xc32/v2.15/bin/xc32-gcc" -g -x c -c -mprocessor=32MZ2048EFM100 -MMD -MF build/default/production/main.o.d -o build/default/production/main.o main.c -DXPRJ_default=default -legacy-libc make: *** [.build-impl] Error 2 make: Leaving directory '/Users/cobusve/MPLABXProjects/aaa.X' nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed make: Leaving directory '/Users/cobusve/MPLABXProjects/aaa.X' nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed BUILD FAILED (exit value 2, total time: 314ms)
I tried jumping through every hoop here, even did the hokey pokey but nothing would work to get the IDE to accept my linker script! I even posted a question on the forum here and got no help.
At first I thought I would be clever and remove the script I just added, and just re-add it to the project, but no luck there.
So now I was following the instructions exactly, my project was building without the script, I right-clicked on "Linker Files" selected "Add Existing Item" and then selected my script and once again it showed up as a source file and caused the project build to fail by trying to compile this as C code 😞
Next attempt was to remove the file, then close the IDE. Open the IDE, build the project and then after this add the existing file. Nope, still does not work 😞
I know MPLAB-X from time to time will cache information and you can get rid of this by deleting everything from the project except for your source files, Makefile and configurations.xml and project.xml. I went ahead and deleted all these files, restarted the IDE, added the file again - nope - still does not work. So much for RTFM!
Eventually our of desperation I tried to rename the file before adding it back in. Even this did not work until I got lucky - I changed the extention of the file to gld (a commonly used extension for gnu linker files), and tried to re-add the file, and this eventually worked !
If you are having a hard time getting MPLAB-X to add your linker script, do not dispair. You are probably not doing anywthing wrong!
The right way to add a linker script to your project is indeed to just add it to "Linker Files" as they say, sometimes you just get unlucky due to some exotic bugs in the IDE. Just remove the file from your project, change the extention to something else (it seems like you can choose anything as long as it is different) and add the file back in and it should work.
If not come back here and let me know and we can figure it out together :)