Linux for Embedded Devices - First Approach -

Linux is a very popular operating system in many computer systems and it's a first choice on data centers and high end software infrastructure, but the flexibility of the penguin’s kernel made this to be very suitable for extremely low end devices.

Come with me and discover the blessings and curses of the linux kernel in embedded systems, low resource devices and (not-so-hard-real-time things).

What is linux?

In short, linux is only the kernel of a family of operating systems known by the generic name of “Linux”. 

In this family you can find from very UNIX-like classic systems like RedHAT Enterprise Linux or IBM SuSE Linux to the very tiny openWRT distribution in your router or the very unrecognizable linux-based Android system in your phone.

All of them have the common denominator of the Linux kernel, even if the "programs running on it are based on a virtual machine (like android), or the scheduler is tuned for ethernet packet handling (openWRT), or the input/output subsystem is overpowered to handle a lot of high bandwidth non-volatile storages.

The key concept to understand the differences and similarities across all linux systems is the differentiation of the kernel (properly Linux) and the userland, the collection of programs, libraries, configuration files, filesystem conventions and protocols that the user touches to communicate with the kernel.

The kernel (Linux) is responsible to provide program and thread coordination, memory management and resource abstraction to the userland programs (the “users” of the kernel services)

These “users” provide an interface with the user (Desktop interface, web browser, touch or presentation GUI, or none in many cases)

The programs written in userland rarely access linux services directly. Instead, this uses a library like libc or other that provides abstraction under kernel interface changes.

The collection of libraries, system services (programs that provide some abstraction to the kernel interface) and programs is know as USERLAND and vary really much between linux systems (android, gnu/linux or embedded linux)

Why Linux in Embedded Systems?

Now you may be asking the question of the year… Why do I want to use Linux in an embedded system?

Well… Linux is not suitable to all embedded systems, specially if your system lacks a? considerable amount of RAM and the CPU doesn't have a Memory Management Unit (very recommended if you handle many processes in non trustable manner like network packet or very dynamic processes) but in other hand, if you need to manage a big application processor without an operating system, the challenge increases very quickly and the possible bug-madness makes this way very impractical.

Linux is ubiquitous across many architectures and is de-facto standard in application processors from ARM, but is very suitable if your architecture is more classic like x86/x86_64, PowerPC, SPARC or MIPS (Did someone say RISC-V?)

Some facts to decide if you need a Linux system for your embedded device:

  • If you don't have tens of megabytes of RAM, Linux kernel (even in a minimal configuration) is a not-so-cool idea… Linux needs RAM… the minimal value is 8MB… recommended 32 or more…
  • If your processor does not have a MMU maybe you wanna reconsider the usage of Linux: Even if the kernel can operate without MMU, the userland programs normally assumes that it is running on a MMU-capable system and whacks the system resources expecting some help from the address translation hardware.
  • If your system needs an interrupt with very extreme low latency, Linux (and maybe application processor) is not for you: Linux (like many other OS) is not built around real time capabilities, even if you can tune the kernel extremely and obtain very decent results with it. But… if you are using an application processor with complex cache hierarchy and out of order instruction processing, you need more than a good OS for real-time or hard-predictive behavior.

Linux is Fat for many embedded systems
(image from https://www.deviantart.com/gothicdarkshine/art/Very-Fat-Tux-208818283)

But in other hands, Linux may be the better option for your embedded devices:

  • Many application processor like cortex-A series is designed exclusively to run Linux variants and all the support of the software is only in linux
  • If you need to manage efficiently complex resources like MMU, IOMMU, advanced DMA, complex interfaces like PCIe, USB or SATA, the Linux kernel provides an excellent software stack not only free of charge but, also, tested by a large amount of people in real-world situations
  • Linux provides a really efficient and probed network stack around a myriad of protocols like TCP/IP, 6LoPAN, ZigBee, SLIP/PPPoE and many old-school protocols. Other stacks like LwIP do not have the quality and the secured design around the code. Also, security patches are released regularly and quickly. The major investigation around network security is made around the Linux kernel.
  • In the security section, the active community around Linux and the very professional work (literally state-of-the-art in security schemas are placed in linux development) maintain a robust base of code and guarantee a regular security advisory for a risky issues (by example, meltdown and specter were quickly mitigated on linux before other systems)
  • The free nature of the Linux kernel source enables many people to adapt them to a particular purpose resulting in a great adaptability of the software from the handheld devices to mainframes or deeply embedded systems with real time requirements.

Linux System Anatomy

Despistes the differences across many systems, the embedded Linux has essential characteristics that were found in all variants.

  • The Kernel: In fact, a big C program that have no dependencies of libraries or other resources (technically you said this is a statically linked program)
  • Into the kernel you found a startup code capable of initializing the systems in your machine (normally the kernel expects to have some initialization before it is loaded), common code like schedulers, block management, driver load and helper functions like memory copy or list management.
  • Additionally, the kernel binary contains the basic drivers required by the architecture to operate (like clock drivers, CPU initialization, essential IO drivers, etc). You can bundle many drivers from different processors and select the correct one using the devicetree.
  • Beside the kernel binary, you need a device tree file (may be appended with the kernel image for convenience). The device tree is a structure containing a description of the hardware, your drivers and their initialization parameters (how much RAM or FLASH are in the system, what clocks are used, who is configured the pins of the chip and so on…).
  • Some architectures (notably X86) do not use device tree but instead use another table-like system bundled with the BIOS or UEFI: The ACPI tables. In fact, the purpose is the same (inform the kernel what drivers need to initialize and what are the layout of the system) but the technical details vary so much between both methods.
  • Many systems choose to use an initial ram filesystem (that can be found separately or be bundled with the kernel for convenience like devicetree) that contains a basic binary utilities for discover and initialize more drivers in the system, found the real root filesystem, and perform convenient system integrity checks or perform updates.
  • This initial ram filesystem (initramfs) is loaded in ram and works from it while the final root filesystem is prepared.
  • If the system does not make use of initramfs, the kernel needs to contain the drivers and instructions to access the real root filesystem with the final userland. These requirements can be passed via devicetree or via bootloader.
  • Finally, the root filesystem is the device that contains all files, programs, libraries, directories and data that compose the operating system over the kernel (formerly the userland). Additionally, the filesystem may contain dynamic loaded modules that run into the kernel.

The layout of the root filesystem varies greatly between various linux systems. For example, Android systems make an entirely distinct layout than a traditional linux distro (sometimes known as GNU/Linux distribution) like RedHAT or Debian, but both systems contains at least varios common directorios to know:

  • The /dev directory: A virtual filesystem that contains special files representing the various devices instantiated in the system. The drivers into the kernel create specific files here to communicate with the userland via normal file input/output operation
  • The /proc directory: A virtual filesystem that the main purpose is to show the state of all process in a separate directory (every process is a directory with the number of process containing various files that represent the state of the process). Additionally, the /proc directory contains some dynamic information published by the kernel at runtime like the CPU information, the memory usage, the network status or the uptime.
  • The /sys directory: A virtual filesystem that contains internal kernel structures representation. While /dev contains driver-specific devices with self defined protocol and /proc contains runtime information of the kernel, the /sys directory maintain an information of internal kernel structures like modules loaded, devices interfaces or firmware load/unload (including, but not limited, to possible FPGA bitstreams, coprocessor code and status, etc)

Other common directories and contents are the system libraries (usually in /lib or /usr/lib) and basic binary utilities contained usually in /bin or /usr/bin (that contain important programs like initialization controller program called simply “init”)

Upcoming…

In this article, we took a closer look at Linux as a system and saw what problems it solves and what it is for. Next, we will go inside the userland anatomy and startup process.

The idea is to cover all theoretical and practical issues to create our own linux system from scratch ending with a view of buildroot system and mentioning other alternatives for embedded linux development.

See you next!

Martín Ribelotta

Embedded Linux Developer at Emtech S.A

Any Comments or questions, please feel free to contact us: info@emtech.com.ar