Embedded Linux has emerged as a powerful and popular choice for developing embedded systems. With the use of open-source operating systems like Linux, the development process becomes more efficient, allowing for the quick and effortless creation of embedded applications. This article provides a comprehensive introduction to Embedded Linux, starting with a definition of embedded systems and their characteristics. It then delves into the main components of Embedded Linux and explores the reasons why Linux is widely chosen for embedded systems. By the end of this article, readers will have a clear understanding of Embedded Linux and its significance in the world of embedded systems development.
What is Embedded Linux?
Before defining embedded Linux, let’s first see the definition of embedded systems.
What is an Embedded System?
We can define embedded systems in many ways. But the easiest way to define them is as special-purpose computers designed for specific applications. In other words, they are systems with small computers, such as microcontrollers or microprocessors, integrated inside them. Unlike general-purpose computers, such as desktops or laptops, these processors perform only specific functionalities.
Embedded systems are more than 50 years old in the market. They are fundamentally single-board computers, but their functions are limited and specific. Embedded processors are a special type of microprocessor designed specifically for embedded applications. Embedded processors consist of all components, like the memory unit, microprocessors, input/output unit, etc., embedded on a single board. Their functionality is subject to constraints such as less memory, processing speed, and being embedded as part of the complete device, including the hardware, in contrast to desktop and laptop computers.
You can find more information about embedded systems in the following article: Embedded Systems Architecture
Embedded Linux Introduction
Embedded Linux is nothing but the usage of Linux kernel and other open-source software development tools such as open-source libraries in embedded systems applications development. Hence, instead of using a bare-metal embedded systems approach where we have to write every piece of the software ourselves, we make use of the Linux operating system to design embedded applications.
It will make our embedded development process quick and effortless. Because Linux provides support for all types of software that we need to use in our embedded applications such as TCP/IP stack, serial communication protocols, graphics libraries, etc. We only have to configure Linux and create an image according to our underlying processor architecture and this process is known as a board support package.
There is no specific Linux kernel image for embedded devices. An extensive range of devices, workstations, and embedded systems can be built up by the same Linux kernel code by configuring and porting it to different processor architectures. Mentor Graphics is one of the leading embedded Linux service providers. The following diagram shows its commercial platforms and services.
Why Choose Linux for Embedded Systems?
There are many reasons why Linux is being used so widely in embedded systems applications such as mobile phones, agriculture, modern vehicles, multimedia systems and many more. Let’s discuss some of them.
Because Linux is an open-source kernel and anyone can view and modify its source code according to their requirements. On top of that, when creating a Linux image for your targeted embedded hardware, you can remove or add components of the Linux kernel as per your requirements. In this way, we can create a kernel image for memory-constrained embedded devices.
Open-source software components and libraries allow the design and development of embedded products quickly by making use of open-source software components. Because Linux has a large support community and they make all widely used software components freely available and we will not need to redevelop already available components from scratch such as graphics libraries, TCP/IP stack, Linux Kernel, I2C, SPI libraries, and other device drivers, etc.
In short, we only need to focus on our main application instead of developing already available software components.
Free or Low cost
Due to its open-source nature, we can deploy these software components in our embedded application with or without modification free of cost. It will significantly reduce the price of our embedded device.
Linux supports a wide range of processor architectures such as ARM, x86, PowerPC, RiscV, MIPS, SuperH. Although Linux mainly works on MMU architecture microprocessors. However, non-MMU architecture is also supported with limitations.
Examples of Embedded Linux based Systems
- Wireless Routes
- Smart Phones
- Wireless hotspots
- Video and Multimedia systems
- Wearable Sensors such as smartwatches and biomedical equipment
Minimum Hardware Requirement to use Linux on Embedded Processors
Linux Kernel supports 32-bit and 64-bit processor architectures and it supports almost all modern popular processor architectures such as:
- ARM ( used in almost types of applications)
- X86 ( Multimedia and industrial applications)
- MIPS ( networking applications such as routers and hotspots)
- PPC/PowerPC ( hard real-time and deadline-constrained applications)
- SH ( Multimedia applications)
In order to run Linux on a target-embedded processor, a minimum of 8MB of RAM is required. But a real practical application requires at least 32MB RAM. But the actual requirement of RAM memory depends on your embedded application size.
Other than RAM, a minimum of 4MB storage memory is also required. The storage memory can be one of the following types:
- NAND or NOR Flash
- SD or MMC cards
A lightweight Linux such as uCLinux is also available which can run on microprocessors or microcontrollers which do not have a memory management unit.
Embedded Linux Architecture
The following block diagram shows the architecture of embedded Linux based systems.
The embedded system build process is usually performed on the host PC using cross-compilation tools. This is because the target hardware does not have enough resources to run the tools that are used to generate a binary image for the target embedded hardware. The process of compiling code on one system (the host system) and running the generated source code on another system is known as cross-compilation.
Main Components of Embedded Linux Systems
- Cross compilation and development toolchain ( installed on a host system)
- Device Tree
- Root file system
- System Programs
Now, let’s review each component and its purpose in embedded Linux based systems development.
A toolchain is a collection of development tools, such as GCC compiler, C libraries, and GNU debugger, which are used to create source code for the target embedded hardware. Normally, cross-compilation toolchains are utilized in embedded Linux, because the target embedded processor does not have sufficient resources for these toolchains. In cross-compilation systems, development is performed on the host system (a powerful PC), and then source code is deployed on the target device using different interfaces such as serial, ethernet, etc. Serial communication is the most commonly used interface between the host system and a target device.
The tools that are used for communication available in Linux are Minicom, Picocom, Gtkterm, Putty, and HyperTerminal in Windows.
This is a piece of code that runs when we apply power to the embedded hardware first time. Bootloader performs various hardware initialization steps before loading the operating system. When a processor boots up or resets, each processor has a number of predefined hardware steps and configurations.
The followings are the main roles of a bootloader:
- Target hardware initialization
- Load the application binary ( operating system, root file system, device tree ) from the non-volatile external storage to the RAM memory
- RAM connects externally to the SOC and it stores run-time data, operating system, root file system, application software, and stack/heap.
- After that execute the main operating system code from the RAM memory
Different microprocessors may have a distinct process of booting sequence but the underlying concepts remain the same.
In embedded Linux, two generic or universal bootloaders are popular such as Uboot and barebox.
Embedded Linux Boot flow Process
What exactly are the steps and what is required to successfully boot the Linux kernel of embedded Linux boards such as BeagleBone, Raspberry Pi, etc? If we take the example of Beaglebone Black, this board has an AM335x SoC manufactured by Texas Instruments. In order to boot Linux on this Soc following are the four main components as shown in the figure below:
- The first component is a first stage bootloader or a ROM bootloader. This is usually stored inside the flash memory of SoC by the manufacturer and we cannot change it.
- The main role of RBL is to load the second stage bootloader that is SPL (a secondary program loader) or MLO (memory loader) from the internal SRAM of SoC.
- The job of MLO is to load and execute a third stage bootloader such as U-Boot from the DDR memory of the development board but DDR is off the SoC.
- The third stage bootloader which is U-boot loads the Linux kernel from persistent storage such as an SD card to DDR memory of the development board.
- After that system starts to execute its first process initi and mounts the root file system.
It is a software or operating system kernel that manages the resources of embedded processors optimally and efficiently. The main core component of embedded Linux is the Linux Kernel. It is a layered operating system architecture, which means it is divided into two layers: user space and kernel space memory space.
It provides various services such as:
- Process management ( Allocates CPU resources concurrently to processes/tasks through scheduler)
- Process scheduling ( Schedules concurrently running process to run on the CPU using scheduling algorithms)
- Memory management ( Manage memory for different processes through virtual memory support)
- Interprocess communication (Sometimes tasks require to share data with each other and the interprocess communication feature provides this support through shared memory)
- File management (Manage how information is stored and accessed by the system)
- I/O management ( Supported through device drivers such as character, block, and USB device drivers)
- Networking ( Support for network device drivers )
- Interface with hardware through device drivers
To add and remove code from the Linux kernel at rum time we use a machine called loadable kernel module. They are responsible for communication between kernel and hardware without having to know the functionality of hardware and they are perfect for the drivers of the device. Kernel module run in kernel space. Memory addresses of kernel space and user space are unique and they don’t overlap. This methodology shows that the applications that run in user space have a reliable view of hardware, irrespective of the platform of hardware.
The embedded Linux-based hardware platforms also contain peripherals that do not have the ability to acknowledge their existence to the operating system kernel. There must be a way to inform the Linux kernel about these hardware peripherals.
The Linux kernel contains thousands of device drivers, and during the boot-up process, the kernel should know which non-discoverable hardware devices are connected to your embedded Linux-based system. The question is, how does the kernel find the details of the connected hardware devices? The answer is the device tree.
A device tree is a tree data structure that provides information about the connected hardware devices that are not discoverable themself and other on-chip peripherals of an SoC. Some of the automatically non-discoverable on-chip peripherals are I2C, UART, SP, ethernet, etc. On the contrary, the USB device has the capability or intelligence to inform its presence to the operating system dynamically.
DT describes these devices using a special hardware description language. It decides which drivers to initialize and configure the device parameters such as registers addresses and IRQs. A DT source is combined with the Device Tree Blob and combines with the kernel during the embedded hardware booting process. The bootloader also loads the Device Tree Blob into RAM memory along with the Kernel and it runs before the kernel. In short, DT manages hardware resources of embedded Linux based systems.
Root File systems
In Linux, Filesystems organize data into files and directories inside the storage device. In fact, everything in Linux is a file, stored, and accessed through a file. These files and directories are organized in a hierarchical form.
During the boot-up process, the Linux kernel needs one more component: a root filesystem. A root filesystem is a special type of filesystem that contains all the configuration files required to prepare the execution environment for the embedded device. For example, it prepares graphical displays, and it also contains the first parent process running on Linux (init).
The Linux kernel works with the root file system. This is the file system onto which the root can be mounted. There are two types of file systems for desktop and server distributions. These are the initial root system and the real root system. The initial root system is used for mounting and running the latter. The initial root system is used to load drivers on a desktop. The switch between the initial root file system and the real root file system is called a pivot.
The kernel needs configuration files to know the users and groups in the system. It also needs configuration files to manage file permissions. These files are not read by programs and are used by the kernel to provide a function by a system library.
Classification of Embedded Linux Systems
The classification of embedded Linux systems has been made by considering the structure of the system. It may also be classified on the basis of size and time limits.
Linux features a microarchitecture that usually consumes small memory (100 KB). It is combined with networking stacks and a few basic utilities, which can fit very efficiently in 500 KB of memory. It is adaptable to work with minimal RAM and ROM. ETLinux, LEM, uClinux, uLinux, and ThinLinux are some examples of footprint-embedded Linux. The apparent size of an embedded system determines the capabilities offered by the hardware. Based on size, embedded systems have been categorized into three types: small, medium, and large.
Small systems have a low-powered CPU. ROM is less than 4 MB, and RAM is 8 to 16 MB.
Medium size system
Medium-sized systems contain a medium-powered CPU, 32 MB of RAM, and removable memory cards.
Large size systems
Large-sized systems contain powerful CPUs or multiple CPUs, ample RAM, and permanent storage.
To start learning embedded Linux, one should have familiarity with the Linux operating system, Linux kernel internals, and different distribution of Linux. Linux is an open-source operating system. It’s a vast platform for the development of embedded systems. Embedded systems are everywhere and available in all ranges, small control applications require smaller microprocessors and large parallel processors have colossal memory requirements.
Embedded Linux Build Systems
Embedded Linux build systems are tools and frameworks designed to facilitate the process of creating custom Linux distributions for embedded devices. These systems provide a structured and automated way to build the entire software stack for embedded systems, including the Linux kernel, root filesystem, device drivers, libraries, and applications.
The primary goal of embedded Linux build systems is to simplify the development, customization, and deployment of Linux-based software on resource-constrained embedded devices. These systems offer various benefits, such as optimization for specific hardware, reduction of the software footprint, management of dependencies, and easy integration of device-specific drivers and components.
Popular Embedded Linux Build Systems
Here is a list of popular embedded Linux build systems that are commonly used for developing and customizing Linux distributions for embedded systems:
Yocto Project is a widely used open-source build system that provides tools and resources for building custom Linux distributions. It uses metadata and recipes to define how software components are built and integrated.
Buildroot is a simple and efficient build system that generates root filesystems and Linux kernels for embedded devices. It focuses on creating minimal and optimized systems.
OpenEmbedded is the build system behind the Yocto Project. It provides a powerful framework for building custom Linux distributions and has a modular architecture that allows for flexibility and customization.
OpenWrt is a Linux distribution primarily targeted at wireless routers and networking equipment. It’s known for its flexibility and extensive package repository
Each of these embedded Linux build systems has its own strengths and features. The choice of build system depends on factors such as project requirements, development expertise, desired level of customization, and the specific target hardware.
Embedded Linux build systems are essential tools for several reasons:
- Customization: Embedded devices have diverse requirements, and a build system allows developers to create customized Linux distributions tailored to the specific needs of the device. This ensures that only necessary components are included in the system, optimizing performance and minimizing resource usage.
- Efficient Resource Utilization: Embedded devices often have limited processing power, memory, and storage. A build system helps optimize the software stack to ensure that only essential components are included, maximizing the efficient use of available resources.
- Dependency Management: Managing software dependencies manually can be complex and error-prone. Embedded Linux build systems automate the process of handling dependencies, ensuring that all required libraries and packages are included and properly configured.
- Cross-Compilation: Many embedded devices use architectures different from the developer’s host system. Build systems support cross-compilation, allowing developers to build software for the target device’s architecture on a more powerful host machine.
- Kernel and Bootloader Configuration: Configuring the Linux kernel and bootloader to match the specific hardware of the embedded device can be intricate. Build systems simplify this process by providing tools to configure and build these components.
You may also like to read:
- Cross Compilation Toolchain for ARM – Example with Raspberry Pi
- Bare-metal and RTOS Based Embedded Systems
- Nested Vectored Interrupt Controller (NVIC) ARM Cortex-M Microcontrollers
- Microcontroller Memory Organization and Types – Explained with Memory Segments
- Bare Metal Embedded Systems Linker Script File
- What is Microcontrollers startup file – Understand its various Functions
- Bare Metal Embedded Systems Build Process using GNU Toolchain