Hallo, mit Mehr-Kern Prozessoren wird das Programmieren doch wieder etwas anders, wie ich zuletzt gemerkt hab. Wie löst man elegant unaufwändig folgendes Problem?
Am einem ARM-board ist per spi/i2c ein Gerät angeschlossen. Eine kleine Bibliothek device.so übersetzt befehle wie "Lese register x", "Schreibe Register y mit z" und führt dann ioctl Befehle aus. Es gibt auch ein dump() Kommando, dass alle Register liest und ausgibt.
Aus dem Anwendungsprogramm wird dann das angeschlossene Gerät mit den device_read(x), device_write(y,z) programmiert.
Jetzt ist mir aufgefallen, dass das dump() welches zuerst aufgerufen wird, die eigentlich erst später im Quellcode geschriebenen Register liefert !
Erwartet hatte ich die reset/default Werte – weil ja dump (nach poweron) zuerst gecoded ist. Selbst ein sleep(5); dazwischen hat daran nichts geändert, erst sleep(10); was ja irrsinnige Zeiten sind!!!
So richtig hab ich das nicht verstanden, aber bei mir ist Alarm. Kann denn das wirklich sein? 10 sekunden? Klar durch die vielen printf ist das dump länger beschäftigt.
Aber selbst wenn der dump auf einem anderen Kern läuft als der Rest, kann das wirklich passieren ? Und wie kann ich das verhindern? Mitunter kommt es beim Schreiben der Register auf eine Reihenfolge an – das ist letztlich was mich umtreibt.
Selbst wenn ich als erstes die device.so Befehle threadsave machen und mit locks sichere – im Beispiel wird das erste Kommando in der Anwendung nach den darauffolgenden ausgeführt ?!?
Mit neugierigen Grüßen Arno
Am Dienstag, 15. August 2017 20:14 CEST, "Arno Steffens" epsi@gmx.de schrieb:
Hallo, mit Mehr-Kern Prozessoren wird das Programmieren doch wieder etwas anders, wie ich zuletzt gemerkt hab. Wie löst man elegant unaufwändig folgendes Problem?
Am einem ARM-board ist per spi/i2c ein Gerät angeschlossen. Eine kleine Bibliothek device.so übersetzt befehle wie "Lese register x", "Schreibe Register y mit z" und führt dann ioctl Befehle aus. Es gibt auch ein dump() Kommando, dass alle Register liest und ausgibt.
Das verstehe ich jetzt nicht ganz - der dump-Befehl liest die Register des angeschlossenen Geräts aus, oder?
Aus dem Anwendungsprogramm wird dann das angeschlossene Gerät mit den device_read(x), device_write(y,z) programmiert.
Jetzt ist mir aufgefallen, dass das dump() welches zuerst aufgerufen wird, die eigentlich erst später im Quellcode geschriebenen Register liefert !
Im Quellcode von was? Deinem Programm auf dem ARM oder dem Gerät? Auf dem Multicore ARM sollten Dich die Register besser nicht interessieren. Ist Deine Anwendung überhaupt Multithreaded?
Erwartet hatte ich die reset/default Werte – weil ja dump (nach poweron) zuerst gecoded ist. Selbst ein sleep(5); dazwischen hat daran nichts geändert, erst sleep(10); was ja irrsinnige Zeiten sind!!!
So richtig hab ich das nicht verstanden, aber bei mir ist Alarm. Kann denn das wirklich sein? 10 sekunden? Klar durch die vielen printf ist das dump länger beschäftigt.
Aber selbst wenn der dump auf einem anderen Kern läuft als der Rest, kann das wirklich passieren ? Und wie kann ich das verhindern? Mitunter kommt es beim Schreiben der Register auf eine Reihenfolge an – das ist letztlich was mich umtreibt.
Das kannst Du Deinem GCC schon beibringen - bin gerade an ganz anderen Baustellen, kann Dir aber, so Du Dich einarbeiten möchtest "Multicore-Software" von Gleim/Schüle aus dem DPunkt-Verlag empfehlen.
Gruss RalfD
Hallo, mit Mehr-Kern Prozessoren wird das Programmieren doch wieder etwas anders, wie ich zuletzt gemerkt hab. Wie löst man elegant unaufwändig folgendes Problem?
Am einem ARM-board ist per spi/i2c ein Gerät angeschlossen. Eine kleine Bibliothek device.so übersetzt befehle wie "Lese register x", "Schreibe Register y mit z" und führt dann ioctl Befehle aus. Es gibt auch ein dump() Kommando, dass alle Register liest und ausgibt.
Das verstehe ich jetzt nicht ganz - der dump-Befehl liest die Register des angeschlossenen Geräts aus, oder?
Ja genau. Es sind praktisch lese-Funktionen in einer loop, aber immer noch in der Bibliothek.
Aus dem Anwendungsprogramm wird dann das angeschlossene Gerät mit den device_read(x), device_write(y,z) programmiert.
Jetzt ist mir aufgefallen, dass das dump() welches zuerst aufgerufen wird, die eigentlich erst später im Quellcode geschriebenen Register liefert !
Im Quellcode von was? Deinem Programm auf dem ARM oder dem Gerät?
Quelltext, compiliert für ARM und dort augeführt. dump(); write(a,b); write(c,d); write(e,f);
ALlerdings zeigt mir dump() den Inhalt b,d,f an, und nicht den Inhalt vor der Initialisierung.
Auf dem Multicore ARM sollten Dich die Register besser nicht interessieren. Ist Deine Anwendung überhaupt Multithreaded?
Im Moment noch nicht.
Erwartet hatte ich die reset/default Werte – weil ja dump (nach poweron) zuerst gecoded ist. Selbst ein sleep(5); dazwischen hat daran nichts geändert, erst sleep(10); was ja irrsinnige Zeiten sind!!!
So richtig hab ich das nicht verstanden, aber bei mir ist Alarm. Kann denn das wirklich sein? 10 sekunden? Klar durch die vielen printf ist das dump länger beschäftigt.
Aber selbst wenn der dump auf einem anderen Kern läuft als der Rest, kann das wirklich passieren ? Und wie kann ich das verhindern? Mitunter kommt es beim Schreiben der Register auf eine Reihenfolge an – das ist letztlich was mich umtreibt.
Das kannst Du Deinem GCC schon beibringen - bin gerade an ganz anderen Baustellen, kann Dir aber, so Du Dich einarbeiten möchtest "Multicore-Software" von Gleim/Schüle aus dem DPunkt-Verlag empfehlen.
Ok, schau ich mal. Danke Ralf!
Gruss RalfD
On 08/15/2017 09:39 PM, Arno Steffens wrote:
Hallo, mit Mehr-Kern Prozessoren wird das Programmieren doch wieder etwas anders, wie ich zuletzt gemerkt hab. Wie löst man elegant unaufwändig folgendes Problem?
Am einem ARM-board ist per spi/i2c ein Gerät angeschlossen. Eine kleine Bibliothek device.so übersetzt befehle wie "Lese register x", "Schreibe Register y mit z" und führt dann ioctl Befehle aus. Es gibt auch ein dump() Kommando, dass alle Register liest und ausgibt.
Das verstehe ich jetzt nicht ganz - der dump-Befehl liest die Register des angeschlossenen Geräts aus, oder?
Ja genau. Es sind praktisch lese-Funktionen in einer loop, aber immer noch in der Bibliothek.
Aus dem Anwendungsprogramm wird dann das angeschlossene Gerät mit den device_read(x), device_write(y,z) programmiert.
Jetzt ist mir aufgefallen, dass das dump() welches zuerst aufgerufen wird, die eigentlich erst später im Quellcode geschriebenen Register liefert !
Im Quellcode von was? Deinem Programm auf dem ARM oder dem Gerät?
Quelltext, compiliert für ARM und dort augeführt. dump(); write(a,b); write(c,d); write(e,f);
Wenn Dein Programm nicht extra Zeugs macht, nutzt das nicht aus, dass Deine Maschine mehr als eine CPU hat. Was passiert denn beim ersten Mal, nachdem Du b, d und f in g, h und i geändert hast? Zeig mal Dein Programm.
ALlerdings zeigt mir dump() den Inhalt b,d,f an, und nicht den Inhalt vor der Initialisierung.
Auf dem Multicore ARM sollten Dich die Register besser nicht interessieren. Ist Deine Anwendung überhaupt Multithreaded?
Im Moment noch nicht.
Wenn Dein Programm hauptsächlich dafür da ist, um mit dem spi bzw. i2c-Chip zu kommunizieren, lohnt sich Parallelisierung nicht.
Liebe Grüße Uwe
Gesendet: Dienstag, 15. August 2017 um 21:48 Uhr Von: "Uwe Kleine-König" uwe@kleine-koenig.org An: flug@lug-freiburg.de Betreff: Re: [Flug] Multicore Programmierung
On 08/15/2017 09:39 PM, Arno Steffens wrote:
Hallo, mit Mehr-Kern Prozessoren wird das Programmieren doch wieder etwas anders, wie ich zuletzt gemerkt hab. Wie löst man elegant unaufwändig folgendes Problem?
Am einem ARM-board ist per spi/i2c ein Gerät angeschlossen. Eine kleine Bibliothek device.so übersetzt befehle wie "Lese register x", "Schreibe Register y mit z" und führt dann ioctl Befehle aus. Es gibt auch ein dump() Kommando, dass alle Register liest und ausgibt.
Das verstehe ich jetzt nicht ganz - der dump-Befehl liest die Register des angeschlossenen Geräts aus, oder?
Ja genau. Es sind praktisch lese-Funktionen in einer loop, aber immer noch in der Bibliothek.
Aus dem Anwendungsprogramm wird dann das angeschlossene Gerät mit den device_read(x), device_write(y,z) programmiert.
Jetzt ist mir aufgefallen, dass das dump() welches zuerst aufgerufen wird, die eigentlich erst später im Quellcode geschriebenen Register liefert !
Im Quellcode von was? Deinem Programm auf dem ARM oder dem Gerät?
Quelltext, compiliert für ARM und dort augeführt. dump(); write(a,b); write(c,d); write(e,f);
Wenn Dein Programm nicht extra Zeugs macht, nutzt das nicht aus, dass Deine Maschine mehr als eine CPU hat. Was passiert denn beim ersten Mal, nachdem Du b, d und f in g, h und i geändert hast? Zeig mal Dein Programm.
Na ich weiß nicht. Werden denn nicht auch ohne explizietes Threading beide Cores genutzt?
ALlerdings zeigt mir dump() den Inhalt b,d,f an, und nicht den Inhalt vor der Initialisierung.
Auf dem Multicore ARM sollten Dich die Register besser nicht interessieren. Ist Deine Anwendung überhaupt Multithreaded?
Im Moment noch nicht.
Wenn Dein Programm hauptsächlich dafür da ist, um mit dem spi bzw. i2c-Chip zu kommunizieren, lohnt sich Parallelisierung nicht.
Klar weil das viel langsamer ist. Ich will es ja auch gar nicht parallelisieren. Im Gegenteil hab ich die Befürchtung das da was durcheinander gerät in der Reihenfolge.
@Ralf: GDB kann ich probieren, auf den Bus gucken ist schon schwieriger - hab kein Oszi daheim. Ja, der angeschlossene SPI Chip hat eine im Datenblatt beschriebenes default-Setup. Daher weiß ich was drin sein sollte. Gibts das tracing auch für SPI? Ich muss mir das die nächsten Tage einfach noch mal in Ruhe anschauen. Nicht das ich irgendwas anderes übersehen hab...
Schönen Abend Arno
Am Mittwoch, 16. August 2017 21:58 CEST, "Arno Steffens" epsi@gmx.de schrieb:
@Ralf: GDB kann ich probieren, auf den Bus gucken ist schon schwieriger - hab kein Oszi daheim.
Hmm, nein Du musst ja _nicht_ auf's Kabel schauen - siehe meine letzte Mail. Du kannst Dir vom Kernel die Messages ausgeben lassen:
echo 1 >/sys/kernel/debug/tracing/events/i2c/enable
Schaltet das Debugging an. Du kannst auch einzelne SPI-Adapter selektieren:
echo adapter_nr==1 >/sys/kernel/debug/tracing/events/i2c/filter
Ab dann kannst Du die Messages auslesen:
cat /sys/kernel/debug/tracing/trace
Da sollten dann so Dinge wie i2c_write und i2c_read stehen. Mehr solltest Du eigentlich nicht brauchen. Du siehst was auf den Bus geht und was zurückkommt und siehst in welcher Reihenfolge das geschieht.
Ja, der angeschlossene SPI Chip hat eine im Datenblatt beschriebenes default-Setup. Daher weiß ich was drin sein sollte.
Ah, Fake Facts! Du glaubst zu wissen was drinn steht ;-)
Gruss RalfD
On Wed, Aug 16, 2017 at 09:58:33PM +0200, Arno Steffens wrote:
Gesendet: Dienstag, 15. August 2017 um 21:48 Uhr Von: "Uwe Kleine-König" uwe@kleine-koenig.org An: flug@lug-freiburg.de Betreff: Re: [Flug] Multicore Programmierung
On 08/15/2017 09:39 PM, Arno Steffens wrote:
Hallo, mit Mehr-Kern Prozessoren wird das Programmieren doch wieder etwas anders, wie ich zuletzt gemerkt hab. Wie löst man elegant unaufwändig folgendes Problem?
Am einem ARM-board ist per spi/i2c ein Gerät angeschlossen. Eine kleine Bibliothek device.so übersetzt befehle wie "Lese register x", "Schreibe Register y mit z" und führt dann ioctl Befehle aus. Es gibt auch ein dump() Kommando, dass alle Register liest und ausgibt.
Das verstehe ich jetzt nicht ganz - der dump-Befehl liest die Register des angeschlossenen Geräts aus, oder?
Ja genau. Es sind praktisch lese-Funktionen in einer loop, aber immer noch in der Bibliothek.
Aus dem Anwendungsprogramm wird dann das angeschlossene Gerät mit den device_read(x), device_write(y,z) programmiert.
Jetzt ist mir aufgefallen, dass das dump() welches zuerst aufgerufen wird, die eigentlich erst später im Quellcode geschriebenen Register liefert !
Im Quellcode von was? Deinem Programm auf dem ARM oder dem Gerät?
Quelltext, compiliert für ARM und dort augeführt. dump(); write(a,b); write(c,d); write(e,f);
Wenn Dein Programm nicht extra Zeugs macht, nutzt das nicht aus, dass Deine Maschine mehr als eine CPU hat. Was passiert denn beim ersten Mal, nachdem Du b, d und f in g, h und i geändert hast? Zeig mal Dein Programm.
Na ich weiß nicht. Werden denn nicht auch ohne explizietes Threading beide Cores genutzt?
Ja, aber transparent für Dein Programm. D.h. für Dich sieht es so aus, als laufe alles auf einem Core.
ALlerdings zeigt mir dump() den Inhalt b,d,f an, und nicht den Inhalt vor der Initialisierung.
Auf dem Multicore ARM sollten Dich die Register besser nicht interessieren. Ist Deine Anwendung überhaupt Multithreaded?
Im Moment noch nicht.
Wenn Dein Programm hauptsächlich dafür da ist, um mit dem spi bzw. i2c-Chip zu kommunizieren, lohnt sich Parallelisierung nicht.
Klar weil das viel langsamer ist. Ich will es ja auch gar nicht parallelisieren. Im Gegenteil hab ich die Befürchtung das da was durcheinander gerät in der Reihenfolge.
Übrigens ist "Mein Programm ist mit Multitasking schneller" ein verbreiteter Irrglauben. Ja, manche Sachen werden wirklich schneller. Aber viele von den man glaubt, dass sie schneller werden, werden entweder nicht schneller, oder sind schlecht programmiert, dass richtig ohne Multitasking noch schneller wäre.
@Ralf: GDB kann ich probieren, auf den Bus gucken ist schon schwieriger - hab kein Oszi daheim. Ja, der angeschlossene SPI Chip hat eine im Datenblatt beschriebenes default-Setup. Daher weiß ich was drin sein sollte.
Hier stimme ich Ralf zu. Deine Annahme fußt auf Annahmen:
- Das Datenblatt ist richtig - Der Chip hat seit dem letzten Testlauf *wirklich* ein Reset gesehen.
Die Praxis zeigt, dass man auf beide Annahmen besser nichts verwettet.
Gibts das tracing auch für SPI?
if test -d /sys/kernel/debug/tracing/events/spi; then echo "ja" fi
Ich muss mir das die nächsten Tage einfach noch mal in Ruhe anschauen.
Ja bitte.
Liebe Grüße Uwe
Gesendet: Donnerstag, 17. August 2017 um 11:28 Uhr Von: "Uwe Kleine-König" uwe@kleine-koenig.org An: "Arno Steffens" epsi@gmx.de Cc: flug@lug-freiburg.de Betreff: Re: [Flug] Multicore Programmierung
On Wed, Aug 16, 2017 at 09:58:33PM +0200, Arno Steffens wrote:
Gesendet: Dienstag, 15. August 2017 um 21:48 Uhr Von: "Uwe Kleine-König" uwe@kleine-koenig.org An: flug@lug-freiburg.de Betreff: Re: [Flug] Multicore Programmierung
On 08/15/2017 09:39 PM, Arno Steffens wrote:
Hallo, mit Mehr-Kern Prozessoren wird das Programmieren doch wieder etwas anders, wie ich zuletzt gemerkt hab. Wie löst man elegant unaufwändig folgendes Problem?
Am einem ARM-board ist per spi/i2c ein Gerät angeschlossen. Eine kleine Bibliothek device.so übersetzt befehle wie "Lese register x", "Schreibe Register y mit z" und führt dann ioctl Befehle aus. Es gibt auch ein dump() Kommando, dass alle Register liest und ausgibt.
Das verstehe ich jetzt nicht ganz - der dump-Befehl liest die Register des angeschlossenen Geräts aus, oder?
Ja genau. Es sind praktisch lese-Funktionen in einer loop, aber immer noch in der Bibliothek.
Aus dem Anwendungsprogramm wird dann das angeschlossene Gerät mit den device_read(x), device_write(y,z) programmiert.
Jetzt ist mir aufgefallen, dass das dump() welches zuerst aufgerufen wird, die eigentlich erst später im Quellcode geschriebenen Register liefert !
Im Quellcode von was? Deinem Programm auf dem ARM oder dem Gerät?
Quelltext, compiliert für ARM und dort augeführt. dump(); write(a,b); write(c,d); write(e,f);
Wenn Dein Programm nicht extra Zeugs macht, nutzt das nicht aus, dass Deine Maschine mehr als eine CPU hat. Was passiert denn beim ersten Mal, nachdem Du b, d und f in g, h und i geändert hast? Zeig mal Dein Programm.
Na ich weiß nicht. Werden denn nicht auch ohne explizietes Threading beide Cores genutzt?
Ja, aber transparent für Dein Programm. D.h. für Dich sieht es so aus, als laufe alles auf einem Core.
ALlerdings zeigt mir dump() den Inhalt b,d,f an, und nicht den Inhalt vor der Initialisierung.
Auf dem Multicore ARM sollten Dich die Register besser nicht interessieren. Ist Deine Anwendung überhaupt Multithreaded?
Im Moment noch nicht.
Wenn Dein Programm hauptsächlich dafür da ist, um mit dem spi bzw. i2c-Chip zu kommunizieren, lohnt sich Parallelisierung nicht.
Klar weil das viel langsamer ist. Ich will es ja auch gar nicht parallelisieren. Im Gegenteil hab ich die Befürchtung das da was durcheinander gerät in der Reihenfolge.
Übrigens ist "Mein Programm ist mit Multitasking schneller" ein verbreiteter Irrglauben. Ja, manche Sachen werden wirklich schneller. Aber viele von den man glaubt, dass sie schneller werden, werden entweder nicht schneller, oder sind schlecht programmiert, dass richtig ohne Multitasking noch schneller wäre.
@Ralf: GDB kann ich probieren, auf den Bus gucken ist schon schwieriger - hab kein Oszi daheim. Ja, der angeschlossene SPI Chip hat eine im Datenblatt beschriebenes default-Setup. Daher weiß ich was drin sein sollte.
Hier stimme ich Ralf zu. Deine Annahme fußt auf Annahmen:
- Das Datenblatt ist richtig
- Der Chip hat seit dem letzten Testlauf *wirklich* ein Reset gesehen.
Die Praxis zeigt, dass man auf beide Annahmen besser nichts verwettet.
Ich traue es mich nicht zu sagen: Alles meine Schuld :( Ich hab (wenn man so ab und an mal was macht und wieder vergisst, was man vor Wochen getan hat), diese Init-Routine via rc.d schon mal aufgerufen ... also kein Wunder das die Register schon initialisiert waren. Das klärt für mich noch nicht alles, aber wenn etwas zu komisch ist, dann liegt es doch oft daran, das man was übersehen hat. Sorry!
Trotzdem hab ich wieder was gelernt. Auch ums debguggen hab ich mich mal wieder bemüht. GDB mit Eclipse.... Jaja, geht so. Eine Core dump remote auswerten muss hab ich noch nicht hinbekommen. Das muss ich noch recherchieren. Der zeigt mir da nur irgenwas in einer tiefen Ebene Linux-lib/Kernel an, was nicht hilfreich ist. Und bt gingt auch nicht. Na ich bleib dran und übe weiter. Bedauerlich dass es so wenig (anfängerfreundliche, gern deutsche) Literatur dazu gibt. Und leider kann man wohl mmapped memory nicht im GDB beobachten. Komisch, denn das Programm greift korrekt auf den Speicher zu ....
Gibts das tracing auch für SPI?
if test -d /sys/kernel/debug/tracing/events/spi; then echo "ja" fi
Ich muss mir das die nächsten Tage einfach noch mal in Ruhe anschauen.
Ja bitte.
Du siehst, ein wenig Abstand und noch mal draufgucken ... es hilft! Viele Grüße Arno
Liebe Grüße Uwe _______________________________________________ Freiburger Linux User Group Mail an die Liste: flug@lug-freiburg.de Mailingliste verwalten (u.a. abbestellen): https://lug-freiburg.de/mailman/listinfo/flug
Am Dienstag, 15. August 2017 21:39 CEST, "Arno Steffens" epsi@gmx.de schrieb:
Im Quellcode von was? Deinem Programm auf dem ARM oder dem Gerät?
Quelltext, compiliert für ARM und dort augeführt. dump(); write(a,b); write(c,d); write(e,f);
ALlerdings zeigt mir dump() den Inhalt b,d,f an, und nicht den Inhalt vor der Initialisierung.
Da wäre natürlich meine erste Frage: woher kennst Du den Inhalt der Register vor der Initialisierung? Die nächste Frage wäre: wie kommuniziert die Library mit dem Device? Vieleicht asynchron? Das sollte aber dokumentiert sein. Gegebenenfalls solltest Du, nur um sicher zu gehen so was machen:
#include <stdio.h> ... dump(); fflush(stdout);
Auf dem Multicore ARM sollten Dich die Register besser nicht interessieren. Ist Deine Anwendung überhaupt Multithreaded?
Im Moment noch nicht.
Dann hast Du da auch keine sync-Probleme.
Erwartet hatte ich die reset/default Werte – weil ja dump (nach poweron) zuerst gecoded ist.
D.h. es gibt definierte Initialwerte?
Selbst ein sleep(5); dazwischen hat daran nichts geändert, erst sleep(10); was ja irrsinnige Zeiten sind!!!
Hmm - das klingt in der Tat seltsam. Spätestens jetzt würde ich den gdb zücken und mir mal ansehen was da so abgeht. Hast Du Dir schon angesehen was über den I2C Bus läuft? (dumme Frage, ich weiss)
# echo 1 > /sys/kernel/debug/tracing/events/i2c/enable # tail -f /sys/kernel/debug/tracing/trace
Gruss RalfD