std.hardware.gpio

Nativer GPIO-Stack für Linux/ARM64 (Raspberry Pi 4 / BCM2711): von ARM64-Memory-Barriers und rohen Syscall-Wrappern über zwei komplementäre Zugriffsmodi (MMIO-Direktzugriff ohne Kontextwechsel und Linux GPIO-v2 ioctl) bis zu typsicheren Pin-Wrappern, Edge-Detection und Software-PWM. Alle acht Units arbeiten ohne externe Bibliotheken — nur POSIX-Syscalls und direkte Registerzugriffe.

Zwei Zugriffsmodi:

  • Variante A — MMIO (gpio_mmio): Kein Kernel-Kontextwechsel nach GpioInit. Ideal für zeitkritische Anwendungen: Software-PWM, Bit-Bang-Protokolle (I²C, SPI), Frequenzen bis ~1 MHz. Erfordert /dev/gpiomem (ohne Root) oder /dev/mem (mit Root).
  • Variante B — ioctl (gpio_ioctl): Linux GPIO Character Device API v2 (Kernel ≥ 5.10). Unterstützt atomare Multi-Pin-Operationen, Edge-Detection-Events und Consumer-Labels. Zugriff über /dev/gpiochipX.

std.hardware · std.hardware.bluetooth · std.hardware.usb


Architektur

Übersicht der internen Schichten und Abhängigkeiten:

┌─────────────────────────────────────────────────────┐
│  Typsichere Pin-Wrapper                              │
│  gpio_pin  (OutputPin / InputPin)                   │
├─────────────────────────────────────────────────────┤
│  Erweiterungen                                       │
│  gpio_ext  (AltMode · Edge-Detection · SoftPWM)     │
├──────────────────────────┬──────────────────────────┤
│  Variante A: MMIO        │  Variante B: ioctl        │
│  gpio_mmio               │  gpio_ioctl               │
│  (kein Syscall im Loop)  │  (Linux GPIO-v2 API)      │
├──────────────────────────┴──────────────────────────┤
│  Hilfsfunktionen                                     │
│  gpio_util  (StringCopy · DelayMicroseconds)        │
├─────────────────────────────────────────────────────┤
│  Plattform-Konstanten (nur Konstanten)               │
│  rpi4  (BCM2711 Register-Offsets · Pin-Modi)        │
├─────────────────────────────────────────────────────┤
│  Grundschicht                                        │
│  gpio_syscalls · gpio_barriers                      │
└─────────────────────────────────────────────────────┘


Units

Unit Beschreibung
std.hardware.gpio_barriers ARM64-Memory-/Instruction-Barrier-Intrinsics: GpioMemBarrier (DMB SY), GpioInstBarrier (ISB SY)
std.hardware.gpio_syscalls Low-Level Syscall-Wrapper: GpioOpen, GpioClose, GpioIoctl, GpioPoll, GpioMmap, GpioMunmap
std.hardware.gpio_util Hilfsfunktionen: GpioCopyStringToBuf, GpioDelayMicroseconds (CLOCK_MONOTONIC Busy-Wait)
std.hardware.rpi4 BCM2711-Hardware-Konstanten: Register-Offsets (GPFSEL, GPSET, GPCLR, GPLEV, Pull), Pin-Modi
std.hardware.gpio_mmio MMIO-Direktzugriff (Variante A): GpioInit, GpioSetPinMode, GpioWritePin, GpioReadPin, GpioSetPullMode
std.hardware.gpio_ioctl Linux GPIO-v2 ioctl (Variante B): GpioGetChipInfo, GpioRequestLines, GpioSetLineValues, GpioGetLineValues
std.hardware.gpio_pin Typsichere Pin-Wrapper: GpioOutputPin* (nur Write), GpioInputPin* (nur Read)
std.hardware.gpio_ext Erweiterungen: GpioSetAltMode (ALT0–ALT5), GpioWaitForEdge, GpioSoftPWM

std.hardware.gpio_barriers

ARM64 Memory- und Instruction-Barrier-Intrinsics. Pflichtbestandteil für korrekte MMIO-Zugriffe auf dem Cortex-A72 (BCM2711): Der Out-of-Order-Prozessor kann Schreibzugriffe umordnen — ohne Barrieren sieht der GPIO-Controller keine definierte Reihenfolge.

Faustregel: Nach jedem Schreibzugriff auf ein GPIO-Register GpioMemBarrier() aufrufen. Lesezugriffe (GPLEV) benötigen keine Barriere.

Funktionen

Signatur Beschreibung
GpioMemBarrier() Full-System-Memory-Barrier — ARM64: DMB SY · x86-64: MFENCE. Nach jedem GPIO-Register-Schreibzugriff.
GpioInstBarrier() Instruction-Synchronization-Barrier — ARM64: ISB SY · x86-64: LFENCE. Nach MMU-/Cache-Konfigurationsänderungen; für normales GPIO nicht nötig.

std.hardware.gpio_syscalls

Unterste Schicht: direkte POSIX-Syscall-Wrapper für GPIO-Gerätedateien (/dev/gpiomem, /dev/gpiochipX). Wird von gpio_mmio und gpio_ioctl importiert; selten direkt verwendet.

Dateiöffnungs-Flags

Konstante Wert Beschreibung
GPIO_O_RDONLY 0 Nur lesen
GPIO_O_WRONLY 1 Nur schreiben
GPIO_O_RDWR 2 Lesen und schreiben
GPIO_O_SYNC 4096 Synchrones I/O (immer für MMIO setzen)

mmap-Konstanten

Konstante Wert Beschreibung
GPIO_PROT_READ 1 Mapping lesbar
GPIO_PROT_WRITE 2 Mapping schreibbar
GPIO_PROT_RW 3 Lesen und schreiben
GPIO_MAP_SHARED 1 Änderungen im Mapping sichtbar für alle Prozesse
GPIO_MAP_FAILED −1 mmap-Fehler-Sentinel

poll-Event-Flags

Konstante Wert Beschreibung
GPIO_POLLIN 1 Daten zum Lesen verfügbar
GPIO_POLLOUT 4 Schreiben möglich
GPIO_POLLERR 8 Fehler am Dateideskriptor

Funktionen

Signatur Beschreibung
GpioOpen(path: pchar, flags: int64): int64 Öffnet /dev/gpiomem oder /dev/gpiochipX; gibt fd ≥ 0 oder < 0 zurück
GpioClose(fd: int64): int64 Schließt fd
GpioRead(fd: int64, buf: int64, count: int64): int64 Liest count Bytes in buf
GpioIoctl(fd: int64, request: int64, arg: int64): int64 ioctl-Syscall; gibt 0 oder Fehlercode zurück
GpioPoll(fds_ptr: int64, nfds: int64, timeout_ms: int64): int64 poll() über mehrere Dateideskriptoren
GpioMmap(addr: int64, length: int64, prot: int64, flags: int64, fd: int64, offset: int64): int64 Legt mmap-Mapping an; gibt Startadresse oder GPIO_MAP_FAILED zurück
GpioMunmap(addr: int64, length: int64): int64 Gibt Mapping frei
GpioPollFdSet(ptr: int64, fd: int64, events: int64) Befüllt pollfd-Eintrag (8 Bytes: int32 fd, int16 events, int16 revents)
GpioPollFdRevents(ptr: int64): int64 Liest revents aus pollfd-Eintrag

std.hardware.gpio_util

Zwei plattformunabhängige Hilfsfunktionen, die von gpio_ioctl (String-Kopie für Consumer-Label) und gpio_ext (Busy-Wait für SoftPWM) benötigt werden.

Konstanten

Konstante Wert Beschreibung
GPIO_CLOCK_MONOTONIC 1 POSIX CLOCK_MONOTONIC für clock_gettime
GPIO_TIMESPEC_SIZE 16 Größe von struct timespec (sec 8 Bytes + nsec 8 Bytes)
GPIO_NS_PER_US 1 000 Nanosekunden pro Mikrosekunde
GPIO_NS_PER_SEC 1 000 000 000 Nanosekunden pro Sekunde

Funktionen

Signatur Beschreibung
GpioCopyStringToBuf(src: pchar, dst: int64, max_len: int64): int64 Kopiert null-terminierten String nach dst; schreibt max. max_len-1 Bytes + NUL; gibt Anzahl geschriebener Bytes zurück
GpioDelayMicroseconds(delay_us: int64) Busy-Wait für mindestens delay_us Mikrosekunden via CLOCK_MONOTONIC; Genauigkeit ±1–2 µs

std.hardware.rpi4

BCM2711-Hardware-Konstanten für den Raspberry Pi 4. Enthält ausschließlich con-Definitionen — keine Funktionen. Wird von gpio_mmio importiert.

Plattform-Adressen

Konstante Wert Beschreibung
RPI4_PERIPHERAL_BASE 0xFE000000 Peripheral-Basis-Adresse (BCM2711)
RPI4_GPIO_BASE 0xFE200000 GPIO-Basis (PERIPHERAL_BASE + 0x200000)
RPI4_GPIO_MAP_SIZE 4096 Mapping-Größe (eine Seite für alle GPIO-Register)
RPI4_MAX_PIN 53 Maximale Pin-Nummer auf BCM2711
RPI4_MAP_FAILED −1 mmap-Fehler-Sentinel
RPI4_HAS_NEW_PULL_REGS 1 Standard: neue Pull-Register (BCM2711 Rev ≥ 1.2)

Function-Select-Register (GPFSEL)

3 Bits pro Pin, 10 Pins pro 32-Bit-Register:

Konstante Offset Beschreibung
RPI4_GPFSEL0 0x00 Pins 0–9
RPI4_GPFSEL1 0x04 Pins 10–19
RPI4_GPFSEL2 0x08 Pins 20–29
RPI4_GPFSEL3 0x0C Pins 30–39
RPI4_GPFSEL4 0x10 Pins 40–49
RPI4_GPFSEL5 0x14 Pins 50–53

Set / Clear / Level-Register

Konstante Offset Beschreibung
RPI4_GPSET0 0x1C Pins 0–31 setzen (Write-1-to-set)
RPI4_GPSET1 0x20 Pins 32–53 setzen
RPI4_GPCLR0 0x28 Pins 0–31 löschen (Write-1-to-clear)
RPI4_GPCLR1 0x2C Pins 32–53 löschen
RPI4_GPLEV0 0x34 Pins 0–31 lesen (Read-Only)
RPI4_GPLEV1 0x38 Pins 32–53 lesen

Pull-Widerstands-Register

Konstante Offset Beschreibung
RPI4_GPPUD 0x94 Pull-Control Legacy (0=None, 1=Down, 2=Up)
RPI4_GPPUDCLK0 0x98 Pull-Clock Pins 0–31 (Legacy)
RPI4_GPPUDCLK1 0x9C Pull-Clock Pins 32–53 (Legacy)
RPI4_PUP_PDN_REG0 0xE4 Pull-Register Pins 0–15 (Neu, 2 Bits/Pin)
RPI4_PUP_PDN_REG1 0xE8 Pull-Register Pins 16–31
RPI4_PUP_PDN_REG2 0xEC Pull-Register Pins 32–47
RPI4_PUP_PDN_REG3 0xF0 Pull-Register Pins 48–53

Pin-Modus-Codes (GPFSEL 3-Bit-Kodierung)

Konstante Wert Beschreibung
RPI4_MODE_INPUT 0 (000) Eingang
RPI4_MODE_OUTPUT 1 (001) Ausgang
RPI4_MODE_ALT0 4 (100) Alt-Funktion 0
RPI4_MODE_ALT1 5 (101) Alt-Funktion 1
RPI4_MODE_ALT2 6 (110) Alt-Funktion 2
RPI4_MODE_ALT3 7 (111) Alt-Funktion 3
RPI4_MODE_ALT4 3 (011) Alt-Funktion 4
RPI4_MODE_ALT5 2 (010) Alt-Funktion 5

std.hardware.gpio_mmio

MMIO-Direktzugriff auf BCM2711-GPIO-Register (Variante A). Öffnet /dev/gpiomem und legt ein mmap-Mapping über die Register an. Nach dem einmaligen GpioInit-Aufruf sind alle weiteren Pin-Operationen reine Speicherzugriffe ohne Syscall — ideal für zeitkritische Bit-Bang-Protokolle und Software-PWM.

Kontext-Konstanten und Pin-Flags

Konstante Wert Beschreibung
GPIO_CTX_SIZE 24 Größe des heap-allozierten GPIO-Kontexts in Bytes
GPIO_PIN_INPUT 0 Pin-Modus: Eingang
GPIO_PIN_OUTPUT 1 Pin-Modus: Ausgang
GPIO_PIN_LOW 0 Pegel: LOW
GPIO_PIN_HIGH 1 Pegel: HIGH
GPIO_PULL_NONE 0 Kein Pull-Widerstand
GPIO_PULL_DOWN 1 Pull-Down-Widerstand
GPIO_PULL_UP 2 Pull-Up-Widerstand

Kontext-Verwaltung

Signatur Beschreibung
GpioCtxAlloc(): int64 Alloziert GPIO-Kontext (24 Bytes); gibt Zeiger zurück
GpioCtxFree(ctx: int64) Gibt Kontext frei (nur den Kontext-Puffer, nicht das Mapping)
GpioGetMem(ctx: int64): int64 Gibt Basisadresse des mmap-Mappings zurück
GpioIsMapped(ctx: int64): int64 1 wenn Mapping aktiv, 0 wenn nicht initialisiert
GpioHasNewPull(ctx: int64): int64 1 wenn neue BCM2711-Pull-Register aktiv

Initialisierung und Freigabe

Signatur Beschreibung
GpioInit(ctx: int64): int64 Öffnet /dev/gpiomem (kein Root) oder /dev/mem (Root); legt Mapping an; GpioMemBarrier() danach; gibt 1 bei Erfolg zurück
GpioClose(ctx: int64) GpioMemBarrier() + munmap; setzt is_mapped = 0; No-op wenn nicht initialisiert

Pin-Operationen

Signatur Beschreibung
GpioSetPinMode(ctx: int64, pin: int64, mode: int64): int64 Konfiguriert Pin via GPFSEL-Register (RMW + GpioMemBarrier()); gibt 1 bei Erfolg zurück
GpioWritePin(ctx: int64, pin: int64, state: int64): int64 Setzt (GPSET) oder löscht (GPCLR) Pin atomar ohne RMW; GpioMemBarrier() danach
GpioReadPin(ctx: int64, pin: int64): int64 Liest Pegel aus GPLEV-Register; gibt 0/1 zurück, -1 bei Fehler
GpioSetPullMode(ctx: int64, pin: int64, mode: int64): int64 Konfiguriert Pull-Widerstand; unterstützt neues BCM2711-Format und Legacy-3-Schritt-Protokoll

import std.hardware.gpio_mmio;
import std.alloc;
import std.io;

fn BlinkLed(pin: int64, times: int64): void {
    var ctx := GpioCtxAlloc();
    GpioInit(ctx);
    GpioSetPinMode(ctx, pin, GPIO_PIN_OUTPUT);

    var i: int64 := 0;
    while (i < times) {
        GpioWritePin(ctx, pin, GPIO_PIN_HIGH);
        GpioDelayMicroseconds(500000);   // 500 ms
        GpioWritePin(ctx, pin, GPIO_PIN_LOW);
        GpioDelayMicroseconds(500000);
        i := i + 1;
    }

    GpioClose(ctx);
    GpioCtxFree(ctx);
}


std.hardware.gpio_ioctl

Linux GPIO-v2 ioctl-Interface (Variante B, Kernel ≥ 5.10). Öffnet /dev/gpiochipX und verwendet die standardisierte gpio_v2_*-Kernel-API. Unterstützt atomare Multi-Pin-Operationen (bis 64 Pins gleichzeitig), Consumer-Labels und Edge-Detection über Line-Fds.

ioctl-Codes

Konstante Wert Beschreibung
GPIO_GET_CHIPINFO_IOCTL 0x8044B401 Chip-Info lesen (_IOR, 68 Bytes)
GPIO_V2_GET_LINE_IOCTL 0xC250B407 Lines anfordern (_IOWR, 592 Bytes)
GPIO_V2_LINE_GET_VALUES_IOCTL 0xC010B40E Line-Werte lesen (_IOWR, 16 Bytes)
GPIO_V2_LINE_SET_VALUES_IOCTL 0xC010B40F Line-Werte setzen (_IOWR, 16 Bytes)

Line-Flags (gpio_v2_line_flag)

Konstante Bit Beschreibung
GPIO_V2_LINE_FLAG_USED 0 Pin bereits belegt
GPIO_V2_LINE_FLAG_ACTIVE_LOW 1 Aktiv-Low-Logik
GPIO_V2_LINE_FLAG_INPUT 2 Eingang
GPIO_V2_LINE_FLAG_OUTPUT 3 Ausgang
GPIO_V2_LINE_FLAG_EDGE_RISING 4 Steigende Flanke auslöst Ereignis
GPIO_V2_LINE_FLAG_EDGE_FALLING 5 Fallende Flanke löst Ereignis aus
GPIO_V2_LINE_FLAG_OPEN_DRAIN 6 Open-Drain-Ausgang
GPIO_V2_LINE_FLAG_OPEN_SOURCE 7 Open-Source-Ausgang
GPIO_V2_LINE_FLAG_BIAS_PULL_UP 8 Pull-Up aktivieren
GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN 9 Pull-Down aktivieren
GPIO_V2_LINE_FLAG_BIAS_DISABLED 10 Pull-Widerstand deaktivieren

Struct-Größen

Konstante Wert Beschreibung
GPIO_CHIP_INFO_SIZE 68 gpiochip_info: name[32] + label[32] + lines(u32)
GPIO_LINE_VALUES_SIZE 16 gpio_v2_line_values: bits(u64) + mask(u64)
GPIO_LINE_REQUEST_SIZE 592 gpio_v2_line_request (vollständige Struktur)
GPIO_V2_LINES_MAX 64 Maximale Lines pro Request

Funktionen

Signatur Beschreibung
GpioGetChipInfo(chip_path: pchar): int64 Öffnet /dev/gpiochipX und liest gpiochip_info; gibt heap-allozierten Puffer zurück (0 = Fehler)
GpioChipInfoFree(info: int64) Gibt den von GpioGetChipInfo allozierten Puffer frei
GpioChipInfoLines(info: int64): int64 Gibt die Anzahl verfügbarer Lines zurück
GpioRequestLines(chip_path: pchar, pins_ptr: int64, num_lines: int64, flags: int64, consumer: pchar): int64 Fordert Pins an; gibt Line-Fd zurück (−1 = Fehler)
GpioSetLineValues(line_fd: int64, mask: int64, bits: int64): int64 Setzt Ausgangspegel; mask = Bitmap der zu ändernden Lines; bits = Zielwerte; gibt 1 bei Erfolg zurück
GpioGetLineValues(line_fd: int64, mask: int64, bits_out: int64): int64 Liest Pegel; schreibt Ergebnis nach bits_out (min. 8 Bytes); gibt 1 bei Erfolg zurück
GpioReleaseLine(line_fd: int64) Schließt Line-Fd (gibt Pins frei)

import std.hardware.gpio_ioctl;
import std.alloc;
import std.io;

fn IoctlBlinkLed(pin: int64): void {
    // Chip-Info abfragen
    var info := GpioGetChipInfo("/dev/gpiochip0");
    PrintLn("Lines: " + IntToStr(GpioChipInfoLines(info)));
    GpioChipInfoFree(info);

    // Pin als Ausgang anfordern
    var pins: int64 := alloc(4);
    poke32(pins, pin);   // Pin-Nummer als int32 eintragen

    var lineFd := GpioRequestLines("/dev/gpiochip0", pins, 1,
                                    GPIO_V2_LINE_FLAG_OUTPUT, "blink");
    free(pins, 4);

    // 5× blinken
    var i: int64 := 0;
    while (i < 5) {
        GpioSetLineValues(lineFd, 1, 1);  // mask=1 (Line 0), bits=1 (HIGH)
        GpioDelayMicroseconds(500000);
        GpioSetLineValues(lineFd, 1, 0);  // bits=0 (LOW)
        GpioDelayMicroseconds(500000);
        i := i + 1;
    }

    GpioReleaseLine(lineFd);
}


std.hardware.gpio_pin

Typsichere Pin-Wrapper (Variante für MMIO). Implementiert ein Konventions-basiertes Typsystem: GpioOutputPin*-Funktionen existieren nur für Schreibzugriffe, GpioInputPin*-Funktionen nur für Lesezugriffe. Ein Aufruf der jeweils falschen Seite (z. B. GpioOutputPinRead) schlägt mit „unknown function“ beim Compilieren fehl.

Konstanten

Konstante Wert Beschreibung
GPIO_PIN_CTX_SIZE 16 Größe des Pin-Kontexts: gpio_ctx(8) + pin_nr(8)

OutputPin-Funktionen (nur Write)

Signatur Beschreibung
GpioOutputPinAlloc(gpio_ctx: int64, pin_nr: int64): int64 Alloziert OutputPin-Kontext; verknüpft mit MMIO-Kontext und Pin-Nummer
GpioOutputPinInit(pin_ctx: int64, pull: int64): int64 Setzt Pin-Modus auf OUTPUT + optionaler Pull; gibt 1 bei Erfolg zurück
GpioOutputPinWrite(pin_ctx: int64, state: int64): int64 Setzt Pegel (GPIO_PIN_HIGH / GPIO_PIN_LOW); gibt 1 bei Erfolg zurück
GpioOutputPinFree(pin_ctx: int64) Gibt Pin-Kontext frei

InputPin-Funktionen (nur Read)

Signatur Beschreibung
GpioInputPinAlloc(gpio_ctx: int64, pin_nr: int64): int64 Alloziert InputPin-Kontext
GpioInputPinInit(pin_ctx: int64, pull: int64): int64 Setzt Pin-Modus auf INPUT + optionaler Pull (typisch GPIO_PULL_UP für Taster)
GpioInputPinRead(pin_ctx: int64): int64 Liest Pegel; gibt 0 (LOW), 1 (HIGH) oder −1 (Fehler) zurück
GpioInputPinFree(pin_ctx: int64) Gibt Pin-Kontext frei

import std.hardware.gpio_mmio;
import std.hardware.gpio_pin;
import std.alloc;
import std.io;

fn ButtonControlsLed(ledPin: int64, btnPin: int64): void {
    var ctx := GpioCtxAlloc();
    GpioInit(ctx);

    var led := GpioOutputPinAlloc(ctx, ledPin);
    GpioOutputPinInit(led, GPIO_PULL_NONE);

    var btn := GpioInputPinAlloc(ctx, btnPin);
    GpioInputPinInit(btn, GPIO_PULL_UP);   // Taster gegen GND mit Pullup

    var i: int64 := 0;
    while (i < 1000) {
        var pressed := GpioInputPinRead(btn);
        // Taster mit Pullup: gedrückt = LOW (0), losgelassen = HIGH (1)
        GpioOutputPinWrite(led, 1 - pressed);
        GpioDelayMicroseconds(5000);   // 5 ms Entprellzeit
        i := i + 1;
    }

    GpioOutputPinFree(led);
    GpioInputPinFree(btn);
    GpioClose(ctx);
    GpioCtxFree(ctx);
}


std.hardware.gpio_ext

Erweiterungen für Alternativfunktionen, Edge-Detection und Software-PWM. Baut auf gpio_mmio und gpio_ioctl auf.

Alt-Modus-Konstanten

Die Bit-Codes sind nicht linear (BCM2711 GPFSEL 3-Bit):

Konstante Wert Beschreibung
GPIO_PIN_ALT0 4 (100) Alternativfunktion 0 (z. B. SPI0, I2C auf bestimmten Pins)
GPIO_PIN_ALT1 5 (101) Alternativfunktion 1
GPIO_PIN_ALT2 6 (110) Alternativfunktion 2
GPIO_PIN_ALT3 7 (111) Alternativfunktion 3
GPIO_PIN_ALT4 3 (011) Alternativfunktion 4
GPIO_PIN_ALT5 2 (010) Alternativfunktion 5

Funktionen

Signatur Beschreibung
GpioSetAltMode(ctx: int64, pin: int64, mode: int64): int64 Setzt Pin auf Alt-Funktion (GPIO_PIN_ALT0–ALT5); delegiert an GpioSetPinMode; gibt 1 bei Erfolg zurück
GpioWaitForEdge(line_fd: int64, timeout_ms: int64): int64 Blockiert via sys_poll auf Line-Fd bis zur nächsten Flanke; timeout_ms: 0=sofort, −1=unbegrenzt; gibt 1=Ereignis, 0=Timeout, −1=Fehler zurück
GpioSoftPWM(ctx: int64, pin: int64, frequency: int64, dutyCycle: int64, duration_ms: int64) Software-PWM per Busy-Wait; blockiert CPU vollständig für duration_ms; dutyCycle: 0–100; frequency: ≤ ~1 MHz

SoftPWM-Randfälle

Eingabe Verhalten
frequency ≤ 0 Sofortige Rückkehr (Guard)
dutyCycle = 0 Pin bleibt LOW für die gesamte Dauer
dutyCycle ≥ 100 Pin bleibt HIGH für die gesamte Dauer
frequency > 1 000 000 period_us wird auf 1 µs geklemmt (kein Überlauf)

import std.hardware.gpio_mmio;
import std.hardware.gpio_ext;
import std.hardware.gpio_ioctl;
import std.alloc;

fn FadeLed(pin: int64): void {
    var ctx := GpioCtxAlloc();
    GpioInit(ctx);
    GpioSetPinMode(ctx, pin, GPIO_PIN_OUTPUT);

    // Fade-In: 0 % → 100 % Helligkeit
    var duty: int64 := 0;
    while (duty <= 100) {
        GpioSoftPWM(ctx, pin, 1000, duty, 20);  // 1 kHz, 20 ms pro Schritt
        duty := duty + 5;
    }

    GpioClose(ctx);
    GpioCtxFree(ctx);
}

fn WaitForButton(lineFd: int64): void {
    // Wartet auf fallende Flanke (Tasterdruck) — max. 10 Sekunden
    var r := GpioWaitForEdge(lineFd, 10000);
    if (r == 1) { Print("Taster gedrückt!\n"); }
    if (r == 0) { Print("Timeout.\n"); }
}


Variante A vs. Variante B

Entscheidungshilfe für die Wahl des Zugriffsmodus:

Kriterium MMIO (gpio_mmio) ioctl (gpio_ioctl)
Syscalls im Betrieb Keine (nach GpioInit) Pro Set/Get ein ioctl
Zeitkritisch (< 10 µs) Ja Nein
Software-PWM / Bit-Bang Ideal Ungeeignet
Multi-Pin atomar Nein (sequenziell) Ja (bis 64 Pins)
Edge-Detection Über gpio_ext + ioctl Nativ (EDGE-Flags)
Root erforderlich Nein (/dev/gpiomem) Nein (/dev/gpiochip0)
Portabilität RPi4/BCM2711 Alle Linux-GPIO-Treiber

Verwandte Units

Letzte Aktualisierung: 2026-06-07