ARM Toolchain – Crosstool

Was able to get an arm-elf toolchain built and working fine, but not so much luck in building an arm-elf-linux toolchain. It cross-compiled programs without errors, but the compiled executable crapped out at runtime. So googling for answers… I came across Dan Kegel’s crosstool – a really cool GNU toolchain builder. It downloads all the correct gcc, glibc, binutils, etc. and builds your toolchain. I built two toolchains, arm-unknown-linux and arm-xscale-linux. The toolchain built with it works great.

Note:
The Ubuntu shell is not bash by default! Instead it is linked to something called dash. Just make sure you relink /bin/sh to bash instead of dash. No idea when they did this, but I found that out after encountering this maddening error, pointing to some header files during the build:

missing terminating ” character.

Using it:

Example (for kernel compilation makefile):

export ARM_TOOLCHAIN=/opt2/crosstool/arm-unknown-linux-gnu/bin
export PATH=$ARM_TOOLCHAIN:$PATH

make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnu-

ARM Toolchain

Updated (April 26, 2008)

Here’s my cheat-sheet for building a 64-bit GNU ARM toolchain (cross-compiler x64 to ARM). So far this has been working well for me on an LPC2148 (ARM7TDMI-S), i.e. gcc and gdb via OpenOCD JTAG.

Notes:

  1. Some builds (like binutils-2.18 and newlib-1.15) needed the setting MAKEINFO=/usr/bin/makeinfo to be passed to the make (binutils-2.17 and newlib-1.16 didn’t need this).
  2. Update: some systems (like Ubuntu 8.10) have strict checking turned on, where warnings are treated as errors. You may need to disable this the build of binutils and gdb using the –disable-werror configuration option.

Here are the steps:

environment (needed only for build):

export BINUTILS_VERSION=2.18
export GCC_VERSION=4.2.3
export NEWLIB_VERSION=1.16.0
export GDB_VERSION=6.8
.
export DIST=/opt1/gnuarm.dist    # tars will be downloaded here
export WORKDIR=/opt4/gnuarm.tmp    # tars will be unzipped and built here
export GNUARM_HOME=/opt/gnuarm   # Resulting binaries will be installed here
.
export SRC=$WORKDIR/src
export BUILD=$WORKDIR/build
export PREFIX=$GNUARM_HOME
export TARGET=arm-elf
.
md -p $DIST
md -p $SRC
md -p $BUILD
.
sudo mkdir -p $PREFIX

download:

cd $DIST
wget ftp://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VERSION}.tar.bz2
wget ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.bz2
wget ftp://ftp.gnu.org/gnu/gdb/gdb-${GDB_VERSION}.tar.bz2
wget ftp://sources.redhat.com/pub/newlib/newlib-${NEWLIB_VERSION}.tar.gz
wget http://www.gnuarm.com/t-arm-elf

untar:

cd $SRC
tar jxf $DIST/binutils-${BINUTILS_VERSION}.tar.bz2
tar jxf $DIST/gcc-${GCC_VERSION}.tar.bz2
tar jxf $DIST/gdb-${GDB_VERSION}.tar.bz2
tar zxf $DIST/newlib-${NEWLIB_VERSION}.tar.gz
cp $DIST/t-arm-elf gcc-${GCC_VERSION}/gcc/config/arm/t-arm-elf

binutils:

md $BUILD/binutils
cd $BUILD/binutils
$SRC/binutils-${BINUTILS_VERSION}/configure –target=$TARGET –prefix=$PREFIX –enable-interwork –enable-multilib
make all install 2>&1 | tee make.out

gcc core:

md $BUILD/gcc
cd $BUILD/gcc
$SRC/gcc-${GCC_VERSION}/configure –target=$TARGET –prefix=$PREFIX
–enable-interwork –enable-multilib –enable-languages=”c,c++” –with-newlib –with-headers=$SRC/newlib-${NEWLIB_VERSION}/newlib/libc/include

make all-gcc install-gcc 2>&1 | tee make.out

newlib:

md $BUILD/newlib
cd $BUILD/newlib
$SRC/newlib-${NEWLIB_VERSION}/configure –target=arm-elf –prefix=$PREFIX –enable-interwork –enable-multilib

make all install 2>&1 | tee make.out

gcc (phase two):

cd $BUILD/gcc
make all install 2>&1 | tee make.out

gdb:

md $BUILD/gdb
cd $BUILD/gdb
$SRC/gdb-${GDB_VERSION}/configure –target=$TARGET –prefix=$PREFIX –enable-interwork –enable-multilib

make all install 2>&1 | tee make.out

post-setup:

echo ‘export GNUARM_HOME=/opt/gnuarm’ >> ~/.profile
echo ‘export PATH=$GNUARM_HOME/bin:$PATH’ >> ~/.profile

The scripts can be downloaded from here.

Slug – Tips

Reducing Memory

Given that it has only 32MB of RAM, NSLU2 runs Asterisk as is very well, but if you want to add more daemons you might need to miser down on the memory.

Dropbear
Dropbear consumes only 2.4MB vs 8.2MB of SSH (who would’ve ever thought I’d be concerned about savings of 6MB of memory!)

Install dropbear:

apt-get install dropbear

Edit the /etc/default/dropbear configuration file:

NO_START=0
DROPBEAR_PORT=22

Remove sshd and start dropbear:

update-rc.d -f ssh remove
/etc/init.d/dropbear start

Here is a comparison of memory usage:

NSLU2:~# ps -eo comm,pid,%mem,vsize | grep dropbear
dropbear 1743 root 1.7 1916
dropbear 1884 root 3.4 2440

NSLU2:~# ps -eo comm,pid,%mem,vsize | grep sshd
sshd 1808 root 3.5 5148
sshd 1904 root 7.6 8216

Asterisk: If you’re running Asterisk, you might want to replace your modules.conf with minimal one found here Slimming Asterisk, it’ll prevent hoards of asterisk modules from loading.

Reducing Disk Writes

If your using a flash drive, you’ll definitely want to reduce the number of disk writes to the drive.

1. Mount with ‘noatime’ parameter, this will stop the kernel from writing the access time every time the file accessed.

/dev/sda1 / ext3 defaults,noatime,errors=remount-ro 0 1

2. Disable syslogd MARK entries
Disable syslogd MARK entries by adding this line to /etc/default/syslogd. You don’t need this if you’re using Debian 5.0.1 (Lenny) – it uses rsyslogd (instead of syslogd) and MARK entries are disabled by default (the “ModLoad immark” is commented out in /etc/rsyslog.conf).

SYSLOGD=”-m 0″

3. Log files are sync’d immediately to the filesystem the moment they are written to. To prevent immediate sync’ing, dash out all entries in /etc/default/syslogd. It will still write to the log files, just that they won’t get sync’d immediately.

4. Move samba caching to a ramfs
On doing a “find /var -mmin -10 -ls” I found some files that were being written to regularly by samba. Moved this to a small ramfs, by adding this line in /etc/fstab:

none    /var/cache/samba    ramfs    maxsize=512    0    2

5. Set swappiness value to zero (default is 60):

echo 0 > /proc/sys/vm/swappiness

or set this in /etc/sysctl.conf:

vm.swappiness = 0

6. Tune disk writes. Set the following in /etc/sysctl.conf:

vm.dirty_background_ratio = 5              # default = 5
vm.dirty_ratio = 50                                # default = 10
vm.dirty_writeback_centisecs = 500        # default = 500
vm.dirty_expire_centisecs = 3000           # default =3000

Spinning Down the Drive

After trying a couple of different ways to do this (hdparm, scsi-stop, etc), I found I had the best luck with the sg_start utility (from sg3_utils package):

Get the packages:

sudo apt-get install sg3-utils libsgutils1

Example command to spin down:

sg_start –stop –pc=2 /dev/sdb

Very useful. Besides using it for the slug, I also use it to force spin down my external drive after unmounting it and just before I pull the USB cable – so that I don’t get that horrible “clunk” noise in the drive.

Other

Some other things you might want to put into your Linux on Slug:

1. Enforce file system check
Given that the NSLU2 is headless, you definitely don’t want to be left helpless, should it ever go into maintenance mode asking you to do fsck. So enforce fsck, add the following in /etc/default/rcS:

FSCKFIX=yes

2. Power Button
The default setup causes the power button to reboot. I changed it to shutdown:

ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -h now

My Slug :-)

Got my NSLU2 today. It’s small, less than 5w, no moving parts, no fan. Specs: 266MHz ARM processor (XScale IXP420 ARMv5TE), 32MB SDRAM, 8MB Flash, 2GB USB Flash.

First thing I did was to replace the Linksys firmware with Linux. The possibilities for use of this thing are endless: as a print server, file server, internet radio, file downloads, etc. At 5w you don’t have to worry about wasting energy (compared with a 70w laptop or a 300w desktop), and can run it 24×7 without fear of damaging it.

I installed Debian/NSLU2 – Debian/ARM running on NSLU2.

The instructions for installing Debian/NSLU2 were pretty straight forward and worked with no problem.

FYI, pullout locations: for JTAG, GPIO, USB ports.

RedBoot Bootloader

Here’s some tips I got about accessing the firmware’s Redboot bootloader. That is, before you do anything you might want to make sure you can get to RedBoot bootloader’s command prompt on the NSLU2. By default RedBoot listens on 192.168.0.1, so you’ll need to add a route to that first.

First turn off the NSLU2 and execute this in a terminal:

sudo route add 192.168.0.1 eth0
sudo arping -f 192.168.0.1; telnet 192.168.0.1 9000

Then turn on the NSLU2. The above telnet will wait…

[spari@localhost ~]$ sudo arping -f 192.168.0.1; telnet 192.168.0.1 9000
ARPING 192.168.0.1 from 192.168.1.108 eth0

The moment it connects and returns the RedBoot prompt, hit Control-C (you will have less than 2 seconds to do that!):

[spari@localhost ~]$ arping -f 192.168.0.1; telnet 192.168.0.1 9000
ARPING 192.168.0.1 from 192.168.1.108 eth0
Unicast reply from 192.168.0.1 [00:31:41:59:26:54] 5.134ms
Sent 12 probes (12 broadcast(s))
Received 1 response(s)
Trying 192.168.0.1…
Connected to 192.168.0.1 (192.168.0.1).
Escape character is ‘^]’.
== Executing boot script in 1.430 seconds – enter ^C to abort
^C
RedBoot>

Tomato on Buffalo WHR-HP-54

Just got my Buffalo WHR-HP-54 from Newegg yesterday, and today… I flashed it with Tomato firmware. I also found it to be much better and more intuitively designed than OpenWRT.

Here are the steps:

  1. Open a terminal keep this command ready (DO NOT PRESS ENTER). Note that 192.168.11.1 is the default IP of the Buffalo router:

    tftp -v -m binary 192.168.11.1 -c put tomato-firmware.trx

  2. In another terminal ping the router:

    ping 192.168.11.1

  3. Then unplug the router.
  4. Wait 5 secs and plugin the router again and wait for ping to resume.
  5. Then immediately (within say 3 pings) pressed enter on the above tftp command.
  6. The pinging will stop and the tftp command will finish in less than 1 second. The router will reset itself, and it will reboot. This will take about 1-2 minutes. So do not disturb the router for at least 2 minutes.
  7. Then in browser goto 192.168.1.1.

That’s it! you should be able to see the Tomato screen.