Ubuntu 9.04 – NSLU2
The first release of Ubuntu for ARM architecture, Ubuntu 9.04 is working great on NSLU2. So far I’ve had running NFS, dhcp3, bluetooth (setup as a PAN AP), WiFi, CUPS, lirc (using the “linux input layer” drivers), wpa_supplicant, mjpg-streamer, mpd. Also successfully cross-compiled and loaded modules: autofs, gpsca, and rt73usb (for my WiFi dongle).
The installation took almost 6-8 hours on a 256kbps DSL connection, external USB flash. Most of it seems to be processing. In many instances during the installation it looked like it was frozen — progress bar stays at the same % mark for sometimes even an hour. Also towards the end when it says installation is completed, it gives an impression that it’s hung: there’s just a blue screen with a blinking prompt at the last line. It stays like that about 20min, and then returns back, prompting you for setting hardware clock. After that, it’s done, reboots.
First thing I did to avoid going through that agonizingly long process again, is backup the filesystem and the NSLU2 internal flash image.
Sheeva Plug
An ARM-based Linux server in a wall-wart – check this out! the Sheeva Plug, introduced by
Marvell. It’s like a headless Intel P3 or AMD Athlon server in a wall-wart, but just drawing only 10 W of power and under $90. You get a system with a 1.2 GHz ARM926EJ-S compatible processor (Marvell’s MV88F6281 Sheeva technology based processor, ARMv5), 512 MB SDRAM, 512 MB Flash, 1 USB 2.0, an SDIO slot, a 1Gig Ethernet, plus it has the JTAG and console available (via dedicated mini-USB port on the side; on the Slug you had to hardware hack and pull the wires out for these). In addition Marvell has made it totally open source (software, hardware, everything,…). Compare that with the Slug’s: 266 MHz, 32 MB SDRAM, 8 MB Flash.
Marvell website already provides a flash image of Ubuntu 9.04 with detailed instructions here.
Here’s some articles/links: Cnet, Slash Gear, NY Times, Scientific American, Plug Computers.
Slug Upgrade – on Batteries
I’m in a place where we have random power cuts during this time of the year, so didn’t want to risk bricking my slug (NSLU2) during an upgrade and so decided to power it by batteries. My fear was that I might end up bricking the slug if there was a power cut right when flashing it. Later I found out it was unfounded, as according to the upslug2 documentation there is really no way for you frag the RedBoot bootloader unless you intentionally do so, as by default, even if your flash image contains RedBoot and SysConfig sections, it does not overwrite the RedBoot and SysConfig areas (they remain untouched).
Anyway… here are some notes on upgrading a slug while on battery power.
Decided to upgrade my Slug to Debian 5.0 (debian-5.0beta1.zip). Followed the steps here (used the upslug2 method for flashing). It’s handy to have a serial console to see if it’s picking up the DHCP stuff properly. I hooked up the Slug directly to my laptop (running Ubuntu) via crossover cable.
Here are some stats. The Slug upgrade took 2 hrs 50min (on a 266MHz Slug, with a 200Kbps DSL connection, 57MB download). At around 2 hrs you’re prompted to create root and user accounts. About 15 minutes later you’re prompted for additional package selection (I unchecked all). In the next 30 minutes it prepares and flashes the kernel image to the Slugs flash memory. On a Slug (with a 2GB USB flash drive plugged into it), 4 freshly charged AA NiMH 2700mAH batteries (5.6v no load) lasted 3 hrs 10min before it dropped to a 4.3v (no load).
Freaky Assembly?
After a looong time, I was debugging some embedded C code and thought I found something freaky:
C code
for (i = 0; i < 1000000; i++);
ARM code disassembly (as generated by GNU ARM gcc)
0×0000019c <main+196>: mov r3, #0 ; 0×0
0×000001a0 <main+200>: str r3, [r11, #-16]
0×000001a4 <main+204>: b 0×1b4 <main+220>
0×000001a8 <main+208>: ldr r3, [r11, #-16]
0×000001ac <main+212>: add r3, r3, #1 ; 0×1
0×000001b0 <main+216>: str r3, [r11, #-16]
0×000001b4 <main+220>: ldr r2, [r11, #-16]
0×000001b8 <main+224>: mov r3, #999424 ; 0xf4000
0×000001bc <main+228>: add r3, r3, #572 ; 0×23c
0×000001c0 <main+232>: add r3, r3, #3 ; 0×3
0×000001c4 <main+236>: cmp r2, r3
0×000001c8 <main+240>: bls 0×1a8 <main+208>
The three highlighted lines above in affect initialize r3 with 999999 (first initializes r3 with 999424, then adds 572 to it, then adds 3 to it).
What puzzled me was why couldn’t it do that directly (mov r3, #999999)?
Then after some scratching my head, an almost faint memory of ARM assembly language dawned on me… ARM instructions are 32-bit, of which Operand 2 can be only 12-bits. In addition:
- Of these 12 bits, 8-bits are for data, and 4-bits are used for ROR.
- The ROR bits are in turn multiplied by 2 before being applied on the 8-bits.
The combination of ROR and shifting by 2 greatly extends the range. The assembler automatically does it for you if it sees an operand greater than 8-bits.
This can be a great interview question :-).
Do the math, verify…
999424 + 572 + 3 is the closest tuples you can get to add up to 999999 using the 12-bit ROR with x2 multiplier for the RoR.
Just for verification, here are the instructions from memory:
1b8: 3D39A0E3 ; 0xE3A0393D
1bc: 8F3F83E2 ; 0xE2833F8F
1c0: 033083E2 ; 0xE2833003
To get 999424 (0×0F4000):
0×0000003D ROR 18 (0×9 x 2) = 0×000F4000 (ROR 18 = LSL 6)
As confirmed by the instruction: E3A03 93D
To get 572 (0×023C):
0×0000008F ROR 30 (0xF x 2) = 0×0000023C (ROR 30 = LSL 2)
As confirmed by the instruction: E2833 F8F
To get 3 (0×0003):
0×00000003 ROR 00 (0×0 x 2) = 0×00000003 (ROR 00 = LSL 0)
As confirmed by the instruction: E2833 003
Note: the LSL is just for convenience, it’s good only if data has all zeros padded on the left (at least enough to cover the LSL).
Slug Flash
Where is the bootloader, kernel and initial ramdisk? The boot sequence is documented here.
Some notes on the slug’s flash memory organization, taken from system logs:
From dmesg:
Searching for RedBoot partition table in IXP4XX-Flash.0 at offset 0×7e0000
6 RedBoot partitions found on MTD device IXP4XX-Flash.0
Creating 6 MTD partitions on “IXP4XX-Flash.0″:
0×00000000-0×00040000 : “RedBoot” # 256 KB
0×00040000-0×00060000 : “SysConf” # 128 KB
0×00060000-0×00080000 : “Loader” # 128 KB
0×00080000-0×001e0000 : “Kernel” # 1.375 MB
0×001e0000-0×007e0000 : “Ramdisk” # 6 MB
0×007e0000-0×00800000 : “FIS directory” # 128 KB
From /proc/mtd:
dev: size erasesize name
mtd0: 00040000 00020000 “RedBoot”
mtd1: 00020000 00020000 “SysConf”
mtd2: 00020000 00020000 “Loader”
mtd3: 00160000 00020000 “Kernel”
mtd4: 00600000 00020000 “Ramdisk”
mtd5: 00020000 00020000 “FIS directory”
From /proc/partitions:
31 0 256 mtdblock0
31 1 128 mtdblock1
31 2 128 mtdblock2
31 3 1408 mtdblock3
31 4 6144 mtdblock4
31 5 128 mtdblock5
Balancing Robot
Botka, The Barely Standing Robot. This is one impressive balancing robot. Not even a bit of jitter. Midway through the video the thing takes on some solid whacks and still standing. For comparison: NXTway-G (the Lego Mindstorms NXT uses the Atmel AT91SAM7S ARM processor).
Botka probably uses some sophisticated PID control? fuzzy logic enhanced or a Kalman Filter? given it’s amazing response even in motion.
I remember doing Kalman Filters way back in my graduate courses, pretty hairy level of mathematics, but real cool nevertheless once you got a simulation working. Never thought I’d see the daylight of that again. It seems to be integral to many embedded industrial control systems.
Anything which requires very accurate real-time prediction and correction like image stabilization, noise reduction, maglevs, satellite navigation, cruise control,…
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:$PATHmake ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnu-
ARM Toolchain
Updated (April 26, 2008)
Here’s how I built 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:
- 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).
- 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.
ARM boards
Just got back from a trip to Chicago – Oak Park, a pretty nice area, a nicely renovated “gentrified” neighborhood, west of Chicago.
Researching a good ARM board to buy. Narrowed it down to these (all these boards have USB and SD card reader):
ARM7TDMI-S boards:
- Olimex SAM7-P256 (SAM7-Pxxx Rev. E) – Atmel AT91SAM7S256, 256K Flash, 64K RAM, 60MHz, 18MHz crystal. $87.
- Olimex LPC-P2148 – NXP LPC2148, 512K Flash, 32K+8K RAM, 60MHz, 12MHz crystal. $77.
.
ARM7TDMI-S boards w/Ethernet:
- Olimex SAM7-LA2 – Atmel AT91SAM7A2, 1MB Flash, 4MB SRAM, 30MHz, 6MHz crystal. $140.
- Olimex SAM7-EX256 – Atmel AT91SAM7X256, 256K Flash, 64K RAM, 55MHz, 18MHz crystal. This board is loaded with stuff. $120.
.
ARM920T boards w/MMU (for running embedded Linux):
- Olimex CS-E9302 – Cirrus Logic EP9302, 16MB Flash, 32MB SDRAM, 200MHz. Cirrus Logic has a very good linux forum. $180.
- Olimex SAM9-L9260 – Atmel AT91SAM9260, 512MB NAND Flash, 64MB SDRAM, 180MHz, 18MHz crystal. $217.
- … or just get a Slug – XScale IXP420 (ARMv5TE), 8MB Flash, 32MB SDRAM, 266MHz. $80.
Arduino GPS
Just to get my hands dirty and wrap it up with the AVR’s, I created a GPS data logger – using an Arduino board, GPS receiver chip, 4×20 LCD, and a uALFAT microSD board.

A good document on NMEA commands and data formats used by GPS chips is here. Regarding the GPS unit, it was SiRF vs Trimble, and I went for SiRF, the SiRF III (the EM-406A by USGlobalSat). I picked it over the Trimble Lassen IQ and the Parallax.
Of course you can buy a GPS data logger board with LCD for about $200. But the whole point is that it’d be a learning exercise, an interesting one :-).
I decided to write it in raw C (UART driver, LCD driver, flash data logger,…) instead of Arduino’s Wiring language. This amounts to pretty much reading most of the 300 page data sheet for the MCU, giving you a thorough understanding of all aspects of the MCU – GPIO, clocks, counters, interrupts, UART, SPI, I2C,… all related considerations like registers, masks, timings, memory organization,…
(photo updated, 12/2007).