Ich habe jetzt mal eine Frage zu einem hypothetischen Zustand. Wird im AVR ein Interrupt ausgelösst (erstmal egal welcher) wird erstmal das Interruptflag (cli) gelöscht, damit die Interruptroutine nicht "gestört" wird. Angenommen während diesem Interrupts treten mehrere Ereignisse ein die eines Interrupts würdig währen, aber wegen dem "cli" nicht ausgelösst werden (So eine Interrupttabelle ist lang. Es steht also viel zu Auswahl.). Die Hardware setzt dann die entsprechenden Bits in den entsprechenden Ports, die den Interrupt eigendlich auslösen sollten. Ist die erste Interruptroutine nun mit "reti" abgeschlossen, werden Interrupts wieder erlaubt (sei). Von den Interrupts die jetzt noch anstehen kann also die nächste angesprungen werden. Meine Frage zu diesem Zustand ist jetzt: Welcher Interrupt wird dann als nächstes ausgeführt? Wird die Interrupttabelle einfach von vorn nach hinten abgearbeitet? Grüße
Tiny10Nutzer schrieb: > Welcher Interrupt wird dann als nächstes ausgeführt? Wird die > Interrupttabelle einfach von vorn nach hinten abgearbeitet? Ja. Zumindest kann ich mich an nichts im Datenblatt erinnern, das etwas anderes behaupten würde. Wenn sich der AVR zwischen den eigentlichen Befehlen der Abarbeitung der Interupt Flags widmet, müsste er sich sonst irgendwo merken, welches Flag er zuletzt untersucht hat. Ein derartiges Register, in dem er sich das merken könnte, ist aber meines Wissen nicht bekannt. Das wäre auch nicht sehr ökonomisch, da verschiedene AVR ja auch eine verschiedene Anzahl an Interrupt Quellen hat.
:
Bearbeitet durch User
Tiny10Nutzer schrieb: > Welcher Interrupt wird dann als nächstes ausgeführt? Wird die > Interrupttabelle einfach von vorn nach hinten abgearbeitet? Ja.
Im Datenblatt unter 'Reset and interrupt handling' nachlesen. z.B. ATmega1284: The lowest addresses in the program memory space are by default defined as the Reset and Interrupt Vectors. The complete list of vectors is shown in ”Interrupts” on page 61. The list also determines the priority levels of the different interrupts. The lower the address the higher is the priority level. RESET has the highest priority, and next is INT0...
Freu... So dumm bin ich gar nicht... Es ist aber auch so, dass "der nächste anstehende Interrupt" auf das "sei" wartet und nicht einfach übergangen wird...?
> Freu... So dumm bin ich gar nicht... Mitfreu; es bleibt nur noch etwas Feinarbeit: > ...ausgelösst... währen...eigendlich... Nichts für ungut.
Tiny10Nutzer schrieb: > Freu... So dumm bin ich gar nicht... > > Es ist aber auch so, dass "der nächste anstehende Interrupt" auf das > "sei" wartet und nicht einfach übergangen wird...? Ja. Das folgt daraus, wie der ganze Interrupt Mechanismus funktioniert. Ein Ereignis löst ja nicht direkt den Interrupt aus, sondern es setzt erst mal nur 1 Bit in einem Register. Zwischen 2 Befehlen scannt der AVR einfach diese Bits (in der vorgegebenen Reihenfolge) und wenn eines davon gesetzt ist dann wird der Interrupt durchgeführt: Rücksprungsadresse speichern, das Bit zurücksetzen, einen cli durchführen, die ISR anspringen. Daraus folgt: diese spezielle Bit, welches registriert ob ein Ereignis eingetreten ist, kann selbstverständlich auch dann gesetzt werden, wenn der Prozessor gerade in einer ISR ist. Sobald die INterrupts global wieder zugelassen werden, wird dann auch dieses gesetzte Bit gefunden und die weitere Interrupt Behandlung setzt ein. D.h. 1 Ereignis kann 'auf Halde' liegen ohne dass es 'übersehen' wird.
:
Bearbeitet durch User
der alte Hanns schrieb: >> Freu... So dumm bin ich gar nicht... > > Mitfreu; es bleibt nur noch etwas Feinarbeit: >> ...ausgelösst... währen...eigendlich... > Nichts für ungut. Sorry du bist nicht up-to-date. Heute nennt man sowas "Legastheniker" und nicht Dumm oder zu Faul ordentlich zu schreiben. Das war früher mal. Heute bekommst du da ein Attest. Früher gabs auch mal rotzfreche Bälger ohne Erziehung, heute haben die nur ADS. Möglichkeit 2 (nur für Internetforen): "Habs mit Smartphone geschrieben".
Also so böse hatte ich es nicht gemeint und hoffe, dass es nicht so verstanden wurde. Es ist ja leider ein allgemeines Phänomen, jeden zweiten Morgen packt mich das kalte Grausen, wenn ich die Regionalzeitung aufschlage.
@ der alte Hanns Na das von dir hatte ich jetzt nicht so böse aufgefasst. Ich hatte jetzt den Text einfach zu schnell auf Fehler überflogen. Den Hinweis von dir fand ich jetzt aber doch nützlich (weiß jetzt, dass ich vielleicht nicht so schnell drüber fliegen sollte). Aber so 100 %tiges saubere Deutsch (hab ich mir sagen lassen) kann wohl kein Deutscher. Trotzdem kann ich sagen, hab ich so hier und da meine Schwächen und finde das auch gar nicht so arg schlimm. Vieleicht noch als Hinweis: Ich bin vielleicht nicht so jung, wie es den Anschein macht. @ all Danke für euere schnellen und zuverlässigen Antworten. Ihr habt mir sehr geholfen. Grüße
Karl Heinz schrieb: > Zwischen 2 Befehlen scannt der AVR einfach diese Bits (in der > vorgegebenen Reihenfolge) und wenn eines davon gesetzt ist dann wird der > Interrupt durchgeführt Hallo! Das kann dann natürlich bei sehr großer Interrupt-Last dazu führen, dass ein INT , der in der Reihenfolge "ganz hinten" liegt, nie dran kommt. Dann muß man am Konzept der Software oder der Hardware etwas ändern.
Tiny10Nutzer schrieb: > Wird die > Interrupttabelle einfach von vorn nach hinten abgearbeitet? In der Reihenfolge der Priorität, näheres steht im Manual. Die Priorität kann recht komplex sein, wenn es mehrere Gruppen gibt und diese noch eine interne Priorität haben. Die eigentlich logischste Lösung gibt es aber meines Wissens bei keinem Prozessor: dass die ausstehenden Interrupts in der Reihenfolge ihre Auftretens abgearbeitet werden. Ausserdem kann der Prozessor i.A. nicht erkennen, ob eine unbearbeiteter Interupt schon mehr als einmal aufgetreten ist, da ist eine Softwarelösung gefragt, sofern es überhaupt eine sinnvolle Lösung gibt. Z.B. kann man bei einer seriellen Schnittstelle abfragen, ob mehr als ein Byte empfangen wurde, die meisten haben ja ein FIFO. Georg
@ Route 66 (route_66) >Das kann dann natürlich bei sehr großer Interrupt-Last dazu führen, dass >ein INT , der in der Reihenfolge "ganz hinten" liegt, nie dran kommt. Dann ist dein Prozessor so oder so überlastet.
Hallo zusammen, mir stellt sich da noch eine Frage! Wird bei einem 'sei' der Interruptzähler zurück gesetzt, so das die Interuptbehandlung bei RESET beginnt oder setzt sie ihre Arbeit mit dem dem behandeltem Ereignis folgendem Interrupt fort? Gruss Roman
RomanK schrieb: > Hallo zusammen, > > mir stellt sich da noch eine Frage! Wird bei einem 'sei' der > Interruptzähler zurück gesetzt, so das die Interuptbehandlung bei RESET > beginnt oder setzt sie ihre Arbeit mit dem dem behandeltem Ereignis > folgendem Interrupt fort? > > Gruss > > Roman Dumm von mir, die Frage schloss ein RETI ein.
RomanK schrieb: > Hallo zusammen, > > mir stellt sich da noch eine Frage! Wird bei einem 'sei' der > Interruptzähler zurück gesetzt, Welcher Zähler? Es gibt auf dem AVR keinen derartigen Zähler. Ein Ereignis setzt ein Bit und wenn Interrupts zugelassen sind, triggert dieses gesetzte Bit letzten Endes den Aufruf der zugehörigen ISR. Die Reihenfolge in der diese Bits ausgewertet werden beginnt jedesmal wieder von vorne.
Danke Karl-Heinz, ich meinte ja auch die Interrupttabelle, und nicht irgendeinen Zähler. Gruss Roman
RomanK schrieb: > Danke Karl-Heinz, > > ich meinte ja auch die Interrupttabelle, und nicht irgendeinen Zähler. Auch dann versteh ich die Frage nicht. Eine Tabelle kann nicht zurückgesetzt werden. Ist das entsprechende Bit auf 1, zb das TOV0 Bit im Register TIFR, welches anzeigt, dass der Timer 0 seinen Overflow erreicht hat, und sind die restlichen Bedingungen gegeben (Overflow INterrupt freigegeben, globale Interrupts freigegeben, kein Bit für einen höher priorisierten Interrupt gesetzt), so wird nach Abarbeitung des gerade auszuführenden Befehls die ISR für den Overflow Interrupt angesprungen (und das Bit wieder gelöscht). Hat man keine ISR bzw. diesen Interrupt nicht freigegeben, dann bleibt das Bit gesetzt bis man es per Programm löscht oder eben diesen Interrupt frei gibt, sodass die ISR dann eben aufgrund des gesetzten Bits sofort angesprungen wird. Mir scheint, du denkst dir da zu viel Eigenintelligenz rein. Der ganze Mechanismus ist ganz simpel.
:
Bearbeitet durch User
RomanK schrieb: > ich meinte ja auch die Interrupttabelle Der "folgende" Interrupt ist der in der Tabelle, der die höchste Priorität hat - aber das wurde doch schon ausführlich beschrieben. Georg
Hallo Karl-Heinz, dann wird die Tabelle also doch der Wertigkeit nach abgearbeitet und es kann kein Interrupt hängen bleiben z.B. weil das Ende der Tabelle nie erreicht wird. Weiter oben wurde so ein Szenario mal skizziert. Es ging mir dabei um die Frage, was passiert wenn während der Behandlung eines Interruptes zwischenzeitlich mehrere Interrupts ausgelöst werden. Geht es dann nach Rückkehr aus dem ersten Interupt weiter mit dem nächstniederwertigen Interrupt oder beginnt die Abarbeitung der Interrupts wieder beim höchstwertigem? Ich glaube ich sehe schon die Lösung. "Den letzten beissen die Hunde", wie es schön heisst. Gruß Roman
Hi >dann wird die Tabelle also doch der Wertigkeit nach abgearbeitet und es >kann kein Interrupt hängen bleiben z.B. weil das Ende der Tabelle nie >erreicht wird. Weiter oben wurde so ein Szenario mal skizziert. Nein. Bei Freigabe wird der Interrupt mit der höchsten Priorität abgearbeitet. >Ich glaube ich sehe schon die Lösung. "Den letzten beissen die Hunde", >wie es schön heisst. Genau. Aber bei so einer Interruptbelastung hast du noch andere Probleme. MfG Spess
RomanK schrieb: > Hallo Karl-Heinz, > > dann wird die Tabelle also doch der Wertigkeit nach abgearbeitet und es > kann kein Interrupt hängen bleiben z.B. weil das Ende der Tabelle nie > erreicht wird. Weiter oben wurde so ein Szenario mal skizziert. Ich denke, dein Hauptproblem dürfte sein, dass du dir diese Abarbeitung als Tabellensuche vorstellst. Das ist ziemlich sicher intern nicht so realisiert. Das ist konzeptionell einfach nur ein digitales Schaltwerk (also eine Kombination aus Gattern), an dessen Ende eine Leitung auf High geht (und alle anderen auf Low bleiben), nämlich die, welche ISR auszuführen ist. > Es ging mir dabei um die Frage, was passiert wenn während der Behandlung > eines Interruptes zwischenzeitlich mehrere Interrupts ausgelöst werden. Exakt gesprochen können die 'Interrupts nicht ausgelöst werden'. Die Ereignisse treten ein und die entsprechenden Bits werden in den entpsrechenden Registern gesetzt. > Geht es dann nach Rückkehr aus dem ersten Interupt weiter mit dem > nächstniederwertigen Interrupt oder beginnt die Abarbeitung der > Interrupts wieder beim höchstwertigem? Nach jedem regulärem Befehl kommt das 'Interrupt Auswerte Netzwerk' zum Zug, welches entscheidet welches der (zu diesem Zeitpunkt) am höchsten priorisierte Interrupt ist, der ausgeführt werden kann (weil seine Freigaben vorhanden sind). Da gibt es kein Gedächtnis, was vorher passiert ist. Das einzige Gedächtnis ist das eine Bit welches anzeigt "Ereignis eingetreten" > Ich glaube ich sehe schon die Lösung. "Den letzten beissen die Hunde", > wie es schön heisst. Exakt. Aber wie weiter oben schon mal jemand sagte: WEnn du den Prozessor so zuballerst, dass er immer nur ein und denselben höchstpriorisierten Interrupt abarbeitest, dann hast du sowieso ein mächtiges Problem mit der grundsätzlichen Leistungsfähigkeit deines AVR
:
Bearbeitet durch User
Kommentar: Meine Programme sind jetzt noch recht einfach. Ich habe hier und da schon kleinere Probleme alle Schreibbefehle in der richtigen Reihenfolge unterzubringen. Bis jetzt nutze ich nur 2 Interrupts. Demnächst werden 2 weitere dazu kommen. Ich kann mir sehr gut vorstellen, dass wenn ständig so viele Interrupts am Werk sind und dem Prozessor keine Luft zum Atmen gelassen wird, dass der Watchdog praktisch jedes Mal auslösen wird (das Programm immer abstürzen wird). Grüße
Tiny10Nutzer schrieb: > unterzubringen. Bis jetzt nutze ich nur 2 Interrupts. Demnächst werden 2 > weitere dazu kommen. Ja, macht ja nichts. > Ich kann mir sehr gut vorstellen, dass wenn ständig so viele Interrupts > am Werk sind und dem Prozessor keine Luft zum Atmen gelassen wird, dass > der Watchdog praktisch jedes Mal auslösen wird (das Programm immer > abstürzen wird). Langsam. Mit 16Mhz getaktet macht dein µC rund 14 MILLIONEN Befehle in der Sekunde (einen gesunden Mix an Befehlen vorausgesetzt). Da musst du schon mächtig zeitkritisch arbeiten, ehe du ihn da an die Grenze bringst, so dass der AVR nur noch ISR (und da immer dieselbe) abarbeitet. Lass dich nicht davon beeindrucken, dass dein mit 4Ghz getakteter PC (unter Windows) ab und zu ein Päuschen einlegt. Auf deinem µC bist du alleine auf dem nackten Silizium. Da gibt es kein Betriebssystem oder einen Virenchecker oder Abfragen von Mails oder einfach nur Speicher aufräumen, welches dir Rechenzeit unter dem Hintern wegzieht. Der µC macht genau und nur die Befehle, die du hingeschrieben hast. Die Rechenzeit gehört zu 100% dir.
:
Bearbeitet durch User
In meinem momentanen Projekt habe ich ein Software-BAM (PWM), dass schon sehr viel Rechenleistung einnimmt (verbraucht 2 Interrupts, aber nicht gleichzeitig). Zusätzlich will ich auf nur einer Leitung bidirektional Kommunizieren. Dabei muss ich bei einer eingehenden Nachricht per Interrupt die Zeiten messen (gesucht wird der zeitlich kürzeste Wechsel zwischen High und Low). Ich habe dann vor bei einer ausgehenden Nachricht den CPU-Takt (hab noch keinen Plan wie) so anzupassen, dass ich die ausgehenden High-Low-Wechsel genau zwischen den BAM-Interrupts legen kann. Und dann darf ich auch noch Abstürze verhindern... Wenn das funktioniert mache ich Luftsprünge und drei Kreuze...
Tiny10Nutzer schrieb: > In meinem momentanen Projekt habe ich ein Software-BAM (PWM), dass schon > sehr viel Rechenleistung einnimmt (verbraucht 2 Interrupts, aber nicht > gleichzeitig). Zusätzlich will ich auf nur einer Leitung bidirektional (und ein Interrupt allein dauert schon eine Lichtminute lang)
Der Interrupt selber daurt nicht sonderlich lang. Er tritt nur so oft auf und darf nicht verschoben werden.
@ Tiny10Nutzer (Gast) >In meinem momentanen Projekt habe ich ein Software-BAM (PWM), dass schon >sehr viel Rechenleistung einnimmt Dann machst du was falsch. Gerade BAM ist je sehr resourcenschonend. >gleichzeitig). Zusätzlich will ich auf nur einer Leitung bidirektional >Kommunizieren. Dabei muss ich bei einer eingehenden Nachricht per >Interrupt die Zeiten messen (gesucht wird der zeitlich kürzeste Wechsel >zwischen High und Low). Wie groß sind die? 1ms? 1h? > Ich habe dann vor bei einer ausgehenden >Nachricht den CPU-Takt (hab noch keinen Plan wie) so anzupassen, dass >ich die ausgehenden High-Low-Wechsel genau zwischen den BAM-Interrupts >legen kann. Das ist eher leicht, beim Senden kann man das mit einer passenden Statemachine machen.
Tiny10Nutzer schrieb: > Ich kann mir sehr gut vorstellen, dass wenn ständig so viele Interrupts > am Werk sind und dem Prozessor keine Luft zum Atmen gelassen wird, dass > der Watchdog praktisch jedes Mal auslösen wird (das Programm immer > abstürzen wird). Der AVR führt zwischen Interrupts immer erst einen Mainzyklus aus. Es kann daher gut sein, daß der Watchdog auch bei hoher Interruptrate nicht auslöst. Den Watchdog schaltet man während der Entwicklung eh immer ab. Er kann Fehler maskieren und erschwert die Fehlersuche. Er wird erst implementiert und getestet, nachdem die Applikation einwandfrei läuft.
Tiny10Nutzer schrieb: > Zusätzlich will ich auf nur einer Leitung bidirektional > Kommunizieren. Dabei muss ich bei einer eingehenden Nachricht per > Interrupt die Zeiten messen (gesucht wird der zeitlich kürzeste Wechsel > zwischen High und Low). Ich habe dann vor bei einer ausgehenden > Nachricht den CPU-Takt (hab noch keinen Plan wie) so anzupassen, dass > ich die ausgehenden High-Low-Wechsel genau zwischen den BAM-Interrupts > legen kann. Und dann darf ich auch noch Abstürze verhindern... Das klingt irgendwie durcheinander. Wenn Du Details preisgeben würdest, könnte man abschätzen, ob und welche Probleme es geben könnte.
Karl Heinz schrieb: > Aber wie weiter oben schon mal jemand sagte: WEnn du den Prozessor so > zuballerst, dass er immer nur ein und denselben höchstpriorisierten > Interrupt abarbeitest, dann hast du sowieso ein mächtiges Problem mit > der grundsätzlichen Leistungsfähigkeit deines AVR Hallo! Das muß nicht an der Leistungsfähigkeit des AVR liegen. Anfänger unterschätzen oft dessen Geschwindigkeit und wählen z.B. für einen Anzeigemultipex eine viel zu große Wiederholrate, und machen dann im Timer-Interrupt noch Dinge, die dort nicht hingehören. Dann kann auch ein ausreichend leistungsfähoiger AVR nur die Hände heben! Das Gesamtkonzept muß stimmen. Da kann ich hier nur voll zustimmen: Peter Dannegger schrieb: > Das klingt irgendwie durcheinander. > > Wenn Du Details preisgeben würdest, könnte man abschätzen, ob und welche > Probleme es geben könnte.
vadammt schrieb: > (und ein Interrupt allein dauert schon eine Lichtminute lang) Also dauert ein Interrupt ungefähr 18 Millionen km lang? Interessant, so groß ist doch ein Chip gar nicht ;-)
>Es ging mir dabei um die Frage, was passiert wenn während der Behandlung >eines Interruptes zwischenzeitlich mehrere Interrupts ausgelöst werden. Normalerweise weisst man verschiedenen INTs auch verschiedene INT-Prioritäten zu. Beim (normalen) AVR geht das nicht (hardwaremässig)!
MCUA schrieb: > Normalerweise weisst man verschiedenen INTs auch verschiedene > INT-Prioritäten zu. Aber i.d.R. nur, wenn der µC schachtelbare Interrupts vorsieht. Was auf den AVRs (vor den Xmegas) nicht zutrifft. Bei AVRs sind dessen Interrupt-Prioritäten normalerweise kein wichtiges Thema. Wenn sie es werden, dann hat man möglicherweise zu viele zu häufige Interrupts - und hat aufs falsche Konzept oder aufs falsche Pferd gesetzt.
:
Bearbeitet durch User
A. K. schrieb: > Aber i.d.R. nur, wenn der µC schachtelbare Interrupts vorsieht. Was auf > den AVRs (vor den Xmegas) nicht zutrifft. Meines Wissens geht das bei den "normalen" AVRs ohne Probleme. Wenn die Interrupt-Routine zu Anfang das Interrupt-Flag setzt, sind während ihres Laufs weitere Interrupts möglich. Die Interrupts werden dann geschachtelt - wie normale Unterprogramme auch.
>> Aber i.d.R. nur, wenn der µC schachtelbare Interrupts vorsieht. Was auf >> den AVRs (vor den Xmegas) nicht zutrifft. >Meines Wissens geht das bei den "normalen" AVRs ohne Probleme. Nö, geht nicht. AVR (nicht xmega) unterstützt nicht mehrere INT-Prioritäten. Die o.g. (fest vergebenen) Prioritäten sind die innerhalb Eines INT-Aufrufes, was etwas völlig anderes ist.
Markus Weber schrieb: > Meines Wissens geht das bei den "normalen" AVRs ohne Probleme. Man hat dann aber keine Prioritäten, sondern jeder Interrupt unterbricht jeden anderen. Um das zu vermeinden müsste man in den ISRs zusätzlich mit den einzelnen Enable-Flags der Interrupts rumspielen.
@ MCUA (Gast) Richtig zitieren bitte! >>Meines Wissens geht das bei den "normalen" AVRs ohne Probleme. >>Wenn die Interrupt-Routine zu Anfang das Interrupt-Flag setzt, sind >>während ihres Laufs weitere Interrupts möglich. Die Interrupts werden >>dann geschachtelt - wie normale Unterprogramme auch. >Nö, geht nicht. AVR (nicht xmega) unterstützt nicht mehrere >INT-Prioritäten. Doch, man kann verschachtelte Interrupts auf dem AVR in Software nachbilden!
MCUA schrieb: >>> Aber i.d.R. nur, wenn der µC schachtelbare Interrupts vorsieht. Was auf >>> den AVRs (vor den Xmegas) nicht zutrifft. >>Meines Wissens geht das bei den "normalen" AVRs ohne Probleme. > Nö, geht nicht. AVR (nicht xmega) unterstützt nicht mehrere > INT-Prioritäten. Ich glaube, wir haben aneinander vorbeigeredet. Es ging mir nicht um Prioritäten, sondern um die angesprochenen verschachtelten Interrupts. Diese sind ohne Weiteres möglich. Zu den Prioritäten: Es wird immer wieder behauptet, dass es so etwas bei AVR nicht gibt. Das ist nicht ganz richtig. Es gibt zwei Prioritätsebenen: Unterbrechbare und nicht unterbrechbare Interrupt-Routinen. Zwei Prioritätsebenen sind natürlich nicht viel, ich hatte allerdings noch keine Anwendung, bei der ich mehr als zwei Ebenen gebraucht hätte.
Markus Weber schrieb: > Zu den Prioritäten: > Es wird immer wieder behauptet, dass es so etwas bei AVR nicht gibt. Das > ist nicht ganz richtig. Es gibt zwei Prioritätsebenen: /Unterbrechbare/ > und nicht unterbrechbare Interrupt-Routinen. Genauso ist das. Allerdings entspricht es nicht ganz der üblichen Steuerung von Interruptprioritäten. Denn diese sperren grundsätzlich auch Interrupts gleicher Priorität. Also insbesondere auch weitere Instanzen des auslösenden Interrupts. Genau das ist bei "deinem" Nachbau eines Prioritätensystems auch bei der Top-Priorität der Fall, nicht aber bei der Priorität zweiten Ranges, denn diese kann durch andere gleichrangigige Interrupts unterbrochen werden und auch durch eine erneute Instanz von sich selbst. Man kann das lösen, aber je nach der Zahl der beteiligten Interrupts können dadurch die exklusiven Teile der ISRs der Interrupts zweiten Ranges ziemlich länglich werden, was nicht unbedingt im Sinne des Erfinders ist... > Zwei Prioritätsebenen > sind natürlich nicht viel, ich hatte allerdings noch keine Anwendung, > bei der ich mehr als zwei Ebenen gebraucht hätte. Das ist der eigentliche Punkt, fast immer reicht auch die Priorisierung nach "deinem" Schema, sogar ohne die Korrekturen bezüglich des zweiten Prioritäts-Levels. Aber es ist wie immer: Das Problem sind die Ausnahmen. Sie bestätigen zwar die Regel, aber wenn man nun ausgerechnet so ein Ausnahme-Problem hat, muß man sich dann doch was Besonderes einfallen lassen...
>Doch, man kann verschachtelte Interrupts auf dem AVR in Software >nachbilden! Was sagte ich denn oben? >Beim (normalen) AVR geht das nicht (hardwaremässig)!
>Das ist der eigentliche Punkt, fast immer reicht auch die Priorisierung...
Ja? Bereits 68k (v. 1979) hat 7 davon. Wohl nicht, weil mans nicht
braucht.
Jede kompliziertere Steuerung braucht mehrere INT-Ebenen.
Ausserdem kostet das in heutiger Zeit fast gar nichts mehr.
Beim Simulieren muss man noch aufpassen: die alten Simulatorversion (AVRStudio 4.x) hat die Reihenfolge der Interrupts nicht richtig beachtet - da wurde in der Reihenfolge des Auslösens simuliert. Real geht es nach der Position des Vektors. Das 2 Interrupts gleichzeitg anstehen kann schon mal leicht vorkommen, etwa wenn die nicht Synchron kommen, sondern etwa einmal Timer und einmal die UART oder ein externer Interrupt.
A. K. schrieb: > Bei AVRs sind dessen Interrupt-Prioritäten normalerweise kein wichtiges > Thema. Oh doch, es gibt leider durchaus Anwendungfälle, in denen das wirklich wichtig wird. Z.B. immer dann, wenn irgendwelche Timer-Funktionalität bezüglich der Datenbreite erweitert werden muß. Also z.B. Kombination aus möglichst genauer Zeitmessung via ICP bei gleichzeitigem Erfordernis eines großen zu messenden Zeitbereiches (und damit der Notwendigkeit, auch die Timer-Überlaufe zu tracken). Wer da nicht auf die Interrupt-Prioritäten achtet, hat schon verloren! Und das ist durchaus kein Szenario, was den AVR irgendwie wirklich an seine Grenzen bringt. Denn das ist ja wohl, was du suggerieren willst: dass sowas nur eine Rolle spielt, wenn man an die Grenzen des Machbaren geht. Das ist Quatsch! Und selbst, wenn es wirklich so wäre: Es gibt Leute, die WOLLEN und KÖNNEN die Hardware bis an ihre Grenzen nutzen. Naja, die wissen dann auch, was sie tun und schreiben ihren Code schon deshalb nicht in C...
Ulrich schrieb: > Beim Simulieren muss man noch aufpassen: die alten Simulatorversion > (AVRStudio 4.x) hat die Reihenfolge der Interrupts nicht richtig > beachtet Richtig und gleichzeitig auch falsch. Nur der Simulator V1 hat dieses wirklich extrem üble Manko. Im Studio 4.x ist aber nicht nur dieser Simulator verfügbar, sondern für viele Devices auch der Simulator V2. Der hat diesen (und etliche andere) Bugs des Simulators V1 nicht mehr. Dafür allerdings wieder ein paar neue... Aber die sind glücklicherweise zu 100% in der Interaktion zwischen Simulator und dem GUI angesiedelt, die Simulation der Hardware selber hingegen scheint jetzt wirklich weitestgehend fehlerfrei zu sein. Jedenfalls bin ich noch auf keinen Fehler dort gestoßen. Und die Fehler bei der Interaktion mit dem GUI lassen sich alle ziemlich problemlos "workarounden", jedenfalls wenn man versteht, was da passiert...
In diesem Zusammenhang finde ich dieses Script http://mit.eit.h-da.de/VorlesungenBeispiele_Wirth_WS1011/1000_Interrupt.pdf ganz interessant.
Ich benutze Studio 4. Jetzt habe ich auf Simulator 2 umgestellt und die Ergebnisse sind noch wilder. Den elementaren Teil, mit dem ich Probleme habe, habe ich jetzt extrahiert. Der folgenden Code soll den Interrupt zu erst nach 255 Timer-Zyklen, dann nach 16 und dann nach 8 anspringen. Der Interrupt selbst ist nur 7 CPU-Zyklen lang. Ergebnis Simulator 1: Die 16ner Verzögerung wird sauber angesprungen. Die 8ter jedoch erst nach 256+8 Timerzyklen. Ergenis Simulator 2: Die 16ner Verzögerung wird nach 15 Zyklen angesprungen. Die 8ter wird nach 256+7 angesprungen. Was mache ich falsch?
1 | .include "tn13Adef.inc" |
2 | |
3 | .def tmp = r16 |
4 | .def itmp5 = r5 |
5 | .def itmp6 = r17 |
6 | |
7 | ;;; Interrupt-Sprungvectoren festlegen |
8 | .org 0x0000 |
9 | rjmp reset_order ; Reset Handler |
10 | .org 0x0006 |
11 | rjmp timer0_matchA ; Timer0A Match Handler |
12 | |
13 | reset_order: |
14 | ldi tmp, low(RAMEND) ; Stackpointer initialisieren |
15 | out SPL, tmp |
16 | ldi tmp, 255 ; erste Verzögerung für timer0_matchA |
17 | out OCR0A, tmp ; zuständig für timer0_matchAtimer0_matchA |
18 | ldi tmp, 1 << OCIE0A ; OCIE0A: Interrupt bei Timer Vergleich A |
19 | out TIMSK0, tmp |
20 | ldi itmp6,0b00100000 |
21 | in itmp5,OCR0A |
22 | ldi tmp, 1 << CS00 ; CS00 setzen: für Timerzähler kein Vorteiler |
23 | out TCCR0B, tmp |
24 | sei ; Interrupt erlauben |
25 | rjmp main ; zum Hauptprogramm springen |
26 | |
27 | main: |
28 | rjmp main |
29 | |
30 | timer0_matchA: |
31 | |
32 | lsr itmp6 ; logisches verschieben nach rechts |
33 | add itmp5,itmp6 |
34 | out OCR0A,itmp5 ; Timerinterrupt-Punkt auf neue Position setzen |
35 | |
36 | reti ; 7-cycle-finish |
Tiny10Nutzer schrieb: > dann nach 8 anspringen Das kannst du eh vergessen, denn ... Tiny10Nutzer schrieb: > Der Interrupt selbst ist nur 7 > CPU-Zyklen lang. Nein. Der ISR-Code ist 7 Zyklen lang, der Interrupt insgesamt aber 11 Zyklen. Und der minimal mögliche Abstand zwischen zwei Auslösungen ist in deinem Fall 13 Zyklen. In dem Moment, wo du das +8 nach OCR0A schreibst, hat der Timer diesen Punkt schon passiert, daher das 256+8.
:
Bearbeitet durch User
Tiny10Nutzer schrieb: > Der Interrupt selbst ist nur 7 > CPU-Zyklen lang. Falsch. Der Interrupteintritt dauert 4 Zyklen und der RJMP zum Handler nochmal 2. Es sind also 13 Zyklen. Und da nach jedem Interrupt mindestens 1 Main-Befehl ausgeführt wird, ist der früheste Wiedereintritt erst nach 14..17 Zyklen möglich.
Peter Dannegger schrieb: > der RJMP zum Handler nochmal 2 Ups, die hab ich doch glatt vergessen. ;-)
Dann habe ich mich natürlich geirrt. Ich dachte gelesen zu haben, dass der Eintritt in den Interrupt 2 Zyklen verbrauch und der Austritt nochmal 2. Daher bin ich auf 2-Eintriit + 3-Befehle + 2-Austritt auf 7 gekommen.
Ich habe mal versucht zu verbildlichen was ich da versuche. Jetzt wird mir auf jeden Fall klar warum da eine Verschiebung um einen Zyklus zu stande kommt.
In meinem Bestreben mein Verständnis für die logischen Abläufe zu erweitern, habe ich auch die Darstellung erweitert. Ich muss sagen, dass ich so langsam echt auf dem Schlauch stehe... Ich muss doch irgendwo einen gewaltigen Denkfehler haben.
Was stört Dich daran, einen Quelltext *.asm zu nennen? Dann müßte ihn nicht jeder Leser umbenennen.
Tiny10Nutzer schrieb: > Ich muss sagen, dass > ich so langsam echt auf dem Schlauch stehe... Das Schreiben nach OCR0A erfolgt deutlich später, als in deinen aufgeschriebenen "logischen Ablauf". Das wurde dir doch schon gesagt.
Das meine ich ja gar nicht. Ich meine die Ungleichheit bei:
1 | 21 276 15+8=23 271+8=279 |
2 | 22 277 23 |
3 | 23 278 23 |
4 | Interrupt 7 Zyklen bis hier |
Habe ich auch grade entdeckt. Jetzt stimmt das Beispiel wieder. Aber... Simulator 2 in Studio 4 zeigt mir hier die Interruptabstände -1 an.
Tiny10Nutzer schrieb: > Aber... Simulator 2 in Studio 4 zeigt mir hier die Interruptabstände -1 > an. Gerade mal selber ausprobiert. Die Abstände sind bei beiden gleich, nur im Sim2 ist die Anzeige im Interrupt immer eins niedriger. Sim1 muss hier falsch liegen, denn das rjmp (braucht 2 Takte) der Hauptschleife liegt auf den ungeraden Takten. Dann kann der erste Opcode der ISR nicht auf einem geraden Takt liegen. Bei Sim1 vergehen anscheinend 5 (statt 4) Takte beim Interrupt-Einsprung.
Vieleicht habe ich dich grade missverstanden. Was ich meinte war: Ich habe in meinem Beispiel-Code von oben einen Breakpoint im Interrupteintritt gesetzt und zu OCR0A 64 dazuaddiert. Jetzt erwarte ich (entsprechend meiner Darstellung), dass der nächste Interrupteintritt genau 64 Zyklen später erfolgt. Laut Simulator 2 erfolgt dieser aber 63 Zyklen später.
Tiny10Nutzer schrieb: > Was ich meinte war: Ich habe in meinem Beispiel-Code von oben einen > Breakpoint im Interrupteintritt gesetzt und zu OCR0A 64 dazuaddiert. > Jetzt erwarte ich (entsprechend meiner Darstellung), dass der nächste > Interrupteintritt genau 64 Zyklen später erfolgt. Laut Simulator 2 > erfolgt dieser aber 63 Zyklen später. Wieso 64? Nirgendwo in deinem Code oben gibt es diesen 64er Abstand. Ich habe deinen Code genommen und simuliert. Bei beiden Simulatoren waren die Abstände 16 und 264 (256+8), also genau wie erwartet.
Ähmm ja... Ich habe den Zyklus-Zähler immer auf 0 gestellt. Klar die 0 ist der erste Zyklus.
Für mein Verständnis: Vom Austritt aus dem Hauptprogramm in den Interrupt werden 4 Zyklen und 2 Stackbytes und beim Austritt aus dem Interrupt zurück in das Hauptprogramm werden 2 Zyklen verbraucht und 2 Stackplätze wieder frei gegeben.? Bei jeder Interrupt-Art?
Tiny10Nutzer schrieb: > Bei jeder Interrupt-Art? Es gibt nur eine Art Interrupt, mit etlichen Vektoren. Allerdings gibt es bei den AVRs verschiedene CPU-Typen: also 2-Byte PC, 3-Byte PC und Hardware-Stack. Die sich im exakten Zeitverhalten unterscheiden dürften.
:
Bearbeitet durch User
Ich habe im Datenblatt des Tiny13A nachgelesen. Entweder ich habe es überlesen oder es steht dort nicht, wieviele Takte verbraucht werden.
Tiny10Nutzer schrieb: > Vom Austritt aus dem Hauptprogramm in den Interrupt werden 4 Zyklen und > 2 Stackbytes Mindestens vier Zyklen. Das nennt sich "Minimum der konstanten Interruptlatenz". Und bei AVRs mit 22Bit-PC beträgt diese sogar 5 Takte, weil nämlich statt zwei hier sogar drei Bytes auf dem Stack landen müssen. > und beim Austritt aus dem Interrupt zurück in das > Hauptprogramm werden 2 Zyklen verbraucht und 2 Stackplätze wieder frei > gegeben.? Nein, das dauert auch immer 4 Takte (bei 22Bit-PC sogar 5) und holt zwei bzw. drei Bytes vom Stack. > Bei jeder Interrupt-Art? Natürlich. Es gibt ja schließlich aus Sicht der AVR-MCU sowieso nur genau eine Art von Interrupts: DEN Interrupt als solchen. Das einzige, was sonst noch Sache des Cores ist, ist die Wahl der Reihenfolge der Abarbeitung, wenn mehrere Interruptanforderungen "pending" sind. Alles Andere ist allein Sache der Peripherie und unterscheidet sich deshalb auch oft, je nach der Peripherie, die dafür verantwortlich ist.
Der RJMP Befehl im Hauptprogramm braucht 2 Zyklen, und der wird immer noch erst einmal zu Ende ausgeführt. Es gibt also noch zusätzliche ein Unsicherheit bei der Interrupt Latenz. Je nach Vorgeschichte sind es dann 63, 64 oder 65 Zyklen bis zum nächsten Interrupt. Um das los zu werten könnte an den µC etwa in den Standby mode versetzen.
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.