angle-left Das Umsetzen von Ideen wird zum «Kinderspiel»
zurück zur Übersicht

Das Umsetzen von Ideen wird zum «Kinderspiel»

Zephyr RTOS zählt zu den beliebtesten Real Time Operating Systems (RTOS) im Bereich Internet of Things (IoT), welches im Jahr 2016 von der Linux Foundation ins Leben gerufen wurde. Durch die Unterstützung bekannter Chip-Hersteller wie Intel, NXP, Nordic Semiconductor, ST-Microelectronics oder Silicon Labs läuft Zephyr RTOS auf über 350 verschiedenen Boards und entwickelt sich durch die Unterstützung von über 1000 Mitwirkenden stetig weiter.

Autor: Raffael  Anklin

Bei Zephyr läuft der Kernel in einer minimalen Ausführung bereits ab zirka 2kB RAM. Zusätzlich lassen sich diverse Network-Protocol-Stacks (IP, Bluetooth Low Energy, 6LoWPAN, IEEE802.15.4, Openthread, Bluetooth Mesh, etc.) hinzufügen. Durch diese Kommunikationsstandards lassen sich vernetzte IoT-Geräte entwickeln. Zudem sind diverse Treiber APIs für verschiedene Peripherien (UART, SPI, TWI, CAN, etc.) hardwareunabhängig standardisiert. Dies ermöglicht Flexibilität bei der Auswahl des Chips unter Beibehaltung der Software, was bei den aktuellen Lieferengpässen von elektronischen Bauteilen sehr hilfreich ist. Mithilfe von Kconfig, ein zur Konfiguration von Linux verwendeter Standard, lassen sich Einstellungen am Zephyr Build System vornehmen. Dieses besteht aus CMake und einem Buildtool west, welches mittels Python die gewünschte Systemkonfiguration zusammenstellt. Mithilfe von west lassen sich auch hardwarespezifische Funktionalitäten vereinen wie das Kompilieren, Flashen und Debuggen mit unterschiedlichen Toolchains. Der Quellcode wird unter der GPL 2.0 Lizenz angeboten und ist somit frei für kommerzielle Zwecke Nutzbar. Mithilfe des Online-Wikis und diverser Beispielprojekte ist ein umsetzten von Ideen mittels Zephyr RTOS ein Kinderspiel.

Warum Zephyr rToS?

Zephyr RTOS wurde speziell für energieeffiziente und ressourcen-beschränkte Mikrocontroller-Systeme (SOCs) entwickelt. Das Open-Source Projekt bietet die Unterstützung von unzähligen Hardwareplattformen und den neusten Kommunikationsstandards. Dies ermöglicht eine effiziente, miniaturisierte und standardisierte Einbindung von Sensoren oder Aktoren über kleinste Mikroprozessoren in das Internet. Der verallgemeinerte Begriff IoT beschreibt ein solches Szenario, wobei oftmals kleinste Geräte Daten an eine Cloud senden. Viele Hersteller aber auch Entwickler erweitern die Code-Base von Zephyr ständig. Dadurch werden Kosten und Entwicklungszeit eines Produktes stark reduziert. Mithilfe einer ausführlichen Dokumentation gelingt ein schneller Einstieg in die Welt von IoT und der Programmierung von Mikrocontrollern. Wer bereits einige Erfahrung mit Linux gesammelt hat erkennt einige Gemeinsamkeiten, welche das RTOS mit seinem Mutter-Betriebssystem teilt. Ähnlich wie bei Linux werden regelmässig sogenannte Long-Term-Stable (LTS) Releases veröffentlicht.

Zephyr und IoT Sicherheit

Für die Übertragung von Daten an eine Cloud bietet Zephyr nebst anderen die häufig verwendeten Netzwerkprotokolle CoAP, MQTT oder HTTP an. Damit die Daten sicher an ihr Ziel gelangen, müssen diese verschlüsselt gesendet werden. Dies geschieht über eine gesicherte Verbindung mittels der Transport-Layer-Security (TLS) oder früher auch als Secure-Socket-Layer (SSL) bezeichnet. Um eine solche Verbindung aufzubauen, kommen komplexe Algorithmen zum Einsatz, welche nicht für den Einsatz auf Mikrocontrollern optimiert sind. Zudem würde eine komplette TLS-/SSL-Bibliothek den Speicher eines kleinen Microcontrollers übersteigen. Daher wird von Zephyr MbedTLS verwendet, um die Daten sicher von A nach B zu übertragen. Diese Library besitzt einen wesentlich kleineren Memory-Footprint und ist somit ausführbar auf kleinsten SOCs im Gegensatz zu den umfangreichen SSL- oder TLS-Bibliotheken.

Zephyr Kernel

Ein Kernel bildet das Herzstück eines RTOS, welcher Sprichwörtlich alle Fäden zieht. Die sogenannten Threads stellen eigenständige Prozesse dar. So kann ein RTOS mehrere Abläufe gleichzeitig durchführen, wenn auch nur scheinbar, da die CPU immer nur einen Thread gleichzeitig bearbeiten kann. Der Kernel entscheidet, wann welcher Thread in der CPU laufen soll. Im Falle von Zephyr handelt es sich um ein prioritätsbasierten Scheduler. Um die Ausführung aller Threads so schnell wie möglich zu garantieren (Real-Time), entschiedet der Scheduler aufgrund von Prioritäten und Wartezeiten die Reihenfolge, in welcher die einzelnen Threads abgearbeitet werden.

Das Verwenden von mehreren Threads wird als Multithreading bezeichnet. Dabei gibt es unterbrechbare Threads (Preemtive-Threads) und nicht unterbrechbare Threads (Cooparitve-Threads). Preemtive-Threads können jederzeit vom Scheduler unterbrochen werden. Bei gleich priorisierten Preemtive-Threads erhält jeder Prozess ein gleich langes Zeitfenster von Scheduler. Dies ermöglicht eine faire Aufteilung der CPU-Zeit mittels Time-Slicing.

Bei Cooperative-Threads ist ein Unterbrechen nur durch ein Interrupt möglich. Während eines Interrupts kann dem Scheduler signalisiert werden, dass ein anderer Thread auf seine Abarbeitung wartet. Selbst wenn der zu aktivierende Thread eine höhere Priorität aufweist, muss auf die Beendigung des aktuellen Threads gewartet werden. Dies garantiert die zeitnahe Abarbeitung des momentanen Threads. Es können jedoch Probleme bei zu langem Blockieren entstehen. Zum Beispiel sollte das aktive Pollen von Peripherie unbedingt vermieden werden, da dadurch andere Prozesse keine CPU-Zeit mehr erhalten. Wer sich mit dem Multithreading vertraut machen möchte, kann den Beispielcode «Dining Philosophers» studieren, welcher im Source Code von Zephyr enthalten ist.

Zephyr Kernel Optimierung

Um auf die Bedürfnisse der Anwendung zu reagieren, kann der Zephyr Kernel entsprechend zugeschnitten werden. Die RTOS Funktionalität lässt sich sogar ganz deaktivieren (kein Multithreading) um einfache Abläufe oder lediglich event-basierte Programme zu realisieren. Eine solche Konfiguration erhöht die Real-Time-Fähigkeit der Anwendung und belegt nur sehr wenig Arbeitsspeicher (ca. 2KByte RAM). Ein mögliches Szenario wäre das Ansteuern eines Blinklichtes oder das periodische Auslesen eines Sensors.

Zur Erweiterung des Kernels dienen sogenannten Kernel-Services. Diese beinhalten Datenspeicher-Strukturen (FIFO, LIFO-Stacks), die Verwaltung von Threads (Multithreading) sowie das Synchronisieren von Threads mittels Semaphore oder das Blockieren von Peripherie über einen Mutex. Diese Kernel-Bestandteile werden vorausgesetzt um komplexere Systeme wie z.B. Netzwerk-Stacks betreiben zu können. Jedoch belegt dieses umfangreichere Kernel mehr Ressourcen. Es empfiehlt sich mindestens ca. 8KByte RAM zur Verfügung zu stellen, falls Zephyr als ernsthaftes RTOS betrieben werden soll. Der Speicherbedarf kann mit jedem zusätzlichen Thread oder Netzwerk-Stack stark ansteigen, wodurch bei einfachen IoT Anwendungen mindestens 50kByte RAM empfehlenswert sind.

Zephyr ein Linux für Microcontroller

Da sich hinter der Entwicklung von Zephyr die Linux Foundation befindet, lassen sich ähnliche Ansätze zur Konfiguration und Umsetzung des Kernels erkennen. Die Konfiguration des Kernels erfolgt identisch zu Linux mithilfe der Scriptsprache Kconfig. Somit lassen sich tausende von Kernel-Parametern über die grafische Oberfläche einstellen. Dieser Konfigurationsassistent gliedert die Einstellungsmöglichkeiten in verschiedene Themengebiete. Dadurch erhält der Benutzer einen schnellen Überblick über die möglichen Einstellungen. So lässt sich zum Beispiel die Stack Grösse des Main Threads auf 1024 erhöhen, indem das Flag «CONFIG_MAIN_STACK_SIZE = 1024» in der Konfiguration definiert wird oder das Aktivieren des USB-Stacks mit einem simplen «CONFIG_ USB_DEVICE_STACK=y». Vor jedem kompilieren werden alle Einstellungen  überprüft und bei Problemen vor dem eigentlichen Generieren des Codes gemeldet. Dies erspart dem Benutzer Zeit, da er nicht selbst auf die Fehlersuche im Programmcode von Zephyr gehen muss. Als Eigentliches Build-System wird anschliessend CMake verwendet.

Um die vielen Boards, Shields und Architekturen zu unterstützen, werden Device-Tree-Files verwendet. Diese bereits in Linux verwendeten Files geben an um welche Hardware es sich handelt und welche Peripherie vorhanden ist. So können ganze Hardware-Setups aus verschiedenen Boards, Shields mit unterschiedlich bestückten Sensoren und Aktoren definiert werden. Ein DTS (Device Tree Source) wird in Zephyr vollumfänglich für das Zusammenspiel des Kernels mit der Hardware und den einzelnen Treibern verwendet. Er beschreibt zum Beispiel die Register-Adressen der UART-Peripherie und definiert die zugehörige Baud-Rate und weitere Betriebseinstellungen inklusive des zugehörigen Treibers.

Saubere Trennung von Hardware und Software

Um anwendungsspezifische Setups zu testen, müssen also keine Definitionen im Code vorgenommen werden. Mittels Device-Tree-Overlay-Files lässt sich zum Beispiel ein angeschlossener I2C-Sensor durch dessen Adresse und Sensortyp in die Anwendung integrieren. Der zuständige Treiber wird anschliessend vom Kernel initialisiert. Dies ermöglicht eine saubere Trennung von Hardware und Software wodurch das Portieren von Code einfacher wird.

Ein zusätzliches Feature bietet die Shell von Zephyr RTOS, welche an eine Linux Umgebung erinnert. Mittels UART, RTT, USB oder Telnet lässt sich eine Sitzung mit dem Microcontroller aufbauen. Nach dem Aktivieren der Shell über die simple Konfiguration (Kconfig) erfolgt die Interaktion wie mit einer gewohnten Linux Shell. Nebst umfangreichen, bereits eingebauten Befehlen welche zum Beispiel das Experimentieren mit Peripherie oder ganzen Netzwerk-Protokoll-Stacks ermöglichen kann die Shell zum Interagieren mit der Applikation genutzt werden. Das Registrieren von eigenen Shell-Befehlen ermöglicht es, mitgegebene Parameter auszulesen und löst die definierten Callbacks aus.

Zephyr Network Stacks

Zephyr RTOS unterstützt viele Kommunikations- und Netzwerk Protokolle. Im Falle von Bluetooth ist ein hauseigener Bluetooth-Stack implementiert. Dieser ist für das Zusammenspiel mit Zephyr OS optimiert.

Ebenfalls besitzt die Code Base von Zephyr eine eigene Implementierung des Bluetooth Mesh Stacks. Dieser auf dem Bluetooth-Low-Energy basierende Standard  ermöglicht  es, die Reichweite einzelner Bluetooth Geräte zu erhöhen. Bisher konnte nebst Punkt-zu-Punkt Verbindungen lediglich eine sternförmige Topologie genutzt werden, wobei sich ein Central-Device mit mehreren Peripheral-Devices verbindet. Bei der Mesh-Struktur arbeiten alle Bluetooth Teilnehmer zusammen und leiten die Nachrichten untereinander weiter. Dies erweitert den Einsatzbereich von Bluetooth fähigen Geräten.

Nebst Bluetooth-Mesh unterstützt Zephyr Open-Thread, welche den häufig verwendeten Kommunikationsstandard Zigbee ablösen soll. Dieses Mesh-Netzwerk verwendet zur Übertragung kein Bluetooth,  sondern  setzt  auf den IEE802.15.4 Standard. Somit könnte ein Lichtsystem wie Phillips Hue mit einen Zephyr Chip implementiert werden.

Das Verwenden von TCP-/ UDP-Verbindung erfolgt über die BSD-Sockets-API und ist somit kompatibel zur Linux Umgebung. Übrigens ist die Kommunikation mittels Sockets auf Ethernet, WLAN, CAN-Bus oder Point-to-Point Protocol (PPP) möglich.

Fazit

Einerseits überzeugt Zephyr RTOS als einfache, kompakte Lösung für IoT-Anwendungen. Anderseits bietet es auch viele Erweiterungen, die in diesem Bericht kurz gestreift wurden. An der Embedded Computing  Conference vom 31. Mai 2022 in Winterthur besteht die Möglichkeit, sich am Stand des Instituts für Sensorik und Elektronik der FHNW vertiefter über Zephir RTOS zu informieren.