Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Eine no_std-Rust-Umgebung

Der Begriff „Embedded Programming“ (Programmierung eingebetteter Systeme) umfasst ein breites Spektrum unterschiedlichster Programmierbereiche. Das Spektrum reicht von der Programmierung von 8-Bit-Mikrocontrollern (wie dem ST72325xx mit nur wenigen Kilobyte RAM und ROM bis hin zu Systemen wie dem Raspberry Pi (Modell B 3+), der über einen 32/64-Bit-Quad-Core-Prozessor (Cortex-A53 mit 1,4 GHz) und 1 GB RAM verfügt. Je nach Zielsystem und Anwendungsfall gelten bei der Programmierung unterschiedliche Einschränkungen und Rahmenbedingungen.

Es gibt zwei grundlegende Kategorien der Programmierung eingebetteter Systeme:

Hosted Environments

Derartige Umgebungen ähneln einer herkömmlichen PC-Umgebung. Das bedeutet, dass Ihnen eine Systemschnittstelle (z. B. POSIX) zur Verfügung steht, die Grundfunktionen (Primitive) für die Interaktion mit verschiedenen Systemkomponenten bietet – etwa Dateisystemen, Netzwerkfunktionen, Speicherverwaltung, Threads usw. Standardbibliotheken wiederum basieren in der Regel auf diesen Grundfunktionen, um ihre Funktionalität zu implementieren. Zudem können eine spezifische System-Root-Umgebung (sysroot) sowie Einschränkungen bei der RAM- oder ROM-Nutzung vorliegen; auch spezielle Hardware oder Ein-/Ausgabeschnittstellen (I/Os) können vorhanden sein. Insgesamt vermittelt die Programmierung den Eindruck, in einer auf einen speziellen Einsatzzweck ausgerichteten PC-Umgebung zu arbeiten.

Rein physische Umgebung

In einer rein physischen Umgebung wird vor Ihrem Programm kein Code geladen. Ohne die vom Betriebssystem bereitgestellte Software kann die Standardbibliothek nicht geladen werden. Stattdessen kann das Programm zusammen mit den verwendeten Crates ausschließlich die Hardware (Bare Metal) nutzen. Um zu verhindern, dass Rust die Standardbibliothek lädt, verwenden Sie no_std. Die plattformunabhängigen Teile der Standardbibliothek sind über libcore verfügbar. libcore schließt außerdem Funktionen aus, die in eingebetteten Umgebungen nicht immer erwünscht sind. Eine dieser Funktionen ist ein Speicherallokator für die dynamische Speicherverwaltung. Falls Sie diese oder andere Funktionalitäten benötigen, stehen Ihnen häufig entsprechende Crates zur Verfügung.

Die libstd-Laufzeitumgebung

Wie bereits erwähnt, erfordert die Verwendung von libstd eine gewisse Systemintegration; dies liegt jedoch nicht nur daran, dass libstd eine einheitliche Schnittstelle zu Betriebssystem-Abstraktionen bereitstellt, sondern auch daran, dass es eine Laufzeitumgebung (Runtime) mitliefert. Diese Laufzeitumgebung kümmert sich unter anderem um die Einrichtung eines Stack-Overflow-Schutzes, die Verarbeitung von Kommandozeilenargumenten sowie das Starten des Haupt-Threads, bevor die main-Funktion des Programms aufgerufen wird. In einer no_std-Umgebung steht diese Laufzeitumgebung nicht zur Verfügung.

Zusammenfassung

#![no_std] ist ein Attribut auf Crate-Ebene, das angibt, dass das Crate gegen das core-Crate anstatt gegen das std-Crate gelinkt wird. Das libcore-Crate wiederum ist eine plattformunabhängige Teilmenge des std-Crates, die keinerlei Annahmen über das System trifft, auf dem das Programm ausgeführt wird. Dementsprechend stellt es APIs für Sprachprimitive wie Gleitkommazahlen, Strings und Slices bereit sowie APIs, die Prozessorfunktionen wie atomare Operationen und SIMD-Befehle zugänglich machen. Es fehlen jedoch APIs für Funktionen, die eine Plattformintegration erfordern. Aufgrund dieser Eigenschaften eignen sich no_std- und libcore-Code für jegliche Art von Bootstrapping-Code (Stufe 0), wie etwa Bootloader, Firmware oder Kernel.

Überblick

Eigenschaftno_stdstd
heap (dynamischer Speicher)*
collections (Vec, BTreeMap, usw.)**
Schutz vor Stack-Überlauf
führt Initialisierungscode vor der main-Funktion aus
libstd verfügbar
libcore verfügbar
schreibt firmware, kernel, oder bootloader code

* Nur wenn Sie das alloc-Crate und einen geeigneten Allocator wie alloc-cortex-m verwenden.

** Nur wenn Sie das collections-Crate verwenden und einen globalen Standard-Allocator konfigurieren.

** HashMap und HashSet stehen aufgrund des Fehlens eines sicheren Zufallszahlengenerators nicht zur Verfügung.

Siehe auch