giovedì 28 febbraio 2013

ARM7 GNU Toolchain for Linux

Moooolto tempo fa (2008) ho lavorato alla compilazione di una toolchain cross-compiler per ARM7 su Linux (che tutt'ora utilizzo), e da questo ne ho tratto una specie di how-to che ho gia' allora pubblicato sul sito della mia azienda PRECMA S.r.l.

Quella qui di seguito e' la prima parte, a cui segue la seconda relativa alla compilazione della toolchain 4.3.3 GNU con abilitata l'opzione "strip dead code"  in newlib.

There is an upgrade of this howto for a more recent toolchain here.

ARM7 GNU Toolchain for Linux

It is possible to build a complete and very professional development enviroment for ARM7 on a Linux workstation, complete of C/ASM cross compiler, debugger (through JTAG port), IDE and even project revision utility.
In this page I describe how to build a complete ARM7 GNU GCC cross-compiling toolchain for Linux host. If you are a Windows guy you can easly download a pre-built one as YAGARTO.

In order to cross-compile C and ASM language programs for ARM7 CPUs, you need a cross-compiler. The wold-wide used and famous GNU GCC compiler can be used.
Because in this case there is no Linux operating system running on the target system (ARM7), we need a compiler configured to build self-running programs; this kind of compiler is often referred as "ELF" compiler (arm-elf-gcc). Some other times is referred as "EABI" (arm-eabi-gcc) but I don't know exactly the reason.
Moreover, the widely used Linux C Standard Library "glibc" can NOT be used, because it's made to run on linux hosts. Fortunately RedHat developed and mantains a different C Standard Library suitable for non-os-based targets, named "newlib": we will use it.

For debugging the target board we plan to use the GNU "gdb" debugger with the graphical interface "insight" and an USB adapter JTAG port: I suggest the Amontec JTAG Key.
In order to use the JTAG port standard with the GNU gdb we need a program that wraps the JTAG calls and converts them in the gdb standard, and vice-versa.
This great program is available as open source and is openocd.

Note: the ARM7 hardware allows only TWO hardware breakpoint in flash memory at a time: this is a limit of the ARM7 architecture, not of the toolchain we are building. Anyway, two breakpoints at a time are sufficient for a very deep debugging task.

For the following configurations I assume that you have a bin directory in your home and that you want to install the toolchain in /home/your-home/bin/arm-elf
I also assume that you will extract all the archives in a local directory called /home/your-home/gnu_arm_toolchain/

So: first of all we have to download all the software we need. Download and extract all the archieves listed below in /home/your-home/gnu_arm_toolchain/
Then download the file and copy it in the directory /home/your-home/gnu_arm_toolchain/gcc-4.2.2/gcc/config/arm

Then edit your/home/your-home/.bashrc file adding the following line:
export PATH=$PATH:/home/your-home/bin/arm-elf/bin

Then run the following configure and make commands:

configure --target=arm-elf --prefix=/home/your-home/bin/arm-elf --enable-interwork --enable-multilib --with-float=soft
and then:
make all install

GCC 4.2.2
configure --target=arm-elf --prefix=/home/your-home/bin/arm-elf --enable-interwork --enable-multilib --with-float=soft --enable-languages="c,c++" --with-newlib --with-headers=/home/your-home/gnu_arm_toolchain/newlib-1.16.0/newlib/libc/include
and then:
make all-gcc install-gcc

NEWLIB 1.16.0
configure --target=arm-elf --prefix=/home/your-home/bin/arm-elf --enable-interwork --enable-multilib --with-float=soft
and then:
make all install

Then come back in the GCC source directory and run:
make all install

configure --target=arm-elf --prefix=/home/faumarz/bin/arm-elf --enable-interwork --enable-multilib --with-float=soft
and then:
make all install

That's all. Now you have a complete and running toolchain for ARM7 with THUMB/ARM interwork on your linux workstation:

arm-elf-addr2line  arm-elf-gcc        arm-elf-insight    arm-elf-run
arm-elf-ar         arm-elf-gcc-4.2.2  arm-elf-ld         arm-elf-size
arm-elf-as         arm-elf-gccbug     arm-elf-nm         arm-elf-strings
arm-elf-c++        arm-elf-gcov       arm-elf-objcopy    arm-elf-strip
arm-elf-c++filt    arm-elf-gdb        arm-elf-objdump
arm-elf-cpp        arm-elf-gdbtui     arm-elf-ranlib
arm-elf-g++        arm-elf-gprof      arm-elf-readelf

Try arm-elf-gcc -v to have a test of the cross compiler running. You also have the standard C library with complete floating point math routines. By the way, I suggest not to use the stadard C printf function because is incredibly flash-ROM-consuming. You can find some substitues on the web: use them (i.e.the Procyon ARMlib one).


I assume that you use the Amontec JTAG key or another FTDI based JTAG adapter.
Download the latest FTDI direct (DXX) drivers for linux on the web page:

Unzip the package and then:
As root user copy the following files to /usr/local/lib
cp /usr/local/lib
Change directory to /usr/local/lib
cd /usr/local/lib
Make symbolic links to these files using the following commands:
ln -s
Change directory to /usr/lib
cd /usr/lib
Make symbolic links to these files using the following commands:
ln -s /usr/local/lib/
Add the following line to /etc/fstab:
none /proc/bus/usb usbdevfs defaults,devmode=0666 0 0
There have been reports that you may need to use the following command for some distros
none /proc/bus/usb usbdevfs defaults,mode=0666 0 0 (use usbfs in 2.6 kernels)
In my system (SuSE 10.3 x64) I have to add:
none /proc/bus/usb usbfs defaults,devmode=0666 0 0
Remount all in the fstab file
mount –aFor the next step (compiling OpenOCD) you'll need also to copy the WinTypes.h and ftd2xx.h files in /usr/local/include


You need svn (subversion) to download the last version of OpenOCD:
svn checkout svn://

Then open a console in the downloaded directory and follow the intructions:
If you are (like me) in a x64 linux workstation you have to specify to the compiler that you want to compile in 32bit mode instead of 64bit mode, because the FTDI library drivers needed by OpenOCD are binary pre-compiled in 32bit mode. So run the following command:
export CFLAGS=-m32

Then continue with the others:
./configure --enable-ft2232-ftd2xx --prefix=
/home/your-home/bin/openocd --enable-amtjtagaccel
and then:
make install
Maybe you'll have to symlink /home/your-home/bin/openocd/bin/openocd to /home/your-home/bin/openocdOtherwise you can simply copy the compiled openocd binary in your /home/your-home/bin/ directory.

To use OpenOCD and Insight you will have to deal with the openocd configuration and script files for your target chip. I created some for the LPC2000 family microcontrollers, you'll have to create your own.
Note on debugging: if you want to debug the C source with JTAG and Insight you should use -O0 optimize flag (no optimization), otherwise some C source code line can be omitted or changed by the optimizer.

The Integrated Development Environment

As an optimail IDE you can use the Geany linux IDE editor (very good and fast), with a lot of available plugins and native tags search, symbols viewer, project and make controls:

For a long time I used Kate, a very good editor/IDE similar to Geany and with a lot of plugins too (ctags, build, etc.); before that I used Nedit (Nirvana Editor) but now it seems to be no more supported/developed. Many people use the Eclipse IDE, but I don't like it (too big and heavy, native for Java and written in Java).

The classic GNU make utility is perfect as building tool and for project revision control I suggest the PRCS tool (Project Revision Control System):

PRCS is a quite old and small command line program, but for local development projects and even for small netwoks multi-developer projects repository mantainence is great.

If you plan to use the LPC2000 family microcontrollers you can get also the lpc21isp command-line programmer to download flash from RS232:

Start up with your code

You can find a good tutorial in a 10-parts articles published on
Building Bare-Metal ARM Systems with GNU

J.C. Wren published a great sample code (much more than a sample code, to be honest) on his page
Thank you, J.C.!

Real Time Operating System

Last but not least, you can even embed in your project a free (Open Source) real time operating system: FreeRTOS

Some more reference websites

Nessun commento:

Posta un commento