Building an ARM bare metal cross-compiler

SAM7-EX256

Note

You can get precompiled packages from CodeSourcery if you are using a 32bit x86 and not 64bit x86_64 operating system.

Update

At the moment I’m using a prebuilt toolchain from https://launchpad.net/gcc-arm-embedded/+download, just download, unzip and add it to the PATH (export PATH=$PATH:/home/chris/tools/gcc-arm-none-eabi-4_6-2012q2/bin). There is also a source package and even a Windows installer.

Step for step:

1. If not yet installed:

Use the package manager of you Linux distribution to install some required packages, I’m using Fedora and yum here. First we need Git to download the build script:

[chris@thinkpad ~]$ sudo yum install git

2. Install build dependencies:

[chris@thinkpad ~]$ sudo yum install mpfr-devel flex gmp-devel libmpc-devel autoconf texinfo bison ncurses-libs ncurses-devel expat expat-devel make gcc gcc-c++

You may also try sudo yum groupinstall "Development Tools" or sudo yum-builddep gcc.

If you are also building openocd: sudo yum install libftdi-devel.

3. Get the build script:

You can get the build script from https://github.com/esden/summon-arm-toolchain, it is also a good idea to have a look at its forks on GitHub, they may use newer versions of the compiler and other issues may be fixed already.

[chris@thinkpad ~]$ git clone git://github.com/esden/summon-arm-toolchain.git

4. Edit the build script as you wish:

[chris@thinkpad ~]$ cd summon-arm-toolchain
[chris@thinkpad summon-arm-toolchain]$ vim summon-arm-toolchain
# Install location of your final toolchain
PREFIX=${HOME}/tools/summon-arm-toolchain
# du -hs ~/tools/summon-arm-toolchain # 309M

#When using Fedora's openocd sudo yum install openocd
#OOCD_EN=0
OOCD_EN=1

To beware for download failures you should remove the --no-passive-ftp in wget -c --no-passive-ftp $2 && touch ${STAMPS}/$1.fetch:

[chris@thinkpad summon-arm-toolchain]$ sed -i 's/--no-passive-ftp//g' summon-arm-toolchain

5. Execute the build script

[chris@thinkpad summon-arm-toolchain]$ ./summon-arm-toolchain
Settings used for this build are:
TARGET=arm-none-eabi
PREFIX=/home/chris/tools/summon-arm-toolchain
DARWIN_OPT_PATH=/opt/local
SUDO=
QUIET=0
USE_LINARO=1
OOCD_EN=1
OOCD_GIT=
LIBSTM32_EN=0
LIBOPENCM3_EN=1
DEFAULT_TO_CORTEX_M3=0
CPUS=
4 cpu's detected running make with '-j5' flag
Found Linux OS.
...

6. Get a cup of coffee

7. Edit your .bashrc

Add a line like this:

export PATH=$PATH:/home/chris/tools/summon-arm-toolchain/bin

8. Now see if it is working

You have to open a new terminal so that your new ~/.bashrc gets loaded.

[chris@thinkpad ~]$ which arm-none-eabi-gcc
~/tools/summon-arm-toolchain/bin/arm-none-eabi-gcc
[chris@thinkpad ~]$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (Linaro GCC 4.5-2011.02-0) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

9. Compile something

[chris@thinkpad olimex_sam7_ex256_startup_minimal]$ make clean
rm *.o *.bin *.elf *.map
[chris@thinkpad olimex_sam7_ex256_startup_minimal]$ make all
arm-none-eabi-gcc -D__ASSEMBLY__ -DAT91SAM7X256 -g -mcpu=arm7tdmi -c -O0 -Wall -I./inc cstartup.S -o cstartup.o
arm-none-eabi-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./inc -DAT91SAM7X256 lowlevel.c -o lowlevel.o
arm-none-eabi-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./inc -DAT91SAM7X256 main.c -o main.o
arm-none-eabi-gcc -nostartfiles -Wl,-Map=AT91SAM7X256.map,--cref -lc -lgcc -T elf32-littlearm.lds -Ttext 0x201000 -Tdata 0x200000 -n -o at91sam7x_getting_started_sram.elf cstartup.o lowlevel.o main.o
arm-none-eabi-objcopy --strip-debug --strip-unneeded at91sam7x_getting_started_sram.elf -O binary at91sam7x_getting_started_sram.bin
arm-none-eabi-gcc -nostartfiles -Wl,-Map=AT91SAM7X256.map,--cref -lc -lgcc -T elf32-littlearm.lds -Ttext 0x100000 -Tdata 0x200000 -n -o at91sam7x_getting_started_flash.elf cstartup.o lowlevel.o main.o
arm-none-eabi-objcopy --strip-debug --strip-unneeded at91sam7x_getting_started_flash.elf -O binary at91sam7x_getting_started_flash.bin
[chris@thinkpad olimex_sam7_ex256_startup_minimal]$

In some older makefiles you may have to replace arm-elf- with arm-none-eabi- and everything should be fine.

To use openocd you have to add an udev rule to be able to communicate with your board. Just use lsusb to get the IDs.

[chris@thinkpad ~]$ lsusb
Bus 007 Device 002: ID 15ba:0004 Olimex Ltd. OpenOCD JTAG TINY
Bus 004 Device 002: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port

Edit or create the file /etc/udev/rules.d/10-local.rules and add a rule for our JTAG adapter:

[chris@thinkpad ~]$ sudo vim /etc/udev/rules.d/10-local.rules
ATTR{idVendor}=="067b", ATTR{idProduct}=="2303", GROUP="plugdev", MODE="0660" # Prolific Technology, Inc. PL2303 Serial Port
ATTR{idVendor}=="15ba", ATTR{idProduct}=="0004", GROUP="plugdev", MODE="0660" # Olimex Ltd. OpenOCD JTAG TINY

Now we need to reload all udev rules so that the change takes effect:

[chris@thinkpad ~]$ sudo groupadd plugdev
[chris@thinkpad ~]$ sudo usermod -aG plugdev chris #replace chris with your username
[chris@thinkpad ~]$ sudo udevadm control --reload-rules
[chris@thinkpad ~]$ ls -l /dev/ttyUSB0
crw-rw----. 1 root dialout 188, 0 Apr  5 17:18 /dev/ttyUSB0

The device /dev/ttyUSB0 has still the wrong permissions even after an reboot so the easiest solution is to become a member of the dialout group:

[chris@thinkpad ~]$ sudo usermod -aG dialout chris
[chris@thinkpad ~]$ sudo reboot

Good luck :-)