Linux on embedded devices

Introduction

Pro Linux Embedded Systems

After booting, you need to inspect several other things. Most embedded engineers (rightly) concern themselves with the file system to be used by the board. A quick way to see what file systems the kernel supports is to inspect /proc/filesystems.

Pay attention to the nodev file systems; they aren’t associated with a physical device but rather act as a way for the kernel and user programs to communicate.

As devices initialize, the practice is to use a certain data structure, a kobject, to track its existence. Kobjects are data structures used throughout the kernel that are exposed through the sysfs file system mounted at /sys:

# mkdir /sys
# mount -t sysfs none /sys
$ cd /sys

More information with "cat /proc/devices" and "cat /proc/filesystems".

After building a root filesystem using eg. Buildroot, you can check what it contains by mouting it via a loopback:

# mkdir –p /mnt/arm-rfs
# mount –t ext2 –o loop rootfs.arm-20090310.ext2 /mnt/arm-rfs

During the bootup process, the kernel always looks for an initial RAM disk. The initial RAM disk comes from a file attached to the kernel during the build process that is uncompressed into RAM memory when the kernel starts. If a file to boot the system (initrd) is present, the kernel attempts to use the initial RAM disk. The kernel looks for an initial RAM disk root file system and then for the root file system as instructed on the command line. Every kernel has one of these file systems, stored as a compressed cpio archive. If you didn’t tell the kernel to create one, there’s a very small, empty archive.

A device node is a way for a user program to communicate with a kernel device driver. These are created on the file system so the kernel build can gather them into the RAM disk it uses to boot the file system:

$cd $RFS
$mkdir dev
$cd dev
$sudo mknod console c 5 1
$sudo mknod null c 3 1

zImage: This is a zlib compressed image of the kernel, ready to boot on a board.

uImage: This is a zlib compressed image, ready to boot on a board that’s running the U-Boot boot loader. It’s much like the zImage but contains additional data that makes booting with UBoot more efficient.

After compiling the kernel, the vmlinux file residing in the root of the kernel tree isn’t the file used to boot the board. You need to use the file in the arch/<target arch>/boot directory to boot the board. Some users mistakenly think this is the file used to boot the board, but this file is the image of the kernel after it’s decompressed into memory on the target.

Boot loaders also act as an interface to the flash devices on the board. Flash memory (named so because the reprogramming process was reminiscent of a flash camera to the designer) is a type of Electrically Erasable Programmable Read-Only Memory (EEPROM) where individual areas (called blocks or erase blocks) can be erased and written; before the invention of flash memory, EEPROMs could only be erased and rewritten in their entirety. With no moving parts and low power consumption, flash memory is an excellent storage medium for embedded devices. Flash support in the boot loader gives you the ability to manage the flash memory by creating segments, which are named areas of the flash memory, and to write data, such as a root file system or kernel image, into those areas.

U-Boot has the ability to uncompress the kernel rather than have the kernel decompress itself.

 

Projects that don't use Automake/configure typically require setting the CROSS_COMPILE env't variable:

export CROSS_COMPILE=powerpc-linux

 

To get a view of what the make file will do, use the –recon parameter: $ make--recon

 

A RAM buffer–based file system resides in RAM, because the file system cache is never written to any storage medium. This file system type appeared in the 2.6 kernel and is most commonly known through the initramfs file system. This is different than a RAM disk: a RAM disk reserves some portion of RAM and uses a driver to make that portion appear as though it’s a block-based device.

Any block-based file system can be used on an MTD device, as long as it’s mounted read-only. For example, an ext2 file system can be placed on the flash media and will work fine as long as it isn’t used for writing; this can be enforced by mounting the file system as read-only. One of the niceties of using a block-based file system is that tools readily exist to both create and inspect the file system. File systems like ext2 and ext3 include the necessary tools with nearly every Linux distribution.

A block-based file system can also be loopback mounted, a technique that allows you to create the file system in a file and then mount the file as though it was a block device.

The Linux operating system lets you create an ext2 file system on an MTD block device, and you can read and write to the device with apparently no problem—but sooner or later, you’ll damage the device because the Linux driver doesn’t perform the wear-leveling required by this type of device.

MTD devices come in two flavors: NAND and NOR flash. NAND can perform read operations faster than NOR, but NOR is a faster technology for writing. When you use a file system that runs on top of these devices, there is one difference: the file system driver in the Linux kernel (in this case, specifically, JFFS2 or YAFFS2) handles the details for you.

Ramfs: This is a very fast file system that has a small amount of overhead (just a few KB), but it continues growing until all the memory on the device is consumed. When the file system is mounted as read-only, this problem doesn’t arise, making this a safer choice for a production system.

Tmpfs: The tmpfs file system is just like the ramfs file system with the additional feature of limiting the amount of memory the file system can consume.

You can get the same output as ldd on the target by doing the following when running a program:

$ LD_TRACE_LOADED_OBJECTS=1 some-program

Although you can write your own init, the program included with BusyBox is small and packs enough power to be well suited to an embedded system.

/sysfs: Contains driver and hardware information. This file system is recommended because it’s the preferred way for the kernel to communicate information about the hardware configuration of the system to userland. In this way, sysfs file systems supports the udev devicemanagement system.

You can create the minimal contents for a root file system by doing the following:

$ mkdir ~/minimal-rfs; cd minimal-rfs
$ mkdir ./proc ./tmp ./dev
$ sudo mknod ./dev/console c 5 1
$ sudo mknod ./dev/null c 1 3

The application resides in the root of the file system and must continue running or the system will halt, because at least one process must kept running in a Linux system. This root file system can be built as an initramFS and therefore assembled with the kernel and included in the kernel image file deployed on the device. The application is placed in the root directory of the target machine and is statically linked, so it doesn’t require any additional files. When you use this approach, the kernel’s init= parameter must be set to the application or the application must be named linuxrc so that it’s run when the system starts;

Embedded Linux Primer - A Practical, Real-World Approach

Programming Embedded Systems, 2nd Edition

Designing Embedded Hardware

Resources

Books

Forums

Sites and articles