Hallo zusammen, ich verwende bei meinem ATmega328 mehrere externe und interne Interruptquellen (timer, SPI, pinchange). Gibt es eine Möglichkeit zu erkennen, ob manche Interruptanforderungen verloren gehen, weil vielleicht die CPU nicht schnell genug alle Interruptanforderungen abarbeiten kann? Natürlich könnte man eine theoretische worst-case Analyse aufgrund der Ausführungszeiten und vorraussichtlichen Häufigkeit der Interrupts machen, aber vielleicht geht es ja auch einfacher?
Dennis Heynlein schrieb: > Beitrag "Interrupts beim ATmega" Hallo Dennis, ich finde in obigem Beitrag leider nur allgemeines zum Thema Interrupts. Ich habe auch den Interrupt Abschnitt im AVR-GCC Tutorial gelsen. Dort steht leider auch nichts dazu, wie man sein Programm auf mögliche Interruptverluste überprüfen kann. Hat noch jemand eine Idee?
Kommt ein interrupt während eines interrupts, wird dieser nach der vorherigen interrupt-routine ausgeführt. Es geht also kein INT verloren
Martin schrieb: > Kommt ein interrupt während eines interrupts, wird dieser nach der > vorherigen interrupt-routine ausgeführt. Es geht also kein INT verloren Außer der "Interrupt im Interrupt" kommt noch ein zweites mal, dann geht die erste Anforderung verloren. Wenn das eintritt hat man aber schon irgendwo anders ein Problem in seinem ganzen Konzept.
Martin schrieb: > Kommt ein interrupt während eines interrupts, wird dieser nach der > vorherigen interrupt-routine ausgeführt. Es geht also kein INT verloren Hallo Martin, das ist mir bekannt. Mir geht es um den Fall, dass die CPU bereits einen Interrupt bearbeitet und dann ein weiterer Interrupt auftritt und kurze Zeit später noch einer gleichen Typs. Damit ginge dann der erste wartende Interrupt verloren. Mir geht es darum im Dauertest abzusichern dass es praktisch nicht vorkommt. Eine theoretisch worst-case-Betrachtung ersetzt es natürlich nicht, würde mir aber zusätzliche Sicherheit geben.
test schrieb: > Außer der "Interrupt im Interrupt" kommt noch ein zweites mal, dann geht > die erste Anforderung verloren. Wenn das eintritt hat man aber schon > irgendwo anders ein Problem in seinem ganzen Konzept. Ich habe wie beschrieben viele unterschiedliche Interruptquellen bei denen nicht genau bekannt ist, wie häufig sie auslösen. Da das ganze nicht wirklich kritisch ist würde es mir reichen, wenn nur selten mal ein Interrupt verloren geht. Das würde ich gerne praktisch absichern. Mir ist klar, dass der Königsweg darin besteht alle Intteruptroutinen so kurz wie möglich zu gestalten und mit Flags zu arbeiten. Mir geht es darum zu erkennen, ob / oder wie häufig praktisch Interrupts verworfen werden mußten wegen CPU Überlastung durch zu viele Interruptanforderungen pro Zeit.
Tja. Egal was du machst, gibt es immer eine Grenze, ab der der µC nicht mehr mitkommt. Dein Problem steckt aber hier > Ich habe wie beschrieben viele unterschiedliche > Interruptquellen bei denen nicht genau bekannt ist, > wie häufig sie auslösen. solange du da nichts drüber weißt, ist alles andere sinnlose Überlegung. > Mir geht es darum zu erkennen, ob / oder wie häufig > praktisch Interrupts verworfen werden mußten Im schlimmsten Fall brauchst du dazu Hardware-Unterstützung. Im einfachsten Fall kommt das ISR-Jobflag System zum Zug, bei dem du in der ISR vereinbaren kannst: Tritt der Interrupt auf, und ist das Jobflag schon (noch immer) gesetzt, dann wird es kritisch.
:
Bearbeitet durch User
Falk Brunner schrieb: > http://www.mikrocontroller.net/articles/Multitaski... Hallo Falk, das ist ein sehr interessanter Link. Dort wird aber erklärt, wie man die Dauer des Hauptprogrammes über Interrupts im Millisekundentakt mittels Interrupt absichert und nicht ob sich Interrupts auftürmen.
Ein voller Eimer Wasser läuft über und das Wasser läuft dann weg. Da der µC ohnehin immer ein paar Takte braucht, wird dir, wenn die Interruptquelle schneller ist als der µC, sicher ein gleicher Interrupt verloren gehen.
Artur schrieb: > Mir geht es um den Fall, dass die CPU > bereits einen Interrupt bearbeitet und dann ein weiterer Interrupt > auftritt und kurze Zeit später noch einer gleichen Typs. Damit ginge > dann der erste wartende Interrupt verloren. Es gibt im Prozessor keine automatische Möglichkeit, diesen Fall zu erkennen. > Mir geht es darum im > Dauertest abzusichern dass es praktisch nicht vorkommt. Eine theoretisch > worst-case-Betrachtung ersetzt es natürlich nicht, würde mir aber > zusätzliche Sicherheit geben. Du musst sicherstellen, daß deine ISRs kürzer sind, als die kürzeste vorkommende Interrupt-Wiederholzeit. Kennst du letztere nicht, kannst du nichts garantieren. Zu der Analyse gehört aber such die Überlegung, was genau passiert, wenn du mal eine Interruptanforderung nicht bedienen kannst. Oliver
Artur schrieb: > Ich habe wie beschrieben viele unterschiedliche Interruptquellen bei > denen nicht genau bekannt ist, wie häufig sie auslösen. Bei einigen Interrupts ist es bekannt, z.B. Timer, UART. Bei anderen ist es egal, z.B. I2C, ADC, EEPROM, Master-SPI. Erzähl dochmal genauer, welcher Interrupt bei Dir kritisch sein könnte.
Karl Heinz schrieb: > Im einfachsten Fall kommt das ISR-Jobflag System zum Zug, bei dem du in > der ISR vereinbaren kannst: Tritt der Interrupt auf, und ist das Jobflag > schon (noch immer) gesetzt, dann wird es kritisch. Hallo Karl Heiz, wäre super wenn das so ginge. Meinst du mit Jobflag das Interrupt Flag? So wie ich das Datenblatt verstanden habe wird doch das Interruptflag, z.B. bei Pegelwechsel an einem Pin, auf 1 gesetzt (hier im EIFR – External Interrupt Flag Register), dann sofort der Interrupt angesprungen, dabei automatisch die 1 wieder gelöscht und dann der Code des Interrupts ausgeführt. Währenddessen kann ein weiterer Pegelwechsel gleich nochmal das Flag von 0 auf 1 setzten. Das Flag wird solange nicht 0, bis der Interrupt bearbeitet wird. Wenn vor der Bearbeitung dieses wartenden Interrupts noch ein Pegelwechsel auftritt, wird das Interruptflag nochmals auf 1 gesetzt. Da es aber bereits auf 1 steht geht die Information verloren, dass jetzt eigentlich zweimal der Interruptcode ausgeführt werden müsste. Der Interruptverlust bleibt doch leider unbemerkt, oder?
@ Artur (Gast) >> http://www.mikrocontroller.net/articles/Multitaski... >Hallo Falk, das ist ein sehr interessanter Link. Dort wird aber erklärt, >wie man die Dauer des Hauptprogrammes über Interrupts im >Millisekundentakt mittels Interrupt absichert und nicht ob sich >Interrupts auftürmen. Bitte nochmals lesen und NACHDENKEN!
@ Artur (Gast) >Wenn vor der Bearbeitung dieses wartenden Interrupts noch ein >Pegelwechsel auftritt, wird das Interruptflag nochmals auf 1 gesetzt. Da >es aber bereits auf 1 steht geht die Information verloren, dass jetzt >eigentlich zweimal der Interruptcode ausgeführt werden müsste. >Der Interruptverlust bleibt doch leider unbemerkt, oder? Ja. Das kann der AVR leider nicht erkennen, das könnte man nur in Hardware machen.
Artur schrieb: > Wenn vor der Bearbeitung dieses wartenden Interrupts noch ein > Pegelwechsel auftritt, wird das Interruptflag nochmals auf 1 gesetzt. Da > es aber bereits auf 1 steht geht die Information verloren, dass jetzt > eigentlich zweimal der Interruptcode ausgeführt werden müsste. Die eigentliche Frage ist, muß er das wirklich? Oder ist es nur ein Prellen oder ein Störimpuls. Das kann man allgemein nicht beantworten. Dazu muß man schon konkret wissen, was den Interrupt bewirkt und wie er ausgewertet werden soll. Man muß sich also erstmal Gedanken machen, welche maximale Nutzsignal-Interruptrate erwarte ich von der Quelle.
Peter Dannegger schrieb: >>> http://www.mikrocontroller.net/articles/Multitaski... >>Hallo Falk, das ist ein sehr interessanter Link. Dort wird aber erklärt, >>wie man die Dauer des Hauptprogrammes über Interrupts im >>Millisekundentakt mittels Interrupt absichert und nicht ob sich >>Interrupts auftürmen. > Bitte nochmals lesen und NACHDENKEN! Hallo Falk, ich bin nochmal durchgegangen und ich weiß wirklich nicht wo du da das Ei des Kolumbus versteckt siehst. In der Datei ACF? In diesem Abschnitt? Diese Überprüfung kann an zwei Stellen durchgeführt werden. * Am Ende der Hauptschleife nach Abarbeitung aller Ausgaben. Wenn hier die Variable flag_1ms schon wieder aktiv ist, dauerte die Abarbeitung länger als 1ms. Wenn man ein sehr strenges Timing sicherstellen möchte, ist das ein Fehler, der erkannt und signalisiert werden kann. * In der ISR. Wenn hier die Variable immer noch aktiv ist, wurde sie von der Hauptschleife noch nicht erkannt und zurück gesetzt. Das ist definitiv ein Fehler, denn jetzt würde ohne Fehlererkennung ein Timerdurchlauf von der Hauptschleife verschluckt werden. Diese Prüfung ist etwas nachgiebiger, weil zwischenzeitlich ein Durchlauf der Hauptschleife mehr als 1ms, jedoch nicht länger als 2ms dauern darf. Siehe auch den Abschnitt Interrupt#Zeitverhalten_eines_Timerinterrupts. Sinnvollerweise nutzt man nur eine der beiden Prüfungen, nicht beide zusammen.
Artur schrieb: > Karl Heinz schrieb: >> Im einfachsten Fall kommt das ISR-Jobflag System zum Zug, bei dem du in >> der ISR vereinbaren kannst: Tritt der Interrupt auf, und ist das Jobflag >> schon (noch immer) gesetzt, dann wird es kritisch. > > Hallo Karl Heiz, wäre super wenn das so ginge. Meinst du mit Jobflag das > Interrupt Flag? Nein. Ich meine die Technik des Jobflags
1 | uint8_t Job; |
2 | |
3 | ISR( ... ) |
4 | {
|
5 | Job = 1; |
6 | }
|
7 | |
8 | int main |
9 | {
|
10 | |
11 | ....
|
12 | while( 1 ) |
13 | {
|
14 | |
15 | if( Job ) |
16 | ...
|
Vielleicht mal etwas deutlicherer Klartext: Solange du nicht weißt, in welchen Zeitabständen deine Interruptanforderungen kommen, und was es bedeutet, wenn du mal eine verpasst, brauchst du nirgends weiterzulesen. Dann hast du schlicht keine Chance, das Problem zu lösen. Geht nicht. Fertig. Wenn du aber die kürzeste Zeit zwischen den Interruptanforderungen kennst, kannst du versuchen, deine ISR's noch kürzer zu gestalten. Das geht nicht ohne Zyklen zählen, oder ähnliche Anaylsen. Wenn du innerhalb der vorgegeben Zeit in der ISR alles abarbeiten kannst, prima. Wenn nicht, so kannst du versuchen, ein eigenes Flag-System zu bauen, das z.B. die Interruptanforderung selber und die relevanten Daten dazu in eine queue schreibt. Die eigentlich Abarbeitung übernimmt dann das Hauptprogramm. Wenn deine ISR damit kurz genug wird, verlirst du keine Interrupts, aber die Abarbeitung bzw. Reaktion darauf kann verspätet erfolgen (eben erst dann, wenn das Hauptprogramm Zeit findet, den Request abzuarbeiten). Das funktioniert natürlich nur, wenn im Mittel das Haupprogramm schnell genug ist, alle Request abzuarbeite, ansonsten läuft deine Queue irgendwann über. Wenn du es nicht schaffst, das Flag/Queue-System innerhalb der zur Verfügung stehehden ISR-Zeit abzuarbeiten, dann bist du wieder am Ausgangspunkt: Zu langsam... Oliver
Karl Heinz schrieb: > Ich meine die Technik des Jobflags > > uint8_t Job; > > ISR( ... ) > { > Job = 1; > } > > int main > { > > .... > while( 1 ) > { > > if( Job ) > ... Wenn ich das richtig verstanden habe hilft diese Technik nur sicherzustellen, dass der Teil unter "if( Job )" nicht mehr Zeit benötigt als der Interrupt als Takt vorgibt. Ich möchte aber sicherstellen, dass meine 3 unterschiedlichen Timer die ich verwende, mehrere Pinchange Interrupts und die SPI Kommunikation sehr zügig funktioniert und daher im Interrupt abgearbeitet werden soll. Die Main-Loop ist sehr voll mit Berechnungen, die eine sehr zeitnahe Ausführung auf Flag-Basis nicht ratsam machen.
Hallo Oliver, vielen Dank für deine umfangreiche Antwort. Da sind viele gute Ideen dabei. Ich sehe, es gibt aber anscheinend keinen einfachen Mechanismus der mir sagen könnte ob das Interruptsystem überläuft. Es sei denn Falk kann mich noch darauf stoßen.
Um zu verhindern, dass dir keine interrupts verloren gehen, musst du die ISR so klein wie möglich halten. Bedeutet, serielle kommunikation in einen puffer zwischen speichern und diesen in der main-Schleife auswerter (solange der puffer voll ist). Timer sind kritisch, da diese nicht später im Hauptprogramm ausgeführt werden dürfen, aber evtl kannst du im Hauptprogramm etwas die Daten vorbereiten und sie dann anschliesend nur im der ISR ausgeben. Pin change interrupts kann man auch in einen puffer schreiben und später im Hauptprogramm auswerten. Ein Rinspeicher beschreiben ist in unter 20 Takten möglich, wenn deine Auswertung eines interrupts länger als 20 takte benötigt, die daten in einen puffer schreiben und in der Hauptschleife auswerten. Ganz verhindern kann man das "verschlucken" von interrupts nicht, aber in dem man die ISR so kurz wie möglich gestaltet kann man einiges erreichen. Probleme können aber Taster machen, die prellen. Diese müsste man entweder in Hardware entprellen oder bei auftreten eines interrupts eine systemzeit mit abspeichern damit man ein prellen ausschliesen kann.
@ Artur (Gast) >Wenn ich das richtig verstanden habe hilft diese Technik nur >sicherzustellen, dass der Teil unter "if( Job )" nicht mehr Zeit >benötigt als der Interrupt als Takt vorgibt. Ja. >Ich möchte aber sicherstellen, dass meine 3 unterschiedlichen Timer die >ich verwende, mehrere Pinchange Interrupts und die SPI Kommunikation >sehr zügig funktioniert und daher im Interrupt abgearbeitet werden soll. Kann man machen. >Die Main-Loop ist sehr voll mit Berechnungen, die eine sehr zeitnahe >Ausführung auf Flag-Basis nicht ratsam machen. Alles eine Frage der Programmierung. Wenn man es will, kann man lange Berechnungen auf mehrere Schritte aufteilen und mit mehreren Aufrufen erledigen. Siehe Multitasking. Aber was hast du denn konkret zu tun? So eine allgemeine Beschreibeung nützt wenig. Nenn mal ein paar konkrete Zahlen.
@ Artur (Gast) >dabei. Ich sehe, es gibt aber anscheinend keinen einfachen Mechanismus >der mir sagen könnte ob das Interruptsystem überläuft. Auf unterstet Ebene, nein. Schrieb ich bereits. Beitrag "Re: AVR - Erkennen ob Interrupts verloren gehen" Aber man kann es mal so sehen. Interrupts können nun durch andere, gerade laufende Interrupts blockiert und damit verschluckt werden, weil der AVR von hause aus keine Prioritäten für die Interrupts hat. Hält man aber alle ISRs kurz, kann das nicht passieren, auch nicht im schlimmsten, definierten Fall (den man ja berechnen/simulieren kann). Klar, wenn man maximal mit 10kHz rechnet, duch was auch immer ein Pin aber mit 100kHz toggelt, dann war's das. Aber sowas ist vermeidbar.
Wenn du feststellen willst, ob du Interrupts verlierst, musst du das Ueberlaufmanagement einfach selbst machen. Am Anfang der Interruptroutine einen Zaehler hochsetzen. Ist er groesser als 1, laeuft die Interruptroutine schon und du brichst ab. Ist er 1, gibst du die Interrupts wieder frei und machst die eigentliche Interruptbearbeitung. Am Ende der Bearbeitung sperrst du die Interrupts wieder und dekrementierst den Zaehler wieder. Alles, was groesser als Null ist, sind verlorene Interrupts. Die kannst du zum Beispiel auf eine andere Variable aufaddieren und in der Hauptschleife ausgeben. Nicht vergessen, den Zaehler wieder auf Null zu setzen, sonst war das die letzte Interruptausfuehrung. Alternativ kann man das Aufaddieren auch am Anfang der Interruptroutine machen, dann entgehen einem Deadlocks in der Interruptverarbeitung nicht.
cybmorg schrieb: > Wenn du feststellen willst, ob du Interrupts verlierst, musst du > das > Ueberlaufmanagement einfach selbst machen. Am Anfang der > Interruptroutine einen Zaehler hochsetzen. Ist er groesser als 1, laeuft > die Interruptroutine schon und du brichst ab. Ist er 1, gibst du die > Interrupts wieder frei und machst die eigentliche Interruptbearbeitung. > Am Ende der Bearbeitung sperrst du die Interrupts wieder und > dekrementierst den Zaehler wieder. Alles, was groesser als Null ist, > sind verlorene Interrupts. Die kannst du zum Beispiel auf eine andere > Variable aufaddieren und in der Hauptschleife ausgeben. Nicht vergessen, > den Zaehler wieder auf Null zu setzen, sonst war das die letzte > Interruptausfuehrung. Alternativ kann man das Aufaddieren auch am Anfang > der Interruptroutine machen, dann entgehen einem Deadlocks in der > Interruptverarbeitung nicht. Hallo cyvmorg, das hört sich nach einer guten Lösung an. Sie ist nicht einfach, sie erzeugt overhead, ab sie scheint machbar. Hast du sowas schon praktisch getestet?
Artur schrieb: > cybmorg schrieb: >> Wenn du feststellen willst, ob du Interrupts verlierst, musst du >> das >> Ueberlaufmanagement einfach selbst machen. Am Anfang der >> Interruptroutine einen Zaehler hochsetzen. Ist er groesser als 1, laeuft >> die Interruptroutine schon und du brichst ab. Ist er 1, gibst du die >> Interrupts wieder frei und machst die eigentliche Interruptbearbeitung. >> Am Ende der Bearbeitung sperrst du die Interrupts wieder und >> dekrementierst den Zaehler wieder. Alles, was groesser als Null ist, >> sind verlorene Interrupts. Die kannst du zum Beispiel auf eine andere >> Variable aufaddieren und in der Hauptschleife ausgeben. Nicht vergessen, >> den Zaehler wieder auf Null zu setzen, sonst war das die letzte >> Interruptausfuehrung. Alternativ kann man das Aufaddieren auch am Anfang >> der Interruptroutine machen, dann entgehen einem Deadlocks in der >> Interruptverarbeitung nicht. > > Hallo cyvmorg, > das hört sich nach einer guten Lösung an. Sie ist nicht einfach, sie > erzeugt overhead, ab sie scheint machbar. Hast du sowas schon praktisch > getestet? Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts gesperrt. D.h. die ISR wird kein zweites Mal erreicht. mfg.
Thomas Eckmann schrieb: > Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts > gesperrt. Na ja. Man kann sie freigeben. Hier im Forum wird zwar meistens davon abgeraten, solange man aber weiß was man tut, kann man das natürlich machen.
Thomas Eckmann schrieb: > Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts > gesperrt. D.h. die ISR wird kein zweites Mal erreicht. Die kann man sofort nach Eintritt in die ISR wieder einschalten mit sei(). Oder den Interrupt gleich richtig ausschalten, wie es hier geschrieben steht: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Interrupts_mit_avr-gcc #include <avr/interrupt.h> ISR(XXX,ISR_NOBLOCK) /* veraltet: INTERRUPT(SIG_OVERFLOW0) */ { /* Interrupt-Code */ }
Karl Heinz schrieb: > Thomas Eckmann schrieb: > >> Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts >> gesperrt. > > Na ja. > Man kann sie freigeben. > Hier im Forum wird zwar meistens davon abgeraten, solange man aber weiß > was man tut, kann man das natürlich machen. Leider wissen die meisten das aber nicht. mfg.
Thomas Eckmann schrieb: > Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts > gesperrt. D.h. die ISR wird kein zweites Mal erreicht. Im Text habe ich explizit erklaert, wann die Interrupts freizugeben und zu sperren sind. Wie man das ueberlesen kann, ist mir unverstaendlich.
Artur schrieb: > Hallo cyvmorg, > das hört sich nach einer guten Lösung an. Sie ist nicht einfach, sie > erzeugt overhead, ab sie scheint machbar. Hast du sowas schon praktisch > getestet? Das ist eigentlich recht einfach, ich arbeite oft mit mehreren Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten. Der Ueberlaufzaehler ist eine einfache Erweiterung davon. Overhead erzeugt die Loesung natuerlich schon - aber wenn du so nah am Limit deines Kontrollers bist, dass es dafuer nicht mehr reicht, hast du wahrscheinlich noch andere Probleme.
cybmorg schrieb: > Im Text habe ich explizit erklaert, wann die Interrupts freizugeben und > zu sperren sind. Wie man das ueberlesen kann, ist mir unverstaendlich. >> Am Ende der Bearbeitung sperrst du die Interrupts wieder Wie das funktionieren soll, ist mir unverständlich. mfg.
cybmorg schrieb: > Das ist eigentlich recht einfach, ich arbeite oft mit mehreren > Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung > verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten. Wer will das wissen? Ein Atmega 328 hat keine verschiedenen Prioritätsebenen. Im Ausgangspost hat der TO explizit erklaert, daß er einen Atmega 328 benutzt. Wie man das ueberlesen kann, ist mir unverstaendlich. mfg.
Thomas Eckmann schrieb: > Ein Atmega 328 hat keine verschiedenen Prioritätsebenen. Natuerlich hat er das nicht. Sonst muesste ich das ja nicht haendisch implementieren. > Im Ausgangspost hat der TO explizit erklaert, daß er einen Atmega 328 > benutzt. Wie man das ueberlesen kann, ist mir unverstaendlich. Das liebe ich so hier am Forum: Wenn man in's Klo gegriffen hat, ist Zugeben und Schnabel halten die letzte Alternative - lieber aus vollen Rohren feuern, vielleicht merkt es keiner! > Wie das funktionieren soll, ist mir unverständlich. Meinst du den ganzen Ablauf, oder nur das Sperren am Ende der Bearbeitung? Letzteres macht ein einfaches cli(). Oder ist unklar, warum? Wenn ich den Interruptzaehler anfasse, muss das gegen nebenlaeufige Zugriffe gesichert passieren, also werden die Interrupts vorher wieder gesperrt. Die Freigabe, dass ueberhaupt wieder Interrupts bearbeitet werden, geschieht danach "automatisch", wie ueblich.
cybmorg schrieb: > Das ist eigentlich recht einfach, ich arbeite oft mit mehreren > Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung > verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten. > Der Ueberlaufzaehler ist eine einfache Erweiterung davon. Hallo cybmorg, schicke Sache. Hast du da mal etwas (Pseudo-)code zur Veranschaulichung? Mich würde insbesonders der Code am Ende jeder ISR interessieren, der dann explizit (?) die aufgelaufenen Interrupts niedrigerer Priorität abarbeitet ... LG, Sebastian
cybmorg schrieb: > Wenn ich den Interruptzaehler anfasse, muss das gegen > nebenlaeufige Zugriffe gesichert passieren, also werden die Interrupts > vorher wieder gesperrt. Die Freigabe, dass ueberhaupt wieder Interrupts > bearbeitet werden, geschieht danach "automatisch", wie ueblich. Und wenn in der Zeit zweimal der gleiche Interrupt auftritt, hast du mit dem Gehampel gar nichts gewonnen. Völliger Humbug das Ganze. mfg.
:
Bearbeitet durch User
Thomas Eckmann schrieb: > Und wenn in der Zeit zweimal der gleiche Interrupt auftritt, hast du mit > dem Gehampel gar nichts gewonnen. Völliger Humbug das Ganze. Wenn gerade ein Interrupt bearbeitet wird, könnte ein schnell folgender Interrupt, der ja nur kurz den Zähler erhöht und sich dann selbst beendet, im ersten Interrupt direkt angehängt werden. Schneller käme ja ein mit Flag zwischengepeicherter Interrupt auch nicht zum Zug.
Mein Gott, hier wird schon wieder ewig über vermeintliche Lösungen diskutiert, ohne des reale Problem WIRKLICH zu kennen! Beitrag "Re: AVR - Erkennen ob Interrupts verloren gehen"
Artur schrieb: > Wenn gerade ein Interrupt bearbeitet wird, könnte ein schnell folgender > Interrupt, der ja nur kurz den Zähler erhöht und sich dann selbst > beendet, im ersten Interrupt direkt angehängt werden. Schneller käme ja > ein mit Flag zwischengepeicherter Interrupt auch nicht zum Zug. Den Interrupt gibt es aber nicht umsonst. Der kostet jede Menge Zeit, die ja angeblich nicht vorhanden ist. Sonst könnte man sich das ja alles grundsätzlich sparen. Das Zählergehampel mit Wiederfreigabe kann aber auch nicht zu 100% garantieren, daß kein Interrupt verloren geht. Maximal ein Interrupt kann im Flagregister gespeichert werden. Mehr gibt die AVR-Hardware einfach nicht her. Tritt allerdings während einer ISR derselbe Interrupt nochmals auf, kann man diesen auch durch Abfrage des Interrupt-Flags vor Verlassen der ISR bearbeiten. Wenn es denn unbedingt sein muß. Man kann aber auch vernünftig programmieren lernen und sich diesen Mist komplett ersparen. mfg.
Thomas Eckmann schrieb: > Das Zählergehampel mit Wiederfreigabe kann aber > auch nicht zu 100% garantieren, daß kein Interrupt verloren geht. Es gibt Ingenieure, die Probleme loesen und Ingenieure, die endlos darueber referieren koennen, was an Loesungsansaetzen anderer schlecht ist und wieso das Problem sowieso nicht loesbar ist. Rate mal, welche von Beiden keiner braucht.
cybmorg schrieb: > Thomas Eckmann schrieb: >> Das Zählergehampel mit Wiederfreigabe kann aber >> auch nicht zu 100% garantieren, daß kein Interrupt verloren geht. > > Es gibt Ingenieure, die Probleme loesen und Ingenieure, die endlos > darueber referieren koennen, was an Loesungsansaetzen anderer schlecht > ist und wieso das Problem sowieso nicht loesbar ist. Rate mal, welche > von Beiden keiner braucht. Mehr als so ein blödes Gelaber fällt dir jetzt nicht ein? In der Digitaltechnik gibt es zwei Möglichkeiten. Entweder es funktioniert zu 100% oder es funktioniert nicht. Dazwischen ist gar nichts. mfg.
Thomas Eckmann schrieb: > In der Digitaltechnik gibt es zwei Möglichkeiten. Entweder es > funktioniert zu 100% oder es funktioniert nicht. Dazwischen ist gar > nichts. Da du von nichts, was du baust/programmierst die Funktion zu 100% garantieren kannst, reduziert sich bei deiner Sichtweise jeglicher Output deiner Taetigkeit auf: Gar nichts. Wie du das deinem Arbeitgeber vermittelst, dass er dich fuer gar nichts bezahlen soll, wuerde mich interessieren.
cybmorg schrieb: > Thomas Eckmann schrieb: >> In der Digitaltechnik gibt es zwei Möglichkeiten. Entweder es >> funktioniert zu 100% oder es funktioniert nicht. Dazwischen ist gar >> nichts. > > Da du von nichts, was du baust/programmierst die Funktion zu 100% > garantieren kannst, reduziert sich bei deiner Sichtweise jeglicher > Output deiner Taetigkeit auf: Gar nichts. Wie du das deinem Arbeitgeber > vermittelst, dass er dich fuer gar nichts bezahlen soll, wuerde mich > interessieren. Das muss ich sogar garantieren, du Witzfigur. mfg.
cybmorg schrieb: > Das ist eigentlich recht einfach, ich arbeite oft mit mehreren > Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung > verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten. Wozu brauchst Du im AVR mehrere Interruptebenen? Ein Interrupt ist so kurz wie möglich zu halten, und das heisst, wirklich wenige Takte. Großartige Software-Division oder Speicher umkopieren oder PID-Regler berechnen macht man einfach nicht im Interrupt. Zum Beispiel Uart: Byte einlesen, in Ringpuffer schreiben, Ringbuffer Pointer inc, Flag setzen, dass Daten vorhanden, raus. Braucht vielleicht 20 Takte. Die Auswertung, was dann mit den Daten passiert, machst Du im Hauptprogramm.
> cybmorg schrieb: > Mehr als so ein blödes Gelaber fällt dir jetzt nicht ein? > Thomas Eckmann schrieb: > Das muss ich sogar garantieren, du Witzfigur. Kleiner Kampf? Das ist ein Spiel mit kleinen ferngelenkten Modellpanzern über's Internet. Ist umsonst. Ich wär' dabei... Beitrag "Panzer über Internet fernsteuern für Jedermann"
@ Timm Thaler (timm-thaler) >Wozu brauchst Du im AVR mehrere Interruptebenen? Andere Controller haben die und können sie zweckdienlich nutzen. Der AVR hat keine, man kann und muss damit leben. > Ein Interrupt ist so >kurz wie möglich zu halten, Ja. > und das heisst, wirklich wenige Takte. Nein. So kurz wie NÖTIG! Das kann je nach Anwendung auch mal ne Millisekunde oder mehr sein. Manchmal auch nur 10us. >Großartige Software-Division oder Speicher umkopieren oder PID-Regler >berechnen macht man einfach nicht im Interrupt. Siehe oben. >Zum Beispiel Uart: Byte einlesen, in Ringpuffer schreiben, Ringbuffer >Pointer inc, Flag setzen, dass Daten vorhanden, raus. Braucht vielleicht >20 Takte. In Hardcore Assembler bestenfalls, in C geht unter 50 Takten kaum was. Aber selbst damit lässt sich ganz gut leben. Aber solange der OP nicht mal mit seinen realen Aufgaben und Anforderungen rausrückt, ist das alles sinnlos. Fakt ist, der AVR ist schon ein fixes Kerlchen, der auch ohne Interruptlevel verdammt viel verdammt schnell machen kann. Ohne Interrupts zu verschlucken.
Falk Brunner schrieb: > Das kann je nach Anwendung auch mal ne > Millisekunde oder mehr sein. Ich hab ja schon viel mit AVRs verbrochen, für das ich mich heute schäme. Aber Interrupts, die ne Millisekunde, also um die 10.000 Takte dauern, sind mir noch nicht untergekommen. Nicht dass ich nicht glaube, dass es sowas gibt, aber ich kann mir nich vorstellen, wo man sowas braucht. Hast Du ein paar Beispiele? Das interessiert mich ernsthaft, man lernt ja nie aus. Falk Brunner schrieb: > In Hardcore Assembler bestenfalls, in C geht unter 50 Takten kaum was. Wenn ich C programmieren wöllte, nähme ich nen PC. ;-) Im AVR wird natürlich ASM programmiert.
Artur schrieb: >> cybmorg schrieb: >> Mehr als so ein blödes Gelaber fällt dir jetzt nicht ein? > >> Thomas Eckmann schrieb: >> Das muss ich sogar garantieren, du Witzfigur. Das ist jetzt aber eine falsche Quellenangabe. Beide Zitate sind von Thomas. Zur Vollständigkeit fehlt aber noch: Thomas Eckmann schrieb: > Man kann aber auch vernünftig programmieren lernen und sich diesen Mist > komplett ersparen. cybmorg hat hier einen interessanten Beitrag geleistet, der für bestimmte Situationen für mich sicherlich hilfreich sein wird. Thanks for that! Ob diese Lösung für den OP geeignet ist sei dahingestellt. Bei entsprechendem Vorwissen kann der OP das sicher auch selbst entscheiden. Auf Risiken, zum Beispiel die Möglichkeit von Starvation, die nötige Synchronisation des Zugriffs auf gemeinsame Resourcen auch in der ISR, könnte man hinweisen. Ich sehe aber keinen triftigen Grund angesichts eines fachlichen Beitrags hier persönlich beleidigend zu werden. LG, Sebastian
An alle ein herzliches Dankeschön! Hallo Falk, ich möchte das Programm zumindest vorerst nicht an die Öffentlichkeit geben, entschuldige bitte. Es läuft ja auch schon recht stabil, lediglich vereinzelt gibt es Abstürze, die vielleicht ein Interruptüberlauf sein könnten, oder was ganz anderes. Heute habe ich wieder einen Bug gefunden, ein vergessenes Atomic. Wenns richtig gut läuft wars das schon. Besonderen Dank an cybmorg, für die unkonventionelle Idee dem AVR Fähigkeiten abzutrotzen, die eigentlich nicht vorgesehen sind. Sowas finde ich großartig. Meine Fragen sind beantwortet. Vielen Dank für eure Hilfsbereitschaft! Ich werde mich revanchieren. Lasst euch nicht abhalten weiterzudiskutieren. Schönen Gruß Artur
@ Timm Thaler (timm-thaler) >Hast Du ein paar Beispiele? Das interessiert mich ernsthaft, man lernt >ja nie aus. Ich hab hier eine Steuerung in einem kommerziellen Gerät, dort läuft ein kooperatives Multitasking. Ein Timer mit 10ms gibt den Grundtakt vor. In diesem Timer steckt die wesentliche Verarbeitung, d.h. Datenerfassung über einen externen ADC, PI-Regler, Überwachung der Parameter, Daten für den Netzwerktransport vorbereiten, wobei hier nochmal ein Teiler in Software drinsteckt, d.h. nicht alle Funktionen laufen mit 10ms Periodendauer, die meisten deutlich langsamer! Dieser Timerdurchlauf dauert je nach Konstellation bis zu 4ms. Was bei 10ms Periodendauer kein Problem ist. Man muss aber auch sagen, dass dieser Controller kein ganz normales C nutzt, es ist ein etwas eigenes Framework, wo es nur ereignisgesteuerte Funktionen gibt und eben diese Timer. Eine main-Funktion gibt es nicht! >Wenn ich C programmieren wöllte, nähme ich nen PC. ;-) Im AVR wird >natürlich ASM programmiert. Jaja, als Hobby ganz nett, im produktiven Einsatz aber meist nicht sinnvoll. Bestenfalls die ISR könnte man als reinen Assembler machen, wenn es denn WIRKLICH nötig ist. Ist es aber gar nicht so oft wie man denkt.
Falk Brunner schrieb: > kooperatives Multitasking. Ein Timer mit 10ms gibt den Grundtakt vor. In > diesem Timer steckt die wesentliche Verarbeitung, d.h. Datenerfassung > über einen externen ADC, PI-Regler, Überwachung der Parameter, Daten für > den Netzwerktransport vorbereiten... Also nichts, was man mit einem Timer auf 10ms mit 15 Takten, einer Mainloop im Timertakt mit zeitgesteuerten Calls der einzelnen Subroutinen und ein bißchen Buffer für die Netzwerkdaten auch machen könnte. > Jaja, als Hobby ganz nett, im produktiven Einsatz aber meist nicht > sinnvoll. Dieses Hobby bringt mir in einem aktuellen Projekt mit 15 AVRs für verschiedenste Steueraufgaben etwa 20kEur. Ich weiss, Peanuts, aber so ein Hobby würde sich mancher wünschen, denke ich. Eine jitterfreie Software-PWM für 8 Kanäle in C? Bis da die Daten aus dem SRAM geladen sind, ist meine PWM-Routine mit direktem Registerzugriff schon durch.
@ Timm Thaler (timm-thaler) >Also nichts, was man mit einem Timer auf 10ms mit 15 Takten, einer >Mainloop im Timertakt mit zeitgesteuerten Calls der einzelnen >Subroutinen und ein bißchen Buffer für die Netzwerkdaten auch machen >könnte. Du bist ein Pfennigfuchser, ähhh Taktzähler. ;-) >> Jaja, als Hobby ganz nett, im produktiven Einsatz aber meist nicht >> sinnvoll. >Dieses Hobby bringt mir in einem aktuellen Projekt mit 15 AVRs für >verschiedenste Steueraufgaben etwa 20kEur. In C wäre das wahrscheinlich ebenso, ggf. sogar einfacher machbar. Aber ich will niemanden bekehren. Die ewige Diskussion hatten wir schon zur Genüge. >Ich weiss, Peanuts, aber so >ein Hobby würde sich mancher wünschen, denke ich. 20kEur Umsatz oder Gewinn? >Eine jitterfreie Software-PWM für 8 Kanäle in C? Bis da die Daten aus >dem SRAM geladen sind, ist meine PWM-Routine mit direktem >Registerzugriff schon durch. Jaja, alles ganz nett und ne sportliche Herausforderung, aber Profis nehmen einfach einen passenden PWM-IC, von dem es heute mehr als genug gibt und fertig. Professionelle Industrielösungen reizen Teilkomponenten selten aus, dafür setzen sie auf bestehende, getestete Komponenten. Ist In Summe deutlich effektiver. Und wie gesagt, es gibt schon noche in paar kleine Nischen für ASM. Und dass man auch in C eine recht gute Soft-PWM hinkriegt, ist nichts neues. (Jaja, es gibt geringen Jitter und man braucht mehr Takte als in ASM, spielt aber in Summe keine Rolle).
Falk Brunner schrieb: > Professionelle Industrielösungen reizen Teilkomponenten > selten aus, dafür setzen sie auf bestehende, getestete Komponenten. Ja, diese Industrielösungen kenne ich auch: Schaltkreisgräber mit völlig überdimensionierten µC, weil da wahrscheinlich Java programmiert wird. Die Peripherie mit irgendwelchen Spezial-IC gemacht, die es in 5 Jahren nicht mehr gibt. Falk Brunner schrieb: > aber Profis > nehmen einfach einen passenden PWM-IC Ein PWM-IC, der 8 PWM jeweils um 1/8 Periode versetzt ausgibt, um nicht alle Verbraucher gleichzeitig einzuschalten? Wäre mir neu...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.