Mon, 20 Feb 2012

Digi-Key Dorkery version 0.5

This script adds a few much-needed features to the Digi-Key search interface.

Get it Here

Current feature list for version 0.5:

Changes in version 0.5:

Suggestions welcome!

posted at: 21:42 | path: / | permanent link to this entry

Tue, 03 Jan 2012

Digi-Key Dorkery version 0.4

This script adds a few much-needed features to the Digi-Key search interface.

Get it Here

Current feature list for version 0.4:

Changes in version 0.4:

Suggestions welcome!

posted at: 01:08 | path: / | permanent link to this entry

Sat, 05 Nov 2011

A basic ARM toolchain from scratch

Anyone working with ARM microcontrollers will inevitably run into the problem of acquiring a working compiler suite for their device. Many resort to prebuilt "freebie" suites from vendors, and an unlucky few try to roll their own and give up. This quick tutorial will hopefully save some heartache for those who like to know where their bits came from.

The goal will be to build a complete toolchain with working gcc, binutils, and uClibc, sufficient to compile both OS-less microcontroller firmware and high-level linux software.

Step 1: Setup

This bootstrap will be done in a simple directory tree that keeps clean source trees separate from build directories. This makes it trivial to nuke a dir and start over if you make a mistake. First, you will need a top-level directory. Mine is ~/armcross2. Then, you will need these subdirectories:

Once those are created, download and unpack your sources into the source directory. I will be using the following, which were the latest at the time:

Next, create a script in the top directory called env.sh . This will hold environment variables for convenience, and must be executed first every time you open a terminal to be sure that they are set. In it, place the following:

top=~/armcross2  # Change me
target=arm-linux-uclibceabi
arch=arm
tools=$top/tools
sysroot=$top/sysroot
export PATH=$tools/bin:/usr/bin:/bin
[ -z "$oldps1" ] && oldps1="$PS1"
PS1="(toolchain) $oldps1"

Don't change the target unless you like pain. I could explain what it means, but it really boils down to how different tools interpret it, and most of the target-related problems tend to come from gcc which is no fun at all. Now load your environment with the "." command (that's a single period):

.  env.sh

The PS1 line causes the terminal prompt to change so that you know your environment is loaded. Now you're ready to compile.

Step 2: binutils

binutils, as its name implies, is a suite of tools for manipulating and inspecting program binaries. It includes the linker, assembler, and tools for converting object code to various formats that one might need.

To compile and install it, execute these commands:

cd $top/build
mkdir binutils; cd binutils
../../source/binutils-*/configure \
  --target=$target \
  --prefix=$tools \
  --with-sysroot=$sysroot
make -j4
make install

Step 3: linux headers

There are two important sets of headers on a linux system, one comes from libc and the other comes from the kernel. Neither are terribly important when you have no operating system but gcc won't compile without them. First comes the kernel headers.

cd $top/build
mkdir linux; cd linux
make -C ../../source/linux-*/ O=`pwd` headers_install \
  ARCH=$arch CROSS_COMPILE=$target- \
  INSTALL_HDR_PATH=$sysroot/usr/

Step 4: gcc bootstrap

A full toolchain bootstrap requires building GCC 3 separate times. In theory this first build is sufficient to produce microcontroller firmware, however in my experience it is too difficult to use since it seems to not have enough information about where headers are located.

cd $top/build
mkdir gcc-1; cd gcc-1
../../source/gcc-*/configure \
  --target=$target \
  --prefix=$tools \
  --without-headers --with-newlib --disable-shared \
  --disable-threads --disable-libssp --disable-libgomp \
  --disable-libmudflap --disable-libquadmath \
  --enable-languages=c
make -j4 all-gcc
make install-gcc

Step 5: libc headers

Next the libc headers need to be installed. This will involve first configuring uClibc, which has a menu-driven system identical to that used by the kernel. Use the arrow keys to navigate, enter to select, and press escape twice to go back to the previous menu.

cd $top/build
mkdir uclibc; cd uclibc
make -C ../../source/uClibc-*/ O=`pwd` menuconfig

Now configure as follows: First, set the "Target Architecture" to arm. Then enter the "features and options" submenu and set "Target Processor Endianness" to "Little Endian". Go up a level and enter the "General Library Settings" menu, and set "Thread support" to "older (stable) version of linuxthreads". You don't have to have a libc with threading support, but if it is disabled you will need to adjust the configure options to gcc parts 2 and 3. Finally, back out and save your configuration, then complete the installation:

make -C ../../source/uClibc-*/ O=`pwd` install_headers install_startfiles \
  DESTDIR=$sysroot CROSS=$target- \
  RUNTIME_PREFIX=/ DEVEL_PREFIX=/usr/ STRIPTOOL=true \
  KERNEL_HEADERS=$sysroot/usr/include

Step 6: gcc, Part 2

First, a dirty trick. In order to compile all the components of gcc, a libc is required. But libc hasn't been built yet, and can't be until gcc #2 is done. What to do? Fake it. A libc.so with no contents will be created first, which will placate the linker well enough to get gcc built, and then the real libc will be built in the next step.

$target-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $sysroot/usr/lib/libc.so
cd $top/build
mkdir gcc-2; cd gcc-2
../../source/gcc-*/configure \
  --target=$target \
  --prefix=$tools \
  --with-sysroot=$sysroot \
  --disable-libssp --disable-libgomp --disable-libmudflap \
  --disable-libquadmath --enable-languages=c
make -j4
make install

Step 7: libc

Next, the final libc will be built.

cd $top/build/uclibc
make -C ../../source/uClibc-*/ O=`pwd` all install -j4 \
  DESTDIR=$sysroot CROSS=$target- \
  RUNTIME_PREFIX=/ DEVEL_PREFIX=/usr/ STRIPTOOL=true \
  KERNEL_HEADERS=$sysroot/usr/include

Step 8: gcc, Part 3

Now the third and final gcc will be built against the new libc and with all features enabled. One more hack is required; as documented here and here a configure script must be modified to not run a test it is unable to execute.

cd $top/build
mkdir gcc-3; cd gcc-3
../../source/gcc-*/configure \
  --target=$target \
  --prefix=$tools \
  --with-sysroot=$sysroot \
  --enable-__cxa_atexit \
  --disable-libssp --disable-libgomp --disable-libmudflap \
  --enable-languages=c,c++
make -j4
make install

Step 9: Profit!!

If you made it this far, you have gcc compiled and installed into your tools directory. Congratulations! All you have to do to use it, is add your tools/bin directory to PATH and prefix toolchain commands with your target setting (in this case, arm-linux-uclibceabi-). You can check out a makefile I used for a Cortex-M3 device here

posted at: 03:03 | path: / | permanent link to this entry

Tue, 25 Oct 2011

Digi-Key Dorkery version 0.3

This script adds a few much-needed features to the Digi-Key search interface.

Get it Here

Current feature list for version 0.3:

Changes in version 0.3:

Suggestions welcome!

posted at: 02:13 | path: / | permanent link to this entry

Wed, 25 May 2011

HTTP network install menu using gPXE and pxelinux

One cool feature of syslinux, the bootloader commonly used on Linux install media, is pxelinux -- a form of the loader that runs in the Preboot Execution Environment, allowing systems on a LAN to boot into a menu of OS installers and tools. pxelinux can also integrate with gPXE, an open-source embedded network stack designed to replace the factory ROMs on network cards with advanced features like HTTP support but also capable of building into many bootable image formats including ISO and hard-disk images.

What I hacked on today is a way to configure gPXE to fetch all of the pxelinux confguration over HTTP rather than the traditional TFTP, thus creating the possibility of bootstrapping an installer over the internet. To make this more useful in practice, instead of creating a PXE image which would require a functioning DHCP server to launch I created a disk image that can be loaded onto a USB key or virtual flash device such as those found on DRAC or iLO management cards. This means I can now remotely flash gpxelinux onto a server and network boot into an install of Fedora or Scientific Linux, for example.

To get started, first set up a typical pxelinux environment and make it reachable via HTTP. Then build a gPXE image with a URL to that environment hardcoded in it using these steps:

git clone git://git.kernel.org/pub/scm/boot/syslinux/syslinux.git
make
cd gpxe/src

cat >netinst.gpxe <<EOD
#!gpxe
dhcp net0
set 209:string pxelinux.cfg/default
set 210:string http://my.http.server/pxeroot/
imgload pxelinux.0
boot pxelinux.0
EOD

make bin/gpxe.sdsk EMBEDDED_IMAGE=netinst.gpxe,../../core/pxelinux.0 NO_WERROR=1

You can then upload gpxe.sdsk to a DRAC Virtual Flash. Alternately, replace "gpxe.sdsk" with "gpxe.dsk" for a hard drive image or "gpxe.usb" for a USB-key friendly output. I found the sdsk (floppy image) format to work best with the DRAC's Virtual Flash device.

Some tips:

  1. Many Dell servers ship with Broadcom NICs which require firmware to function correctly. I could not reliably pull down files using gPXE with one of these NICs. The gPXE project is purportedly working on improving this as a Google Summer of Code project. You will need to change 'net0' to e.g. 'net2' if you have additional non-Broadcom NICs that you wish to boot from.
  2. You can change the 'dhcp' line in the gPXE script to configure a static IP instead, see the gPXE wiki page on scripting for examples.

posted at: 14:24 | path: / | permanent link to this entry