Switching ARM GNU Tool Chain and Libraries in Kinetis Design Studio

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:

GNU toolchain inside KDS installation folder

GNU toolchain inside KDS 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:

arm-none-eabi-gcc

arm-none-eabi-gcc

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:

GNU ARM Eclipse Project Settings

GNU ARM Eclipse Project Settings

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):

PATH Settings in KDS

PATH Settings in KDS

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.

Both Toolchains inside KDS

Both Toolchains inside KDS

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:

Make in toolchain bin

Make in toolchain bin

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).

KDS -nanolibc option

KDS -nanolibc option

Linker Flags for GNU GCC ARM Embedded

Linker Flags for GNU GCC ARM Embedded

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:

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:

Heap Size with KDS GNU Libraries

Heap Size with KDS GNU Libraries

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 🙂

26 thoughts on “Switching ARM GNU Tool Chain and Libraries in Kinetis Design Studio

  1. Pingback: printf() for the FRDM-K64F Board and Kinetis Design Studio | MCU on Eclipse

  2. Pingback: Listing Code and Data Size for each Source File with GNU and Eclipse | MCU on Eclipse

    • 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?

      Like

  3. Pingback: GNU Libs with Debug Information: Rebuilding the GNU ARM Libraries | MCU on Eclipse

  4. Pingback: Semihosting with GNU ARM Embedded (LaunchPad) and GNU ARM Eclipse Debug Plugins | MCU on Eclipse

  5. Pingback: C++ with Kinetis Design Studio | MCU on Eclipse

  6. 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;”

    Like

    • 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)

      Like

  7. Pingback: Failed to Debug with GDB: Breakpoints or Expressions on non-existing Locations | MCU on Eclipse

  8. 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.

    Like

    • 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.

      Like

  9. Pingback: Using Kinetis Design Studio V3.0.0 with the Launchad 4.9-2015-q2 Release | MCU on Eclipse

  10. 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%)

    Like

  11. 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?

    Like

    • 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

      Like

  12. 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).

    Like

    • 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.

      Like

  13. 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

    Like

    • 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

      Like

      • 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…

        Like

  14. Pingback: Zephyr: Thoughts and First Steps on the ARM Cortex-M4F with gcc, gdb and Eclipse | MCU on Eclipse

  15. 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

    Like

    • 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?

      Like

  16. Pingback: Execute-Only-Code with GNU and gcc | MCU on Eclipse

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.