Linux-based software platforms
In this section the Linux kernel part of an embedded software platform is discussed.
While FreeRTOS (see Part2) has support for several compilers, the Linux kernel community has chosen GCC. Although less flexible, it simplifies things a lot and allows developers to take advantage of gcc specific features and extensions. Therefore, it is hard to build to kernel with another compiler technology (e.g. read this and this).
Architecture (in)dependent code
Although originally only written for x86, Linux has evolved to a general purpose OS which can run on lots of different architectures. There is only one way to achieve this i.e. by clearly separating architecture-dependent and architecture-independent code. ‘Architecture’ is typically (but not always) a cpu core type (e.g. arm, powerpc).
In the Linux kernel, the arch/ directory hosts architecture-dependent code:
In these subdirectories, architecture-specific constructs can be found such as definition of atomic functions, boot code, barriers etc.
If we dig deeper, we find ‘machines’ or ‘platforms':
- mach-at91/: machines based on Atmel’s at91sam processor family
- mach-imx/: Freescale imx-based machines
A machine (or platform) defines specific hardware. This could be a board or a generalization of it (e.g. board based on specific SoC, MCU or MPU). Terminology is not very clear here because a different layout is used for every arch/ subdirectory. In any case, developers try to re-use code between boards as much as possible.
A board always needs to describe a set of devices. These devices:
- are integrated in the board’s MCU, or
- are additional board peripherals (such as a temperature sensor).
These devices, called platform devices, can’t be automatically discovered and must be described somewhere. For long, this was done in the machine directory (and thus every board-spec change resulted in a kernel re-compile), but recently, this can be done in the board’s device tree (e.g. arch/arm/boot/dts). The device tree is a hierarchical description of the hardware, and only loosely coupled with the kernel. As a result, a new board definition does not necessarily result in a kernel re-compile.
Recently, device tree overlays have been developed in order to support BeagleBone capes or whatever kind of shield for small embedded devices. These overlays dynamically change the device tree, but it is still ongoing development.
Platform devices only come to life when a compatible platform driver is found. Like any other Linux driver, they live in the drivers/ directory.
Linux User Space
Applications have access to the board’s functionality via standard Linux user space interfaces.
Devices (except for networking devices) are located in /dev e.g. /dev/ttyUSB0, /dev/rtc0.
Information on the system (cpu, memory, clocks… but also drivers and devices) can be found in sysfs (/sys), as well as in procfs (/proc).
Since application frameworks can be written in various ways, it is beyond the scope of this article.
Simple Platform Abstraction (SIPLAB)
To conclude this series, we describe the architecture of our very own SIPLAB, a thin abstraction layer between application and (RTOS and drivers). Siplab and the rationale behind it has already been discussed in this article. Here is an high-level overview:
The Virtual OS directory (VOS/) implements basic OS features such as threads and locks. Supporting Linux enables developers to do host simulation.
Siplab supports several hardware platforms. Currently, we support Stm32f10x and Linux host simulation (Pc/). Every platform might have several boards (Board/*c) and implements the common driver interfaces (Drivers/). The VOS/ directory has (mainly startup) code to get the VOS up-and-running on a specific HW platform.
The Board includes and common driver interfaces can be found in the one and only Include/ directory:
Of course, useful code is re-used and placed in common directories such as Libs/, Protocols/ etc.
Currently, Siplab only supports one toolchain which is GCC.