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.
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...?
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.
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.
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.
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
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.
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)
@ 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.
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...
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?
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.
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.
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.
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.
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.
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.
Tiny10Nutzer schrieb:> Vom Austritt aus dem Hauptprogramm in den Interrupt werden 4 Zyklen und> 2 StackbytesMindestens 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.