Hallo,
werden Interrupts eigentlich gespeichert, solange diese noch nicht
ausgeführt worden sind? (In meinem Fall für einen Atmega328)
Wie verhält es sich, wenn ich eine Interruptroutine für eine Steigende
und fallende Flanke erstelle (z.B. von einem Button (Prellen
vernachlässige ich jetzt mal))
Wenn ich diesen Button sehr schnell drücke, sodass ein Interrupt
ausgelöst wird, obwohl die erste Interrupt-Routine noch nicht fertig
ist, wird diese danach wider ausgelöst? Wie viele Interrupts können
gespeichert werden?
Was passiert wenn ich ein Delay habe (nehmen wir mal an 5 Sekunden) und
ich drücke während des Delays den Button ein paar mal. Wird der
Interrupt auch ausgelöst?
Es ist nicht so, dass ich diese Probleme habe (vor allem nicht mit dem
Delay), es interessiert mich nur, wie soetwas vom uC gehändelt wird.
Gruß
Johannes
Naja das hängt halt maßgeblich im Prozessor ab.
Normalerweise gibt es eine IRQ-Priorisierung. Die gibt an, welcher
Interrupt welchen unterbrechen darf. Wieviele Prios es gibt, hängt vom
Prozessor ab.
Ein Prio-1 IRQ kann einen Prio-2 überfahren. Dann bleibt die Prio-2-ISR
einfach stehen, die Prio 1 wird ausgeführt, und zurück in die 2er
gesprungen.
Es gibt aber auch asynchrone Interrupts, da wird dann nicht zwangsläufig
unterbrochen bzw. hängt es vom Programmierer ab, ob der das möchte.
Wenn bereits eine ISR am laufen ist, und es wird ein IR mit gleicher
Prio gefeuert, dann geht der IRQ m.W.n. verloren. Es wäre aber auch
irgendwie merkwürdig, warum zweimal der gleiche IR gefeuert werden
sollte.
Deshalb gilt es auch, die ISR möglichst schlank zu halten, und alles
zeitaufwändige Handling in eine eigene, im regulären Programmablauf
befindliche Routine zu bearbeiten, die je nach Prozessor dann synchron
oder asynchron abgearbeitet werden kann.
Konkret auf deinen Atmega328 bezogen: Nein, der hat keine Möglichkeit
Interrupts zu schachteln bzw zu speichern. Wenn du deine aktuelle
Interrupt-Routine nicht abschließt, bevor ein neuer Interrupt geht der
neue Interrupt "verschütt".
Daher gelten die oben genannten Prinzipien.
Stefan S. schrieb:> Konkret auf deinen Atmega328 bezogen: Nein, der hat keine Möglichkeit> Interrupts zu schachteln
Nicht von sich aus, nein. Aber man kann sehr wohl die Interrupts im
Interrupt wieder freigeben.
Martin S. schrieb:> Wenn bereits eine ISR am laufen ist, und es wird ein IR mit gleicher> Prio gefeuert,
Das wird er nicht - jedenfalls nicht bei den Prozessoren, die ich kenne.
Wenn der Prozessor sich in einer Interruptroutine befindet, werden die
Interrupts dieser Prioritätsebene (und aller niedrigeren) normalerweise
gesperrt. Das "auslösende" Device hat üblicherweise nur ein Flag, um
anzuzeigen, was genau passiert ist und kann das nicht unterbringen,
solange der "alte" Interrupt noch nicht fertig abgearbeitet ist.
Es gibt Prozessoren, wo in dieser Situation (Interruptmaske
fälschlicherweise vor der Beendigung des Interrupts "aufgemacht") ein
"spurious Interrupt" ausgelöst wird.
Johannes schrieb:> Was passiert wenn ich ein Delay habe (nehmen wir mal an 5 Sekunden)
Wenn du ein delay(x) im Programm hast, hast du einfach ein beschissenes
Programm!
Max M. schrieb:> Wenn du ein delay(x) im Programm hast, hast du einfach ein beschissenes> Programm!
Aber den Interrupts ist das wurscht - die werden trotzdem ausgeführt.
_delay_ms() und _delay_us() blockieren keine Interrupts.
Max M. schrieb:>> Wird ein Interrupt gespeichert?>>> für einen Atmega328)>> @Johannes> @Martin> @Stefan>> Was ist so schwer daran die Docu zu lesen?
Ach richtig. Ich vergaß ja vollkommen, dass es nur einen einzigen
Prozessor auf der Welt gibt...
(Sag mal - liest Du Dir eigentlich auch durch, was du schreibst?)
Wenn der TO nunmal nach einem AtMega fragt, was nutzt dann eine Antwort
auf die Frage nach dem Leben, dem Universum und dem ganzen Rest?
Oliver
P.s. 42
Oliver S. schrieb:> Wenn der TO nunmal nach einem AtMega fragt
Ich verstand seine Frage als grundsätzlich, mit fernen Bezug auf seinen
Atmega.
Daher ist die Antwort weder falsch noch unpassend.
Johannes schrieb:> werden Interrupts eigentlich gespeichert, solange diese noch nicht> ausgeführt worden sind?
Das widerspricht dem Sinn eines Interrupts. Die sollen ja gerade das
laufende Programm unterbrechen (Interrupt == Unterbrechung). Natürlich
kannst Du innerhalb eines Interrupts eine Art Speicherung einbauen. Im
Falle Deines Buttons könntest Du z.B. den Tastendruck in einen Puffer
schreiben.
Wenn Du eine längere Aufgabe bearbeitest oder schläfst, dann unterbricht
Dein Körper trotzdem automatisch alle 2 Sekunden, um zu atmen. Das
geschieht meistens unbewusst. Und genau wie bei Interrupts ist es auch
hier nicht sinnvoll, das Atmen für 2 Stunden einzustellen und danach
3600 Atemzüge nachzuholen.
Viele Grüße, Stefan
Matthias S. schrieb:> Max M. schrieb:>> Wenn du ein delay(x) im Programm hast, hast du einfach ein beschissenes>> Programm!>> Aber den Interrupts ist das wurscht - die werden trotzdem ausgeführt.> _delay_ms() und _delay_us() blockieren keine Interrupts.
Wenn sie in der Interruptfunktion stehen schon. ;-) Das ist ja bei
Anfängern nicht unbedingt ausgeschlossen.
Dussel schrieb:> Wenn sie in der Interruptfunktion stehen schon. ;-) Das ist ja bei> Anfängern nicht unbedingt ausgeschlossen.
delay in einer ISR wird normalerweise vom Compiler ignoriert!
Beim Atmega328 könnte man das Setzen des Interrupt Flags als Speichern
eines Interrupts bezeichnen. Tritt ein Interrupt auf und tritt während
der Ausführung der Interruptserviceroutine ein weiter gleicher Interrupt
auf wird das Flag gesetzt und speichert diesen Interrupt solange bis es
manuell oder durch die entsprechende ISR automatisch gelöscht wird.
Ein zwei gleiche Interrupts werden so nicht gespeichert, da nur jeweil
ein Flag vorhanden ist. Mehrere andere Interrupts können mit den
entsprechenden Flags gespeichert werden und werden mit den zugehörigen
ISRs nacheinander abgearbeitet wenn keine andere ISR läuft, sie an der
Reihe sind und keine besondere Programmiermaßnahmen getroffen wurden.
Level Interrupts werden so nicht gespeichert, da da kein Flag gesetzt
wird.
Max M. schrieb:> Dussel schrieb:>> Wenn sie in der Interruptfunktion stehen schon. ;-) Das ist ja bei>> Anfängern nicht unbedingt ausgeschlossen.> delay in einer ISR wird normalerweise vom Compiler ignoriert!
Wo hast du denn diese schlaue Weisheit her?
Martin S. schrieb:> Daher ist die Antwort weder falsch noch unpassend.
Im Bezug auf den AtMega ist die Antwort in vielen Punkten sachlich
falsch.
Oliver
Matthias S. schrieb:> _delay_ms() und _delay_us() blockieren keine Interrupts.
Für die beiden gilt das...
Am Rande:
In meiner kleinen Arduino Welt, benötigt delay() selber Interrupts, so
dass man sich in einer ISR, auf die Art, fix mal eben einen Deadlock
einfängt.
Johannes schrieb:> werden Interrupts eigentlich gespeichert, solange diese noch nicht> ausgeführt worden sind?
Wie schon geschrieben, es wird nichts gespeichert solange die ISR nicht
aufgerufen wurde.
Aber ein laufender Interrupt kann durchaus von einem anderen
unterbrochen werden. Der Status wird über den Stack gespeichert, und
wenn der spätere Interrupt abgearbeitet ist, wird die erste Routine
wieder aufgenommen. Dabei besteht aber offensichtlich die Gefahr eines
stack overflows. Google einfach nach "atmega nested interrupts", es gibt
jede Menge tutorials und diskussionen hierzu.
Klaus P. schrieb:> Aber ein laufender Interrupt kann durchaus von einem anderen> unterbrochen werden.
Beim AVR ist das standardmäßig erst einmal nicht der Fall; beim
Eintritt in eine ISR löscht die Hardware das I-Flag, dieses wird
normalerweise dann durch RETI wieder gesetzt.
Es ist natürlich unbestritten, dass man das I-Flag auch selbst in
der ISR setzen kann; dann sollte man aber sehr genau wissen, was man
tut.
Der schon genannte Ratschlag, die ISRs so kurz wie möglich zu halten,
ist gemeinhin die bessere Methode.
Dass man irgendwelche manuell betätigten Taster gar nicht erst
interrupten lässt, ist eine völlig andere Sache. Mensch und Mechanik
sind langsam genug, als dass man das völlig unproblematisch in einem
regelmäßigen Timerinterrupt abfragen kann, der dann auch gleich die
Entprellung erledigt. Ausnahme: ein Interrupt durch einen Taster, mit
dem die MCU aus dem Schlaf geweckt wird. Dann ist aber die erste
Amtshandlung der ISR, den Taster als Interruptquelle sofort
abzuschalten.
Dussel schrieb:>> Aber den Interrupts ist das wurscht - die werden trotzdem ausgeführt.>> _delay_ms() und _delay_us() blockieren keine Interrupts.> Wenn sie in der Interruptfunktion stehen schon. ;-) Das ist ja bei> Anfängern nicht unbedingt ausgeschlossen.
Nö, das ist Quak. Die Delay Routinen der avrlibc lassen während ihrer
Ausführung ganz normal alle freigegebenen Interrupts zu, ob sie nun in
der ISR stehen oder nicht.
Das das Delay dann nicht mehr stimmt, ist eine andere Sache.
Wenn man es explizit tut, kann man auch andere Interrupts innerhalb
einer ISR auch wieder zulassen, der AVR sperrt zwar während der
Abarbeitung einer ISR das globale ISR Flag, aber niemand hindert einen
daran, es in der ISR wieder freizugeben. (avrlibc sieht dazu das
'ISR_NOBLOCK' vor). Aha, da war Jörg schneller.
Die Priorität ist beim AVR festgelegt und zwar absteigend mit den IRQ
Vektoren. D.H. die höchste Priorität hat Reset, im Allgemeinen folgt
dann INT0, siehe Vektortabelle.
Matthias S. schrieb:> Die Priorität ist beim AVR festgelegt und zwar absteigend mit den IRQ> Vektoren.
Die spielt allerdings nur eine Rolle, um festzulegen, welche ISR
zuerst bedient wird, wenn beim Freigeben der Interrupts (SEI) mehr
als ein Interrupt bereits anhängig ist.
Wenn man innerhalb einer ISR die Interrupts freigibt, dann dürfen
wiederum alle weiteren Interrupts diese ISR unterbrechen.
Oliver S. schrieb:> Martin S. schrieb:>> Daher ist die Antwort weder falsch noch unpassend.>> Im Bezug auf den AtMega ist die Antwort in vielen Punkten sachlich> falsch.
Wo? Ausschließlich die Frage Synchron/Asynchron passt zum Mega nicht.
Sonst?
Martin S. schrieb:> Normalerweise gibt es eine IRQ-Priorisierung.
Hat der AtMega nicht.
> Es gibt aber auch asynchrone Interrupts.
Hat der AtMega nicht.
>> Wenn bereits eine ISR am laufen ist, und es wird ein IR mit gleicher> Prio gefeuert, dann geht der IRQ m.W.n. verloren. Es wäre aber auch> irgendwie merkwürdig, warum zweimal der gleiche IR gefeuert werden> sollte.
Die erste Aussage ist für den AtMega (und sehr viele ander Prozessoren)
falsch, die zweite sowieso.
> Deshalb gilt es auch, die ISR möglichst schlank zu halten, und alles> zeitaufwändige Handling in eine eigene, im regulären Programmablauf> befindliche Routine zu bearbeiten, die je nach Prozessor dann synchron> oder asynchron abgearbeitet werden kann.
Ok
Kein sehr guter Schnitt...
Oliver
Jörg W. schrieb:> Die spielt allerdings nur eine Rolle, um festzulegen, welche ISR> zuerst bedient wird, wenn beim Freigeben der Interrupts (SEI) mehr> als ein Interrupt bereits anhängig ist.
Soweit ich weiss, würde es auch dann wichtig sein, wenn zwei IRQs
gleichzeitig eintreffen.
Arduino F. schrieb:> In meiner kleinen Arduino Welt, benötigt delay() selber Interrupts
Das tut mir leid. Aber da ist euch wohl der Ticker mit seinen millis()
o.ä. im Weg. Das kann natürlich mal blöd sein. Aufm STM32 hatte ich mal
den Delay mit Systick() in einer Elektromagnet-Bedien ISR. Da hing er
dann, bis ich die Prioritäten umgeschnurzelt hatte und Systick()
wichtiger machte. Das geht aufm AVR nicht, Timer 0 (oder was auch immer
da triggert) ist ziemlich weit hinten.
Martin S. schrieb:> Es gibt aber auch asynchrone Interrupts, da wird dann nicht zwangsläufig> unterbrochen bzw. hängt es vom Programmierer ab, ob der das möchte.Synchrone Interrupts stehen in direktem Zusammenhang mit dem
Befehlsablauf. Sowas wie Division durch 0 fällt darunter. Werden oft
auch zwecks Unterscheidung als Traps oder Exceptions bezeichnet.
Asynchrone Interrupts werden von Ereignissen ausgelöst, die mit dem
Befehlsablauf nichts zu tun haben. Das sind die üblichen
Hardware-Interrupts durch Timer, UART etc.
Matthias S. schrieb:> Jörg W. schrieb:>> Die spielt allerdings nur eine Rolle, um festzulegen, welche ISR>> zuerst bedient wird, wenn beim Freigeben der Interrupts (SEI) mehr>> als ein Interrupt bereits anhängig ist.>> Soweit ich weiss, würde es auch dann wichtig sein, wenn zwei IRQs> gleichzeitig eintreffen.
Das stimmt zwar, dürfte aber in der realen Welt seltener als ein
Sechser im Lotto sein. :)
Oliver S. schrieb:> Martin S. schrieb:>> Normalerweise gibt es eine IRQ-Priorisierung.>> Hat der AtMega nicht.
Der Atmega2560 hat sogar 12 Interruptvektoren.
>> Es gibt aber auch asynchrone Interrupts.>> Hat der AtMega nicht.
Zitat:
External interrupts can be sensed and registered either synchronously or
asynchronously. Synchronous
sensing requires I/O clock whereas asynchronous sensing does not
requires I/O clock. This implies that
the interrupts that are detected asynchronously can be used for waking
the device from sleep modes
other than idle mode because the I/O clock is halted in all sleep modes
except idle mode.
The sense configuration for external interrupts and pin change
interrupts for Atmel ATmega2560 is given
in Table 1-2 External Interrupts Sense Configuration. For device
specific sense configuration, refer to the
respective datasheet.
Sowie:
Asynchronous Sensing in ATmega2560
From Table 1-2 External Interrupts Sense Configuration interrupts INT3:0
are registered asynchronously.
Pulses on INT3:0 pins wider than the minimum pulse width (typically 50ns
for ATmega2560) will generate
an interrupt. Shorter pulses are not guaranteed to generate an
interrupt.
Synchronous Sensing in ATmega2560
From Table 1-2 External Interrupts Sense Configuration, interrupts
INT7:4 are registered synchronously.
The value on the INT7:4 pins are sampled before detecting edges. If edge
or toggle interrupt is selected,
pulses that last longer than one clock period will generate an
interrupt. Shorter pulses are not guaranteed
to generate an interrupt. For both types of sensing, if low level
interrupt is selected, the low level must be
held until the completion of the currently executing instruction to
generate an interrupt.
>> Wenn bereits eine ISR am laufen ist, und es wird ein IR mit gleicher>> Prio gefeuert, dann geht der IRQ m.W.n. verloren. Es wäre aber auch>> irgendwie merkwürdig, warum zweimal der gleiche IR gefeuert werden>> sollte.>> Die erste Aussage ist für den AtMega (und sehr viele ander Prozessoren)> falsch, die zweite sowieso.
Zitat:
Interrupt Priority
Priority for the interrupts is determined by the interrupt vector
address. An interrupt with lowest interrupt
vector address has the highest priority. So reset has the highest
priority followed by INT0, then INT1 and
so on. If two interrupts occurs simultaneously, then the interrupt with
higher priority is served first.
Sowie
Once the CPU enters the ISR, the global interrupt enable bit (I-bit) in
SREG will be cleared so that
all other interrupts are disabled. In order to use nested interrupts,
the I-bit has to be set by software
when the CPU enters an ISR.
>> Deshalb gilt es auch, die ISR möglichst schlank zu halten, und alles>> zeitaufwändige Handling in eine eigene, im regulären Programmablauf>> befindliche Routine zu bearbeiten, die je nach Prozessor dann synchron>> oder asynchron abgearbeitet werden kann.>> Ok>> Kein sehr guter Schnitt...
Gelle?! Das denke ich mir doch auch ;-)
Fairerweise muss man sagen, dass diese Aussagen nicht zwangsläufig auf
den Mega des TO zutrifft, aber Du hast ja prinzipiell in Frage gestellt,
dass der Atmega das überhaupt kann / hat.
Im Zweifelsfalle steht vermutlich kaum was anderes in den jeweiligen
Datenblättern, weil o.g. seit 30 Jahren Standard ist.
Martin S. schrieb:>>> Normalerweise gibt es eine IRQ-Priorisierung.>>>> Hat der AtMega nicht.>> Der Atmega2560 hat sogar 12 Interruptvektoren.
Bei Priorisierung von Interrupts können hoch priorisierte Interrupts
niedriger priorisierte Interrupt-Handler unterbrechen. Die bei AVRs
vorhandene Entscheidung, welcher Vektor bei mehreren anstehenden
Interrupts angesprungen wird, versteht man darunter üblicherweise nicht.
AVRs Vektoren sind priorisiert, die Interrupts an sich aber nicht.
> External interrupts can be sensed and registered either synchronously or> asynchronously.
Atmel schreibt hier "synchronous sensing", nicht "synchronous
interrupt". Wenn man genau sein und Missverständnisse vermeiden will,
kann man notfalls dazuschreiben, auf was genau man sein "(a)synchron"
bezieht. Ob auf den Befehlsfluss oder die Taktversorgung.
Es kann sich lohnen, das Blickfeld etwas über AVRs hinaus zu erweitern,
auch wenn es in einem Thread um AVRs geht. Das vermeidet
Missverständnisse, was typübergreifende Begriffe und proprietäre
Formulierungen betrifft.
Matthias S. schrieb:>> Die spielt allerdings nur eine Rolle, um festzulegen, welche ISR>> zuerst bedient wird, wenn beim Freigeben der Interrupts (SEI) mehr>> als ein Interrupt bereits anhängig ist.>> Soweit ich weiss, würde es auch dann wichtig sein, wenn zwei IRQs> gleichzeitig eintreffen.
Beides oder weder noch.
Bei eingeschalteten Interrupts entscheidet der Prozessor an einer
bestimmten Stelle der Schritte der Abarbeitung anhand der zu diesem
Zeitpunkt anstehenden Interrupt-Anforderungen über den Vektor.
Entscheidend ist somit nicht, wie gleichzeitig sie eintreffen, sondern
welche Interrupt-Anforderungen zu genau diesem Zeitpunkt aktiv sind.
Man kann das noch feiner runterbrechen, indem man zwischen dem Zeitpunkt
der Entscheidung, überhaupt einen Interrupt auszuführen, und der
Entscheidung über den dafür genutzten Vektor unterscheidet. Das muss
sich nicht decken, beispielsweise wenn die Entscheidung über den Vektor
erst unmittelbar davor getroffen wird, was mehr oder weniger deutlich
nach dem Stack-Push vom PC geschehen kann.
Beim AVR ist das Interrupt-Handling eigentlich sehr einfach:
Jeder Interrupt hat ein eigenes Interrupt-Flag (ein paar Ausnahmen
gibt's allerdings). Wenn die Bedingung für den Interrupt eintritt, wird
dieses Flag gesetzt. Das ist die eine Seite. Auf der anderen steht dann
die Auslösung des Interrrupts. Die ist von drei Flags abhängig, nämlich
besagtem Interrupt-Flag, dem Interrupt-Enable-Flag für diesen Interrupt
und dem globalen Interrupt-Enable im SREG. Sind alle drei gesetzt, wird
der Interrupt ausgelöst. Dabei wird automatisch das globale
Interrupt-Enable und das Interrupt-Flag wieder gelöscht. Nach der ISR
wird das globale Interrupt-Enable beim Rücksprung per RETI wieder
automatisch gesetzt.
Sobald die Bedingung wieder eintritt, wird das Interrupt-Flag wieder
gesetzt, egal ob man gerade in der ISR ist oder in einer anderen ISR,
oder ob der Interrupt gerade aus einem anderen Grund ausgeschaltet ist
oder nicht. Der Interrupt wird dann auch wieder ausgelöst, sobald alle
drei Flags gesetzt sind.
Matthias S. schrieb:> Jörg W. schrieb:>> Die spielt allerdings nur eine Rolle, um festzulegen, welche ISR>> zuerst bedient wird, wenn beim Freigeben der Interrupts (SEI) mehr>> als ein Interrupt bereits anhängig ist.>> Soweit ich weiss, würde es auch dann wichtig sein, wenn zwei IRQs> gleichzeitig eintreffen.
Ganz allgemein: Wenn für zwei (oder mehr) Interrupts der Fall, dass die
drei Flags alle gesetzt sind, im selben Taktzyklus auftritt.
Martin S. schrieb:> Der Atmega2560 hat sogar 12 Interruptvektoren.
Hat der nicht, der hat 57.
Es macht ja nichts, daß du bisher noch nie mit den AtMegas zu tun
hattest, aber so deutlich musst du es ja nicht zeigen. Die Dinger sind
nunmal in vielem sehr viel einfacher gestrickt als „richtige“
Mikrocontroller.
Oliver
Rolf M. schrieb:> Ganz allgemein: Wenn für zwei (oder mehr) Interrupts der Fall, dass die> drei Flags alle gesetzt sind, im selben Taktzyklus auftritt.
Nicht unbedingt. Wenn sich die von mir vorhin genannten zwei Zeitpunkte
nicht decken, dann kann es vorkommen, dass ein Handler angesprungen
wird, dessen Interrupt-Anforderung erst einen oder mehrere Takte nach
dem ersten der beiden Interrupts eintrudelte.
Der erste Interrupt hat dann zwar den Prozessor aus der Bahn geworfen
und führte zur Einleitung des Interrupt-Verfahren, aber der Vektor des
zweiten Interrupts wird angesprungen. Noch krasser ist das bei Cortex M,
bei denen eine bereits getroffene Vektor-Entscheidung ggf. wieder
rückgängig gemacht wird, wenn ein höherer Interrupt noch vor dem ersten
Befehl des Handlers reinkommt.
Zudem geht es bei den meisten Prozessoren nicht so sehr um Taktzyklen,
sondern um Befehlszyklen. Wenn die Entscheidung, ein Interrupt-Verfahren
einzuleiten, in an einer bestimmten Stelle in der Befehlsbearbeitung
erfolgt, nicht in jedem Takt. Da gibts freilich Ausnahmen, manchmal sind
Befehle mit langer Laufzeit unterbrechbar.
A. K. schrieb:> Das muss sich nicht decken, beispielsweise wenn die Entscheidung über> den Vektor erst unmittelbar davor getroffen wird, was mehr oder weniger> deutlich nach dem Stack-Push vom PC geschehen kann.
Um das zu wissen, müsste man wohl in den Verilog-Code reingucken. ;-)
Aber jetzt wird es allmählich schon fast Haarspalterei.
Rolf M. schrieb:> Dabei wird automatisch das globale> Interrupt-Enable und das Interrupt-Flag wieder gelöscht.
Mit ein paar wenigen Ausnahmen, z.B. wird das RXC Flag des Uarts erst
beim Lesen des Uart-Data-registers UDR gelöscht.
Genauso sieht es beim UART Transmitter aus. Das UDRE Flag wird erst dann
gelöscht, wenn ein neues Zeichen in UDR zum Versenden geschrieben wird.
Das ermöglicht z.B. beim Senden mit Handshake, im TXD-ISR zuerst die
Handshake-leitung zu testen. Ist diese busy, dann wird der TXD-ISR
disabled (UDRIE) und der ISR ohne das Senden eines Zeichens verlassen.
Irgendwo anders (Timer-ISR) kann jetzt zyklisch das Handshake getestet
werden. Bei Handshake=ready wird UDRIE wieder gesetzt und dadurch der
TXD-ISR erneut ausgeführt. In diesem Fall "merkt" sich das ISR-Flag
tatsächlich den Zustand.
Ab dem Zeitpunkt, an dem das lokale ISR-Flag gelöscht wurde, kann auch
die nächste ISR-Anforderung dieser Quelle registriert werden. Wird z.B.
ein Timer-ISR aufgerufen (und dadurch automatisch das Timer-ISR-Flag
gelöscht), dann kann noch während der Abarbeitung dieses ISR das lokale
ISR-Flag wieder gesetzt werden. Die Abarbeitung erfolgt dann (fast*)
direkt nach dem Beenden der gerade laufenden ISR-Routine.
* fast, weil:
Zwischen 2 ISR-Aufrufen wird immer ein Befehl des Hauptprogramms
ausgeführt:
"When the AVR exits from an interrupt, it will always return to the main
program and execute one more instruction before any pending interrupt is
served."
Viele Grüße, Stefan
Jörg W. schrieb:> A. K. schrieb:>> Das muss sich nicht decken, beispielsweise wenn die Entscheidung über>> den Vektor erst unmittelbar davor getroffen wird, was mehr oder weniger>> deutlich nach dem Stack-Push vom PC geschehen kann.>> Um das zu wissen, müsste man wohl in den Verilog-Code reingucken. ;-)
Oder man probiert es einfach mal aus.
Oliver
Oliver S. schrieb:> Martin S. schrieb:>> Der Atmega2560 hat sogar 12 Interruptvektoren.>> Hat der nicht, der hat 57.> Es macht ja nichts, daß du bisher noch nie mit den AtMegas zu tun> hattest, aber so deutlich musst du es ja nicht zeigen. Die Dinger sind> nunmal in vielem sehr viel einfacher gestrickt als „richtige“> Mikrocontroller.>> Oliver
Dann weißt du mehr als Atmel. Die 12 stehen da nämlich in den Release
Notes.
Martin S. schrieb:> Die 12 stehen da nämlich in den Release Notes.
Welche Release Notes?
Aber da du es nicht glaubst, hier mal ein Screenshot des Datenblatts.
Ich musste es bis zur Unleserlichkeit skalieren, damit alle auf den
Bildschirm passen …
Das Einzige, was an dieser "Priorisierung" (das kam sicher aus der
Atmel-Marketingabteilung) wichtig ist:
Wenn ISR eine Weile disabled waren (durch cli oder einen anderen ISR)
und sich in dieser Zeit mehrere ISR-Flags angesammelt haben, dann werden
diese in der Reihe ihrer Priorität abgearbeitet. Das bedeutet für
niedrigpriore ISRs, dass ihre Latenzzeit worstcase (*) die
Abarbeitungszeit aller höher prioren ISRs beträgt.
(*)
Wenn sich einer dieser ISRs innerhalb dieser Zeit wiederholen kann, wird
es sogar noch schlimmer.
Viele Grüße, Stefan
Hallo,
zusammengefasst. Wenn ein Interrupt eingetroffen und ausgeführt wird,
kann noch ein zweiter gleichen Typs erkannt werden, der dann
abgearbeitet wird wenn der erste des Typs fertig ist. Tritt während der
Abarbeitung des erstens noch ein dritter ein, geht dieser und alle
weiteren verloren, bis der erste fertig ist.
Anders ausgedrückt, an der Tür klingelt es (Interrupt) du gehst gucken
und quatscht mit der Person. Du bearbeitest den ersten Interrupt.
Während dessen klingelt es nochmal. Du registrierst das eine zweite
Person etwas von dir will und merkst dir das. Wenn du das erste
Gespräche beendest gehste zur nächsten Person. Während du jedoch mit der
ersten Person noch redest, ignorierst du konseqent alles weitere
klingeln nach der zweiten Person.
Checker schrieb:> Während du jedoch mit der> ersten Person noch redest, ignorierst du konseqent alles weitere> klingeln nach der zweiten Person.
Nicht ignorieren. Ignorieren würde bedeuten, dass du es mitbekommst. Das
ist aber das Problem, du bekommst erst gar nicht mit dass es da noch
eine 3, 4, 5 usw. Person gibt, die mit dir Quatschen will. Ansonsten
aber ein gutes Analogon.
Checker schrieb:> Tritt während der> Abarbeitung des erstens noch ein dritter ein, geht dieser und alle> weiteren verloren, bis der erste fertig ist.
Nö, der zuletzt eingetroffene - welcher von der Priorität her an der
Reihe ist - wird abgearbeitet. Das Flag kennt keine Reihenfolge-Nr. -
der letzte (aktuelle) "Interrupt-Zustand" wird bearbeitet. Stell Dir
einen PIN-Change-Interrupt vor - wenn es in der Zwischenzeit 3 oder 5
oder 15 davon gab kann nur der letzte (halbwegs) korrekt verarbeitet
werden - oder?
Das "halbwegs" ist auch der Grund dafür, warum man "niederwertige"
Interrupts mit Vorsicht geniessen sollte :-)
Checker schrieb:> Anders ausgedrückt, an der Tür klingelt es (Interrupt) du gehst gucken> und quatscht mit der Person. Du bearbeitest den ersten Interrupt.> Während dessen klingelt es nochmal. Du registrierst das eine zweite> Person etwas von dir will und merkst dir das. Wenn du das erste> Gespräche beendest gehste zur nächsten Person. Während du jedoch mit der> ersten Person noch redest, ignorierst du konseqent alles weitere> klingeln nach der zweiten Person.
Nö, wie vor - der letzte Klingler ist der nächste - alle dazwischen sind
Schall und Rauch :-)
Dieter F. schrieb:> Nö, wie vor - der letzte Klingler ist der nächste - alle dazwischen sind> Schall und Rauch :-)
Nö, im Prinzip hat Checker schon recht: der zweite Klingler hat das Flag
gesetzt, daher weiß man, dass da noch jemand an der Tür steht und
wartet. Die nachfolgenden Klingler setzten nur das schon gesetzte Flag
erneut, die bekommt man also nicht mit.
M. K. schrieb:> Die nachfolgenden Klingler setzten nur das schon gesetzte Flag> erneut, die bekommt man also nicht mit.
Da verstehst Du etwas nicht richtig. Das Flag ist und bleibt gesetzt -
aber nur der letzte - aktuelle - Klingler ist sichtbar. Die
Vergangenheit ist Vergangenheit ... und bleibt es auch.
Oder glaubst Du im Ernst, ein PIN-Change wird gespeichert? Dann verrate
mir bitte wo :-)
Dieter F. schrieb:> Da verstehst Du etwas nicht richtig. Das Flag ist und bleibt gesetzt -
Ja, aber wer hat denn das Flag gesetzt? Der letzte Klingler oder der
Zweite? Das ist doch der Knackpunkt ;)
Dieter F. schrieb:> Oder glaubst Du im Ernst, ein PIN-Change wird gespeichert? Dann verrate> mir bitte wo :-)
Ja, im Pin Change Interupt Flag Register.
M. K. schrieb:> Ja, aber wer hat denn das Flag gesetzt? Der letzte Klingler oder der> Zweite?
Du kannst sie nicht mehr unterscheiden. Du weißt, dass nur noch
mindestens ein Zweiter geklingelt hat. Wie viele es wirklich
waren, verrät dir niemand mehr.
M. K. schrieb:> Ja, aber wer hat denn das Flag gesetzt? Der letzte Klingler oder der> Zweite? Das ist doch der Knackpunkt ;)
Der ERSTE Klingler nach dem aktuellen Interrupt (sorry für das
Geschrei). Ein Flag kann man nur einmal setzen (es sei denn, es wurde
zwischenzeitig gelöscht - aber nicht in diesem Beispiel).
M. K. schrieb:> Ja, im Pin Change Interupt Flag Register.
Im "Pin Change Interupt Flag Register" wird das Flag gespeichert - sonst
REIN GAR NICHTS (nochmals sorry für das Geschrei).
Der Zustand des entsprechenden Ports hat sich in der Zwischenzeit 0 ...
n mal geändert. Nur der letzte Zustand in der Interrupt-Verarbeitung
kann ausgewertet werden. Vergangene Zustände des Ports sind nicht mehr
verfügbar.
Jörg W. schrieb:> Du kannst sie nicht mehr unterscheiden. Du weißt, dass nur noch> mindestens ein Zweiter geklingelt hat. Wie viele es wirklich> waren, verrät dir niemand mehr.Dieter F. schrieb:> Der ERSTE Klingler nach dem aktuellen Interrupt (sorry für das> Geschrei). Ein Flag kann man nur einmal setzen.
Eben, das mein ich doch. Ich glaub wir reden aneinander vorbei. Es wird
gespeichert, dass mindestens noch einer geklingelt hat, es könnte aber
auch tausende gewesen sein, das wissen wir nicht.
Dieter F. schrieb:> Nur der letzte Zustand in der Interrupt-Verarbeitung> kann ausgewertet werden.
Und genau das ist der Knackpunk. Es ist nicht der letzte Zustand sondern
der erste, der die Interrupt-Verarbeitung anschubst. Der letzte Zustand
ist nur der, der (möglicherweise) noch verfügbar ist, angeschubst hat
die Verarbeitung aber der erste Zustand.
Beim obigen Beispiel heißt das also: Nicht der letzte Klingler bewegt
dich dazu noch mal zur Tür zu gehen sondern der zweite Klingler. Ob der
dann noch da ist wenn du zur Tür gehst ist eine völlig andere Frage.
M. K. schrieb:> Und genau das ist der Knackpunk. Es ist nicht der letzte Zustand sondern> der erste, der die Interrupt-Verarbeitung anschubst. Der letzte Zustand> ist nur der, der (möglicherweise) noch verfügbar ist, angeschubst hat> die Verarbeitung aber der erste Zustand.
Nö, das ist Quackes. Nur weil der letzte das Flag nicht setzen kann
heisst nicht, dass er es nicht angestossen hat. Im Falle "Flag" hat der
Letzte Recht. (Punkt)
Nur dessen "Grund" für das Flag kann bearbeitet werden - oder?
M. K. schrieb:> Nicht der letzte Klingler bewegt> dich dazu noch mal zur Tür zu gehen sondern der zweite Klingler.
Nö - den hört der Interrupt gar nicht. Der ist taub für Klingeln. Erst
wenn er beendet ist, werden Klingeln wieder gehört - z. B. die 5. oder
15. Klingel.
Dieter F. schrieb:> Nö - den hört der Interrupt gar nicht. Der ist taub für Klingeln. Erst> wenn er beendet ist, werden Klingeln wieder gehört - z. B. die 5. oder> 15. Klingel.
FSoweit ich weiß wird das Flag gelöscht wenn die ISR angesprungen wird.
M. K. schrieb:> FSoweit ich weiß wird das Flag gelöscht wenn die ISR angesprungen wird
Ja und wieder gesetzt, wenn ein erneutes Interrupt-Ereignis eintritt.
Wie Du auch schon geschieben hast.
M. K. schrieb:> der zweite Klingler hat das Flag> gesetzt
Jörg W. schrieb:>> Ich glaub wir reden aneinander vorbei.> Nö, wir meinen alle dasselbe. :)
Aber bei der Diskussion kann man feststellen, dass es gar nicht so
einfach ist, ein wasserdichtes Manual zu schreiben.
Viele Grüße, Stefan
M. K. schrieb:> Dieter F. schrieb:>> Da verstehst Du etwas nicht richtig. Das Flag ist und bleibt gesetzt ->> Ja, aber wer hat denn das Flag gesetzt? Der letzte Klingler oder der> Zweite? Das ist doch der Knackpunkt ;)
Beide! Bei jedem Eintreten der Interrupt-Bedingung wird das Flag
gesetzt, unabhängig davon, ob es vorher schon gesetzt war oder nicht.
Dieter F. schrieb:> M. K. schrieb:>> Ja, aber wer hat denn das Flag gesetzt? Der letzte Klingler oder der>> Zweite? Das ist doch der Knackpunkt ;)>> Der ERSTE Klingler nach dem aktuellen Interrupt (sorry für das> Geschrei). Ein Flag kann man nur einmal setzen
Und beim zweiten Versuch explodiert es? Da kann ich beliebig oft eine 1
rein schreiben. Sie wird den Zustand nicht mehr ändern, aber
reingeschrieben hab ich sie trotzdem.
Dieter F. schrieb:> M. K. schrieb:>> Die nachfolgenden Klingler setzten nur das schon gesetzte Flag>> erneut, die bekommt man also nicht mit.>> Da verstehst Du etwas nicht richtig. Das Flag ist und bleibt gesetzt -> aber nur der letzte - aktuelle - Klingler ist sichtbar. Die> Vergangenheit ist Vergangenheit ... und bleibt es auch.
Hier vermischst du zwei Sachen: Die Auslösung des Interrupts und den
Status der Hardware. Abgesehen davon: Wenn zwei Pins, die am selben
Pin-Change-Interrupt hängen, ihren Zustand wechseln, sieht man danach
selbstverständlich von beiden den neuen Zustand und nicht nur vom
letzten der beiden.
Rolf M. schrieb:> Beide! Bei jedem Eintreten der Interrupt-Bedingung wird das Flag> gesetzt, unabhängig davon, ob es vorher schon gesetzt war oder nicht.
Quackes - ein Bit kann nur einmal gesetzt werden.
Rolf M. schrieb:> Und beim zweiten Versuch explodiert es? Da kann ich beliebig oft eine 1> rein schreiben. Sie wird den Zustand nicht mehr ändern, aber> reingeschrieben hab ich sie trotzdem.
Nö, was da ist (als Bit) kann nicht mit gleichem Wert "überschrieben"
werden.
Rolf M. schrieb:> sieht man danach> selbstverständlich von beiden den neuen Zustand und nicht nur vom> letzten der beiden.
Bezogen auf M. K. stimmt das.
Warum beantworte ich so etwas eigentlich - dazu sind doch Moderatoren da
oder? :-)
Dieter F. schrieb:> Rolf M. schrieb:>> Beide! Bei jedem Eintreten der Interrupt-Bedingung wird das Flag>> gesetzt, unabhängig davon, ob es vorher schon gesetzt war oder nicht.>> Quackes - ein Bit kann nur einmal gesetzt werden.
Ich kann in ein Register reinschreiben, was ich will, auch das, was
schon drin steht.
> Rolf M. schrieb:>> Und beim zweiten Versuch explodiert es? Da kann ich beliebig oft eine 1>> rein schreiben. Sie wird den Zustand nicht mehr ändern, aber>> reingeschrieben hab ich sie trotzdem.>> Nö, was da ist (als Bit) kann nicht mit gleichem Wert "überschrieben"> werden.
Also hat der Prozessor eine Schaltung eingebaut, die vor dem Setzen des
Registers prüft, ob es schon gesetzt ist und dann den Schreibvorgang
unterdrückt? Oder wie genau wird verhindert, dass der gleiche Wert
nochmal reingeschrieben wird?
Rolf M. schrieb:> Oder wie genau wird verhindert, dass der gleiche Wert> nochmal reingeschrieben wird?
Gar nicht - aber was ist die Auswirkung? Ändert sich irgendetwas?
Dieter F. schrieb:> Gar nicht - aber was ist die Auswirkung?
Die Auswirkung ist, dass deine Aussage
Dieter F. schrieb:> ein Bit kann nur einmal gesetzt werden.
falsch ist. Ob sich irgend etwas ändert ist wieder eine ganz andere
Frage.
M. K. schrieb:> Die Auswirkung ist, dass deine Aussage>> Dieter F. schrieb:>> ein Bit kann nur einmal gesetzt werden.>> falsch ist. Ob sich irgend etwas ändert ist wieder eine ganz andere> Frage.
Setze das Bit bitte 2 mal - und berichte die Auswirkung. Insbesondere
die Aussage, dass das Bit 2 oder n-mal gesetzt wurde ( mit Nachweis der
Änderungen auf Bit-Ebene)
Dieter F. schrieb:> Setze das Bit bitte 2 mal - und berichte die Auswirkung
Du verstehst es einfach nicht. Ursache und Wirkung sind zwei
verschiedene Dinge. Macht hier keinen Sinn weiter zu diskutieren.
M. K. schrieb:> Du verstehst es einfach nicht. Ursache und Wirkung sind zwei> verschiedene Dinge. Macht hier keinen Sinn weiter zu diskutieren.
Nö - Du verstehst es nicht - ein Bit kann man nur setzen oder löschen -
ob mehrfach oder einfach spielt keine Rolle.
Dieter F. schrieb:> ein Bit kann man nur setzen oder löschen -> ob mehrfach oder einfach spielt keine Rolle.
Und genau das verstehst du nicht. Du mischst Aktion (= Bit setzen) mit
Reaktion (= Bit ist gesetzt). Wenn du eine Tasse voll Wasser hast (= Bit
ist gesetzt) kann du in diese Tasse eine weitere Tasse Wasser kippen (=
Bit setzen). Die Tasse ist dann immer noch voller Wasser (= Bit ist
immer noch gesetzt), das ändert aber nichts daran, dass du eine weitere
Tasse Wasser in die Tasse geschüttet hast (= das Bit ein weiteres Mal
gesetzt hast).
Du hast natürlich völlig recht, dass das keine Rolle spielt ob man ein
Bit noch mal setzt wenn es schon gesetzt ist, es ändert aber nichts an
der Aktion dass man es noch mal gesetzt hat.
M. K. schrieb:> Und genau das verstehst du nicht.M. K. schrieb:> Du hast natürlich völlig recht, dass das keine Rolle spielt ob man ein> Bit noch mal setzt wenn es schon gesetzt ist, es ändert aber nichts an> der Aktion dass man es noch mal gesetzt hat.
Ja.
Dieter F. schrieb:> Nö - Du verstehst es nicht - ein Bit kann man nur setzen oder löschen -> ob mehrfach oder einfach spielt keine Rolle.
Richtig. Genau das hatte ich ja geschrieben:
Rolf M. schrieb:> Da kann ich beliebig oft eine 1 rein schreiben. Sie wird den Zustand nicht> mehr ändern, aber reingeschrieben hab ich sie trotzdem.
Oben hattest du aber noch behauptet, das Schreiben wäre gar nicht mehr
möglich, wenn schon eine 1 drin steht.
A. K. schrieb:> Er hat nur asynchrone Interrupts, aber keine synchronen.
Falsch.
Man kann jeden externen (also Pin-bezogenen) AVR-Interrupt zu dem
machen, was einen "synchronen Interrupt" ausmacht (das ist schlicht
einer, den die Software selber induziert, nicht externe Ereignisse). In
den Datenblättern wird auch jeweils ausdrücklich auf diese Möglichkeit
hingewiesen.
Darüber hinaus kann man natürlich auch durch entsprechende
Programmierung der jeweiligen Peripherie-Baugruppen auch fast jeden
anderen Interrupt der AVR8-Peripherie zu einem "synchronen" Interrupt
machen, nur die zu erwartenden Latenzen variieren natürlich etwas...
Das Minimum für die Latenz sind halt zwei Takte, (alle externen
Interrupts und Timer bei entsprechender Konfiguration). Das entspricht
exakt der Minimal-Latenz für die Auslösung von AVR8-Interrupts
überhaupt.
c-hater schrieb:> Falsch.
Postings, die so brachial anfangen, stehen meist auf sehr wackeligen
Beinen.
Du gibst lediglich Beispiele dafür, wie man die Peripherie
"missbrauchen" kann, um das gleiche Verhalten wie bei synchronen
Interrupts zu erzielen. Das bedeutet nicht, dass der AVR synchrone
Interrupts eingebaut hat.
Ich kann auch ein Auto fliegen lassen, indem ich es mit einem großen
Katapult werfe. Das macht daraus aber kein Flugzeug.
Habe ich etwas geraucht - oder habt ihr etwas geraucht?
Wir schreiben von Flags und plötzlich tauchen synchrone und asyncrone
Interrupts auf. Interessant!
@C-Hater: Kannst Du bitte auf der Flag-Ebene bleiben? Danke!
Falls das nicht geht erkläre bitte mal den Unterschied zwischen
synchronen und ansychronen Interrupts auf Basis des besprochenen
ATMega328 in diesem Thread. Ich bin gespannt und warte auf Deine
Ausführungen.
Johannes schrieb:> Hallo,> werden Interrupts eigentlich gespeichert, solange diese noch nicht> ausgeführt worden sind? (In meinem Fall für einen Atmega328)
Ja, es wird ein Interrupt-spezifisches Bit gesetzt (RXC0 wenn ein
Mega368 ein Byte via UART0 empfangen hat) und in der Regel gibt es ein
EnableInt-Bit, mit dem man die Ausführung der zugehörigen ISR freigeben
kann. Falls dann die CPU "Zeit hat", sprich bei gesetztem I-Flag nach
jeder Ausführung eines Befehls, wird der PC auf den Stack ge-pushed und
der ISR-Vector angesprungen. Ein AVR löscht dabei auch das I-Flag bis
spätesten zum RETI, das sich vom RET nur durch setzen des I-Flags
unterscheidet. Gibt es nun ein anderes Interrupt-Bit das auf 1 sitzt und
freigegeben ist, dann wird diese ISR ausgeführt.
Viele Interrupt-Quellen setzen ihr Intflag automatisch zurück, z.B.
UART-Receive, wenn das Data-Register gelesen wird und sind ab dann
bereit das nächste "Interrupt-Ereignis" zu speichern manche müssen aber
auch explizit zurückgesetzt werden, andernfalls gibt es "Dauer-ISR". Ein
"Löw-Level"-Mode von INTn verhält sich auch so. Solange Löw anliegt,
wird die ISR immer wieder neu gestartet. Will man das umgehen, muß man
das zugehörende Enable-Bit löschen.
> Wie verhält es sich, wenn ich eine Interruptroutine für eine Steigende> und fallende Flanke erstelle (z.B. von einem Button (Prellen> vernachlässige ich jetzt mal))>> Wenn ich diesen Button sehr schnell drücke, sodass ein Interrupt> ausgelöst wird, obwohl die erste Interrupt-Routine noch nicht fertig> ist, wird diese danach wider ausgelöst? Wie viele Interrupts können> gespeichert werden?
Bei einem Button wird der μC wohl immer mitkommen, es gibt aber bei der
AVR-UART den Fall, das das Senderegister Daten aufnehmen kann (UDRE User
Data Register Empty). Diese werden, falls das Schiftregister auch frei
ist sofort dorthin weiter geleitet und damit ist, noch bevor die ISR
enden kann UDRE wieder gesetzt. Wird dies von der ISR nicht behandelt,
kommt es nach RETI und der Ausführung eines Befehls der Main-Loop gleich
zum nächsten Int, da ja das auslösende Bit wieder sitzt.
Es werden also schnell folgende "Ereignisse" gespeichert, sobald der
1-Bit-Zähler, der sich diese merkt und nur bis 1 zählen kann, wieder
"Platz hat", sprich gelöscht wurde.
> Was passiert wenn ich ein Delay habe (nehmen wir mal an 5 Sekunden) und> ich drücke während des Delays den Button ein paar mal. Wird der> Interrupt auch ausgelöst?
Nein, denn erst wenn das eine "Ereignis" in der ISR "quittiert wurde,
kann das nächste gespeichert werden.
> Es ist nicht so, dass ich diese Probleme habe (vor allem nicht mit dem> Delay), es interessiert mich nur, wie soetwas vom uC gehändelt
Das les ich gern, denn zunehmend scheint das Verstehen wollen durch
schnelles C&P ersetzt zu werden. Thumbs up!
c-hater schrieb:> A. K. schrieb:>>> Er hat nur asynchrone Interrupts, aber keine synchronen.>> Falsch.>> Man kann jeden externen (also Pin-bezogenen) AVR-Interrupt zu dem> machen, was einen "synchronen Interrupt" ausmacht (das ist schlicht> einer, den die Software selber induziert, nicht externe Ereignisse). In> den Datenblättern wird auch jeweils ausdrücklich auf diese Möglichkeit> hingewiesen.
So vorhanden (z.B. bei vielen Megas) verwendet man da besser den
SPM-Int.
Der ist nur dann nicht aktiv, wenn ein Flash-Write ausgeführt wird, und
kann sonst durch setzen seines Enable-Bits ausgelöst werden (synchron,
"Software-Int"). Da braucht man kein Pin für!
Carl D. schrieb:> und> kann sonst durch setzen seines Enable-Bits ausgelöst werden (synchron,> "Software-Int"). Da braucht man kein Pin für!
Mal 'ne blöde Frage: Warum tut man sich das an, mit den 'Software
Interrupts'? Kann man nicht die benötigte Funktion einfach direkt
aufrufen (call)?
Ich sehe da irgendwie keinen Vorteil...
Christoph
Christoph schrieb:> Carl D. schrieb:>> und>> kann sonst durch setzen seines Enable-Bits ausgelöst werden (synchron,>> "Software-Int"). Da braucht man kein Pin für!> Mal 'ne blöde Frage: Warum tut man sich das an, mit den 'Software> Interrupts'? Kann man nicht die benötigte Funktion einfach direkt> aufrufen (call)?> Ich sehe da irgendwie keinen Vorteil...>> Christoph
Wenn die CPU verschiedene "Run-Modes" kennt, dann ist ein Soft-Int das
einzige Mittel um vom "Anwendungs-Modus" in den "System-Modus" zu
wechseln. Das ist bei einem AVR kein Thema (weil nicht vorhanden), aber
spätestens bei ARM Cortex-M gibt es 2 verschiedene Run-Modes und der
Befehl SVC (SuperVisor Call), der einen Software-Interrupt auslöst.
Dieter F. schrieb:> Falls das nicht geht erkläre bitte mal den Unterschied zwischen> synchronen und ansychronen Interrupts auf Basis des besprochenen> ATMega328 in diesem Thread. Ich bin gespannt und warte auf Deine> Ausführungen.
Brauchst Du nicht mehr - habe es im Datenblatt nachgelesen.
Hallo,
nochmal zurück zum Thema.
Bin auch der Meinung das ein gesetztes Bit ein gesetztes Bit bleibt. Mit
neu setzen ist da nichts. Es wird zwischendurch nicht gelöscht wenn zu
viele Interrupts hintereinander zu schnell eintreffen.
Fakt ist doch es gehen Interrupts verloren, wenn die ISR länger benötigt
wie das zeitliche eintreffen aufeinander folgender Interrupts. Der
zweite Interrupt wird zwar erkannt, kann aber noch nicht abgearbeitet
werden. Selbst hierbei geht schon eine Information verloren, falls
wichtig, wann der Interrupt eingetroffen ist. Aber er wurde erkannt und
wird irgendwann abgearbeitet. Alle weiteren, solange die ISR noch
beschäftigt ist, wiederholen nur die Interruptanforderung. Ignorieren
war vielleicht etwas falsch ausgedrückt. Wenn irgendwann keine
Interrupts mehr eintreffen, wird aus Sicht des µC der vemeintlich 2.
Interrupt abgearbeitet. Real ist es aber der letzte. Der zeitliche Bezug
ging verloren.
Nochmal mit der Türklingel. Es klingelt (Interrupt), man geht zur Tür,
notiert sich die Zeit und quatscht mit der Person. Die ISR wird
abgearbeitet. Während dessen klingelt es wieder. Man merkt sich das noch
jemand von einem was möchte. Während man immer noch mit der ersten
Person (ISR) quatscht, klingelt es immer wieder einmal. Man merkt sich
dennoch nur das irgendwer noch von einem etwas möchte. Nicht wieviele.
Irgendwann ist alles bequatscht und die ISR beendet. Man geht wieder zur
Tür um den nächsten ISR abzuarbeiten und notiert sich erneut die Zeit.
Ab hier gibts eine Diskrepanz. Man weiß nicht ob die neue Person der
zweite oder zehnte war der geklingelt hat. Das heißt auch die notierte
Zeit kann ich nur dem erneuten ISR Aufruf zuordnen. Nicht der
Reihenfolge der zu viel eingetroffenen Interruptanforderungen.
Checker schrieb:> Man weiß nicht ob die neue Person der> zweite oder zehnte war der geklingelt hat.
Ja, man sieht nur die Person, die gerade (nachdem der Besucher gegangen
ist / die ISR abgearbeitet ist) geklingelt hat - nicht die welche es
vorher versucht haben.
Checker schrieb:> Nochmal mit der Türklingel. Es klingelt (Interrupt), man geht zur Tür,> notiert sich die Zeit und quatscht mit der Person. Die ISR wird> abgearbeitet. Während dessen klingelt es wieder. Man merkt sich das noch> jemand von einem was möchte. Während man immer noch mit der ersten> Person (ISR) quatscht, klingelt es immer wieder einmal.
Falsch, es klingelt durchgehend. Deshalb hinkt auch die Türklingel, die
man ja immer wieder los läßt. Das Interruptflag bleibt aber durchgehend
"an".
> Man merkt sich> dennoch nur das irgendwer noch von einem etwas möchte. Nicht wieviele.
Wäre auch mit dem Interruptflag gar nicht möglich.
Checker schrieb:> Hallo,>> nochmal zurück zum Thema.> Bin auch der Meinung das ein gesetztes Bit ein gesetztes Bit bleibt. Mit> neu setzen ist da nichts. Es wird zwischendurch nicht gelöscht wenn zu> viele Interrupts hintereinander zu schnell eintreffen.
Richtig. Deshalb ist es auch müßig, darüber zu diskutieren, ob jetzt in
dem Bit das erste oder das zweite Ereignis gespeichert ist. Es ist eine
1 drin, fertig.
> Alle weiteren, solange die ISR noch beschäftigt ist, wiederholen nur die> Interruptanforderung. Ignorieren war vielleicht etwas falsch ausgedrückt.> Wenn irgendwann keine Interrupts mehr eintreffen, wird aus Sicht des µC> der vemeintlich 2. Interrupt abgearbeitet. Real ist es aber der letzte.
Nein. Für den Prozessor gibt's keinen 2. oder letzten Interrupt. Er hat
eine solche Information überhaupt nicht. Er hat nur ein gesetztes
Interrupt-Flag.
> Ab hier gibts eine Diskrepanz. Man weiß nicht ob die neue Person der> zweite oder zehnte war der geklingelt hat.
Im Gegensatz zu deinem Beispiel weiß man bei der ISR nicht einmal, ob
einer, zwei oder zehn geklingelt haben. Du weißt nur: Es wurde
inzwischen geklingelt. Du weißt weder, wie oft, noch wann.
> Das heißt auch die notierte Zeit kann ich nur dem erneuten ISR Aufruf> zuordnen. Nicht der Reihenfolge der zu viel eingetroffenen> Interruptanforderungen.
Weder Reihenfolge, noch Anzahl.
Stell dir die Analogie so vor: Du hast einen Anrufbeantworter, aber der
Speicher ist voll (oder kein Band eingelegt, wenn er schon etwas älter
ist). Wenn jemand anruft, geht nur die LED an, die anzeigt, dass Anrufe
eingegangen sind. Wenn du nach hause kommst, hast du nur diese LED, die
dir sagt, dass jemand angerufen hat. Du weißt weder wer das war, noch
wann, noch wieviele oder in welcher Reihenfolge. Du hast nur das eine
Bit, das sagt: "jemand hat angerufen".
Hallo,
ich bin überzeugt wir meinen alle das Gleiche, nur die Wortwahl ist bei
dem einen oder anderen etwas anders und daraus das Verständnis der Worte
beim lesenden anders. Ob nun Klingel oder AB, völlig egal. Sinnbildlich
dargestellt das gleiche Ergebnis. Der Klingelknopf soll den von außen
einwirkenden neuen Interrupt darstellen. Das gesetzte Bit für weitere
ISR Anforderungen ist im Kopf des dort wohnenden. Der hat eben nur ein
Bit um sich das zu merken.
Unser gemeinsamer Nenner bleibt ja davon unberührt, weil er richtig ist.
:-)
Wünsche allen noch ruhiges WE.
Dieter F. schrieb:> Ja, man sieht nur die Person, die gerade (nachdem der Besucher gegangen> ist / die ISR abgearbeitet ist) geklingelt hat - nicht die welche es> vorher versucht haben.
Ich korrigiere - wenn diese Person überhaupt noch da ist - wenn nicht
wieß man nur, dass es geklingelt hat.
Wie Rolf schreibt ...
Loipe schrieb:> Falsch, es klingelt durchgehend. Deshalb hinkt auch die Türklingel, die> man ja immer wieder los läßt. Das Interruptflag bleibt aber durchgehend> "an".
Es gibt Interrupt-Systeme, bei denen es vorkommen kann, dass zu dem
Zeitpunkt, zu dem eigentlich der Handler bestimmt werden soll, nicht
mehr bekannt ist, worum es eigentlich ging.
Das ist dann ein wenig so, wie bei der Türklingel. Du wachst auf, gehst
zur Tür, machst auf - und keiner ist da.
Checker schrieb:> Bin auch der Meinung das ein gesetztes Bit ein gesetztes Bit bleibt. Mit> neu setzen ist da nichts. Es wird zwischendurch nicht gelöscht wenn zu> viele Interrupts hintereinander zu schnell eintreffen.
Genauso ist das. Die IRQ-Flags der AVR8 können nur maximal ein
(weiteres) Auftreten des jeweiligen Interrupts puffern.
> Fakt ist doch es gehen Interrupts verloren, wenn die ISR länger benötigt> wie das zeitliche eintreffen aufeinander folgender Interrupts.
Es ist sogar noch viel schlimmer: Jede Interruptsperre hat diese
Wirkung, nicht nur die des eigenen Interrupts, also insbesondere auch
jede andere ISR im System (zumindest so lange sie exklusiv ausgeführt
wird).
> Der> zweite Interrupt wird zwar erkannt, kann aber noch nicht abgearbeitet> werden.
Noch nicht...
> Selbst hierbei geht schon eine Information verloren
Ja. Das gilt allerdings für die "erste" Instanz dieses Interrupts schon
(fast) im gleichen Maße.
Die Unsicherheit über den Zeitpunkt der Abarbeitung bezogen auf den
Zeitpunkt der Auslösung nennt man Interruptlatenz.
Diese setzt sich aus zwei Teilen zusammen, der konstanten Latenz (die
logischerweise für beide Instanzen vollkommen gleich ist) und der
variablen Latenz, die für die Folgeinstanz nur um genau so viel größer
ist, wie der exklusiv ausgeführte Teil der konkreten ISR dauert.
Die restlichen Teile der variable Latenz (i.d.R. das wirklich Schlimme!)
sind für beide Instanzen aber gleich, nämlich die SUMME der
(exklusiven) Laufzeiten aller ISRs mit höherer Priorität zuzüglich der
längsten exklusiven Laufzeit sonstiger Interruptsperren, also der
exklusive Teil aller ISRs geringerer Priorität und von cli/sei-Blöcken
in main().
> Alle weiteren, solange die ISR noch> beschäftigt ist, wiederholen nur die Interruptanforderung. Ignorieren> war vielleicht etwas falsch ausgedrückt.
Naja, semantisch setzt der Begriff "ignorieren" eine gewisse Absicht
voraus, insofern ist er wohl wirklich nicht korrekt. Aber er stellt
zumindest die Wirkung zutreffend dar.
> Wenn irgendwann keine> Interrupts mehr eintreffen, wird aus Sicht des µC der vemeintlich 2.> Interrupt abgearbeitet. Real ist es aber der letzte.
Ganz genau das ist die logische Konsequenz, wie dein Türklingel-Beispiel
recht gut darstellt.
A. K. schrieb:> Es gibt Interrupt-Systeme, bei denen es vorkommen kann, dass zu dem> Zeitpunkt, zu dem eigentlich der Handler bestimmt werden soll, nicht> mehr bekannt ist, worum es eigentlich ging.
Jepp. Der klassische PC(AT) mit seinen kaskadierten Interruptcontrollern
z.B. ist ein sehr schönes Beispiel dafür, wie man ein Interruptsystem
besser nicht aufbauen sollte. Broken by design...
Aber auch der Amiga z.B. hatte ein sehr ähnliches Problem. Fiel dort nur
nicht so auf, weil man die Hardware schon sehr ungewöhnlich nutzen
musste, um den Effekt hervorzulocken.
Wie auch immer: wenn die Hardware schon Scheisse ist, wird Software
hilflos, selbst wenn der Programmierer komplett durchblickt. Da bleibt
nur Schadensbegrenzung. Die allseits beliebten "hardware behaviour work
arounds", die ja immer so viel billiger sind, als einfach mal die
Hardware nachzubessern...
c-hater schrieb:> Die Unsicherheit über den Zeitpunkt der Abarbeitung bezogen auf den> Zeitpunkt der Auslösung nennt man Interruptlatenz.>> Diese setzt sich aus zwei Teilen zusammen, der konstanten Latenz (die> logischerweise für beide Instanzen vollkommen gleich ist) und der> variablen Latenz, die für die Folgeinstanz nur um genau so viel größer> ist, wie der exklusiv ausgeführte Teil der konkreten ISR dauert.>> Die restlichen Teile der variable Latenz (i.d.R. das wirklich Schlimme!)> sind für beide Instanzen aber gleich, nämlich die SUMME der> (exklusiven) Laufzeiten aller ISRs mit höherer Priorität zuzüglich der> längsten exklusiven Laufzeit sonstiger Interruptsperren, also der> exklusive Teil aller ISRs geringerer Priorität und von cli/sei-Blöcken> in main().
Ja - Latenz. Heisst für mich, der Zustand - welcher den Interrupt
ausgelöst hat - kann noch bestehen, muss aber nicht. Das ist bitter und
muss bei der Abarbeitung eines Interrupts berücksichtigt werden.
Alternativ muss man entsprechende Maßnahmen (welche auch immer) treffen.
c-hater schrieb:> Jepp. Der klassische PC(AT) mit seinen kaskadierten Interruptcontrollern> z.B. ist ein sehr schönes Beispiel dafür, wie man ein Interruptsystem> besser nicht aufbauen sollte.
Yep. Da lugt noch der alte 8080 um die Ecke.
Näher dran am Forum: Viele klassischen ARMs, besonders die mit Interrupt
Controller PrimeCells von ARM drin, wie dem VIC. Etwa die LPC2000
Familie. Der VIC speichert die Anforderung nicht selbst sondern reicht
sie kombinatorisch durch.
Wenn z.B. eine UART eine bereits ausgegebene Interrupt-Anforderung
wieder zurück nimmt, etwa bei einem FIFO Timeout Interrupt, der von
eintrudelndem Byte abgebrochen wird, dann gibts einen "spurious
interrupt", von dem keiner weiss, wo er herkommt.
> Broken by design...
Für das Interrupt-System der klassischen ARM Architektur kann man das
generell sagen, jedenfalls bei verschachtelten Interrupts.
> Aber auch der Amiga z.B. hatte ein sehr ähnliches Problem. Fiel dort nur> nicht so auf, weil man die Hardware schon sehr ungewöhnlich nutzen> musste, um den Effekt hervorzulocken.
Bei 68000 wars der vektorierte Modus. Wenn der Urheber des Interrupts
beim Vektor-Zyklus selbst nicht mehr wusste, welchen er dem Prozessor
liefern soll. Autovektoriert wars sauber.
Bei den LPC2000 musste man das unbedingt im Auge haben, sonst gabs
gelegentliche nicht leicht verfolgbare Schmutzeffekte.
> Wie auch immer: wenn die Hardware schon Scheisse ist, wird Software> hilflos
In jedem grösseren Mikrocontroller gibts ziemlich viel Scheisse. Meist
kann man damit leben, wenn man sie kennt.
A. K. schrieb:>> Broken by design...>> Für das Interrupt-System der klassischen ARM Architektur kann man das> generell sagen, jedenfalls bei verschachtelten Interrupts.
Heisst das "wer ARM nimmt ist arm dran" :-) ?
Typischer Weise gibt es je Interruptquelle ein Pending-Flag, d.h. es
kann nur ein Ereignis je Quelle gespeichert werden. Das Pending-Flag
bewirkt dann das Ausführen des Handlers, sobald der Interrupt erlaubt
ist.
Je nach Quelle wird das Pending-Flag beim Eintritt in den Handler
automatisch gelöscht oder muß per Software gelöscht werden.
Als Fallgrube beim AVR muß zum Löschen von Pending-Flags eine 1 in das
Bit geschrieben werden (auf 0 setzen hat keinen Effekt).
Das Pending-Flag kann auch abgefragt (gepollt) werden, es muß also zur
Behandlung der Quelle nicht unbedingt ein Interrupt ausgeführt werden.
Wird ein Interrupt längere Zeit gesperrt, muß bei erneuter Freigabe
vorher das Pending-Flag gelöscht werden, sonst kriegt man einen
Interrupt auf veraltete Ereignisse. Aufpassen muß man bei asynchronen
Timern, da das Flag durch die Synchronisationsregister verzögert
gelöscht wird. Z.B. beim T1 des ATtiny261 muß man 2 NOPs dazwischen
einfügen.