Quell'esempio di elinux usa un IO mappato in memoria . Il kernel esporta anche un'interfaccia dello spazio utente tramite /sys/class/gpio
, 1 che è anche documentata su elinux . Lavorando in C useresti basso livello read()
/ write()
anziché echo
, ovviamente. Non utilizzare funzioni basate su stream di livello superiore.
Alcuni programmatori si arrabbiano un po 'quando gli viene detto di usare un'interfaccia di file per cose che credono debbano essere fatte con le chiamate di sistema. Questa è puramente una questione di stile : equivalgono esattamente alla stessa cosa . Non esiste un "sovraccarico I / O aggiuntivo", ecc., Che accede a un file in questo caso perché non è un file reale, è un'interfaccia del kernel. Esattamente come qualsiasi altro sistema ABI che tu abbia mai usato, solo diverso. L'uso di /proc
e /sys
nodi è stato a lungo preferito dagli sviluppatori del kernel, ma vedo ancora persone determinate a utilizzare le chiamate di sistema dove possono - ad esempio sysfs()
, nonostante il fatto che man 2 sysfs
dica chiaramente:
Questa chiamata di sistema derivata da System-V è obsoleta; non usarlo. Sui sistemi con / proc, le stesse informazioni possono essere ottenute tramite / proc / filesystems; usa invece quell'interfaccia.
Questa è una pagina man della libreria C che ti dice di usare l' /proc
interfaccia . Se non è abbastanza buono per convincerti, niente lo è. /sys
è lo stesso tipo di cose. Il punto è: solo perché stai usando un nodo di file invece di qualche API specifica in C non significa che non stai facendo una vera programmazione, o che le prestazioni ne risentiranno, ecc. Ecc. Alcune persone potrebbero dire che in realtà è una bella funzionalità. È anche il metodo raccomandato dalle persone che hanno scritto il kernel del sistema operativo.
Una rapida introduzione all'interfaccia GPIO è disponibile in [kernel-src]/Documentation/ABI/testing/sysfs-gpio
:
GPIOs are only made available to userspace by an explicit
"export" operation. If a given GPIO is not claimed for use by
kernel code, it may be exported by userspace (and unexported later).
Kernel code may export it for complete or partial access.
GPIOs are identified as they are inside the kernel, using integers in
the range 0..INT_MAX. See Documentation/gpio.txt for more information.
/sys/class/gpio
/export ... asks the kernel to export a GPIO to userspace
/unexport ... to return a GPIO to the kernel
/gpioN ... for each exported GPIO #N
/value ... always readable, writes fail for input GPIOs
/direction ... r/w as: in, out (default low); write: high, low
/edge ... r/w as: none, falling, rising, both
/gpiochipN ... for each gpiochip; #N is its first GPIO
/base ... (r/o) same as N
/label ... (r/o) descriptive, not necessarily unique
/ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)
Sembrano vari tutorial e simili online oltre a quello di elinux. Ho usato solo I2C, altrimenti ti darei una risposta più diretta.
Se sei interessato a scrivere il codice spaziale del kernel accedendo a GPIO, puoi dare un'occhiata qui , anche se penso che sia davvero utile solo se vuoi scrivere un driver per un dispositivo specifico e creare la tua API dello spazio utente.
1. Dato che anche l'IO mappato a mem deve utilizzare la lettura / scrittura, non sono sicuro che un metodo offra un vantaggio significativo rispetto all'altro qui. L'uso /sys
dell'interfaccia sarà sicuramente più portatile, se stai cercando un codice che verrà eseguito su cose diverse da un raspberry pi.