Building a Big Endian ARM Cross Compiler Toolchain

GCC 3.3.2

The good folks who created uClibc have created a set of scripts which will build a toolchain with uClibc setup as the default runtime library.

I went to the uClibc toolchain page and clicked on "Download tarball" (near the bottom of the page). This gives a bunch of patches and makefiles which will download sources, patch them, and build a toolchain.

I needed to modify the top level Makefile and set the following:

     ARCH:=arm
     OPTIMIZE_FOR_CPU=armv5b
     USE_UCLIBC_SNAPSHOT:=false
     BUILD_WITH_LARGEFILE:=false
I was using an ARM926 which is an ARM5. You'll also need to edit the toolchain/gcc-3.3.x/sources/uClibc.config file. Here's the version of uClibc.config that I used. You'll probably need to tweak the KERNEL_SOURCE variable.

Binutils has improved enough that no further modifications were required. However, in order to get GCC to create big endian by default, I needed a couple of minor tweaks to the gcc/config/arm/linux-elf.h file. gcc-uclibc-3.3-300-bigend.patch contains these tweaks and should be copied into the toolchain.gcc-3.3.x/sources directory.

You should now be able to run make (from within the toolchain/gcc-3.3.x directory). I got an error about being unable to find libc.a. I then did this

     ln -s toolchain_arm/armv5b-linux-uclibc/lib/libc.a toolchain_arm/lib/libc.a
and performed make again. I would up with a working toolchain located in the toolchain_arm/bin directory.

I think you can also use:

     make BUILD_DIR=/usr/local/armv5b
to place the tools in /usr/local/armv5b rather than toolchain_arm/bin.

I was able to bring up Linux 2.6 using a little-endian version of the toolchain using the uClibc scripts with no additional changes (other than the Makefile changes). I brought up Linux 2.4.21-rmk2 using the big-endian version of the toolchain. You'll need to get the 2.4.21-rmk2 patches, which includes some fixes required to make 2.4.21 work with gcc 3.x.

GCC 2.95.3

At work, I had to create a big-endian ARM toolchain for a project I was working on. This documents the steps that I took to create the toolchain.

First of all, grab a copy of crosstool. This wonderful set of scripts automates most of the drudgery of creating a cross compiler.

You may also want to grab a copy of Karim Yaghmour's book Building Embedded Linux Systems which documents the process quite well in Chapter 4.

I wanted my toolchain to build big endian by default (i.e. without passing -mbig-endian on the command line), so I started digging a bit.

I used a target of armv4b-unknown-linux-gnu and discovered that the assembler still required -EB on the command line. I found a mention about a problem in the configure script here. This fixed gas, but ld still needed to be fixed. After digging around a bit, I discovered that ld supports both big and little endian and that the OUTPUT_FORMAT directive in the linker script file controls this. I wrapped all of the changes up into binutils-2.12.1-arm-bigendian.patch

After building ld, you can use:

     <prefix>-ld --verbose
to see what the default linker script is. The next problem was to get gcc to consider -mbig-endian as the default. I created gcc-2.95.3-arm-bigendian.patch to deal with that.

After you've expanded crosstool, create a directory named 'binutils-2.12.1-patches', if required. (inside the crosstool directory) and copy the binutils patch in. Copy the gcc patch into the 'gcc-2.95.3-patches' directory (which should already exist).

I created my own armb.dat file to use with crosstool's all.sh script as follows:

     eval `cat armb.dat` sh all.sh --notest

Go and get a coffee, and a couple of hours later you should have a toolchain.

Because I'm lazy and don't like typing long names (i.e. armv4b-unknown-linux-gnu-gcc) I created MakeLinks.sh which creates shorter aliases (i.e. arm-gcc instead of the previous monstrosity).

Disclaimer: The patches mentioned above are not terribly generic, and will only work for the target I chose.


Home - linux

Copyright 2006 by Dave Hylands