Few months ago I came across STM32 microprocessors. These processors are use ARM Cortex-M3 core, with clock up to 70Mhz, Internal flash, and RAM, Peripherals include DMA, SPI, CAN, RTC and lot of other.
Of course you need some compiler to develop application for this processor. Standard way of compilation for gcc will lead to very much usable toolchain, until you want to do something with floating point.
Cortex-M3 does not come with FPU, nor any kind of floating point support (VFP, NEON, …). Only support is through Soft-float. Which means that floating instructions are emulated in software, this adds some more code, but maintains compatibility.
There is a small drawback for the vanilla GCC – the code containing any kind of floating operation will cause “Bus Failure” exception.
I have spent many hours googling for the right options for GCC and friends. And came up with conclusion that arm-elf GCC target does not support thumb2 instructions, and the soft-float support is kinda broken due to backward compatibility.
Here are the steps to create GCC with Thumb2 and soft-float support. Please understand what each step does, as there might be a typo in the paths, etc.
First of all you need to download the sources of binutils, gcc, and newlib.
wget http://ftp.gnu.org/gnu/binutils/binutils-2.20.tar.bz2
wget ftp://ftp.gwdg.de/pub/misc/gcc/releases/gcc-4.4.3/gcc-4.4.3.tar.bz2
wget ftp://sources.redhat.com/pub/newlib/newlib-1.18.0.tar.gz
Export some variables used throughout the howto:
export TOOLPATH=/usr/local/cross-arm
export ARMTARGET=arm-softfloat-elf
TOOLPATH will be the destination directory. ARMTARGET is the prefix for the gcc, this also selects the internal target for gcc. Do not change the target unless you know what you are doing.
Next step is to create the binutils (as, ld, …). The release 2.20 does contain bug! Some curly braces are missing in tc-arm file. This is a known bug, and patch is available.
tar xvf binutils-2.20
# patch tc_arm.c with http://sourceware.org/cgi-bin/cvsweb.cgi/src/gas/config/tc-arm.c.diff?r1=1.407&r2=1.408&cvsroot=src&f=h
cd binutils-2.20/
mkdir build
cd build
../configure --target=$ARMTARGET --prefix=$TOOLPATH --enable-interwork --enable-multilib --with-gnu-as --with-gnu-ld --disable-nls
make all
sudo make install
export PATH=${TOOLPATH}/bin:$PATH
cd ../../
Option “interwork” is needed when compiling mixed arm/thumb code. “Multilib” is needed to support arm, thumb, thumb2 at the same time.
Now we need the basic gcc (no libs yet). Unpack the source.
tar xvf gcc-4.4.3.tar.bz2
cd gcc-4.4.3/
This is the most hackish part. You need to edit few files in the gcc sources. First one is “gcc/config/arm/elf.h”.
Edit in your favourite editor, and find “#define SUBTARGET_ASM_FLOAT_SPEC”. Change the few line macro to something like this:
#define SUBTARGET_ASM_FLOAT_SPEC "%{mapcs-float:-mfloat} \
%{mhard-float:-mfpu=fpa} \
%{!mhard-float:-mfpu=softfpa}"
#endif
Patching the “elf” target is next. This patch was found on some mailing list. I have not used the patch program to apply it, instead I’ve edited the file manually, and removed those comments. This will enable the thumb2 multilib.
--- proddev/vendor/gcc/current/gcc/config/arm/t-arm-elf 2009/02/03 23:22:05 2923
+++ proddev/vendor/gcc/current/gcc/config/arm/t-arm-elf 2009/02/04 18:33:29 2924
@@ -11,15 +11,15 @@
MULTILIB_EXCEPTIONS =
MULTILIB_MATCHES =
-#MULTILIB_OPTIONS += march=armv7
-#MULTILIB_DIRNAMES += thumb2
-#MULTILIB_EXCEPTIONS += march=armv7* marm/*march=armv7*
-#MULTILIB_MATCHES += march?armv7=march?armv7-a
-#MULTILIB_MATCHES += march?armv7=march?armv7-r
-#MULTILIB_MATCHES += march?armv7=march?armv7-m
-#MULTILIB_MATCHES += march?armv7=mcpu?cortex-a8
-#MULTILIB_MATCHES += march?armv7=mcpu?cortex-r4
-#MULTILIB_MATCHES += march?armv7=mcpu?cortex-m3
+MULTILIB_OPTIONS += march=armv7
+MULTILIB_DIRNAMES += thumb2
+MULTILIB_EXCEPTIONS += march=armv7* marm/*march=armv7*
+MULTILIB_MATCHES += march?armv7=march?armv7-a
+MULTILIB_MATCHES += march?armv7=march?armv7-r
+MULTILIB_MATCHES += march?armv7=march?armv7-m
+MULTILIB_MATCHES += march?armv7=mcpu?cortex-a8
+MULTILIB_MATCHES += march?armv7=mcpu?cortex-r4
+MULTILIB_MATCHES += march?armv7=mcpu?cortex-m3
# MULTILIB_OPTIONS += mcpu=ep9312
# MULTILIB_DIRNAMES += ep9312
Finally we can build the basic gcc.
mkdir build
cd build
../configure --target=$ARMTARGET --prefix=$TOOLPATH --enable-interwork --enable-multilib --enable-languages="c,c++" --with-newlib --without-headers --disable-shared --with-gnu-as --with-gnu-ld --with-float=soft
make all-gcc
sudo make install-gcc
This will take some time. You can add “-j2″ parameter to make, if you have more processor machine.
Unpack the newlib:
tar xvf newlib-1.18.0.tar.gz
cd newlib-1.18.0
Tell the configure to exclude few libraries, from build process. Edit configure.ac, and look for:
arm-*-elf* | strongarm-*-elf* | xscale-*-elf* | arm*-*-eabi* )
And add “target-libgloss” to the “noconfigdirs” variable. In the end it should look like this:
arm-*-elf* | strongarm-*-elf* | xscale-*-elf* | arm*-*-eabi* )
noconfigdirs="$noconfigdirs target-libffi target-qthreads target-libgloss"
libgloss_dir=arm
;;
Save the modified file and execute autoconf. This will rebuild the configure script. Continue the build process.
mkdir build
cd build
../configure --target=$ARMTARGET --prefix=$TOOLPATH --enable-interwork --disable-newlib-supplied-syscalls --with-gnu-ld --with-gnu-as --disable-shared --with-float=soft
make CFLAGS_FOR_TARGET="-msoft-float" CCASFLAGS="-msoft-float"
The make line is kinda tricky. I had some trouble using the internal malloc along with FreeRTOS. Realizing that FreeRTOS has own manager I used following:
make CFLAGS_FOR_TARGET="-msoft-float -DMALLOC_PROVIDED" CCASFLAGS="-msoft-float -DMALLOC_PROVIDED"
The MALLOC_PROVIDED option tells newlib that we have malloc and free. This needs some glue that I will discuss later.
To install the newlib, you cannot use sudo. This will fail on ranlib not being available. You will need root terminal to do this. E.g:
sudo bash
export PATH=/usr/local/cross-arm/bin:$PATH
make install
exit
cd ../../
Now finish the gcc compiling (libgcc, libstdc++, …)
cd gcc-4.4.2/build
make CFLAGS="-msoft-float" CXXFLAGS="-msoft-float" LIBCXXFLAGS="-msoft-float" all
sudo make install
I’m not sure whether the “-msoft-float” option is really necessary. But it works with them in place.
Now you should end up with gcc toolchain, that supports C and C++ languages, ARM, Thumb, Thumb2 instructions, and uses soft-float emulation.
Just don’t forget to add it to your path everytime you want to compile something
export PATH=/usr/local/cross-arm/bin:$PATH
In next part, I am going to show how to setup OpenOCD and GDB for arm processors.

12 comments
Comments feed for this article
March 5, 2010 at 05:36
Michal
Incidentally I just begun a project with STM32 and decided to use the free CodeSourcery arm-none-eabi-gcc. Do you know if it does the right FP for Cortex-M3?
March 5, 2010 at 11:28
Michal
When I first started with STM32, back in October 2009, Codesourcery did not support Cortex-M3 at all, at least that’s what their page said. I have decided to build my own toolchain.
About the CodeSourcery: They provide sources, and compiled compilers, but it takes more to download things from their pages, than you need to compile stuff using the instructions I gave :)
March 7, 2010 at 22:40
Michal
CodeSourcery’s gcc seems to work fine with -mcpu=cortex-m3, generates Thumb2 code, all looks good. I’m still waiting for a new BusPirate though. My old BP v1a doesn’t work with OpenOCD :-(
April 16, 2010 at 23:55
Dekar
I am using the CodeSourcery toolchain at the moment, but it’s nice to have a tutorial telling you how to do it on your own! :D
April 17, 2010 at 13:49
Michal
At the time I was figuring this out, there was no support for CM3 from CodeSourcery.
Still there are many people that like not to rely on 3rd parties to pack the Gnu toolchain.
April 28, 2010 at 11:14
ratul roy
hello sir ,,,,,i am new to the linux and i am stucking to this floating point error
sir i am trying to port linux2.6.30.4 on s3c2440
i am using tool chain 4.3.3 ,,,,,,i did the extraction with the command
“tar -xf”
after extracting i got two folders opt and usr
in opt there i got one folder named as 4.3.3
i coppied dat one in /usr/local/arm/
to use libraries
actually i am using some qt application and i cross compiled dat
the qt version is 4.4.3
the tar file i got for qt is “qt-embedded-linux-opensource-src-4.3.3″
as i extracted i got one folder named “examples” whr i coppied my qt programs
den i went to “examples.pro” and entered the folders name in albhabatical order,,,,
now i linked the qt-embedded with the bin file
“export PATH=$PATH:/usr/local/arm/4.4.3/bin
i linked the present directory
“export QTDIR=$QTDIR:$PWD
i linked the shared libraries
“export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QTDIR/lib”
the problem i got after loading the linux on arm is the floating point error,,,,
i came to know about soft float but i am unable to do the required changes while cross compiling;;;;;
sir i need ur help ,,,,,,,u plz make me understand about the soft float
plzzzz reply sir,,,,,,,,
May 7, 2010 at 13:06
Ed
It doesn’t seem to work that straightforward on current releases. Newlib always wants to be compiled with “-mfloat-abi=hard” which is causing errors of course. Does anybody know where to remove that option?
May 31, 2010 at 03:28
Scott
You need to make furthur changes to t-arm-elf specifically
MULTILIB_OPTIONS += -mfloat-abi=hard needs changing to soft (and the line after the following line has a similar issue)
March 9, 2011 at 15:14
Andrei
Hi,
I have tried to compile gcc, binutils and newlib using yur tutorial but I have got stuck at the step with patching the elf file.
I don’t understand what should I have to do.
Andrei
March 9, 2011 at 15:51
Michal
just copy the “patch” into a file, and apply it.
patch -p1 < your_file
This is only valid for the version mentioned. I am not sure if it will work with newer gcc.
March 9, 2011 at 18:27
Andrei
Hi,
I have put this in patch_arm file
— proddev/vendor/gcc/current/gcc/config/arm/t-arm-elf 2009/02/03 23:22:05 2923
+++ proddev/vendor/gcc/current/gcc/config/arm/t-arm-elf 2009/02/04 18:33:29 2924
@@ -11,15 +11,15 @@
MULTILIB_EXCEPTIONS =
MULTILIB_MATCHES =
-#MULTILIB_OPTIONS += march=armv7
-#MULTILIB_DIRNAMES += thumb2
-#MULTILIB_EXCEPTIONS += march=armv7* marm/*march=armv7*
-#MULTILIB_MATCHES += march?armv7=march?armv7-a
-#MULTILIB_MATCHES += march?armv7=march?armv7-r
-#MULTILIB_MATCHES += march?armv7=march?armv7-m
-#MULTILIB_MATCHES += march?armv7=mcpu?cortex-a8
-#MULTILIB_MATCHES += march?armv7=mcpu?cortex-r4
-#MULTILIB_MATCHES += march?armv7=mcpu?cortex-m3
+MULTILIB_OPTIONS += march=armv7
+MULTILIB_DIRNAMES += thumb2
+MULTILIB_EXCEPTIONS += march=armv7* marm/*march=armv7*
+MULTILIB_MATCHES += march?armv7=march?armv7-a
+MULTILIB_MATCHES += march?armv7=march?armv7-r
+MULTILIB_MATCHES += march?armv7=march?armv7-m
+MULTILIB_MATCHES += march?armv7=mcpu?cortex-a8
+MULTILIB_MATCHES += march?armv7=mcpu?cortex-r4
+MULTILIB_MATCHES += march?armv7=mcpu?cortex-m3
# MULTILIB_OPTIONS += mcpu=ep9312
# MULTILIB_DIRNAMES += ep9312
I get an error when running:
andrei@Tux:~$ patch -p1 < patch_arm
patching file vendor/gcc/current/gcc/config/arm/t-arm-elf
patch: **** malformed patch at line 4: MULTILIB_EXCEPTIONS =
August 18, 2012 at 03:26
STM Discovery | FreeWays
[...] d’accueil de GCC Guide de compilation GCC avec virgule flottante pour le développement sur STM32 Guide de compilation GCC avec CDT Eclipse pour le développement sur [...]