Zugriff auf die GPIOs per sysfs als Alternative zu den Libraries z.B. pigpio/bcm2835/wiringPi?

  • Servus beinander,

    ich tüftle gerade am Zugriff auf einige Komponenten über SPI, der sich scheinbar mit der Standard-Funktionalität des SPI nicht abdecken lässt.

    Ausserdem stört mich die Tatsache, dass die gängigen Libraries, wie z.B. pigpio, nur einmal instanziierbar sind (was auch nicht weiter verwundert).

    Es gäbe zwar jetzt die Möglichkeit, z.B. bei der pigpio, jedes weitere Programm, das Funktionen aus der Lib benötigt, über die daemon-Schnittstelle zu realisieren ... aber da gehe ich über eine "blackbox" deren Zeitverhalten ich schlecht einschätzen kann. Und das würde ich gerne vermeiden.

    Mittlerweile bin ich so weit, dass ich die Lib nur nutze, um diverse GPIOs anzusteuern. Alles, was z.B. SPI betrifft, habe ich als low-level Funktionen realisiert.

    Jetzt wäre es halt genial, wenn es z.B. ein LKM gäbe, das unter /dev eine devicenode zur Verfügung stellt, über die man einen konkurrierenden Zugriff realisieren kann.

    Leider habe ich diesbezüglich bisher (noch?) nichts finden können.

    Meine Frage wäre halt jetzt: hat jemand von Euch bereits Erfahrunfen sammeln können, was Latenzzeiten, Zuverlässigkeit und konkurrierende Zugriffe betrifft?

    Danke schon mal,

    -ds-

  • Zugriff auf die GPIOs per sysfs als Alternative zu den Libraries z.B. pigpio/bcm2835/wiringPi?? Schau mal ob du hier fündig wirst!

  • Hi,

    kleiner Update:

    ich glaube, ich hab' jetzt was entdeckt, wie ich sehr hardwarenah auf die GPIOs zugreifen und sogar events abfragen kann.

    Ich les' mich das grad mal ein, und poste dann Details ...

    Sieht jedenfalls sehr vielversprechend aus. Konkurrierende Zugriffe klappen jedenfalls :)

    ciao,

    -ds-

  • Servus Prittzl ,

    genau ... ich will direkt die Pins schreiben, lesen und auch events abfangen ( z.B. rising/falling edge).

    Und zwar aus o.g. Gründen ohne eine der Libraries.

    Dabei soll gewährleistet sein, dass ich jeden Pin gegen Zugriff von anderen Prozessen schützen kann bzw. merke, wenn der Pin gerade in Zugriff ist.

    Das Ganze dann idealerweise aus dem Userspace und ohne root-Rechte ...

    Wie gesagt ... ich lese mich gerade mal durch die Beschreibung einer Schnittstelle, die sehr vielversprechend aussieht :)

    cu,

    -ds-

  • Hi,

    das wäre ja blöd, wenn ich in einem Programm einen Pin auf HIGH schalte und in einem anderen auf LOW ... konkurrierende Zugriffe halt.

    Eins der Programma hat halt dann die Arschkarte und darf nicht ... oder nicht sofort, je nachdem.

    Was ich jetzt gefunden habe erweitert /dev/gpiomem um /dev/gpiochip0, /dev/gpiochip1 und /dev/gpiochip2.

    Das sind echte char-devices und da klappt das auch mit dem Verriegeln der Pins. Um noch näher an die Hardware zu kommen, müsste ich wohl ein eigenes Treibermodul schreiben ...

    Was dazu kommt ist, dass ich per pin auch events abfragen kann.

    Also genau das, was ich wollte.

    Über das sysfs habe ich mittlerweile ziemlich viele schlechte Erfahrungen gelesen. Deshalb lass' ich das wohl lieber.

    cheers,

    -ds-

  • Was machst Du da überhaupt?

    Du fragst an den Pins keine Events ab, dafür gibt es Interrupts auf die Du reagierst. Das ist ziemlich einfach, aber dafür brauchst Du einen LKM.

    Ich verwende das SYSFS in meinem Projekt ziemlich erfolgreich.

    Aber ganz ehrlich, was machst Du da überhaupt? Das hört sich alles etwas "komisch" an.

    Ansonsten:

    GPIO und Interrupts

    LKM und GPIO

    Ist zwar für BeagleBone, spielt aber letztendlich keine Rolle.

    Edited once, last by Ozymandias (October 19, 2018 at 9:59 AM).

  • Du fragst an den Pins keine Events ab, dafür gibt es Interrupts auf die Du reagierst. Das ist ziemlich einfach, aber dafür brauchst Du einen LKM.

    Auf der Ebene, auf der auch sysfs aufsetzt, gibt es keine Interrupts ... das passiert dort über polling ...

    Zudem wüsste ich jetzt ad hoc nicht, wie ich mit sysfs einen Pegelwechsel ohne eine imho ineffiziente Abfrageschleife feststellen kann.

    Und dass ein LKM (loadable kernel module) einfach ist, halte ich für ein Gerücht.

    Hast Du schon mal einen Linux Treiber geschrieben? Ich kann Dir versichern: eine Scheiss-Arbeit, total sensibler Code und das debuggen und testen ist ein irrer Aufwand.

    Aber ganz ehrlich, was machst Du da überhaupt? Das hört sich alles etwas "komisch" an.

    Hab' ich doch oben beschrieben ... ich will erreichen, dass ich für einfache Zugriffe auf die GPIOs keine Lib mehr brauche, damit ich mehrere Programme gleichzeitig laufen lassen kann, ohne z.B. das daemon-Interface von pigpio nutzen zu müssen und ohne dass ich das erste Programm als root starten muss.

    Das SPI, so wie es in der Lib gehandelt wird, funktioniert bei den Komponenten, die ich gerade versuche zum Laufen zu bringen, nicht, sondern ich muss das "zu Fuss" machen, weil das Pegeltiming der Lib-Funktionen nicht passt.

    Meine low-level Zugriffe funktioniern, und nur um Pins HIGH/LOW zu setzen oder auf einen Event zu reagieren, brauche ich die Lib mit ihren Einschränkungen nicht ...

    cu,

    -ds-

  • Hi,

    Interessantes Thema, finde ich. Stellst Du deinen Code zur Verfügung?

    Klar doch ... wie immer ...

    ... /dev/gpiochip0, /dev/gpiochip1 und /dev/gpiochip2.

    Das sind echte char-devices und da klappt das auch mit dem Verriegeln der Pins. ...

    Stichwort ist GPIO UAPI -> https://github.com/raspberrypi/li…pi/linux/gpio.h

    Es gibt auch ein paar Beispiele dazu -> https://github.com/raspberrypi/li…14.y/tools/gpio

    cu,

    -ds-

  • Auf der Ebene, auf der auch sysfs aufsetzt, gibt es keine Interrupts ... das passiert dort über polling ...

    Entweder reden wir gerade aneinander vorbei oder wir verstehen uns nicht.

    SYSFS wird im/vom Kernelspace bereitgestellt. Sprich, Du schreibst ein kleines LKM, das Dir die GPIOs wegkapselt. In diesem LKM holst Du Dir den GPIO über ein gpio_request(...) und bekommst ein Handle. Dann konfigurierst Du es als Eingang (gpio_direction_input(..)) und setzt ggf. die Debouncezeit (gpio_set_debounce(...)) und exportierst das Ding in den /sys/class/gpio/.... (gpio_export(...)). Danach machst Du aus dem GPIO ein Interrupt (gpio_to_irq(...)) und registrierst den IRQ-Handler (request_irq(...)), der dann gefeuert wird, wenn sich am Pin was ändert (rising/falling/low/high).

    Und dass ein LKM (loadable kernel module) einfach ist, halte ich für ein Gerücht.

    Du kannst es für ein Gerücht halten. Das, was ich oben beschrieben habe, ich eine Sache von 1-2 Stunden und ca 20 Zeilen Code. Und hättest Du die Links angeschaut, die ich weiter oben gepostet habe, hättest Du die Lösung schon, denn im zweiten Link macht der Kollege genau das...

    Hast Du schon mal einen Linux Treiber geschrieben? Ich kann Dir versichern: eine Scheiss-Arbeit, total sensibler Code und das debuggen und testen ist ein irrer Aufwand.

    Ich mache im Moment genau das. Ein Linux-Treiber für einen SMSC OS8104 MOST-Transceiver. Der Chip hängt mit vier GPIOs (/INT, /AINT, /RESET und /ERROR) am RPI und die Kommunikation läuft über I²C. Der Chip quasi eine Art Netzwerkkarte, die Senden und Empfangen kann. Im Treiber sind zwei FIFOs drin, einer zum Senden und einer zum Empfangen. Die gesamte Konfiguration des Chips ist im DeviceTree hinterlegt...

    Der Zugriff auf die FIFOs läuft über SYSFS, es sind zwei "Devices", auf die aus dem Userspace zugegriffen wird, eben senden und empfangen. Wenn der Chip was empfangen hat, geht die /INT GPIO auf low und löst damit ein Interrupt aus, der dann über I²C die Daten aus dem Puffer im Chip abholt, sie in den Empfangs-FIFO schiebt und die Tiefe des FIFOs um eins inkrementiert. (Producer). Die Applikation geht dann her, schaut ob im FIFOs was drin ist und wenn ja, holt sie es raus und verarbeitet es.

    Und damit es richtig schön wird, hat der Chip auch noch eine (bzw. zwei) I²S Schnittstellen, die sich als ein Sound Device ausgeben, damit man es zum Beispiel im Kodi als Ausgabedevice auswählen kann (das ist noch nicht drin im Treiber).

    Hab' ich doch oben beschrieben ... ich will erreichen, dass ich für einfache Zugriffe auf die GPIOs keine Lib mehr brauche, damit ich mehrere Programme gleichzeitig laufen lassen kann, ohne z.B. das daemon-Interface von pigpio nutzen zu müssen und ohne dass ich das erste Programm als root starten muss.

    Das SPI, so wie es in der Lib gehandelt wird, funktioniert bei den Komponenten, die ich gerade versuche zum Laufen zu bringen, nicht, sondern ich muss das "zu Fuss" machen, weil das Pegeltiming der Lib-Funktionen nicht passt.

    Meine low-level Zugriffe funktioniern, und nur um Pins HIGH/LOW zu setzen oder auf einen Event zu reagieren, brauche ich die Lib mit ihren Einschränkungen nicht ...

    Ja, das sagtest Du alles schon, aber es beantwortet nicht die Frage. Was sind es für Komponenten? Ist es nun GPIO oder ist es SPI? Versuche doch zu erklären, was Du da machst. Vielleicht ist Dein Lösungsansatz nicht der Richtige...

  • Hi,

    ... das Dir die GPIOs wegkapselt. In diesem LKM holst Du Dir den GPIO über ein gpio_request(...) und bekommst ein Handle. Dann konfigurierst Du es als Eingang (gpio_direction_input(..)) ...

    genau das bietet mir ja diese GPIO UAPI -> Zugriff auf die GPIOs per sysfs als Alternative zu den Libraries z.B. pigpio/bcm2835/wiringPi?

    Was soll ich mir da eine abbrechen ?

    Worum es geht habe ich jetzt mindestens zweimal erklärt ... irgendwann muss es gut sein ...

    cu,

    -ds-

  • Nein, hast Du nicht. "ich will auf low level gpio zugreifen" ist keine Erklärung. Willst keine Libs, holst dir dann aber doch eine Lib. So wie ich es beschrieben habe, greifst du eben "so low wie nur möglich" auf GPIO zu...

    Den Rest hast du natürlich ignoriert.

    Aber mach halt, ich bin raus.

  • "ich will auf low level gpio zugreifen" ...

    weil

    Das SPI, so wie es in der Lib gehandelt wird, funktioniert bei den Komponenten, die ich gerade versuche zum Laufen zu bringen, nicht, sondern ich muss das "zu Fuss" machen, ....

    Meine low-level Zugriffe funktioniern, und nur um Pins HIGH/LOW zu setzen oder auf einen Event zu reagieren, brauche ich die Lib mit ihren Einschränkungen nicht ...

    cu,

    -ds-

  • @Ozymandias

    Hast Du denn vielleicht ein Beispiel, wie man an die Interrupt-Vektoren der Prozessoren kommt ?

    Den bcm2835 echte Prozessor-Interrupts via Device-Tree erzeugen zu lassen, da bin ich schon lange hinterher.

    "WiringPi" pollt ja lediglich irgendwann die Interrupt-Register des bcm2835.

    "pigpio" startet ja wenigstens schon mal einen eigenen Prozess zum Pollen des bcm2835, und reagiert ein wenig schneller.

    Du verweist auf:

    GPIO und Interrupts

    LKM und GPIO

    In "GPIO und Interrupts" steht sehr oft die Zeichenfolge "POLL", was darauf schließen lässt, das keine echten Prozessor-Interrupts generiert werden.

    "LKM und GPIO" gibt gesicherte Delays von 25 µs zur Erkennung einer Zustandesänderung an einem GPIO-Pin an.


    In meinen Routinen habe ich mich so beholfen, dass ich einem Core den Prozesss zum Pollen der GPIOs zuordne, und alle anderen Prozesse auf die anderen Cores verteile. Damit kann ich an den GPOIs Impulse bis über 25 kHz sauber erfassen, das entspricht gesicherten Delays von 20 µs.

    Daraus schließe ich, dass auch "LKM und GPIO" keine echten Prozessor-Interrupts nutzt.

    Mit echten Prozessor-Interrupts müsste man doch Delays in ns erreichen ?

    Edited once, last by Prittzl (October 19, 2018 at 6:21 PM).

  • Hi,

    was darauf schließen lässt, das keine echten Prozessor-Interrupts generiert werden.

    den Verdacht habe ich auch, u.a. weil der Broadcom ja kein µC ist.

    Da ich echte Interrupts bisher nicht gebraucht habe und wohl auch nicht brauchen werde, habe ich diesbezüglich meinem Faulpelz nachgegeben und nicht im Kernel danach herumgewühlt ... ;)

    Prittzl : kennst Du das hier schon -> https://elinux.org/images/9/9b/GP…_and_Makers.pdf ??

    cu,

    -ds-

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!