Alberto Embedded & Open experience

Notes on my experience on Open Source Embedded Systems

Initializing an Ubuntu Linux-Embedded Development Machine

with 2 comments

The environment configuration script

Shell scripts are VERY useful! Shell scripts can save time for you automating frequent and tedious procedures.
So improve in Shell scripting!

The first script I introduce will setup easily the shell environment for our embedded project: $HOME/bin/env-setup.sh

#!/bin/bash
# env-setup.sh
# This will be the place where all the environment variables will be setup

#Shell that will have defined all the exported variables
bash

Ok it is empty now but this script will be filled in the following paragraph.

Give the execution permission to the new script:

$ chmod +x ~/bin/env-setup.sh

And add the directory $HOME/bin to the default $PATH variable with:

$ echo 'PATH=$PATH:/$HOME/bin' >> ~/.bashrc

So, in a new shell  typing env-setup.sh will configure it correctly for the project work.

Development tree

It is important to not spread things away in the host machine: things could look messy very soon.
What I suggest is to put all that is necessary under a single directory that we will call PRJROOT.
Create it in a partition with a lot of free space (around 10 Gb or much more) and make sure to have read/write and execution permission on it.

$ mkdir path_of_your_project_root
$ cd path_of_your_project_root

Next we will create a bin directory in the new PRJROOT, a place where useful binaries and development scripts can be placed:

$ mkdir bin

Then we can add the first useful lines in env-setup.sh:

#!/bin/bash
# env-setup.sh
# This will be the place where all the environment variables will be setup

#Our project root
export PRJROOT=path_of_your_project_root
export PATH=$PATH:$PRJROOT/bin

#Shell that will have defined all the exported variables
bash

The Linux kernel

Every subsystem of the Linux kernel nowadays has it’s own git repository and developing on a particular subsystem should be done over its public repository.
But it is important to have a reference Linus tree and here it is useful to understand how a Linux kernel git repository can be setup locally for the development.

Git is the version control software used to manage the Linux kernel. A quick reference on git can be found here: Git Quick Reference and for a specific reference for working on the kernel: Everyday GIT With 20 Commands Or So.

We can install and configure it with:

$ sudo apt-get install git-core
$ git config --global user.name "Alberto Panizzo"
$ git config --global user.email maramaopercheseimorto@gmail.com

Ok now we can clone the Linus kernel:

$ cd $PRJROOT
$ mkdir kernel
$ cd kernel
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linus-linux-2.6

In $PRJROOT/kernel will reside all kernels repositories and in $PRJROOT/kernel/linus-linux-2.6 there will be the Linus Torvalds maintained one (mainline development tree).

To update the Linus local kernel repository:

$ cd $PRJROOT/kernel/linus-linux-2.6
$ git pull
$ git checkout -f master

To setup a subsystem local development tree we can do:

$ cd $PRJROOT/kernel/
$ git clone git_remote_repository_ref subsystem_name  --reference linus-linux-2.6
$ cd subsystem_name
$ git branch your_development_project_name

Let me explain the upward commands:

–reference linus-linux-2.6 will create the local subsystem_name repository sharing the commit history with the linus-linux-2.6 repo. This will save a lot of bandwidth if the new repository is re-based continuously on the Linus one but care on it! deleting an old object in one of the two local repo, will affect the other! (normal development goes straight ahead..)

Cloned the remote repo, it is important to create a local branch with git branch to differentiate our development line from the master one.

Cross-Platform Toolchain

A Toolchain is a set of software tools needed to build binaries that a target machine could execute. A Cross-Platform Toolchain is a Toolchain built to be executed on the architecture of the Host machine and to produce binaries for the target architecture.

There are plenty of ways to get a cross-toolchain: getting it prebuilt, build it with your project build environment (OpenEmbedded ..), build it directly from source etc.
I present here a way that make use of Ptxdist to build an ARM1136-jfs suited one.

First of all Ptxdist

Ptxdist is an open project maintained by Pengutronix with the aim of create an automated management system for cross-build software projects.

From a new shell window we use the following commands to install Ptxdist on the host machine:

$ android.sh
$ mkdir $PRJROOT/build-tools
$ cd $PRJROOT/build-tools
$ wget http://www.pengutronix.de/software/ptxdist/download/v1.99/ptxdist-1.99.20.tgz
$ wget http://www.pengutronix.de/software/ptxdist/download/v1.99/ptxdist-1.99.20-patches.tgz
$ tar -xf ptxdist-1.99.20.tgz
$ tar -xf ptxdist-1.99.20-patches.tgz
$ cd ptxdist-1.99.20/
$ ./configure --prefix=$PRJROOT
$ make
$ sudo make install

Feel free to substitute the version to the newest one founded. Then  we can proceed on configure Ptxdist:

$ ptxdist setup

The showed menu permit to manage different kind of configuration, the useful ones are:

  • Proxies: Are you behind a proxy?
  • Source Directories: Here we can set the unified src directory where Ptxist download all the packages (${PRJROOT}/build-tools/src).
  • Developer Options: The option “environment variable whitelist” permit to save pointed variables from being erased before Ptxdist begin his job. The default behaviour is to flush all the environment to prevent conflicts. Here can be pointed out the variable PRJROOT so all the paths can be defined relatively from this one.

Feel free to navigate and understand all other entry in the configuration menu..

Then OSELAS Toolchain

OSELAS include lot of open-source projects, one of these is OSELAS-Toolchain. We can download it with:

$ cd $PRJROOT/build-tools
$ wget http://www.pengutronix.de/oselas/toolchain/download/OSELAS.Toolchain-1.99.3.4.tar.bz2
$ tar -xf OSELAS.Toolchain-1.99.3.4.tar.bz2
$ cd OSELAS.Toolchain-1.99.3.4/

This package contain different ptxdist projects that can be found in the ptxconfigs dir:

$ ls ptxconfigs/
arm-1136jfs-linux-gnueabigcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
arm-1136jfs-linux-gnueabigcc-4.3.2glibc-2.8binutils-2.19kernel-2.6.27-sanitized.ptxconfig
arm-cortexa8-linux-gnueabigcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
armeb-xscale-linux-gnueabigcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
armeb-xscale-linux-gnueabigcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
arm-hardfloat
arm-iwmmx-linux-gnueabigcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
arm-iwmmx-linux-gnueabigcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
arm-oabi
arm-v4t-linux-gnueabigcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
arm-v4t-linux-gnueabigcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
arm-v5te-linux-gnueabigcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
arm-v5te-linux-gnueabigcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
arm-v5tevfp-linux-gnueabigcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
arm-xscale-linux-gnueabigcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
arm-xscale-linux-gnueabigcc-4.2.3glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
avr
i586-unknown-linux-gnugcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
i586-unknown-linux-gnugcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
i686-unknown-linux-gnugcc-4.1.2glibc-2.5binutils-2.17kernel-2.6.18.ptxconfig
i686-unknown-linux-gnugcc-4.3.2glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
java
mingw
mipsel-softfloat-linux-gnugcc-4.2.3glibc-2.8binutils-2.18kernel-2.6.27-sanitized.ptxconfig
newlib

The project that we are looking for is:

arm-1136jfs-linux-gnueabi_gcc-4.3.2_glibc-2.8_binutils-2.19_kernel-2.6.27-sanitized.ptxconfig

That we can choose with:

$ ptxdist select ptxconfigs/arm-1136jfs-linux-gnueabigcc-4.3.2glibc-2.8 binutils-2.19kernel-2.6.27-sanitized.ptxconfig
$ ptxdist menuconfig

In the shell we have the configuration menu with a lot of interesting personalizations (c-lib, binutils, gcc configuration ..) but what we are interested in now is defining the correct installation prefix:

  • misc: we can define the installation prefix (${PRJROOT}/tools)  and other parameters.

Finished the configuration step we can proceed to the build process:

$ ptxdist go

I say this now.. a clean Ubuntu host machine do not have all the packages needed to build everything. Simply install packages when you are prompted to do it.

At the end of the building process the cross-toolchain binaries will be located in:

$PRJROOT/tools/OSELAS.Toolchain-1.99.3/arm-1136jfs-linux-gnueabi/gcc-4.3.2-glibc-2.8-binutils-2.19-kernel-2.6.27-sanitized/bin/

Configuration and build of the kernel

The Lunux kernel configuration scripts are context-sensible: the configuration menu depends on the value of certain environment variables.

At this point it is important the ARCH variable that must be set to “arm” to configure an arm suited linux kernel. So we can do:

$ cd $PRJROOT/kernel/linus-linux-2.6
$ export ARCH=arm
$ make our_[family]_defconfig #to initialize some importat configuration
$ make menuconfig  #to personalize the configuration.

For i.MX31 our_[family]_defconfig should be mx3_defconfig. Configuring the linux kernel needs lot of practice, lot of dependencies are automatically resolved but we must know what we are doing every time.

After the configuration we can proceed to the build process. To let the build system know what toolchain must be used, we have to set the CROSS_COMPILE variable to the path (an architecture prefix) of the OSELAS toolchain built:

$ export CROSSCOMPILE=$PRJROOT/tools/OSELAS.Toolchain-1.99.3/\
  arm-1136jfs-linux-gnueabi/gcc-4.3.2-glibc-2.8-binutils-2.19-kernel-2.6.27-\
  sanitized/bin/arm-1136jfs-linux-gnueabi-
$ make

At the end of the build process the kernel image can be found at: arch/arm/boot/zImage and the modules can be installed with:

$ make modules_install INSTALLMODPATH=rootfilesystem_dir

INSTALLMODPATH tell where to install the modules.

We can update the env-setup.sh script with the new variables:

#!/bin/bash
# env-setup.sh
# This will be the place where all the environment variables will be setup

#Our project root
export PRJROOT=path_of_your_project_root
export PATH=$PATH:$PRJROOT/bin

#Kernel configurations
export ARCH=arm
export CROSS_COMPILE_V6=$PRJROOT/tools/OSELAS.Toolchain-1.99.3/\
 arm-1136jfs-linux-gnueabi/gcc-4.3.2-glibc-2.8-binutils-2.19-kernel-2.6.27-\
 sanitized/bin/arm-1136jfs-linux-gnueabi-
export CROSS_COMPILE=CROSS_COMPILE_V6

#Shell that will have defined all the exported variables
bash

The root filesystem

The root filesystem is the body of the software in an embedded project. As the kernel is built with the cross toolchain, also the software stack that reside upon it must be too.

Depending on what is required by the embedded project, we decide the features that have to be in, and next, what open project we have to use to build the root-filesystem.

Open projects that can do this are (some):

  • Busybox: Simple and light application that provide a lightweight gnu shell environment with a lot of applets that emulate the standard gnu utils.
  • OSELAS-BSP: Using Ptxdist as the build management tool, OSELAS provide some projects well suited for PhyCORE products. Those project can be  customized for every other product.
  • OpenEmbedded: Project that make use of the bitbake build management system and provide a number of distributions that can be suited on a number of documented hardware. As OSELAS-BSP, porting to new hardware is not a painful task.
  • Android: Android is a complete stack for mobile hardware platforms. Needs some modifications in kernel and porting to a new hardware is not obvious, but can be done 🙂

To continue in this document we assume that in /nfsroot-name_of_the_stack there will be a good root filesystem for our purpose.

Connection between  the Host and the Target machine

An embedded development board need to have at last UART and Ethernet capability. The UART port (RS-232) is used for early debugging and late system console, the Ethernet instead will be used to download kernel and root-fs on the target machine.

Minicom

This is the most common utility that permit to have serial communication between Host and target machine. It can be installed and configured with:

$ sudo apt-get install minicom
$ minicom -s

Where, in “Serial port setup” the serial connection must to be configured as the board documentation say (indicate firstly the serial device).

tftp server

Lot of bootloaders uses the tftp protocol to download files from the host machine. We can install a suitable tftp server with:

$ sudo apt-get install tftpd-hpa

Next we have to create the reference directory for the server and make possible for us to write and read on this:

$ sudo mkdir /tftp
$ sudo chmod a+r /tftp
$ sudo chmod a+w /tftp

At the end we have to configure correctly the server. The configuration file is /etc/inetd.conf and looks like:

#servicename sockettype protocol wait/nowait user serverprogram serverprogarguments

tftp dgram udp wait root /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /tftp

at the end, restart the server to make it load the new configurations:

$ sudo /etc/init.d/tftpd-hpa restart

nfs server

Used to make able the target machine to boot a nfs development filesystem. We can install a nfs server with:

$ sudo apt-get install nfs-kernel-server

Next the configuration file is /etc/exports and would look like:

# /etc/exports: the access control list for filesystems which may be exported
#        to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#

/nfsroot-name_of_the_stack 192.168.64.1/255.255.255.0(rw,no_all_squash,no_root_squash)

where  192.168.64.1/255.255.255.0 is the network addresses allowed to mount this resource.

To restart the service after having modified the configuration file, simply:

$ sudo /etc/init.d/nfs-kernel-server restart

Ok this is the end..  Stay tuned for updates!

Alberto!

Advertisements

Written by Alberto!

24/11/2009 at 10:51 am

2 Responses

Subscribe to comments with RSS.

  1. Hi ,
    Thanks for this guide. Had a question . What are the files I would need to build a kernel specific to a development board ?

    Eg if I have a Tegr2 Dev board what would i need to build a kernel specific to this system ?

    chetan

    01/01/2011 at 4:34 am

    • Well, it is not simple to answer.
      The entire set of machine code and drivers files needed to support properly a target is not an easy stuff to manipulate. In this article I mention the machine specific defconfig as a good base to configure the kernel to be built over a specific target, but this method is not practicable for all targets (especially for the ones that are not supported at all 🙂 ).
      The better suggestion I can give you is: ask to the linux-arm@lists.infradead.org mailing list and start to study deeply the kernel build mechanism.

      Good Luck!
      Alberto!

      Alberto!

      03/01/2011 at 12:16 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: