Rob's Technical Article: Building the Stellaris Toolchain on Gentoo


The other day I decided to try and roll a toolchain for the Stellaris M4F chip that's recently joined the group of Launchpad devices that sell for too little to not have one. So I combed google for places where people have actually done this. I ran into some rather interesting information but found that many people were pretty misled about the way you do floating point on these things. So I am here to set the story straight.

The Stellaris M4F has hardware floating point. I'm not talking about some FPU sitting across the bus, it's on the processor. GCC provides a softfp ability for many operating systems to leverage exceptions to emulate floating point of the hardware is missing. I've discovered with GCC and the ARM M series compiler, enabling softfp anywhere along the line not only dooms you to emulating floating point using integer math, it also prevents you from linking with any hardware floating point code. If you don't clearly specify that you want hard floating point everywhere along the way, GCC will default to softfp.

First detail is how to run the crossdev command to get the Stellaris toolchain you've always wanted. Here, we need to tell everything that we want a hardfloat toolchain, what type of processor and floating point we support and whatnot. What's annoying is that this stuff will have to be repeated everywhere, because it seems to me that if you let GCC do what it will, you're sure to end up with softfp. I know I'm repeating this a lot, but if you slip up, you'll get hosed. If you're lucky, you'll be consistently broken and your stuff will run float emulation. Otherwise, you're going to get some nasty linker issues.

crossdev -t arm-stellaris-eabi --env 'EXTRA_ECONF="--with-cpu=cortex-m4 --with-tune=cortex-m4 --with-mode=thumb --with-fpu=fpv4-sp-d16 --with-float-abi=hard"'

After this runs to completion, you will need to download the newlib library set. This is glibc, libm, libg for embedded environments. Crossdev will have built these, but you don't want to use what crossdev builds; they're built with softfp. Don't ask me why crossdev didn't get the hint, but it didn't force the matter when it built libc, libm and libg. So we're going to have to do it over, manually.

I put all of the commands to build this into a script. Here is the build script I used for newlib. If you copy it, you'll have to edit the paths to fit your installation.

#!/bin/bash

set -e

export ARCH="arm"
export CROSS_COMPILE="arm-stellaris-eabi-"
export CFLAGS="-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -Wa,-mimplicit-it=thumb"
export CC="arm-stellaris-eabi-gcc"

cd newlib-2.0.0/newlib

./configure --host=arm-stellaris-eabi --prefix=/raid/home/rob/share/ti/stellaris-libc/bins

make -j6
make install

echo ""
echo "Done with libc build."
echo ""

Once I've built that, I opened up the makedefs file that's packaged in the StellarisWare directory. I changed the pointers to LIBC, LIBM and LIBG.

#
# Get the location of libgcc.a from the GCC front-end.
#
LIBGCC=/raid/home/rob/share/ti/stellaris-libc/bins/arm-stellaris-eabi/lib/libg.a

#
# Get the location of libc.a from the GCC front-end.
#
LIBC=/raid/home/rob/share/ti/stellaris-libc/bins/arm-stellaris-eabi/lib/libc.a

#
# Get the location of libm.a from the GCC front-end.
#
LIBM=/raid/home/rob/share/ti/stellaris-libc/bins/arm-stellaris-eabi/lib/libm.a

Also in that file, I changed the linker line to ensure that the compiler's built-in libraries were not going to cause problems.

#
# The flags passed to the linker.
#
LDFLAGS=--gc-sections -nodefaultlibs -nostdlib

And finally, the most important part, I changed the floating point processor to "hard" on the FPU line.

ifeq (${VARIANT}, cm4f)
CPU=-mcpu=cortex-m4
FPU=-mfpu=fpv4-sp-d16 -mfloat-abi=hard
else
$(error Unknown processor variant ${VARIANT}!)

You will want to clean your StellarisWare install before building. When I built, the build failed on some example projects, but the main driverlib and usblib were already built, so I wasn't further concerned.

After building StellarisWare, I built my project and verified using arm-stellaris-eabi-objdump that it was using hardware floating point. Then I flashed, tested and verified the build.

Adjusting the StellarisWare makedeps file works great for StellarisWare stuff. If you want to write something else you will want to add this little stub to CFLAGS so you don't end up compiling for the wrong machine.

export CFLAGS="-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -Wa,-mimplicit-it=thumb"

As an exercise for the reader, see if the processor's vsqrt operand is used when you make a call to sqrt(). If it is, great... if not, MAKE IT HAPPEN! You know I'm gonna.

Enjoy!




Here are some useful web pages along these lines:

http://recursive-labs.com/blog/2012/10/28/stellaris-launchpad-gnu-linux-getting-started/

Watch out for this one's softfp mistake. You can see from the last post on the list, they never saw a single floating point instruction.

http://forums.gentoo.org/viewtopic-t-943440-start-0.html

http://sourceware.org/newlib/


By: Rob Stoddard