Probleme mit CFRunLoopRun()

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Quellcode

    1. void MyTimerFunction(CFRunLoopTimerRef timer,void* info) {
    2. printf("Klingelingeling - der Timer ist da %i\n",counter++);


    Dort ist ein fehler. Richtig muss es lauten:

    Quellcode

    1. void MyTimerFunction(CFRunLoopTimerRef timer,void* info) {
    2. printf("Klingelingeling - Ich bin der Eiermann ... Meine Eier sind der Güteklasse %i\n",counter++);
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Du kannst RunLoopSources und RunLoopTimern eine Priorität mitgeben. Dummerweise macht die IOWarrior-Lib die RunLoopSource für Dich, sodass Du das selbst machen müsstest, um die Priorität zu setzten. Und ebenfalls dummerweise ignoriert die CFRunLoop die Priorität bei Timern. Innerhalb einer RunLoop verdrängt normalerweise keine Source eine andere - first come, first serve. Das sollte eigentlich für alle normalen Situationen ok sein. Wenn Du in Deinem Programm Konflikte zwischen den Quellen der RunLoop hast, hast Du wahrscheinlich ein grundlegenderes Problem in Deiner Design. Entweder blockiert eine Deiner Callout-Handler die RunLoop zu lange oder Du hast irgendwo die Handler nicht vernünftig gegeneinander entkoppelt. Wenn Du für längere Zeit in einer Funktion bleiben musst, ist es wahrscheinlich erwägenswert, diese Sachen in einen eigenen Thread zu packen und in den RunLoop-Callouts nur das IO-Handling zu machen - über die Kommunikation zwischen den Threads kannst Du dann auch Prioritäten selbst implementieren. Aber eigentlich soll es dafür keine Notwendigkeit geben.

    Tom, Du hast natürlich Recht - sorry für den Bug im Code. Ganz korrekt muss es heißen:

    Quellcode

    1. void MyTimerFunction(CFRunLoopTimerRef timer,void* info) {
    2. printf("Palim palim! Ich hätte gerne %i Flaschen Pommes.\n",counter++);
    3. }
    Multigrad - 360°-Produktfotografie für den Mac
  • nabend,

    danke erstmal für die antwort.
    ich hab mir alles genau angesehen und durch ziemlich viel fummelei und noch mehr printf's herausgefunden,
    daß tatsächlich mehrere interrupts durch die callback hochkommen, obwohl nur kurz eine taste gedrückt ist,
    das war vor meiner timer-implementierung nicht so.
    verstehe ich wirklich nicht, wo da noch ein interrupt herkommt.
    ich mach erstmal essen..

    cu

    // timer-callout:
    printf(" \n");

    // irq-callback
    printf("nanu, sie sagen ja gar nichts..??\n");

    // timer-callout:
    printf("ja, die klingel ist kaputt\n");

    //leider ist ein dialog schwer zu implementieren *g*
    kiu. ivory with tiger - working since 2001
  • Original von kiu
    mehrere interrupts durch die callback hochkommen, obwohl nur kurz eine taste gedrückt ist,
    das war vor meiner timer-implementierung nicht so.
    verstehe ich wirklich nicht, wo da noch ein interrupt herkommt.

    Und Du bist sicher, dass das nicht evtl. vom Prellen der Taste kommt? Vielleicht sind davor auch mehrere Interrupts angekommen, aber Deine alte Implementation hat nicht beide empfangen oder so... wer weiß?

    Ich würde mich ohnehin nicht auf die Zahl der Interrupts verlassen, sondern Interrupts nur zum Anlass nehmen, die Inputs auszulesen und anhand der gelesenen und gespeicherter Daten zu entscheiden, ob tatsächlich etwas passiert ist - in diesem Fall wäre das wahrscheinlich: input geht von 0 auf 1 und war davor schon einige ms auf 0 (oder so ähnlich). Ich kenne so einige HIDs, die recht eigenwillig Interrupts feuern und etwas Nachbearbeitung der Daten erfordern. Nach meinen Erfahrungen sind bei USB nur Bulk und Control Pipes wirklich verlässlich, Interrupt und Isochronous Pipes sind mit Vorsicht zu genießen - YMMV.
    Multigrad - 360°-Produktfotografie für den Mac
  • Mattik wird absolut Recht haben. Irq sind (nur) "Aufmerksamkeitsbitten". Gerade in deinem Fall, in dem wir es mit Mechanik und Induktionen zu tun haben, geht ein flankengesteuerter Irq gerne mehrfach heraus.

    Einfachste Möglichkeit ist es, in deiner Irq-Routine den Zeitstempel zu merken. Beim nächsten Mal verlangst du einfach eine gewisse Differenz. Die errechnet sich aus der maximalen Frequenz, die du erwarten darfst. Mach den Irq-Ausgang so schnell wie möglich.

    Du solltest das Software-Monoflop (das ist es im Wesentlichen) retriggerbar machen, dies bedeutet, dass du auch den Zeitstempel _abgelehnter_, weil geprellter Irq speicherst. Das führt zwar dazu, dass du ein einfaches "stehen" hast, wenn das Dingens so lange prellt, bis das nächste "echte" Signal kommt. In diesem Falle ist aber ohnehin jede Information pure Raterei.

    Bedenke übrigens noch, dass möglicherweise, wenn es ganz übel kommt, der Irq *vor* der Stabilität der ausgelesenen Information liegt. Das sollte zwar nicht passieren, passiert aber. Aus diesem Grunde hängt man sich, wenn man es sauber haben will, auf das letzte Prellen, nicht auf das erste, wie oben beschrieben. Du dürftest aber langsam genug sein.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Mattik wird absolut Recht haben. Irq sind (nur) "Aufmerksamkeitsbitten". Gerade in deinem Fall, in dem wir es mit Mechanik und Induktionen zu tun haben, geht ein flankengesteuerter Irq gerne mehrfach heraus.


    Das seh ich etwas anders. Erstmal ist es bei USB nicht ein irq wie man ihn von der Hardware her kennt. Du hast bei USB eine Interrupt Pipe die du lesen (pollen) musst. Üblicherweise hast du ein Polling Interval von 10ms. Das Ding heisst nur deshalb Interrupt weil du in der Software nicht genau weisst ob Daten kommen oder nicht.
    Bei HID übernimmt OS X das polling für dich und löst halt den Interrupt Callback aus wenn was aus der Pipe kommt. Da nun A) viele Geräte für die verwarzte Windows USB Implemtation entwickelt wurden und B) OS X auch so einige Probleme mit HID Interrupts hat kann es vorkommen dass du mehrere Interrupts empfängst. Mit einem USB Analyzer kann man dann aber feststellen dass von Gerät nur einer kommt.

    Einfachste Möglichkeit ist es, in deiner Irq-Routine den Zeitstempel zu merken. Beim nächsten Mal verlangst du einfach eine gewisse Differenz. Die errechnet sich aus der maximalen Frequenz, die du erwarten darfst. Mach den Irq-Ausgang so schnell wie möglich.

    Du solltest das Software-Monoflop (das ist es im Wesentlichen) retriggerbar machen, dies bedeutet, dass du auch den Zeitstempel _abgelehnter_, weil geprellter Irq speicherst. Das führt zwar dazu, dass du ein einfaches "stehen" hast, wenn das Dingens so lange prellt, bis das nächste "echte" Signal kommt. In diesem Falle ist aber ohnehin jede Information pure Raterei.

    Bei der Interrupt Pipe kann man das Polling Intervall auslesen. Damit sind schon die Infos für die maximale Frequenz vorhanden.
    Eine andere Alternative wäre mit einem Timer selbst den Report auszulesen. Dann kann man notfalls per Software entprellen.
    Oder entprellte Tasten :)
    Bedenke übrigens noch, dass möglicherweise, wenn es ganz übel kommt, der Irq *vor* der Stabilität der ausgelesenen Information liegt. Das sollte zwar nicht passieren, passiert aber. Aus diesem Grunde hängt man sich, wenn man es sauber haben will, auf das letzte Prellen, nicht auf das erste, wie oben beschrieben. Du dürftest aber langsam genug sein.

    Bei USB nicht richtig. Siehe oben. Du bekommst die Daten im Interrupt Callback geliefert. Sie werden im Callback nicht abgeholt.

    Chris
    Man macht einfach solange irgendwelche Dinge, bis man tot ist.
    Und dann bekommen die anderen Kuchen.
  • Ich meinte das freilich unabhängig von der konkreten Implementierung (USB HID). Dennoch:

    Du weißt ja nicht, was auf der anderen Seite der Pipe geschieht.

    Die Frequenz des Pollings erlaubt keinen Rückschluss auf die Frequenz des Motors und schon gar nicht auf die Frequenz des Prellens. Das entorellen muss dann gegebenenfalls softwaremäßig erfolgen. Davon sprach ich ja gerade!?

    Ob die Daten im CB bereits einen gültigen Zustand haben, hängt nicht davon, ab, ob sie geschickt oder abgeholt werden. Egal wo sie wie wann herkommen, werden sie irgendwann an "der unmittelbaren Quelle" ausgelesen. Zu diesem Zeitpunkt hofft man, dass sie gültig sind. Dass muss aber gerade bei unsauberen Signalen nicht der Fall sein, da der Latch möglicherweise andere "Vorstellungen von 1 und 0" (also Pegeln) hat, als die Irq-Auslösung, die ja an einer Flanke hängt.

    Haben wir hier ein Prellen, so ist es durchaus möglich, dass du ein "vorlaufendes" Prellen hast. Holst du exakt mit diesem Signal den Zustand, so ist er nicht gültig. Du wirst freilich dann ein späteres Prellen haben, in dessen Verlauf die Daten stabil sind. Daher setzt man sich üblicherweise auf den letzten Preller oder zumindest einen späteren. HW-mäßig geht das sehr einfach, sw-mäßig leider nicht.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • also erstmal ein paar fackten von mir:

    1.es ist tatsächlich so wie mattik sagte, daß sich die callback und die callout nicht beharken.
    hab den timer-add auskomentiert und das problem der verrückten interrupts bestand noch.

    2. ist es so, daß ich wirklich sauberste irq's empfangen habe. ein callback-aufruf pro flanken-änderung. siehe anhang.

    3. ist mir was komisches aufgefallen. meines verständnisses her:
    -machen usb client und host handshake,
    -host pollt client so oft wie der client mitgeteilt hat, daß er gepollt werden muß,
    -die api des os pollt den host, bei windows ist der pollingwert=0 und kann nicht geändert werden, bei osx ist das natürlich anders, darum haben wir ja auch setinterruptcallback und winuser nicht. (ätsche-bätsche),
    bei änderung kommt dann die callback hoch.

    wenn ich eine taste gedrückt hielt, kam der interrupt für die zustandsänderung sofort und dann im abstand von ca. 0,75 secunden immer eine ausgabe meines zustandes, also die callback kam alle 0,75s hoch.

    wenn ich jetzt eine taste gedrückt halte fliegen in bruchteilen von sekunden die callbacks, als ob der host-controller häufiger gepollt wird.. ist aber sehr unwahrscheinlich. ich seh mir heute nochmal den ablauf des programms an und versuch heut mal noch paar sachen auszukommentieren und das alte verhalten meines programmes wiederzufinden.
    kiu. ivory with tiger - working since 2001
  • Hmmm, Dein Log verstehe ich - ehrlich gesagt - nicht ganz. Den Part mit dem Pollen auch nicht: Dass der Host den Client in regelmäßigen Abständen pollt kann ich noch nachvollziehen. Aber dass die API dann den Host pollt? Nee - wenn ich das richtig verstanden habe, wird ein Interrupt, wenn er beim Host ankommt, vom IOKit in den User Space hochgepumpt, wo er dann in Deinem Callback ankommt. Also push statt poll. 100 und mehr Interrupts pro Sekunde würden mich nicht wirklich überraschen - das ist bei HIDs normal. Dann fängt halt der Spaß an, den eingehenden Datenwust durchzufiltern...
    Multigrad - 360°-Produktfotografie für den Mac
  • mh , also leute ich muß mich da nochmal kurz einlesen, in osx, hid und usb-interrupt pipes.
    ich möchte schon wissen, warum wer wem was zu leide tut :)
    wer eine gute seite kennt, die daß bildlich darstellt, (deusch wird die ja nicht sein?)
    wäre ich dankbar.

    das log war leider das mit dem zwischen-buffer, tut mir leid, das kann mann nur verstehen,
    wenn mann weiß, daß buffer von der callback hochgereicht wird und port diesen wert übernimmt, fals ein unterschied zwischen port und buffer besteht.
    hab ich jetzt rausgenommen.

    es läuft!! hab gestern nacht noch im code gesucht und die beste stelle für ein verzögerungsglied gefunden:
    unmittelbar vor runloopstop in der callback. usleep(50000); und das wars.
    es muß doch prell-werte gegeben haben, die mir vorher nicht aufgefallen sind.
    jetzt wird die taste ausgelesen, gewartet und erst dann aus der callback in eine while-loop in die main. hier wird das control-menu usw abgearbeitet und der tastenwert verarbeitet.
    das ist der punkt, wann die prellwerte mein programm gestört haben müssen.
    vor wiedereintritt in cfrunlooprun, bei der abarbeitung des menus.
    ist zwar alles nicht sehr effizient, aber ich logge nicht aus, nur weil ich einmal die taste für zurück betätige, sonder komme wirklich in das menu darüber.
    macht sich bei der präsi besser, wenn mann nicht immer das programm neu starten muß :)

    ich hab nur noch zwei klitze kleine problemchen, ansonsten siehts richtig gut aus.
    ich werd jetzt mit brachialer gewalt an meiner doku weiterarbeiten.
    mann sieht sich aber.

    danke danke und bis bald
    kiu. ivory with tiger - working since 2001