iX 8/2016
S. 108
Praxis
Embedded Computing
Aufmacherbild

Open-Source-Echtzeitbetriebssystem Zephyr

Im Aufwind

Wer Anwendungen für das Internet der Dinge entwickelt, muss mit wenig auskommen, denn Smartwatches oder Sensoren verfügen nur über wenige Ressourcen. Mit Zephyr hat die Linux Foundation ein leichtgewichtiges Echtzeitbetriebssystem speziell für diesen Zweck herausgebracht. iX stellt einige Funktionen vor.

Als die Linux Foundation im Februar 2016 ihr erstes Echtzeitbetriebssystem namens Zephyr auf den Markt brachte, dachten viele an einen weiteren Versuch im Bereich Echtzeit-Linux. Diese Annahme war falsch, Zephyr ist ein klassisches Embedded-Betriebssystem.

Davon gibt es einige. ChibiOS, FreeRTOS und Konsorten kommen als Quellcodearchive auf den Rechner des Entwicklers; Kosten fallen meist erst beim Ausliefern fertiger Produkte an. Zephyr unterscheidet sich insofern, als es vollständig kostenlos ist, da es unter der Apache-Lizenz Version 2 steht. Außerdem soll es vor allem IoT-Projekten (Internet of Things) helfen, die in der Regel nur über kleine Budgets verfügen.

Zephyr bietet Entwicklern die Wahl zwischen einem Nano- und einem Mikrokernel von Wind Rivers Rocket (Abb. 1). Quelle: Linux Foundation

Das sowohl auf x86- als auch auf ARM-CPUs lauffähige Betriebssystem kann zwischen zwei Kernen wählen. Der lediglich 4 KByte umfassende, echtzeitfähige Nanokernel bietet nur Run-to-Completion-Scheduling, während der größere Mikrokernel mit seinen 8 KByte ein umfangreicheres Multitasking erlaubt. Er bildet eine besser ausgestattete Version des Kernel, die mehr Flexibilität beim Scheduling bietet (siehe Abbildung 1 und [d] über „Alle Links“ am Ende des Artikels).

Als klassisches Embedded-System teilen sich Kernel und Nutzercode den Adressraum. Wer also für Zephyr eine Anwendung kompiliert, erhält eine monolithische Binärdatei mit Kernel und Applikationscode.

Zephyr verwendet den Kernel des kommerziellen Betriebssystems Rocket, den die Intel-Tochter Wind River im November 2015 herausgebracht hat. Das als gut informiert geltende EEJournal stellt Rocket plausibel als Nachfolger des im Jahr 2001 aufgekauften Betriebssystems Virtuoso für Digitale Signalprozessoren (DSP) dar [e]. Als Grund für die Freigabe führt der Bericht den Verkauf von Cloud-Services an. Dadurch kann sich Wind River als Consultant der ersten Wahl für Zephyr beziehungsweise Rocket positionieren und zusätzliche Honorare einfahren. Diese Monetarisierungsstrategie funktioniert deshalb so gut, weil Echtzeitbetriebssysteme sehr beratungsintensiv sind. Auch ChibiOS und FreeRTOS finanzieren sich auf diese Weise.

Das geeignete Board auswählen

Wer die Kompatibilitätsliste auf der Projektwebseite einsieht, kann sich an einem guten Dutzend unterschiedlicher Boards erfreuen [f]. Leider bedeutet kompatibel im Sinne der Linux Foundation nicht unbedingt kompatibel im herkömmlichen Sinn. Der Arduino 101 benötigt beispielsweise ein Kommandogerät für die JTAG-Schnittstelle (Joint Test Action Group), während die Galileos ihre – nicht besonders schnellen – GPIO-Subsysteme (General Purpose Input/Output) nicht einsetzen können [g].

Ganz ohne Zusatzhardware arbeitet unter Zephyr nur der Arduino Due mit ARM-Prozessor, den Massimo Banzi im Jahr 2012 veröffentlichte. Dieses Alleinstellungsmerkmal macht ihn zur idealen Grundlage für erste Gehversuche mit dem Echtzeitbetriebssystem – auch wenn der Arduino Due heute nicht mehr sonderlich populär ist, da ihn leistungsfähigere Varianten überholt haben.

Der Artikel stellt einige Grundfunktionen des Betriebssystem-Leichtgewichts vor. Er zeigt, wie man eine komplette Zephyr-Arbeitsumgebung auf einer Workstation – in diesem Artikel unter Ubuntu 14.04 LTS – einrichtet und auf einem angeschlossenen Arduino Due installiert. Er führt außerdem vor, wie man GPIO-Pins konfiguriert, die Reaktionsgeschwindigkeit misst, mit Threads, Fibers und Semaphoren arbeitet und Speicher alloziert. Vieles können Leser selbst ausprobieren. Das Messen mit einem Modulationsdomänenanalysator dürfte den meisten aber zu aufwendig sein.

Für das Deployment des Codes auf Arduino Due braucht man ein als BOSSA bezeichnetes Werkzeug, das sich durch Eingabe des Kommandos git clone https://github.com/shumatech/BOSSA.git herunterladen lässt. Zum Kompilieren genügen die Befehle cd BOSSA, git checkout arduino und make bin/bossac. Da sich bossac aber nicht automatisch in das Verzeichnis /usr/bin kopiert und dadurch nicht über die PATH-Variable zugänglich ist, empfiehlt es sich, das Werkzeug im Interesse besseren Handlings manuell dorthin zu kopieren.

Eine Zephyr-Arbeitsumgebung installieren

Außerdem benötigt die Workstation ein SDK, dessen Setup-Datei, etwa zephyr-sdk-0.8-i686-setup.run samt MD5- und SHA1-Hash-Dateien unter nexus.zephyrproject.org/content/repositories, dort entweder unter releases oder public, bereitsteht [h]. Das SDK wiederum setzt eine Gruppe von Paketen voraus, die sich mit sudo apt-get install git make gcc gcc-multilib g++ libc6-dev-i386 g++-multilib installieren lässt. Aktivieren kann man das SDK durch die Befehlsfolge chmod +x zephyr-sdk-0.8-i686-setup.run; sudo ./zephyr-sdk-0.8-i686-setup.run.

Die Linux Foundation erleichtert Entwicklern das Leben insofern, als das Installationsskript alle bisher infrage kommenden Plattformen – zum Zeitpunkt der Drucklegung x86, ARMv7 und ARM-EM4 – gleichermaßen bedient. Für die folgenden Schritte genügt es, die voreingestellten Werte zu übernehmen. Zephyr 0.8 liegt dann im Verzeichnis /opt/zephyr-sdk.

Für das eigentliche Herunterladen des Codes verwendet man – für den GitHub-kritischen Autor ärgerlich – den Befehl git clone https://gerrit.zephyrproject.org/r/zephyr zephyr-project. Damit erhält man eine komplette Zephyr-Arbeitsumgebung, mit der man erste Schritte in die Welt des Echtzeitbetriebssystems unternehmen kann. Seine Position findet das SDK durch zwei Umgebungsvariablen, die der Installer leider nicht automatisch einrichtet. Dieser Missstand lässt sich schnell beheben, entweder auf der Konsole oder – nachhaltiger – in einer Datei ~/.zephyrrc, die sich dann etwa in die eigene ~/.profile oder ~/.bashrc einbinden lässt:

export ZEPHYR_GCC_VARIANT=zephyr
export ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk

Auf eine dritte Variable, die auf das Zephyr-Basisverzeichnis zeigt, weist die Onlinedokumentation zephyrproject.org/doc allerdings nicht hin [i]. Sie sollte ebenfalls gesetzt sein, beispielsweise

export ZEPHYR_BASE=$HOME/develop/zephyr-project

Listing 1: Zephyr ruft "Hello World"

#include <zephyr.h> 
#if defined(CONFIG_STDOUT_CONSOLE) 
#include <stdio.h> 
#define PRINT printf 
#else 
#include <misc/printk.h> 
#define PRINT printk 
#endif 

void main(void) 
{ 
  PRINT("Hello World!\n"); 
} 

Für alle folgenden Beispiele verwendet der Artikel den umfangreicheren Mikrokernel. Als erster Test soll eines der bereitgestellten Samples unter $ZEPHYR_BASE/samples/hello_world/microkernel dienen. Der Hello-World-Code aus src/main.c findet sich in Listing 1.

Zephyr ruft „Hello World“

Für die Ausgabe von „Hello World“ kennt Zephyr analog zu Linux zwei Varianten der Druckfunktion. printk kann man immer aufrufen, es liefert die benötigte Header-Datei $ZEPHYR_BASE/include/misc/printk.h mit.