AVR Interrupt-Verhalten

Gast #3725744
Lesenswert?

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
#3725749
Lesenswert?

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.
Gast #3725758
Lesenswert?

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...
#3725771
Lesenswert?

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.
#3725777
Lesenswert?

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".
Gast #3725782
Lesenswert?

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.
Gast #3725890
Lesenswert?

@ 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
#3725909
Lesenswert?

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.
Gast #3725933
Lesenswert?

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
Gast #3725958
Lesenswert?

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
Gast #3725959
Lesenswert?

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.
#3725967
Lesenswert?

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.
#3725981
Lesenswert?

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.
Gast #3725995
Lesenswert?

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
Gast #3726004
Lesenswert?

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
#3726007
Lesenswert?

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
Gast #3726078
Lesenswert?

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
#3726088
Lesenswert?

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.
Gast #3726111
Lesenswert?

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...
Gast #3726154
Lesenswert?

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)
#3726314
Lesenswert?

@ 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.
#3726566
Lesenswert?

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.
#3726573
Lesenswert?

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.
#3727018
Lesenswert?

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.
Gast #3727314
Lesenswert?

>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)!
#3727318
Lesenswert?

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.
(Firma: guloshop.de) #3727541
Lesenswert?

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.
Gast #3727585
Lesenswert?

>> 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.
#3727634
Lesenswert?

@ 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!
(Firma: guloshop.de) #3727795
Lesenswert?

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.
Gast #3727830
Lesenswert?

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...
Gast #3728014
Lesenswert?

>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.
Gast #3741642
Lesenswert?

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.
Gast #3741769
Lesenswert?

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...
Gast #3741793
Lesenswert?

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...
Gast #3744264
Lesenswert?

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
#3744295
Lesenswert?

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.
Gast #3744309
Lesenswert?

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.
Gast #3744424
Lesenswert?

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.
Angehängte Dateien:
#3744520
Lesenswert?

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.
Gast #3744543
Lesenswert?

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.
#3744557
Lesenswert?

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.
Gast #3744645
Lesenswert?

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?
Gast #3744696
Lesenswert?

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.
Gast #3744934
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren