Embedded Linux

Embedded Linux is something not running on a big desktop PC. Mostly such devices have limited memory and not enough power to do compilation of its code. Additionally such devices might not be individual installations they need to be duplicated and might be used mass production.

Nowadays memory is not such a big issue, since most devices accept memory cards and have therefore >2GByte of space. This is enough for a full complete and no more no more tweaked Linux system to be able to get installed to reduced memory .

If time is not an issue standard Linux distributions as Gentoo can be installed on the device and keeping maintained compiling its new source code.

However embedded Linux devices are created using a powerful PC where the embedded Linux devices can be attached. The powerful PC devices does the configuration and compilation and downloads the result to the embedded Linux devices.

It is common that the powerful Linux PC using an other CPU architecture as a x86 and the small embedded device something as an ARM processor. Therefore cross compilation is necessary.

There are different solutions available to do this:

Device Tree

IBM compatible PC's do as its name says follow a standard architecture. Additional lot is plug and play. In the embedded world SoC manufacturers and board manufacturers hook up the devices as they desire. A Linux kernel therefore faces the unknown. Here device tree comes in to the place it is simply said a kernel readable hardware description of the SoC and board. Device Tree is Linux independent.

Device Tree makes use of *.dtb binary files that are passed among the kernel during boot. *.dtb files are compiled from the *.dts source files or *.dtsi the include source files.

dtc -I dtb -O dts -o output.dts input.dtb is the Device Tree compiler call to get a *.dtb file.

Once Linux has booted with Device Tree its tree can be seen with ls -la /sys/firmware/devicetree/base/ most of it is then human readable cat /sys/firmware/devicetree/base/model

dtc -I fs -O dts -O /sys/firmware/devicetree/base will dump what is actually running

Since a lot of includes make it complex to know the final results, the vendors dtb can be converted to a dts as well as the running Device Tree. Then diff will show the differences

dtc -I fs -O dts /sys/firmware/devicetree/base > running.dts

dtc -I dtb -O dts vendor.dtb > vendor.dts

diff -u vendor.dts running.dts

There are also *dtbo overlay files.Those files are used for add on cards or devices. Overlays are created with dtc -@ -I dts -O dtb -o adc.dtbo adc.dts they do not know how they get later attached to the system so they contain labels with references.

They can be added to a running system.

mount -t configfs none /sys/kernel/config

mkdir /sys/kernel/config/device-tree/overlays/adc

cat adc.dtbo > /sys/kernel/config/device-tree/overlays/adc/dtbo

Important

With a wrong, buggy or not complete device tree the system will not run as desired or have major problems. dmesg | grep -i -E "of_|dt|probe|clock|reset" or dmesg | grep "not" might be a way to observe if it is happy

Booting

Due to the lack of standardization, booting embedded Linux can be quite complex. Some hopefully protected ROM code is the first thing running (BL1).

For the arm architecture the Trusted Firmware-A TF-A is the standard way. It acts as first stage boot loader (FSBL) and runs out of the chips internal RAM ( TF-A BL2). It initializes the hardware clocks and DRAM.

It has power saving functionalities as PCSI the Power State Coordination Interface and other features.

The FSBL then loads the second stage boot loader (SSBL). The bootloader uboot acts as SSBL and runs out of DRAM.

Finally booting needs to know the hardware configuration. Therefore device tree files are used for the FSBL and for the SSBL.

Important

It is quite common that each stage has it own device tree files. So there are device tree files for the FSBL, the SSBL and for Linux. Even more could exist as when OP-TEE is used. They however can be part of a common tree. For STM32 see https://wiki.st.com/stm32mpu/wiki/STM32_MPU_device_tree

uboot

U-boot from http://www.denx.de/en/News/WebHome is a boot loader mainly targeted for embedded systems. Many of those do not have a screen. However u-boot uses a serial link (115200 baud) where a terminal program as gtkterm can be attached. Pressing a key during boot brings up the u-boot console, where commands as help can be typed. printenv gives a lot of information about what u-boot sees and what it will do. setenv modifies them and saveenv makes it persistent. mmc list shows the mmc/sd cards mmc dev 0 sets the one listed as 0. mmc part shows partition table. fatinfo mmc 0:1 gives fat info of disk 0 partition 1. fatls mmc 0:1 shows the files and directories in there. For ext2 there is ext2ls mmc 0:1

minicom is more suited to be used than gtkterm to work with u-boot. However some tricks when copy, modify and past back long commands to u-boot. Setting W to wrap long lines that then can be copied and pasted into an editor, where the syntax of what came out using printenv must be modified from bootargs=console=ttymxc0,115200 <and more> to sentenv bootargs 'console=ttymxc0,115200 <and more>' and watch out to remove the CR minicom has eventually put in when it wrapped the line. Then the command can be cut and pasted back to u-boot. It is worth to verifying the change with printenv before saveenv takes it persistent. It can happen that the memory where those environmental variables are stored gets corrupt or never got initialized. Then u-boot refuses to use it and puts out a warning: *** Warning - bad CRC or MMC, using default environment entering the u-boot menu verify printenv and saveenv can fix that.

Uboot script files can be made as:

mkimage -A arm -T script -O linux -d boot.txt boot.scr


Linurs startpage