Adding a C library to the arm-gcc toolchain

This is a sequel to my previous article Getting Started with the Olimex SAM7-P256. Flashing lights are all very well but I want to add a C library so I can use functions like printf().

There is a streamlined version of the standard C library available for embedded systems called newlib which you can download from the files section at http://www.gnuarm.com/. Here’s how you build it to fit in with the toolchain in my previous article:

First you need to have makeinfo. On Ubuntu, install it like this:

sudo apt-get install texinfo

Now we can build and install the library:

tar xzvf newlib-1.14.0.tar.gz

mkdir build-newlib

cd build-newlib

../newlib-1.14.0/configure --target=arm-elf --prefix=/usr/local/arm7

sudo make all install info

Documentation for newlib can be found at http://sourceware.org/newlib/.

Now we have a C library, how about writing Hello World! That was not as easy as it sounds, mainly because I wanted printf() to send its output to the serial port. It took me a lot of documentation-reading and hair-pulling to work out how to do that.

To redirect STDOUT, you need to override the syscalls.o module which is part of libc. Copy the syscalls.c and swi.h files from the newlib source into your project directory and modify the _write() function to send its data to the serial port.

I’ve got some example code to demonstrate this. You can download it by clicking the link here:

ArmHelloWorld.tar.bz2

I’ve tried to keep the code as simple and readable as possible. I’ve also included a couple of shell scripts to make it easier to download and run the code. Here is how you would compile and run it:

tar jxvf ArmHelloWorld.tar.bz2

cd HelloWorld

make

./startarm

Next you need to connect a serial cable and start up a serial terminal on your PC at 9600,n,8,1. Once that is running, launch the example code by typing this:

./runram

If all goes well, you should see “Hello World.” appear on your serial terminal.

If not, well then happy debugging !


UPDATE: Dan Ashbrook kindly pointed out that my port assignments for the 2nd serial port are incorrect in Board.h. I have now corrected the file, you can download it here: ArmHelloWorld.tar.bz2

UPDATE: I recently tried to do this on Ubuntu 8.04 and it didn’t work until I applied this patch to the newlib configure script.

7 thoughts on “Adding a C library to the arm-gcc toolchain

  1. These files are fantastic! Maybe it’s available somewhere else on the web, but as far as I can tell, this is the only place to get the _write code for the SAM7 UART. Thanks again for this huge time-saver (and a chance for me to educate myself on the low-level C using your example).

  2. Hi Adam!

    Thanks a lot for your work, it really helped me with understanding the board. Now I’m trying to get memory allocation working with malloc, but I’m not having any luck there. Have you tried this? It seems there is a problem with the heap.

  3. Building of newlib 14 fails to compile under newest Ubuntu (2.6.32-25-generic #45-Ubuntu SMP Sat Oct 16 19:52:42 UTC 2010 x86_64 GNU/Linux),
    also newlib 18 and 17 are failing to compile

    Newlib 18

    ./targetdep.tex:1374: Prev reference to nonexistent node `Posix’ (perhaps incorrect sectioning?).
    ./targetdep.tex:1359: Next reference to nonexistent node `Posix’ (perhaps incorrect sectioning?).
    ../../../../newlib-1.18.0/newlib/libc/libc.texinfo:165: Menu reference to nonexistent node `Posix’ (perhaps incorrect sectioning?).
    makeinfo: Removing output file `../../../../newlib-1.18.0/newlib/libc/libc.info’ due to errors; use –force to preserve.
    make[4]: *** [../../../../newlib-1.18.0/newlib/libc/libc.info] Error 1

    Newlib 17

    arm-elf-gcc -B/home/m/Downloads/build-newlib/arm-elf/newlib/ -isystem /home/m/Downloads/build-newlib/arm-elf/newlib/targ-include -isystem /home/m/Downloads/newlib-1.17.0/newlib/libc/include -B/home/m/Downloads/build-newlib/arm-elf/libgloss/arm -L/home/m/Downloads/build-newlib/arm-elf/libgloss/libnosys -L/home/m/Downloads/newlib-1.17.0/libgloss/arm -g -O2 -I. -I../../../../../newlib-1.17.0/libgloss/arm/.. -g -O2 -mthumb -c ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S: Assembler messages:
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:37: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:102: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:103: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:104: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:107: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:108: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:109: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:121: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:125: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:127: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:130: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:145: Error: missing expression — `swi’
    ../../../../../newlib-1.17.0/libgloss/arm/linux-syscalls0.S:146: Error: missing expression — `swi’
    make[5]: *** [linux-syscalls0.o] Error 1

Comments are closed.