wiringPi vs. bcm2835 library

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Guten Abend Community,

    nachdem ich mein letztes Problem durch Eure Unterstützung lösen konnte, nun das nächste:

    Wie im letzten Thema von mir beschrieben soll der raspi im Keller befestigt werden, über ein Kabel seine Daten per S0-Protokoll erhalten und diese dann in (s)einer mysql-Datenbank ablegen. Die Auswertung erfolgt dann zu einem späteren Zeitpunkt über das Netz mittels php und voraussichtlich auf einem anderen Rechner.

    Um das Ganze im Trockenlauf zu testen habe ich jetzt ein Programm, das Pin 11 (GPIO 17) als Ausgang schaltet und zyklisch zwischen high und low toggled und ein weiteres, das Pin 12 (PIO 18) als Eingang definiert, einen Interrupt-Handler auf Rising-Edge-Events installiert und in diesem Handler derzeit nur eine Meldung ausgibt.

    Das erste habe ich mit der wiringPi-API geschrieben, für das zweite habe ich die bcm2835-Library verwendet.
    Wenn ich nun das erste Programm starte, kann ich über Webiopi sehen, dass der Pin wunderbar zwischen high und low wechselt.
    Nun nehme ich ein Breadboard und verbinde Pin 11 und Pin 12. Klappt wunderbar - in der Oberfläche sehe ich nun beide Pins blinken.

    Sobald ich aber das zweite Programm aufrufe, friert der Raspi ein und kurz drauf rebootet er (wegen des watchdog-Timers).
    Edit: verwende ich in beiden Programmen nur die wiringPI API dann funktionieren beide Programme anstandslos. Das problem ist also zur Realisierung eher marginal, könnte aber aufgrund des massiven Hängers doch ganz interessant sein, falls man mal einen Mix aus solchen Anwendungen benötigt oder zufällig einsetzt. Vielleicht liegt die Lösung auch in der Mitte - sprich direkt auf die Register zuzugreifen?

    Ich habe schon im web gesucht, aber leider nichts gefunden.
    Gibt es da Unverträglichkeiten zwischen den beiden APIs und ist evtl. jemandem schon mal so was untergekommen?

    Ich werde mal die statische Variante von wiringPI probieren und das Ergebnis dann hier posten.
    In diesem Zusammenhang hätte ich eine Bitte: würdet ihr mir verraten für welche Variante ihr euch entschieden habt und warum?
    Wie gesagt - es geht nicht um ein Script sondern ein C-Programm!


    Vielen dank schon mal und viele Grüße aus dem nächtlichen Rosenheim,
    -ds-

  • Bei beiden Bibliotheken kann man davon ausgehen, daß direkt mit den CPU- bzw. Peripherieregistern gearbeitet wird (angesehen habe ich mir es aber bis jetzt nicht).

    Da muß es crashen, wenn mehrere Programme gleichzeitig zugreifen (auch wenn es verschiedene GPIOs sind: die Initialisierung für z.B. Timer, Speicher, etc. werden dann mehrfach aufgerufen). Selbst wenn Du in beiden Programmen mit derselben Bibliothek arbeiten würdest, gäbe es vermutlich denselben Effekt.
    Die Lib müsste als shared lib für den gleichzeitigen Zugriff mehrerer Prozesse ausgelegt werden, ich bezweifle aber, daß das derzeit schon so realisiert ist. Falls in den Libs eine Lock-/Unlock Funktion vorgesehen ist, wäre das ebenso hilfreich.

    Ich würde mich für eine Lib entscheiden und alle Zugriffe auf GPIOs aus einem Programm machen, das spart vermutlich viel Ärger. ;)

    Gruß, mmi

    P.S.: Vieleicht findet sich ja noch jemand, der bereits einen Blick in den Quellcode geworfen hat. Ich habe meine GPIO Zugriffe nach den Beispielen auf elinux.org selbst realisiert.

  • Ich habe ein ähnliches Problem beobachtet: Ich bin dabei, ein Tachometer für mein Motorrad zu bauen und wollte ein zweites Programm (beides C, auf der Basis von winigPI) zum Simulieren verwenden - die Pins lassen sich schalten, aber das Signal ist sehr instabil... Einer meiner Kollegen meinte, die Software-mässige Anschaltung könnte das Problem sein, aber es kann natürlich gut auch die doppelte Initialisierung sein...


  • Ich habe ein ähnliches Problem beobachtet: Ich bin dabei, ein Tachometer für mein Motorrad zu bauen und wollte ein zweites Programm (beides C, auf der Basis von winigPI) zum Simulieren verwenden - die Pins lassen sich schalten, aber das Signal ist sehr instabil... Einer meiner Kollegen meinte, die Software-mässige Anschaltung könnte das Problem sein, aber es kann natürlich gut auch die doppelte Initialisierung sein...

    Nur so eine Idee: Pullup verwenden?
    ciao,
    -ds-


    Ich nutz die bmc2835-Library von Mike McCauley, aus dem einfachen Grund, daß die SPI-Unterstützung früher verfügbar war und ich dann dabei geblieben bin.

    Moin, moin ...

    ich tendiere gefühlsmäßig ebenfalls eher zur bcm2835-lib.
    Nach einigen Recherchen habe ich vermutlich auch den Grund für den Hänger gefunden. Der schlägt nämlich erst dann zu, wenn tatsächlich ein entsprechendes Signal am GPIO-Pin anliegt.
    Scheinbar gibts da ein Problem bezüglich Kernel-Interrupt-Handling und der bcm2835 Bibliothek.
    Wär jetzt nicht so schlimm - müsste ich halt einen workaround mittels poll und so stricken.

    Die wiringPI hat was - die ist ziemlich übersichtlich und einfach zu benutzen, der Interrupt-Mechanismus funktioniert ebenfalls.
    Die bcm2835 Bibliothek ist imho näher an der Hardware und daher vermutlich flexibler, hat aber wohl - zumindest ein - versteckte(s) Problem(e).

    Ich hasse es einfach über Fallstricke aufs Maul zu fallen, mit denen sich andere schon herumgeärgert haben. Und leider tendiere ich wohl dazu ;> ...

    Aber danke erstmal und mal sehen, was hier noch kommt.
    Ich werd' dann wohl zwischenzeitlich erstmal ein bisserl trial and error praktizieren ...

    greetz,
    -ds-


    Bei beiden Bibliotheken kann man davon ausgehen, daß direkt mit den CPU- bzw. Peripherieregistern gearbeitet wird (angesehen habe ich mir es aber bis jetzt nicht).

    Da muß es crashen, wenn mehrere Programme gleichzeitig zugreifen (auch wenn es verschiedene GPIOs sind: die Initialisierung für z.B. Timer, Speicher, etc. werden dann mehrfach aufgerufen). Selbst wenn Du in beiden Programmen mit derselben Bibliothek arbeiten würdest, gäbe es vermutlich denselben Effekt.
    Die Lib müsste als shared lib für den gleichzeitigen Zugriff mehrerer Prozesse ausgelegt werden, ich bezweifle aber, daß das derzeit schon so realisiert ist. Falls in den Libs eine Lock-/Unlock Funktion vorgesehen ist, wäre das ebenso hilfreich.

    Ich würde mich für eine Lib entscheiden und alle Zugriffe auf GPIOs aus einem Programm machen, das spart vermutlich viel Ärger. ;)

    Gruß, mmi

    P.S.: Vieleicht findet sich ja noch jemand, der bereits einen Blick in den Quellcode geworfen hat. Ich habe meine GPIO Zugriffe nach den Beispielen auf elinux.org selbst realisiert.

    Hi,
    merci für Deine Meinung ...
    Allerdings denke ich, dass die Zugriffe über mmap gemacht werden, und das sollte thread-sicher sein.
    Ich wollte jetzt auch keine großartige Analyse hier lostreten. Das Problem mit dem Hänger habe ich vermutlich eh entdeckt.

    Alles über ein Programm zu managen wird spätestens beim Interrupt-Handlung problematisch.
    Scripte kommen für mich als alteingesessener Assembler- und C-Freak eher nicht in Frage. Lieber schreibe ich dann noch ein KLM zum Handling der GPIO-Pins via ioctl() und /dev/gpio ;)

    Aber das, denke ich, wäre wirklich nur die ultima ratio.

    Also Quellcode buddeln ist eher nicht angesagt, sondern eher Eure Erfahrung(en) mit den verschiendenen APIs.

    Thnx und cul8er,
    -ds-


  • Allerdings denke ich, dass die Zugriffe über mmap gemacht werden, und das sollte thread-sicher sein.

    Yep, meine Zugriffe sind natürlich auch "mmap(ped)". Wie das genau läuft - da habe ich mich bisher noch nicht damit beschäftigt.
    Was passiert, wenn das mehrmals ausgeführt wird:

    Threadsicher erscheint mir das zunächst nicht, aber maßgeblich ist wohl, wie der Kernel damit umgeht ??

  • Yep, meine Zugriffe sind natürlich auch "mmap(ped)". Wie das genau läuft - da habe ich mich bisher noch nicht damit beschäftigt.
    Was passiert, wenn das mehrmals ausgeführt wird:

    Threadsicher erscheint mir das zunächst nicht, aber maßgeblich ist wohl, wie der Kernel damit umgeht ??

    Hi,
    vereinfacht würde ich sagen: jedes Gerät hat reale Adressen, über die man auf es zugreifen kann. Diese sind aber i.d.R. in einer Anwendung nicht verfügbar, sondern darüber liegt der Treiber im Kernel. Will ich nun aber direkt auf z.B. Register zugreifen, dann ich das aus meinen "Userspace" nicht tun, weil nur Zugriffe innerhalb des Speicherbereichs erlaubt sind, den ich vom System zugewiesen bekommen habe (sonst gib's den berühmten memory fault). Um Registerzugriffe direkt aus Anwendungen trotzdem zu ermöglichen erstellt mmap quasi ein Abbild der Register in Deinem Speicherbereich und regelt dann die realen I/O Zugriffe über das OS.
    Mehrfache Aufrufe erzeugen eben mehrere maps und der Zugriff auf diese maps kannst Du über die Flags regeln.
    Ist, meines Wissens, eine komfortable Weiterentwicklung von IPC, das meinerzeit noch überwiegend mit shm() & Co. auskommen musste.

    Näheres dazu findest Du z.B. hier ...

    Grüssle aus dem Bayernland,
    -ds-

  • Danke für Deine Meinung - "mmap" ist soweit auch einleuchtend. Nachdem wir es aber mit der ARM Architektur zu tun haben, bin ich (vielleicht auch ungerechtfertigt) immer recht skeptisch, ob im Kernel die Zugriffe auf die Register (beim RPi evtl. noch spezieller, da Broadcom-spezifisch) bereits für multitasking realisiert und zumindest threadsafe sind.

    Wobei die eleganteste Lösung eine shared lib wäre, die beim Erstaufruf die Initialisierung vornimmt, alle weiteren Zugriffe verschiedener Prozesse wären dann leicht zu regeln. Ich denke da insbesondere an Timer, PWM, etc. mit hohen Frequenzen, die sich direkt den DMA Takt zunutze machen. Da ist eine einmalige Initialisierung unumgänglich, wenn man Multitasking will und die Programmierung läuft ziemlich am Kernel vorbei - es wäre sogar der Stoff für ein RPi-spezifisches Kernelmodul. ;)

    Danke und ebenfalls Gruß aus Bayern, in meinem Fall sogar(!) Franken. :)

  • Moin mmi,


    Code
    Danke für Deine Meinung - "mmap" ist soweit auch einleuchtend. Nachdem wir es aber mit der ARM Architektur zu tun 
    haben, bin ich (vielleicht auch ungerechtfertigt) immer recht skeptisch, ob im Kernel die Zugriffe auf die 
    Register (beim RPi evtl. noch spezieller, da Broadcom-spezifisch) bereits für multitasking realisiert und zumindest 
    threadsafe sind.

    ich für meinen Teil vertraue da den Jungs und/oder Mädels, die den Kernel realisieren. Wenn die keine saubere Arbeit leisten würden, dann denke ich, wäre Krachen und Knirschen des OS an allen Ecken und Enden schon vorprogrammiert.


    Code
    Wobei die eleganteste Lösung eine shared lib wäre, die beim Erstaufruf die Initialisierung vornimmt, alle weiteren 
    Zugriffe verschiedener Prozesse wären dann leicht zu regeln. Ich denke da insbesondere an Timer, PWM, etc. mit hohen
    Frequenzen, die sich direkt den DMA Takt zunutze machen. Da ist eine einmalige Initialisierung unumgänglich, wenn 
    man Multitasking will und die Programmierung läuft ziemlich am Kernel vorbei - es wäre sogar der Stoff für ein 
    RPi-spezifisches Kernelmodul.

    Hmmm .... ich bin mir nicht sicher ob ich weiss, worauf Du hinaus willst, setze aber mal voraus, dass Dir bekannt ist, dass auch über shared libs keine globalen Objekte zur Verfügung gestellt werden können, die prozessübergreifend zugreifbar sind.
    Obwohl ich mit Assembler und C quasi aufgewachsen bin, würde ich mir zudem nicht zutrauen, konkurrierende Zugriffe auf z.B. eine zentrale map so effektiv und fehlerfrei mittels Semaphoren und hastenichtgesehn hinzubekommen wie es die Kernelcrew macht.

    Und solange das mit Bordmitteln funktioniert würde ich einen Teufel tun und mir so was ans Bein zu nageln.
    Mehrere Prozesse gleichzeitig laufen zu haben, die Aufrufe der wiringPI-API verwenden - hab' ich für mich mittlerweile festgestellt - machen bisher noch keinen Trouble. Das einzige, bisher aufgetretene Problem war die Geschichte mit dem Event in der bcm-Lib.
    Aber da die wiringPI-API das ganz elegant über poll umgeht, muss ich mir keinen abbrechen und kann diese API verwenden.


    Code
    Danke und ebenfalls Gruß aus Bayern, in meinem Fall sogar(!) Franken.

    ähh .. wie war das noch? Man muss Gott für alles danken, auch für seine ...


    In diesem Sinne einen schönen Tag noch und cheers,
    -ds-


  • Hmmm .... ich bin mir nicht sicher ob ich weiss, worauf Du hinaus willst, setze aber mal voraus, dass Dir bekannt ist, dass auch über shared libs keine globalen Objekte zur Verfügung gestellt werden können, die prozessübergreifend zugreifbar sind.


    Wir reden vielleicht etwas aneinander vorbei. Die Aussage, daß über shared libs keine globalen Objekte zur Verfügung gestellt werden können, ist mir zu allgemein.

    Ein Beispiel: Eine spezielle timerlib soll hochauflösende timer (möglichst bis zu xxx Mhz) zur Verfügung stellen. Durch Anzapfen des DMA-Takts lassen sich geeignete Interrupts nutzen. Die nötigen Vorbereitungen würden in einer einmaligen Initialisierungsroutine erfolgen. In den späteren Funktionsaufrufen verwaltet und bedient diese lib dann (vielleicht mit entsprechenden callbacks, semaphoren, o.ä.) ihre "Kunden".

    Ich hab's nur mal als Beispiel gedacht, um zu verdeutlichen worauf ich hinaus will. Sowas ist auch nicht so schnell im Kernel zu erwarten, da die Art des DMA-Zugriffs vermutlich speziell für den Broadcom Prozessor ausgelegt werden muß (keine ARM Spezifikation).

    Lassen wir es mal so stehen, ich habe auch nicht vor, zu tief in die Materie einzusteigen, zumal auch die Atmega-Welt hier noch zum Zug kommen soll und die Zeit dann doch sehr begrenzt ist. C ist übrigens auch seit jeher meine erste Wahl - schade, daß die interpretativen Sprachen selbst bei embedded Systemen immer mehr eine Rolle spielen. :(

    Servus, mmi

  • Hi mmi,

    ich finde, Du bist ein putziges Kerlchen und erinnerst mich da an mich selber. Des gfoid ma :shy: !!
    Und ich finde, dass Du interessante Ideen hast, und des gfoid ma erst recht :) !!

    Ich neh'm Dich mal in meine Merkliste auf, denn ich würde mich über diese Thematik gerne mal weiter mit Dir austauschen.
    Was hinzukommt ist die ATMEL Geschichte: ich hab' das seit längerer Zeit aber auf Eis gelegt, weil ich durch einen Umzug einfach ein Platzproblem habe.

    Vielleicht können wir ja hin und wieder mal per pm in Kontakt bleiben, oder hier mal ein spezielles Thema eröffnen. Ich für meinen Teil fand es jedenfalls sehr angenehm mit Dir zu plaudern ... :shy:

    In diesem Sinne viele Grüße vom - heute sonnigen - Alpenrand,
    -ds-

  • So, ich markiere das mal als erledigt.
    D wird wohl nichts mehr kommen.
    Bei der Menge Leute die hier laut Umfrage mit C programmieren hatte ich zwar auf ein wenig mehr kompetente Antworten gehofft - aber ok, seis drum.

    Ich für meinen Teil habe das jedenfalls jetzt so gelöst, dass ich über Makros beide Bibliotheken verwenden kann.
    Derzeit verwende ich die wiringPi und hatte bisher noch keine weiteren Probleme.

    Trotzdem danke an alle,
    ich mach jetzt hier das Licht mal aus ;)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!