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.

About these ads