Rust bricht in die Embedded-Welt ein: Warum C nicht mehr König ist

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Die Ära der Hardware wechselt die Sprache

\n\n

Wenn Sie jemals eine Firmware für einen Mikrocontroller in C geschrieben haben, kennen Sie dieses Gefühl. Das Gefühl, wenn Sie nach drei Stunden Debugging einen Hänger finden – der Zeiger ist ins Nirwana geflogen, und der Watchdog hat alles ertragen. Embedded-Entwicklung war lange Zeit das Terrain von C und Assembler. Aber in den letzten Jahren ist ein neuer Spieler auf die Bühne getreten – Rust. Und es ist nicht nur "eine weitere Sprache", sondern ein echter Durchbruch für eingebettete Systeme.

\n\n

In diesem Artikel werden wir analysieren, warum Embedded-Entwicklung mit Rust kein Hype, sondern eine Notwendigkeit ist. Wir sehen uns reale Codebeispiele an, vergleichen mit C und verstehen, wo man anfängt. Wenn Sie für STM32, ESP32 oder ARM Cortex-M programmieren, sind Sie hier genau richtig.

\n\n

Warum Rust für Embedded die ideale Verbindung ist

\n\n

Eingebettete Systeme sind eine Welt der Einschränkungen. Wenig Speicher, kein Betriebssystem, kein Heap, keine Ausnahmen. Ein Compiler-Fehler ist gut, ein Laufzeitfehler ist schlecht. Rust wurde genau für solche Bedingungen entwickelt.

\n\n

Speichersicherheit ohne Garbage Collector

\n\n

Der größte Schmerz eines Embedded-Entwicklers in C ist Use-after-free, doppeltes Freigeben von Speicher und Pufferüberläufe. Rust löst dies auf Typebene. Das Ownership-Modell und das Borrowing funktionieren sogar in einer no_std-Umgebung – ohne Allokator, ohne Betriebssystem, ohne GC.

\n\n

Stellen Sie sich vor, Sie schreiben einen Treiber für eine LED. In C würden Sie schreiben:

\n\n
// C code\nvoid led_on(GPIO_TypeDef *gpio, uint16_t pin) {\n    gpio->BSRR = pin;\n}
\n\n

Alles gut, bis jemand einen Nullzeiger übergibt. Rust lässt Sie das nicht tun:

\n\n
// Rust code\nfn led_on(gpio: &mut GpioRegisters, pin: u16) {\n    gpio.bsrr.write(|w| w.bits(pin.into()));\n}
\n\n

Hier ist &mut GpioRegisters die Garantie, dass die Referenz gültig und der Zugriff auf die Register exklusiv ist. Der Compiler lässt gefährlichen Code einfach nicht durch.

\n\n

Nullkosten-Abstraktionen

\n\n

Eine der Hauptängste von Embedded-Entwicklern ist, dass eine höhere Sprache Taktzyklen "frisst". Rust folgt dem Prinzip der Zero-Cost Abstractions: Sie zahlen nur für das, was Sie nutzen. Iteratoren, Closures, Traits – all das wird in ebenso effizienten Maschinencode kompiliert wie manuelles Entrollen von Schleifen in C.

\n\n

Darüber hinaus gibt es im Embedded-Ökosystem von Rust Crates, die auf der Ebene einzelner Instruktionen arbeiten. Zum Beispiel generiert cortex-m-rt die Interrupt-Vektor-Tabelle und den Startup-Code ohne eine einzige überflüssige Instruktion.

\n\n

Reales Projekt: LED blinken mit Rust (STM32)

\n\n

Lassen Sie uns ein einfaches Programm für das STM32F3Discovery-Board schreiben. Wir verwenden cortex-m-quickstart und das HAL der embedded rust-Community.

\n\n

Schritt 1: Projekt einrichten

\n\n

Stellen Sie sicher, dass Rust und das Toolchain für ARM Cortex-M installiert sind:

\n\n
rustup target add thumbv7em-none-eabihf\ncargo install cargo-generate
\n\n

Erstellen Sie ein Projekt aus der Vorlage:

\n\n
cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
\n\n

Schritt 2: Code schreiben

\n\n

Öffnen Sie src/main.rs und schreiben Sie den klassischen Blinky:

\n\n
#![no_std]\n#![no_main]\n\nuse cortex_m_rt::entry;\nuse panic_halt as _;\nuse stm32f3xx_hal::{pac, prelude::*};\n\n#[entry]\nfn main() -> ! {\n    // Zugriff auf die Peripherie erhalten\n    let dp = pac::Peripherals::take().unwrap();\n    let mut rcc = dp.RCC.constrain();\n    let mut gpioe = dp.GPIOE.split(&mut rcc.ahb);\n\n    // Pin PE9 als Ausgang konfigurieren (LED LD1)\n    let mut led = gpioe\n        .pe9\n        .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);\n\n    loop {\n        led.set_high().unwrap();\n        cortex_m::asm::delay(8_000_000);\n        led.set_low().unwrap();\n        cortex_m::asm::delay(8_000_000);\n    }\n}
\n\n

Was passiert hier?

\n
    \n
  • #![no_std] — wir be

Blogs

Buchempfehlungen