The Freescale Kinetis Design Studio (KDS) V1.0.1 beta is using a different GNU ARM toolchain than the ARM Inc. supported one on launchpad (GCC ARM Embedded). Additionally, KDS is using newlib 1.19 and newlib-nano 1.0, while there just has been a new release of the GCC ARM Embedded a month ago with the 4.8.4 update 2 release in June this year. So how to upgrade KDS to the latest and greatest GCC ARM Embedded?
In this post you can learn
- How the tool chain is setup in Freescale Kinetis Design Studio (V1.0.1 beta at this time)
- How you can swap in and out the latest and greatest GNU toolchain from ARM Inc. (Launchpad)
- What you need to now about switching projects from one tool chain to another.
Changing Toolchain and Libraries?
A benefit of using open source tools and libraries which are actively maintained is that I can freely pick and choose what I want and need (see “Constructing a Classroom IDE with Eclipse for ARM“). On the other side, distributions like the Freescale Kinetis Design Studio has the advantage that a lot of this customization has been done, and comes with an installer. But if there is a newer GNU toolchain from ARM Inc., it often makes sense to get to that latest and greatest version. But changing the toolchain of a distribution makes sense too if there is a new IDE, but I want to keep the tool chain, e.g.not to introduce any risk in the code generated, but I want to benefit for example from other new parts in the IDE. In any case, what I’m proposing here is way that I can switch back and forward the toolchain, without changing the Kinetis Design Studio IDE. That way the risk of using a new compiler and new libraries can be minimized.
💡 The Eclipse build system has as well the concept of multiple tool chains. Honestly, I have not explored it much. It might be a more elegant solution, but I think it does not work for KDS (or not well enough) to be considered here.
Additionally, both the KDS supplied gcc and libraries have some pros and cons compared with the GNU GCC ARM Embedded version, see “printf() and scanf() with GNU ARM Libraries“. Especially I noticed that the increased RAM usage of the KDS libraries compared to the GNU GCC ARM Embedded one is a reason to switch the toolchain for memory constraint devices. Code size however is in some cases smaller with the KDS default tool chain, sometimes larter. But if RAM is king, then it makes sense to consider the newer ARM toolchain instead of the default KDS one.
In any case: The good thing with this tool chain swapping is: it is reversible, so it is rather easy to switch back and forward the tool chain.
Tool Chain Integration in KDS
The first thing to look at is where the toolchain is installed within KDS. It is (surprise, surprise!) inside the ‘toolchain’ of the installation folder:
The directory structure is compatible with the GNU ARM version from the launchpad, more about this later one. The binaries (compiler/linker/etc) are in the bin subfolder, for example the gcc compiler as arm-none-eabi-gcc.exe:
How to call the compiler (or all the other parts of the tool chain) is specified in the Eclipse project options. KDS is using the GNU ARM Eclipse plugins, and how to find the compiler is specified in the project settings as below:
For the above (default KDS) settings it means that the compiler is named ‘gcc‘, with a prefix ‘arm-none-eabi-‘. So it will call ‘arm-none-eabi-gcc’ as compiler. The ‘use global toolchain path’ it means it will search the system PATH (on Windows) variable to call that executable.
So this means that you need to have the gcc executable present in the system PATH. I know that many toolchains and IDE’s are modifying the PATH for this, but if you have multiple toolchains and IDE’s, this gets really, really messy. KDS instead is pretty smart: instead that the installer does a system PATH modification, it modifies the system PATH just for Eclipse at the time when I start it. So that change is only and only for that Eclipse instance.
For this, KDS adds to the beginning the path to the toolchain\bin to the system PATH variable (under Windows). Have a look at the Eclipse system variables (menu Window > Preferences > C/C++ > Build > Build Variables):
With the knowledge how things are working, it is pretty easy now to switch the toolchain: as I cannot change the way how KDS is adding the path in an easy way, the simplest way is to swap out the folders and use my different toolchain instead.
Swapping Tool Chains
To be able to easily swap the tool chains, I rename the existing toolchain folder inside KDS e.g. to ‘toolchain.orig’ and place the GNU GCC ARM launchpad release into the normal toolchain folder. The latest GNU GCC ARM can be downloaded as zip file from https://launchpad.net/gcc-arm-embedded.
To easily differentiate the versions, I have a text file inside the folder to identify the tool chain.
Make Utility
There is one thing left: Eclipse uses a make to build the project, and the launchpad tools. The KDS v2.0.0 toolchain\bin includes such a make. The easiest way is to copy that make into the launchpad toolchain\bin folder:
Different Linker Options
While the directory structure is compatible, the linker options are not. If using the newlib-nano, then the linker options are different between the default KDS toolchain and GNU GCC ARM Embedded. KDS is using -nanolibc linker option, while the ARM Inc. launchpad toolchain is using -specs=nano.specs. So that option needs to be changed if switching tool chains. Additionally, I have to switch off the usage of the system library (for file operations) with -specs=nosys.specs (see “Tutorial: DIY Kinetis SDK Project with Eclipse – Startup” about more information on this subject).
Comparison
The positive effect of using the latest GNU GCC ARM Embedded and libraries is that my application needs less RAM. With the default GNU libraries in KDS the library needs at least around 0x200 bytes of HEAP, otherwise it will crash in the library startup code. This problem was present in earlier versions of the ARM newlib-nano, and has been discussed in the Launchpad forum:
- https://answers.launchpad.net/gcc-arm-embedded/+question/239920
- https://answers.launchpad.net/gcc-arm-embedded/+question/233446
Since then, this has been improved in the latest newlib-nano release from ARM Inc. And because the libraries in KDS do not include that improvement, they need at least around 400 bytes of RAM allocated for the heap as a minimum:
If not using Processor Expert, such an amount of heap needs to be allocated in the linker file:
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0200; STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
I created with the wizard a project for the FRDM-K64F with both SDK and Processor Expert enabled. With KDS and default GNU tools and libraries I get:
text data bss dec hex filename 7744 680 1252 10176 27c0 kds_sdk_test.elf
While with the new GNU GCC and libraries from launchpad/ARM Inc. no HEAP memory is needed (unless I use the heap, of course), so this greatly reduces the needed RAM for the same application:
text data bss dec hex filename 6544 112 1072 7728 1e30 kds_sdk_test.elf
So with the new libs we have greatly reduced the footprint of the application :-).
That overhead with the heap space in KDS can be avoided with using the normal newlib (not the newlib-nano). However, for this case in KDS, the code size increases, and while there is no heap needed, the RAM size is about the same because now instead of dynamic memory allocation global buffers seem to be used:
text data bss dec hex filename 11908 2160 1288 15356 3bfc kds_sdk_test.elf
Summary
With the knowledge how the toolchain is working in KDS, is it is not very difficult to switch to a newer ARM Inc. tool chain, or later to switch back to a earlier version as needed. This is possible as long the compiler and linker switches are compatible. Right now the KDS default toolchain uses a different linker option for the newlib-nano libraries, so this option needs to be updated. Otherwise, things are compatible or I have not seen any issues. As a huge benefit switching to the latest ARM libraries and tool chain is that they need much less RAM, so are better suited for smaller microcontroller.
Happy Switching 🙂
Pingback: printf() for the FRDM-K64F Board and Kinetis Design Studio | MCU on Eclipse
Pingback: Listing Code and Data Size for each Source File with GNU and Eclipse | MCU on Eclipse
hi erich,
Is it possible to switch the CW10.6 tool chain to gcc v4.8 with the above steps?
LikeLike
Hi Jack,
no, the steps are not the same. CodeWarrior uses a different tool chain intergration (that what is used as panels for the compiler/linker/etc from a user perspective). They look the same, but are not the same as used by KDS. Both KDS and most Eclipse users are using the GNU ARM Eclipse plugins. I have not tried it with CodeWarrior, but you could install the GNU ARM Eclipse plugins (https://mcuoneclipse.com/2013/12/23/diy-free-toolchain-for-kinetis-part-7-gnu-arm-eclipse-plugins/) and then use the GNU ARM Embedded (launchpad) with it. But the projects of CodeWarrior would not be compatible with it, but you can use both project types with that ‘hybrid’ IDE: the GNU ARM Eclipse ones with the GNU ARM Embedded tools, and the CodeWarrior ones with their version of the GNU tools. The CodeWarrior GNU tools are in fact the same as the GNU ARM Embedded one (an older version), but the provided libraries are different (EWL, proprietaroy of Freescale).
I hope this helps?
LikeLike
Pingback: GNU Libs with Debug Information: Rebuilding the GNU ARM Libraries | MCU on Eclipse
Pingback: Semihosting with GNU ARM Embedded (LaunchPad) and GNU ARM Eclipse Debug Plugins | MCU on Eclipse
Pingback: C++ with Kinetis Design Studio | MCU on Eclipse
Hi Erich,
what’s linker file?
“If not using Processor Expert, such an amount of heap needs to be allocated in the linker file:
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0200;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;”
LikeLike
If using the launchpad libraries, no heap is needed (unless you use the heap). The stack size could be reduced too (depends on the application). But most of my applications only use 0x100 stack (then start the RTOS which has their own stack for tasks)
LikeLike
Pingback: Failed to Debug with GDB: Breakpoints or Expressions on non-existing Locations | MCU on Eclipse
Thank you so much! Buffered IO in stock newlib seems to be seriously messed up. Replaced KDS toolchain with the latest gcc-arm-none-eabi-4_9-2015q1-20150306-win32 from launchpad and all problems are gone. BTW, you do not need -specs=nosys.specs linker switch, just write appropriate stubs. Buffered IO was not working right with that switch present.
LikeLike
Yes, with -specs=nosys.specs it tells the linker to use no system stubs (I think it replaces with internal dummy ones).
If you are talking about buffered I/O as using printf() and the like, then yes, the appropriate stubs need to be provided.
LikeLike
Pingback: Using Kinetis Design Studio V3.0.0 with the Launchad 4.9-2015-q2 Release | MCU on Eclipse
Thanks for the walkthrough. I’m getting a pretty generic “Error in services launch sequence” error when I try to debug, any idea how I might get more information on what is actually happening there? (By the way, toolchain change decreased code size by about 25%)
LikeLike
Thanks for the walkthrough. Compilation works fine with a toolchain change, but I’m seeing a generic Error in services launch sequence when I try to debug with PNE. Any idea how I might get more information about what’s really happening there?
LikeLike
I suggest you check if the P&E USB port is listed in the debug launch configuration panel. Other than that: in the console view there is a special ‘sub-view’ where both the GDB and the P&E GDB server log what is going on. Other than that: delete any breakpoints you have still set in the breakpoints view.
I hope this helps,
Erich
LikeLike
Very easy walk-through, thanks Erich.
For my project, ported from CW10.5, i was getting a ‘m_data overflowed by 840 bytes’.
Changing to latest ARM toolchain, this is now 836 bytes 😉
KDS now offers a checkbox ‘Use newlib-nano’ in Settings\Cross ARM C++ Linker.
It shows the flag as “–specs=nano.specs” rather than “-specs=nano.specs” (extra -)
Doesn’t seems to make a difference anyway, although interestingly if i use the checkbox, i get a compilation error under “#if defined(__GNUC__) for an asm line, which i have changed.
I do not get this error if i set the flag manually in Other linker flags (again, with 1 – as you have it).
I also put in “-spces=nonsys.specs” – no effect seen.
Does seem like a ridiculous RAM overhead that was not in CW.
I can get around this by giving more RAM to this project (it is a USB boot-loader, with RAM defined for this project, the rest to the main program on a K20).
LikeLike
I have to say that using ‘–‘ instead of ‘-‘ is the common way for GNU tool options. I believe with ‘–‘ the option can have a dash as the option text. But as for “-spces=nonsys.specs” it does not matter.
As for the RAM overhead: check the linker file about how much stack is allocated to the MSP (main program): it could be that your new linker file say is using 1 KByte of stack, and your CodeWarrior linker file is having something different. The application itself should not use more RAM. Except of course the library. The CodeWarrior EWL library is better suited for small footprint, but newlib-nano comes close. It all depends what kind of library functions you are using (I hope you are not using printf() and the like, so check the linker map file). The other thing is: check that the linker is removing unused functions/variables. Check that you are using -ffunction-sections and -fdata-sections as ‘Optimization’ options, and that you have ‘remove unused sections (-Xlinker –gc-sections)’ turned on.
LikeLike
Thanks Erich.
I’ve found what i think is causing the large amount of RAM overspill in the map file.
I’m getting a fill of 0x1e4 bytes:
*(.bss)
.bss 0x1fff0400 0x1c c:/freescale/kds_3.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/5.4.1/armv7e-m/crtbegin.o
*(.bss*)
*fill* 0x1fff041c 0x1e4
.bss.g_Mem 0x1fff0600 0x400 ./Sources/USB/driver/usb_dci_kinetis.o
.bss.g_bdtmap 0x1fff0a00 0x4 ./Sources/USB/driver/usb_dci_kinetis.o
0x1fff0a00 g_bdtmap
In the code, g_Mem is aligned to a 512 byte boundary:
/* location for BDT Table and buff */
#if defined(__GNUC__)
__attribute__((__aligned__(512)))
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 512
#endif
static uint_8 g_Mem[BYTES_1024];
Seems the linker is not allowing any other memory to be allocated up to this first entry?
Any suggestions, settings?
thanks
Alex
LikeLike
Hi Alex,
this depends how you have organized your linker file. If you have
/* Uninitialized data section */
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
. = ALIGN(4);
__START_BSS = .;
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__END_BSS = .;
} > m_data
Then will start allocating things as they come in the link list. What you need is to allocate the g_Mem variable first:
.bss 0x1ffff200 0x600 load address 0x00000a00
0x1ffff200 . = ALIGN (0x4)
0x1ffff200 __START_BSS = .
0x1ffff200 __bss_start__ = .
*(.bss)
.bss 0x1ffff200 0x1c toolchain/bin/../lib/gcc/arm-none-eabi/4.8.4/armv6-m/crtbegin.o
*(.bss*)
.bss.i 0x1ffff21c 0x4 ./Sources/main.o
*fill* 0x1ffff220 0x1e0
.bss.g_Mem 0x1ffff400 0x400 ./Sources/main.o
This means the linker has to add *fill* to fill up the memory.
You can do this with adding *(.bss.g_Mem) at the beginning:
/* Uninitialized data section */
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
. = ALIGN(4);
__START_BSS = .;
__bss_start__ = .;
*(.bss.g_Mem)
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__END_BSS = .;
} > m_data
With this I get:
.bss 0x1ffff200 0x420 load address 0x00000a00
0x1ffff200 . = ALIGN (0x4)
0x1ffff200 __START_BSS = .
0x1ffff200 __bss_start__ = .
*(.bss.g_Mem)
.bss.g_Mem 0x1ffff200 0x400 ./Sources/main.o
*(.bss)
.bss 0x1ffff600 0x1c toolchain/bin/../lib/gcc/arm-none-eabi/4.8.4/armv6-m/crtbegin.o
*(.bss*)
.bss.i 0x1ffff61c 0x4 ./Sources/main.o
so no fill 🙂
I hope this helps,
Erich
LikeLike
Thanks again Erich – did indeed remove that fill!
Wondering why I did not have to do that with CW…
Anyway, still got a memory over-spill, but its down to 352 bytes from 840.
Time for another sift through the map file to see where its coming from…
LikeLike
It really depends how your other linker file is organzed, and the order of the object files passed to the linker.
LikeLike
Pingback: Zephyr: Thoughts and First Steps on the ARM Cortex-M4F with gcc, gdb and Eclipse | MCU on Eclipse
Hi Erich,
I tried switching to the latest GNU toolchain (gcc-arm-none-eabi-6-2017-q2-update) but now the debugger fails during program launch. Checking the gdb output (commands are presumably issued by the SEGGER J-Link GDB Server) I can see the following error:
910,638 25-exec-run
910,640 25^error,msg=”Don’t know how to run. Try \”help target\”.”
Any ideas what might be causing this? Thanks, Don
LikeLike
Hi Don,
I have been using gcc-arm-none-eabi-6-2017-q2-update-win32 with Eclipse Oxygen, but I have not tried it with KDS (yet?). But I know that recently the new GDB in version 6 has caused a lot of issues in many areas.
I guess you have to use new GNU ARM Eclipse (now GNU MCU Eclipse) plugins if you want to have it working in KDS?
LikeLike
Pingback: Execute-Only-Code with GNU and gcc | MCU on Eclipse