Theoratical Embedded Linux requirments
A System on Chip (SoC), is essentially an integrated circuit that takes a single platform and integrates an entire computer system onto it. It combines the power of the CPU with other components that it needs to perform and execute its functions. It is in charge of using the other hardware and running your software. The main advantage of SoC includes lower latency and power saving.
It is made of various building blocks:
- Core + Caches + MMU – An SoC has a processor at its core which will define its functions. Normally, an SoC has multiple processor cores. For a “real” processor, e.g. ARM Cortex-A9. It’s the main thing kept in mind while choosing an SoC. Maybe co-adjuvanted by e.g. a SIMD co-processor like NEON.
- Internal RAM – IRAM is composed of very high-speed SRAM located alongside the CPU. It acts similar to a CPU cache, and generally very small. It is used in the first phase of the boot sequence.
- Peripherals – These can be a simple ADC, DSP, or a Graphical Processing Unit which is connected via some bus to the Core. A low power/real-time co-processor helps the main Core with real-time tasks or handle low power states. Examples of such IP cores are USB, PCI-E, SGX, etc.
An SoC uses RAM to store temporary data during and after bootstrap. It is the memory an embedded system uses during regular operation.
In an Embedded system or single-board computer, it is the SD card. In other cases, it can be a NAND, NOR, or SPI Data flash memory. It is the source of data the SoC reads and stores all the software components needed for the system to work.
An SoC must have external interfaces for standard communication protocols such as USB, Ethernet, and HDMI. It also includes wireless technology protocols of Wi-Fi and Bluetooth.
First of all, we introduce the boot chain which is the series of actions that happens when an SoC is powered up.
Boot ROM: It is a piece of code stored in the ROM which is executed by the booting core when it is powered-on. This code contains instructions for the configuration of SoC to allow it to execute applications. The configurations performed by Boot ROM include initialization of the core’s register and stack pointer, enablement of caches and line buffers, programming of interrupt service routine, clock configuration.
Boot ROM also implements a Boot Assist Module (BAM) for downloading an application image from external memories using interfaces like Ethernet, SD/MMC, USB, CAN, UART, etc.
1st stage bootloader
In the first-stage bootloader performs the following
- Setup the memory segments and stack used by the bootloader code
- Reset the disk system
- Display a string “Loading OS…”
- Find the 2nd stage boot loader in the FAT directory
- Read the 2nd stage boot loader image into memory at 1000:0000
- Transfer control to the second-stage bootloader
It copies the Boot ROM into the SoC’s internal RAM. Must be tiny enough to fit that memory usually well under 100kB. It initializes the External RAM and the SoC’s external memory interface, as well as other peripherals that may be of interest (e.g. disable watchdog timers). Once done, it executes the next stage, depending on the context, which could be called MLO, SPL, or else.
2nd stage bootloader
This is the main bootloader and can be 10 times bigger than the 1st stage, it completes the initialization of the relevant peripherals.
- Copy the boot sector to a local memory area
- Find kernel image in the FAT directory
- Read kernel image in memory at 2000:0000
- Reset the disk system
- Enable the A20 line
- Setup interrupt descriptor table at 0000:0000
- Setup the global descriptor table at 0000:0800
- Load the descriptor tables into the CPU
- Switch to protected mode
- Clear the prefetch queue
- Setup protected mode memory segments and stack for use by the kernel code
- Transfer control to the kernel code using a long jump
The Linux kernel is the main component of a Linux OS and is the core interface between hardware and processes. It communicates between the hardware and processes, managing resources as efficiently as possible. The kernel performs following jobs
- Memory management: Keep track of memory, how much is used to store what, and where
- Process management: Determine which processes can use the processor, when, and for how long
- Device drivers: Act as an interpreter between the hardware and the processes
- System calls and security: Receive requests for the service from processes
To put the kernel in context, they can be interpreted as a Linux machine as having 3 layers:
- The hardware: The physical machine—the base of the system, made up of memory (RAM) and the processor (CPU), as well as input/output (I/O) devices such as storage, networking, and graphics.
- The Linux kernel: The core of the OS. It is a software residing in memory that tells the CPU what to do.
- User processes: These are the running programs that the kernel manages. User processes are what collectively makeup user space. The kernel allows processes and servers to communicate with each other.
Init and rootfs – init is the first non-Kernel task to be run, and has PID 1. It initializes everything needed to use the system. In production embedded systems, it also starts the main application. In such systems, it is either BusyBox or a custom-crafted application.