Embedded Systems Unit - 2 About Embedded Linux
Embedded Systems Unit - 2 About Embedded Linux
Embedded Systems Unit - 2 About Embedded Linux
Unit_2
About Embedded Linux
Linux is an incredible piece of software. It’s an operating system that’s just as at home
running on IBM’s zSeries supercomputers as it is on a cell phone, manufacturing device,
network switch, or even cow milking machine. What’s more incredible is that this software is
currently maintained by thousands of the best software engineers and it is available for free.
Linux didn’t start as an embedded operating system. Linux was created by a Finnish
university student (Linus Torvalds) who was smart enough to make his work available to all,
take input from others and, most important, delegate to other talented engineers. As the
project grew, it attracted other talented engineers who were able to contribute to Linux,
increasing the burgeoning project’s value and visibility and thus bootstrapping a virtuous
cycle that continues to this day.
Linux was first written to run on the Intel IA-32 architecture and was first ported to a
Motorola processor. The porting process was difficult enough that Linus Torvalds decided to
rethink the architecture so that it could be easily ported, creating a clean interface between the
processor dependent parts of the software and those that are architecture independent. This
design decision paved the way for Linux to be ported to other processors. inux is just a
kernel, which by itself isn’t that useful. An embedded Linux system, or any Linux system for
that matter, uses software from many other projects in order to provide a complete operating
system.
The Linux kernel is written largely in C (with some assembler) and uses the GNU tool
set, such as make; the GCC compiler. The fact that this software could be used on embedded
system or could be modified to make it suitable for embedded deployment contributed greatly
to the acceptance of Linux for devices other than desktop machines.
Why Use Embedded Linux?
Embedded Linux is just like the Linux distributions running on millions of desktops and
servers worldwide, but it’s adapted to a specific use case. On desktop and server machines,
memory, processor cycles, power consumption, and storage space are limited resources—
they just aren’t as limiting as they are for embedded devices. A few extra MB or GB of
storage can be nothing but rounding errors when you’re configuring a desktop or server. In
the embedded field, resources matter because they drive the unit cost of a device that may be
produced in the millions; or the extra memory may require additional batteries, which add
weight. A processor with a high clock speed produces heat; some environments have very
tight heat budgets, so only so much cooling is available. As such, most of the efforts in
embedded programming, if you’re using Linux or some other operating system, focus on
making the most with limited resources.
The biggest difference between using a traditional embedded operating system and Linux is
the separation between the kernel and the applications. Under Linux, applications run in a
execution context completely separate from the kernel. There’s no way for the application to
access memory or resources other than what the kernel allocates. This level of process
protection means that a defective program is isolated from kernel and other programs,
resulting in a more secure and survivable system. All of this protection comes at a cost.
Technical Reasons to Use Embedded Linux
The technical qualities of Linux drives its adoption. Linux is more than the Linux kernel
project. That software is also at the forefront of technical development, meaning that Linux is
the right choice for solving today’s technical problems as well as being the choice for the
foreseeable future. For example, an embedded Linux system includes software such as the
following:
SSL/SSH: The OpenSSH project is the most commonly used encryption and security
mechanism today.
Apache and other web servers: The Apache web server finds its way into embedded
devices that need a full-featured web server.
The C Library: The Linux environment has a wealth of options in this area, from
the fully featured GNU C Library to the minimalist dietlibc.
Berkeley sockets (IP): Many projects move to Linux from another operating system because
of the complete, high- performance network stack included in the operating system. A
networked device is becoming the rule and not the exception.
The following sections explain why the Linux operating system is the best technological fit
for
embedded development.
Standards Based:
The Linux operating system and accompanying open source projects adhere to industry
standards; in most cases, the implementation available in open source is the canonical, or
reference, implementation of a standard. A reference implementation embodies the
interpretation of the specification and is the basis for conformance testing. In short, the
reference implementation is the standard by which others are measured.
Using standards-based software is not only about quality but also about independence.
Basing a project on software that adheres to standards reduces the chances of lock-in due to
vendor-specific features. A vendor may be well meaning, but the benefits of those extra
features are frequently outweighed by the lack of interoperability and freedom that silently
become part of the transaction and frequently don’t receive the serious consideration they
merit.
Process Isolation and Control
The Linux kernel, at its most basic level, offers these services as a way of providing a
common API for accessing system resources:
1. Manage tasks, isolating them from the kernel and each other
Process Isolation and Control The Linux kernel, at its most basic level, offers
these services as a way of providing a common API for accessing system resources.Manage
tasks, isolating them from the kernel and each other.
Memory Management and Linux: Linux uses a virtual memory-
management system. The concept of virtual memory has been around since the early 1960s
and is simple: the process sees its memory as a vector of bytes; and when the
program reads or writes to memory, the processor, in conjunction with the operating system,
translates the address into a physical address.
A Canadian1 cross-compiler build is one where the build, host, and target
machines are all different. You probably aren’t configuring the compiler to run on anything
other than an x86 Linux host, but you may need to support development groups running on
Windows or Mac OS and want to build the software on a Linux host. It’s possible that the
build is running an a 64-bit Linux host, producing a compiler that runs on a 32-bit host that
generates code for an ARM processor, so it pays to understand the mechanics of cross-
building.
Some of the most confusing parameters passed into configure are the values for host, target,
and build. These parameters are called configuration names, or triplets, despite the fact that
they now contain four parts. When you’re building a toolchain, the triplet describing the
target machine is the four-part variety: for example, arm-none-linux-gnueabi. This unwieldy
string prefixes the name of the toolchain executables so it’s clear what the cross-compiler is
targeting. It’s possible to change this prefix, but the best practice is to leave it be.
Bootloaders:
“The first section of code to be executed after the embedded system is powered on or reset on
any platform”
Comparison between PC and Embedded System:
• In an embedded system the role of the boot loader is more complicated since these
systems do not have a BIOS to perform the initial system configuration.
• Boot Loader in x86 PC consists of two parts
– BIOS(Basic Input/Output System)
– OS Loader(located in MBR of Hard Disk)
• Ex. LILO and GRUB
A boot loader isn’t unique to Linux or embedded systems. It’s a program first run by a
computer so that a more sophisticated program can be loaded next. In a Linux system, two
boot loaders usually run before the Linux kernel starts running. The program that the boot
loader runs can be anything, but it’s usually an operating system that then starts additional
programs so the system can be used by a user. The interesting question is, how does the
processor know to run the boot loader? At power-up, the processor goes to a certain memory
address (put there by the processor designer), reads the content of that address, and performs
a jump to the address stored at that location. This address is hard-coded into the processor so
the chip maker doesn’t have to change the silicon design for each customer or when the boot
loader changes. This little bit of code is referred to as the first-stage boot loader.
The code that runs next is what is commonly viewed as the boot loader in a Linux
ystem. This may be a program like U-Boot, RedBoot, or something else smart enough to then
load the operating system. After Linux has been loaded into memory, the boot loader is no
longer needed and is discarded; any evidence of the code in RAM is overwritten by the
operating system. Any device configuration done by the boot loader—for example, setting
the speed of the serial port or an IP address assigned to the network adapter—is also lost.
Linux reinitializes these devices during its startup process.
Boot loaders can be configured either to automatically run a sequence of commands or
to wait for user input via a serial connection or console. Because embedded systems
traditionally lack monitors and keyboards, you interact with the boot loader over a serial
connection using a terminal emulator like minicom. The serial port is the favored way of
presenting a user interface because the programming necessary to interact with a universal
asynchronous receiver/transmitter (UART) that manages a serial port is an order of
magnitude simpler than code to use a USB device or start a remote console over the network.
The boot loader’s user interface looks a little like a terminal shell in Linux, but it lacks the
bells and whistles you normally find, like auto-completion and line editing.
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.
Boot loaders on a desktop system run in two steps: a first- and a second-stage boot
loader. The firststage boot loader does just enough to get the second-stage boot loader
running. On a desktop system, the boot sequence reads one sector of data into memory and
begins executing that code. The first-stage boot loader contains a driver so that it can access a
file system on a fixed drive or possibly download the kernel from a remote source, like a
TFTP server or an NFS share. On a PowerPC or ARM system, the first-stage boot loader is
the code the chip runs after power-up instead of code that is loaded from the hardware.
After the boot loader does its job of getting Linux into memory, the Linux boot-up
process starts. Sometimes the kernel is compressed, and the first code decompresses the
kernel and jumps to an address that’s the kernel’s entry point. This code runs and performs
processor-level configuration, such as configuring the memory management unit (MMU—the
part of the processor that handles virtual memory addressing) and enabling the processor’s
cache. The code also populates a data structure that you can view by doing the following after
the system is up and running:
$ cat /proc/cpuinfo
Next, the kernel runs its board-level configuration. Some boards have peripherals like
PCI controllers or flash-management hardware that must be initialized so they can be
accessed later during the kernel startup process. When it’s ready, the code jumps into the
processor-independent startup code. Linux is now in control of the system; the software starts
the kernel’s threads and process management, parses the command line, and runs the main
kernel process. The kernel first runs what
you indicated on the command line (via the init parameter) and then attempts to execute
/sbin/init, /etc/init, /bin/init, and, finally, /bin/sh.
When the kernel starts the main user process, that process must continue running,
because when the process stops the kernel panics and stops as well. A kernel panic is the
worst sort of kernel error, because this sort of problem results in the system coming to halt.
The following illustration describes the booting process from power-on until the first program
runs.
1. The first-stage boot loader is the code in the processor that reads a location in memory
and may put a message on the console or screen.
2. The second-stage boot loader is responsible for loading what the system will run. In
this case, that is Linux, but it could be any program.
3. If the kernel is compressed, it’s now uncompressed into memory. A jump instruction
follows the decompression step that places the instruction at the next executable
instruction.
4. Processor and board initialization runs. This low-level code performs hardware
initialization. The code then reaches the kernel’s entry point, and processor-
independent code runs to get the kernel ready to run the init process.
5. The kernel entry point is the code that’s in the architecture-independent part of the
kernel tree. This code is located in the start_kernel function in the init/main.c file in
the kernel source tree.
6. The system mounts the initial RAM disk, sees if it contains an /init program, and if so,
runs it. If this program doesn’t exist or isn’t found, the boot process moves to the next
step.
7. One of the parameters passed to the kernel is the device containing the root file
system and the file system type. The kernel attempts to mount this file system and
panics if it isn’t found or isn’t mountable.
8. The program that the kernel first attempts to run is the value of the kernel parameter
init. In lieu of this parameter, the system looks for an init executable by attempting to
run /sbin/init, /etc/init, /bin/init, and finally /bin.sh.
Linux boot process
Boot Loaders for embedded System:
• U-Boot ("Universal Boot loader". Boot loader for PowerPC or ARM based
embedded Linux systems.)
• RedBoot (RedHat eCos derived, portable, embedded system boot loader)
• rrload (Boot loader for ARM based embedded Linux systems)
• FILO (x86 compatible boot loader which loads boot images from the local
filesystem, without help from legacy BIOS services. Expected usage is to flash it
into the BIOS ROM together with LinuxBIOS.)
• CRL/OHH (Flash boot loader for ARM based embedded Linux systems)
• PPCBOOT (Boot loader for PowerPC based embedded Linux systems)
• Alios (Assembler based Linux loader which can do basic hardware initialization from
ROM or RAM. The goal is to eliminate the need for a firmware BIOS on embedded
systems.)
Development Environment:
Much of the activity around embedded development occurs on a desktop. Although
embedded processors have become vastly more powerful, they still pale in comparison to the
dual core multigigabyte machine found on your desk. You run the editor, tools, and compiler
on a desktop system and produce binaries for execution on the target. When the binary is
ready, you place it on the target board and run it. This activity is called cross-compilation
because the output produced by the compiler isn’t suitable for execution on your machine.
Use the same set of software tools and configuration to boot the board and to put the
newly compiled programs on the board. When the development environment is complete,
work on the application proper can begin.
System Design
The Linux distribution used to boot the board isn’t the one shipped in the final product. The
requirements for the device and application largely dictate what happens in this area. Your
application may need a web server or drivers for a USB device. If the project doesn’t have a
serial port, network connection, or screen, those drivers are removed. On the other hand, if
marketing says a touch-screen UI is a must-have, then a suitable UI library must be located.
In order for the distribution to fit in the amount of memory specified, other changes are also
necessary.
Even though this is the last step, most engineers dig in here first after getting Linux
to boot. When you’re working with limited resources, this can seem like a reasonable
approach; but it suffers from the fact that you don’t have complete information about
requirements and the person doing the experimentation isn’t aware of what can be done to
meet the requirements.
QEMU’s build also requires some additional development libraries in order to build. Fetch
these by doing the following on an Ubuntu or a Debian system:
$ cd ~
$ wget http://bellard.org/qemu/qemu-0.9.1.tar.gz
Then, untar:
$ tar zxf qemu-0.9.1.tar.gz