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.
| 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 |
| 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
-
-
std.thread — Threads für parallele Pin-Überwachung
std.signals — Signalbehandlung für sauberes Shutdown (GpioClose)
std.time — Zeitstempel und Timer-Funktionen
Letzte Aktualisierung: 2026-06-07