Fiasco.OS und CubieBoard 2
2015-02-21Dieser Artikel ist eine Anleitung zur Installation von Fiasco.OC auf einem Cubieboard.
Motivation
In einem früheren Artikel wurde bereits ein grundlegendes Setup beschrieben, mit welchem man die reine serielle Ausgabe eines BananaPi mittels eines Terminalprogramms ausgeben kann.
In diesem Beitrag soll es vielmehr darum gehen, wie man ein eigenes Betriebssystem (Nicht-Linux) auf ein Cubieboard 2 aufspielt.
Allgemeines
Fiasco.OC und L4Re
Am Lehrstuhl für Betriebssysteme der TU München kommt das Fiasco.OC Echtzeitbetriebssystem für die Forschung zum Einsatz. Das Betriebssystem basiert auf einer Microkernel-Architektur und kann sowohl für große Systeme, als auch eingebettete Systeme verwendet werden. Fiasco.OC wird hauptsächlich von der Betriebssystemgruppe der TU Dresden entwickelt.
Es besteht prinzipiell aus zwei Teilen, welche separat voneinander gebaut werden müssen. Erstens der Kernel, welcher die rudimentären Primitiven wie Speicherverwaltung, Scheduling etc. realisiert. Zweitens die L4Re Laufzeitumgebung, welcher Fiasco.OC zu einem vollständigen Betriebssystem macht. Die folgende Abbildung veranschaulicht nochmals den grundlegenden Aufbau.
Viele weitere Informationen können auf den Seiten rund um den Fiasco.OC Kernel gefunden werden.
Cubieboard 2
Möchte man ein Betriebssystem auf einem eingebetteten System ausführen, sollte man sich zuerst mit den grundlegenden Systemeigenschaften, wie z. B. den genauen Bezeichner des Prozessors, vetraut machen. Diese Bezeichnung benötigt man später um beim Übersetzungsprozess des Betriebssystems die richtige Zielarchitektur/ -hardware auswählen zu können.
Das Cubieboard 2 basiert auf einem Allwinner A20 Prozessor (sun7i) und gehört somit zur Sunxi SoC-Familie. Der A20 ist ein Dual-Core Prozessor, welcher aus zwei ARM-CortexA7 Kernen besteht. Weitere Informationen findet man im Wiki der Linux-Sunxi Community.
U-Boot (Bootloader)
Nachdem kurz das Betriebssystem und die Zielarchitektur vorgestellt wurden, sei an dieser Stelle noch auf den U-Boot Bootloader hingewießen, welcher standardmäßig auf allen Allwinner SoCs zum Einsatz kommt. Dieser wird im späteren Installationsprozess so konfiguriert, dass das neu erstellte Betriebssystem auch richtig geladen werden kann.
Bauen des Kernels und der L4Re
In diesem Abschnitt wird das Bauen des Kernels und der L4Re Laufzeitumgebung anhand eines beispielhaften Ablaufs auf einem Ubuntu beschrieben.Herunterladen benötigter Pakete und Sourcecode
Bevor man mit dem eigentlichen Bauen des Sourcecodes beginnen kann werden die im Folgenden aufgelisteten Pakete benötigt, welche man über den Paketmanager seines Linux-Systems installieren sollte (hier: Beispiel Ubuntu):
sudo apt-get install subversion
gcc-arm-linux-gnueabi \ libc6-dev libncurses5-dev
g++-arm-linux-gnueabi \ build-essential u-boot-tools
Im Anschluss muss der Sourceode aus den Quellen besorgt werden:
svn co http://svn.tudos.org/repos/oc/tudos/trunk fiasco.oc
Der obige Befehl legt einen Ordner fiasco.oc
an, in welchem
sich im Verzeichnis kernel
der l4-Kernel befindet und
respektive im Verzeichnis l4
die L4Re Laufzeitumgebung.
Die eigentliche Übersetzung
Zuerst übersetzt man den Kernel. Hierzu wechselt man in das entsprechende Verzeichnis und erstellen dort einen Ordner, in welchem der fertige Kernel gebaut werden soll (sog. Buildverzeichnis).
cd fiasco.oc/kernel/fiasco/
make BUILDDIR=build-cubieboard2
Durch den vorangehenden Befehl wird ein Verzeichnis mit dem Namen
build-cubieboard2
angelegt. Anschließend wechselt man in
dieses Verzeichnis und beginnt mit der Konfiguration des Kernels.
cd build-cubieboard2
make menuconfig
Im folgenden ncurses-Dialog
sind folgende Einstellungen
vorzunehmen:
Target configuration
|->Architecture (ARM processor family)
|-> Platform (Allwinner (sunxi))
|-> CPU (ARM Cortex-A7 CPU)
Kernel options
|-> [*] Enable multi processor support
Ein abschließendes betätigten über Save
speichert die
Einstellungen. Bevor der Übersetzungsvorgang gestartet werden kann muss
noch die Datei Makeconf.arm
im Verzeichnis src
angepasst werden. Hier muss das SYSTEM_TARGET
an den
verwendeten Compiler angepasst werden.
# -*- makefile -*-
# vi:se ft=make:
#OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,)
SYSTEM_TARGET ?= arm-linux-gnueabi-
Jetzt kann im Builverzeichnis der make
Befehl ausgeführt
werden. Bei Mehrkernprozessoren kann die Anzahl der zu verwendeten Jobs
mit dem Argument -j
angegeben werden um den
Übersetzungsprozess zu beschleunigen.
# make bei 8 Kernen
make -j 8
Jetzt ist die Laufzeitumgebung L4Re an der Reihe. Hierzu wechselt man
in das Verzeichnis l4
und erstellt auch hier wieder ein
Buildverzechnis.
cd fiasco.oc/l4
make B=build-cubieboard2
Danach wird die Datei Makeconf
im Verzeichnis
mk
angepasst. Hierbei wird SYSTEM_TARGET_arm
wieder auf den zu verwendenden ARM-Compiler gesetzt.
SYSTEM_TARGET_arm = arm-linux-gnueabi-
Anschließend wird die L4Re Laufzeitumgebung mit folgendem Befehl konfiguriert.
make menuconfig O=build-cubieboard2/
Folgende Einstellungen sind im darauf erscheinenden
ncurses
-Dialog vorzunehmen.
Target Architecture (ARM architecture)
CPU variant (ARMv7A type CPU)
Platform Selection (CubieBoard 2)
Danach wird der Buildprozess durch den folgenden Befehl gestartet:
make O=build-cubieboard2 -j8
Konfiguration des Zielsystems
Nach der (hoffentlich) erfolgreichen Erstellung des Betriebssystems folgt in diesem Abschnitt die Konfiguration des Zielsystems.
Erstellen des UImages
Das bereits vorgestellte UBoot lädt das erstellte Betriebssystem als
UImage (vgl. vmlinux), wobei von den Entwicklern der TU-Dresden bereits
ein Maketarget zur Erstellung eines solchen Images zur Verfügung
gestellt wird. Hierzu wird im Buildverzeichnis
l4/build-cubieboard2
folgender Befehl abgesetzt.
make E=hello uimage \ MODULE_SEARCH_PATH=<abs path>/fiasco.oc/kernel/fiasco/build-cubieboard2/
Das Argument MODULE_SEARCH_PATH
zeigt auf das
Buildverzeichnis des Fiasco.OC Kernels. In dem daraufhin erscheinenden
Menü kann nun die zu verwendende Startkonfiguration ausgewählt werden.
Für das ”Hello World!“ Programm wird hier der Eintrag ”hello“
ausgewählt. Das erstellte Image befindet sich danach im Unterverzeichnis
bin/arm_armv7a/
des Buildverzeichnisses.
Installation des UImage auf der SD-Karte
Wichtig: Alle bisherigen Dateien auf der SD-Karte werden in diesem Schritt gelöscht (Backup machen!)
Zuerst wird eine Partition auf der SD-Karte erstellt, in welcher dann später das Image samt für den Startprozess notwendigen Dateien liegt. Hierzu kann man ein Werkzeug wie cfdisk verwenden (grafisch geht es mit gparted). Nach der Partitionierung erfolgt die Formatierung mittels mkfs. In diesem Artikel wird die Partition mit dem ext2-Dateisystem formatiert. Hierzu wird exemplarisch folgender Befehl eingegeben:
sudo mkfs.ext2 /dev/mmcblk0p1
Anschließend kann man das erstellte Kernel-Image auf die SD-Karte überspielen. Allerdings benötigt man für das korrekte Starten des Kernels noch weitere Dateien, wie das folgende Layout zeigt. Diese werden in den folgenden Abschnitten genauer beschrieben.
/dev/mmcblk0p1
|-> uEnv.txt
|-> boot.scr
|-> bootstrap_hello.uimage
Konfiguration des U-Boot (Bootloader)
U-Boot kann über zwei Dateien an die eigenen Bedürfnisse angepasst
werden. Die boot.scr
hat dabei die Aufgabe, wie der Name
schon verrät, die Bootparameter einzustellen bzw. die Standardwerte zu
überschreiben.
Folgender Quellcode in boot.cmd
zeigt die für das Setup
notwendigsten Argumente. Das Kernelimage
(bootstrap_hello.uimage
) soll an die Adresse
0x40000000
abgelegt werden, dies kann im Prinzip eine
beliebige Adresse im Hauptspeicher sein. Für dieses Beispiel reicht aber
die erste mögliche Adresse im Hauptspeicher (siehe hierzu
Tabelleneintrag DDR-II/DDR-III in Kapitel 1.3 “Memory Mapping” des Allwinner
A20 User Manual).
Der Befehl ext2load
lädt mittels
mmc
-Subystem das Kernelimage von der ersten Partition 0 and
die frei gewählte Adresse. Ein abschließendes bootm
initiiert den Startprozess.
setenv kernel_addr_r 0x40000000
ext2load mmc 0 ${kernel_addr_r} /bootstrap_hello.uimage
bootm ${kernel_addr_r}
Die boot.scr
ist eine binäre Datei, damit aus dem
Quellcode (boot.cmd) eine von UBoot lesbare boot.scr
wird,
muss diese noch mit dem folgendem Befehl übersetzt werden.
mkimage -C none -A arm -T script -d boot.cmd boot.scr
Das rechte Bild zeigt den ersten Start mit dem (hoffentlich)
erfolgreich installiertem System. Möchte man allerdings dem Kernel noch
Parameter übergeben gibt es noch weitere Dateien/Einstellungen, die
angepasst werden müssen. Im folgenden wird noch eine beispielhafte
erweiterte Konfiguration der boot.scr
vorgestellt, welche
kurz das Potential der Konfigurationsmöglichkeiten aufzeigen soll.
setenv kernel_addr_r 0x46000000 # 8M
setenv fdt_addr 0x49000000 # 2M
setenv fdt_high 0xffffffff # Load fdt in place instead of relocating
fatload mmc 0 0x43000000 /script.bin
fatload mmc 0 ${kernel_addr_r} /uImage
setenv bootargs "console=ttyS0,115200 hdmi.audio=EDID:0
disp.screen0_output_mode=EDID:1280x1024p60 rw root=/dev/mmcblk0p2 rootwait"
fatload mmc 0 ${fdt_addr} /sun7i-a20-cubieboard2.dtb
bootm ${kernel_addr_r} - ${fdt_addr}
Im obigen Quellcode sind besonders die Zeilen 2, 3 und 11, die den
fdt
(siehe Device Tree vs. Fex) konfigurieren, von
Interesse. Darüber hinaus zeigt die Zeile 8ff. eine Möglichkeit, wie man
Bootargumente an den Kernel übergibt (eine weitere Möglichkeit zeigt der
folgende Abschnitt).
uEnv.txt
Dieser Abschnitt soll kurz zeigen, welche andere Möglichkeit besteht,
beim Booten weitere Kernelargumente zu spezifizieren. Neben der
boot.scr
gibt es noch die uEnv.txt
, welche
hierzu im Plain-Text Format vorliegt. In der uEnv.txt
können, wie im folgenden Quellcode, auch Kernelargumente spezifiziert
werden.
console=ttyS0,115200
consoleblank=0
Vergleicht man dies mit den bootargs
des obigem
erweiterten Listings der boot.cmd
findet man auf jeden Fall
den console
-Parameter wieder, weshalb es hier eben zwei
Möglichkeiten gibt, Kernelparameter zu übergeben.
Device Tree vs. Fex
Der folgende Abschnitt geht nochmal auf die Device Trees und den FEX-Standard ein. Anders als in Desktopsystemen gibt es im Allgemeinen bei eingebetteten Systemen keine Möglichkeit die Hardware “abzufragen”. Vielmehr wird die verfügbare Hardware dem System statisch mitgeteilt. Hierfür dienen die sog. Device Trees (dt) in welchen die Hardware systematisch aufgeführt wird. Hierbei gibt es unterschiedliche Ausprägungen (Quelle).
dtb = device tree blob
dts = device tree source
dtsi = like dts, but I think the 'i' is to indicate that this file is
supposed to be included in another dts(i) file.
FEX auf der anderen Seite ist ein properitäres Format, welches hauptsächlich von der Allwinner-Prozessor-Familie auch zur Beschreibung der Hardware verwendet wird. Daraus folgt, dass man nur eine der beiden Beschreibungssprachen im boot.scr/.cmd benötigt.
Fazit
In diesem Artikel wurde eine Schritt-für-Schritt Anleitung zur Installation des Fiasco.OC-Mikrokerns samt Laufzeitumgebung auf dem Cubieboard 2 beschrieben. Darüber hinaus wurde versucht einige detailiertere Informationen für das bessere Verständnis der beteiligten Komponenten und Begrifflichkeiten zu geben. Die Installationsanleitung wurde so bzw. so ähnlich auch bereits mit anderen Boards (z. B. BananaPi, Beagle Bone Black) erfolgreich getestet. Abschließend hoffe ich, dass diese Anleitung für den ein oder anderen hilfreich sein kann.