Forum: Mikrocontroller und Digitale Elektronik AVR Interrupt-Verhalten


von Tiny10Nutzer (Gast)


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

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Tiny10Nutzer schrieb:
> Welcher Interrupt wird dann als nächstes ausgeführt? Wird die
> Interrupttabelle einfach von vorn nach hinten abgearbeitet?

Ja.

von der alte Hanns (Gast)


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...

von Tiny10Nutzer (Gast)


Lesenswert?

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...?

von der alte Hanns (Gast)


Lesenswert?

> Freu... So dumm bin ich gar nicht...

Mitfreu; es bleibt nur noch etwas Feinarbeit:
> ...ausgelösst... währen...eigendlich...
Nichts für ungut.

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Cyblord -. (cyblord)


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".

von der alte Hanns (Gast)


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.

von Tiny10Nutzer (Gast)


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

von Route_66 H. (route_66)


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.

von Georg (Gast)


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

von Falk B. (falk)


Lesenswert?

@ 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.

von RomanK (Gast)


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

von RomanK (Gast)


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.

von Karl H. (kbuchegg)


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.

von RomanK (Gast)


Lesenswert?

Danke Karl-Heinz,

ich meinte ja auch die Interrupttabelle, und nicht irgendeinen Zähler.

Gruss

Roman

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

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

von RomanK (Gast)


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

von spess53 (Gast)


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

von Karl H. (kbuchegg)


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

: Bearbeitet durch User
von Tiny10Nutzer (Gast)


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

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Tiny10Nutzer (Gast)


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...

von vadammt (Gast)


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)

von Tiny10Nutzer (Gast)


Lesenswert?

Der Interrupt selber daurt nicht sonderlich lang. Er tritt nur so oft 
auf und darf nicht verschoben werden.

von Falk B. (falk)


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.

von Peter D. (peda)


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.

von Peter D. (peda)


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.

von Route_66 H. (route_66)


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.

von Norbert (Gast)


Lesenswert?

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 ;-)

von MCUA (Gast)


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)!

von (prx) A. K. (prx)


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.

: Bearbeitet durch User
von Markus W. (Firma: guloshop.de) (m-w)


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.

von MCUA (Gast)


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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Falk B. (falk)


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!

von Markus W. (Firma: guloshop.de) (m-w)


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.

von c-hater (Gast)


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...

von MCUA (Gast)


Lesenswert?

>Doch, man kann verschachtelte Interrupts auf dem AVR in Software
>nachbilden!
Was sagte ich denn oben?
>Beim (normalen) AVR geht das nicht (hardwaremässig)!

von MCUA (Gast)


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.

von Tiny10Nutzer (Gast)


Lesenswert?

Gehört ja genauso in diesees Thema:

Beitrag "Re: AVR Assembler-Frage"

von Ulrich (Gast)


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.

von c-hater (Gast)


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...

von c-hater (Gast)


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...

von Dieter F. (Gast)


Lesenswert?

In diesem Zusammenhang finde ich dieses Script

http://mit.eit.h-da.de/VorlesungenBeispiele_Wirth_WS1011/1000_Interrupt.pdf

ganz interessant.

von Tiny10Nutzer (Gast)


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

von Stefan E. (sternst)


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.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

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.

von Stefan E. (sternst)


Lesenswert?

Peter Dannegger schrieb:
> der RJMP zum Handler nochmal 2

Ups, die hab ich doch glatt vergessen. ;-)

von Tiny10Nutzer (Gast)


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.

von Tiny10Nutzer (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Tiny10Nutzer (Gast)


Angehängte Dateien:

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.

von Tiny10Nutzer (Gast)


Angehängte Dateien:

Lesenswert?

War die falsche Datei.

von Peter D. (peda)


Lesenswert?

Was stört Dich daran, einen Quelltext *.asm zu nennen?
Dann müßte ihn nicht jeder Leser umbenennen.

von Tiny10Nutzer (Gast)


Lesenswert?

Das war kein Quelltext.

von Stefan E. (sternst)


Lesenswert?

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.

von Tiny10Nutzer (Gast)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

Tiny10Nutzer schrieb:
> Ich meine die Ungleichheit bei

Quiz: Welche Zahl kommt nach 19?

von Tiny10Nutzer (Gast)


Angehängte Dateien:

Lesenswert?

Habe ich auch grade entdeckt. Jetzt stimmt das Beispiel wieder.

Aber... Simulator 2 in Studio 4 zeigt mir hier die Interruptabstände -1 
an.

von Stefan E. (sternst)


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.

von Tiny10Nutzer (Gast)


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.

von Stefan E. (sternst)


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.

von Tiny10Nutzer (Gast)


Lesenswert?

Ähmm ja... Ich habe den Zyklus-Zähler immer auf 0 gestellt. Klar die 0 
ist der erste Zyklus.

von Tiny10Nutzer (Gast)


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?

von (prx) A. K. (prx)


Lesenswert?

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
von Tiny10Nutzer (Gast)


Lesenswert?

Ich habe im Datenblatt des Tiny13A nachgelesen. Entweder ich habe es 
überlesen oder es steht dort nicht, wieviele Takte verbraucht werden.

von c-hater (Gast)


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.

von Ulrich (Gast)


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.

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
Noch kein Account? Hier anmelden.