Toolchain for Cortex-M4

Important links:

These are brief instructions for creating your own GCC based tool-chain for a Cortex-M4 microcontroller, heavily based on this post. I tried a few precompiled ones which I found on the Internet, but always wondered how to make one which would be configured specifically for my micro, not for “ARM” in general. Tool-chains generated by following method was tested by me on ST STM32F407 and Texas Instruments TIVA-C TM4C123 (i.e. one tool-chain for these two µC since they both include the same CPU). My setup as I write this:

  • Host operating system : Ubuntu 14.04 LTS
  • Kernel : 3.13.0-24-generic
  • Few GB of free space on HD.

Making a tool-chain is hard, therefore wise people over the net developed tools to simplify the process. Few years ago, when I attepmpted to build a GCC tool-chain I struggled with lack of information, complexity of the process, and variety of recipes, which all seemed were extremely complex, and in some point in the process I was struck with problem I couldn’t solve. Then I found crosstool-NG – it may seem funny, but all this stuff was new to me, and I was looking for the best way possible to finish the task, some “canonical” way of building a cross-compiler, and for me, crosstool-NG is exactly this. Lets grab the newest version from its website and follow the installation instructions (this step will build only the crosstool-NG itself):

mkdir my-toolchain
cd my-toolchain
# Pay attention which version is the newest. As of writing this, the newest was
# 1.19.0, but at the "header-file" 
# incorrectly indicated the 1.18.0 version
tar jxvf crosstool-ng-1.19.0.tar.bz2 
cd crosstool-ng-1.19.0/
# Resolve some dependencies
sudo apt-get install bison flex gperf texinfo gawk libtool automake libncurses5-dev
# Provide a prefix to some destination which PATH points to.
./configure --prefix=/home/iwasz/local/
make install

Now we perform some setup. All features of our future tool-chain will be set during this step:

# cd back, so we are in "my-toolchain" directory again.
cd ..
mkdir staging
cd staging
ct-ng  menuconfig

The last command brings the following menu-config tool:


Paths and misc options

  • Try features marked as EXPERIMENTAL : Y
  • Prefix : ${HOME}/local/share/${CT_TARGET} . Provide a destination folder that suits your needs, give descriptive name if you plan to host more than one crosscompilers.
  • Number of parallel jobs : 8 (depends on host capabilities of course).
  • Check “Debug Crosstool-NG”, “Save intermediate steps”, and “gzip saved states” as described here.


Target options

  • Target Architecture : arm
  • (cortexm4) Suffix to the arch-part (breaks the build!).
  • Use the MMU : N
  • Architecture level : armv7-m. As you can find here, the ARM architecture for Cortex-M4 is ARMv7E-M. In GCC manual (type /, and -march a few times) we can find that, among many others, available values for -march are armv7, armv7-a, armv7-r, armv7-m. Unfortunately the armv7e-m is invalid (if someone could elaborate on that, it would be perfect), so I choose the most similar armv7-m option. EDIT here : I’ve found that they added armv7e-m in recent version of GCC.
  • Emit assembly for CPU : cortex-m4 (full list of available options can be found in GCC manual somewhere near -mcpu phrase). 
  • Tune for CPU : empty (empty because -mcpu was provided. -mtune is similar to -mcpu, but -mcpu restricts us to one CPU only, while -mtune tries to do its best to optimize for particular CPU while still retaining the possibility to compile for other CPUs).
  • Use specific FPU : fpv4-sp-d16. Cortex-M4 can have FPU, but not necessarily (with FPU it is called Cortex-M4F, and Cortex-M4 without). But the fact is I found this option somewhere over the net, and I am a little bit confused on the topic of FPU.
  • Floating point : hardware (FPU).
  • Default instruction set mode (thumb).

03-target-options Toolchain options. Add some cool Toolchain ID string: 04-toolchain-options Operating System. Set Target OS to bare-metal: 05-operating-system

Binary utilities

  • Binary format: (Flat)
  • binutils version (2.22) – latest which is not marked as EXPERIMENTAL.


C compiler

  • Show Linaro versions : Y
  • gcc version (linaro-4.8-2013.06-1)
  • C++ : Y

07-c-compiler   C-library

  • C library (newlib)
  • newlib version (2.0.0 (EXPERIMENTAL)) - the newest, and works OK.
  • Disable the syscalls supplied with newlib : Y - I provide my own syscalls in every program.

08-c-library Debug facilities

  • gdb : Y


Then dig into “GDB” and check show lianro versions, and choose the newest from linaro, and set Enable python scripting to N (caused build problems for me):


Exit menu-config (few times ESC, and save when prompted) and finally build the toolchain:

ct-ng build
tail -f build.log # in another console (not necessary if debug options were set)

The build process takes some time (30-60 minutes), and if in some point for some reason the build fail, first place you check is the build.log file in staging directory (therefore I pasted this tail -f command earlier, but of course it does not matter how you display the file). For example, in my case, the crosstool-NG decided to fail with this:

... kilobytes, megabytes of logs ....
[ALL  ]    checking whether to use python... yes
[ALL  ]    checking for python... /usr/bin/python
[ALL  ]    checking for python2.7... no
[ERROR]    configure: error: python is missing or unusable
[ERROR]    make[2]: *** [configure-gdb] Error 1
[ALL  ]    make[2]: Leaving directory `/home/iwasz/Documents/my-toolchain/staging/.build/arm-unknown-eabi/build/build-gdb-cross'
[ERROR]    make[1]: *** [all] Error 2
[ALL  ]    make[1]: Leaving directory `/home/iwasz/Documents/my-toolchain/staging/.build/arm-unknown-eabi/build/build-gdb-cross'
[ERROR]  >>
[ERROR]  >>  Build failed in step 'Installing cross-gdb'
[ERROR]  >>        called in step '(top-level)'
[ERROR]  >>
[ERROR]  >>  Error happened in: CT_DoExecLog[scripts/functions@257]
[ERROR]  >>        called from: do_debug_gdb_build[scripts/build/debug/]
[ERROR]  >>        called from: do_debug[scripts/build/]
[ERROR]  >>        called from: main[scripts/]
[ERROR]  >>
[ERROR]  >>  For more info on this error, look at the file: 'build.log'
[ERROR]  >>  There is a list of known issues, some with workarounds, in:
[ERROR]  >>      '/home/iwasz/local/share/doc/crosstool-ng/ct-ng.1.19.0/B - Known issues.txt'
[ERROR]  (elapsed: 58:52.70)

I didn’t thought long on this one (apt-get install libpython2.7-dev maybe???), but disabled the python support for GDB (I modified the instructions accordingly, so hopefully you haven’t had the same error). But in case you had, you should resolve the error (maybe change the configuration using menuconfig, or resolve the problem in other ways, depending on the cause) and rerun ct-ng, or refer to this stack-overflow thread for more info on speeding up the process after build has failed.

Leave a Reply

Your email address will not be published. Required fields are marked *