Hallo zusammen,
ich hätte da mal eine Frage...
Angenommen ein Programm befindet sich gerade in einer ISR, was passiert,
wenn während der Abarbeitung ein zweiter ISR mit höherer, bzw. mit
niedrigerer Priorisierung einläuft.
Im Falle das die Priorisierung höher ist, wird dann der laufende ISR
unterbrochen und der mit der höheren Prio zuerst abgearbeitet und danach
wieder fortgesetzt?
Im Falle das die Priorisierung niedriger ist, ich nehme an, dass der
aktuelle Prozess fortgeführt wird, bis dieser beendet ist, der neue
Interrupt wird dann in einen Puffer geschrieben und danach bearbeitet.
Ist das so in etwa korrekt?
Danke und vG
Kommt auf den Typ des Prozessors/Controllers an.
Beim 8051 gab es Interrupts mit verschiedenen Prioritäten. Wichtigere
Interrupts konnten weniger wichtige unterbrechen. Die Prioritäten
konnten teilweise auch über Register definiert werden.
Beim AVR sind wimre alle Interrupts gleich priorisiert und können sich
somit nicht unterbrechen.
Feivel schrieb:> Hallo zusammen,>> ich hätte da mal eine Frage...>> Angenommen ein Programm befindet sich gerade in einer ISR, was passiert,> wenn während der Abarbeitung ein zweiter ISR mit höherer, bzw. mit> niedrigerer Priorisierung einläuft.
Das kommt auf den Prozessor und/oder den Interrupt-Controller an.
Hallo Feivel,
Name des Prozessors wäre gut zu wissen!
Normal, was ist normal?, ist wenn während der Abarbeitung innerhalb
einer ISR das Flag so gesetzt ist, dass keine Interrupts weiter
aufgerufen werden. Erst mit dem Verlassen der ISR wird das Flag wieder
zurück gesetzt. Dann kann es mit der nächsten ISR entsprechend der
Rangfolge weitergehen.
Gruß
Bernd
Ich sehe schon, dass ist nicht so trivial wie ich es mir vorgestellt
habe.
Mir wurde in diesem Bezug eine ganz allgemeine Frage gestellt welche ich
beantworten soll, es wird kein Prozessor genannt. Ich nehme an, dass
hier von einem x beliebigen Typ ausgegangen wird welcher über eine
Priorisierung von Interrupts verfügt.
In diesem Fall könnte man sagen:
ISRx läuft...
ISRy mit niederer Prio läuft ein -> ISRy wird in einen "Puffer"
gespeichert und abgearbeitet nachdem ISRx fertig ist.
ISRy mit höherer Prio läuft ein -> ISRx wird unterbrochen und ISRy wird
bearbeitet, nachdem ISRy fertig ist, fängt:
- ISRx von vorne an?
- ISRx wird ab Unterbrechung abgearbeitet?
- ISRx wird nicht weiter behandelt?
hmmm...
Feivel schrieb:> Angenommen ein Programm befindet sich gerade in einer ISR, was passiert,> wenn während der Abarbeitung ein zweiter ISR mit höherer, bzw. mit> niedrigerer Priorisierung einläuft.
Abgesehen vom bisherigen "kommt drauf an": im Idealfall ist der
Aufenthalt in der ISR so kurz, dass in der Zeit kein zweiter Interrupt
einlaufen kann... ;-)
Oder andersrum: wer in der ISR ein komplettes Apfelmännchen berechnet
und deshalb nicht auf andere Interrupts reagieren kann, der hat im
Softwarekonzept seines Programms irgendwas falsch gemacht.
Feivel schrieb:> Im Falle das die Priorisierung niedriger ist, ich nehme an, dass der> aktuelle Prozess fortgeführt wird, bis dieser beendet ist, der neue> Interrupt wird dann in einen Puffer geschrieben und danach bearbeitet.
Das gilt auch für den Fall, dass die Priorität gleich ist.
AVR-Controller haben z.B. nur 1 Interruptpriorität.
> der neue Interrupt wird dann in einen Puffer geschrieben
Er wird nicht extra in einen Puffer geschrieben, sondern der Interrupt
setzt sein Interruptflag und das bleibt gesetzt, bis es durch die ISR
gelöscht wird.
Wenn die Interruptroutine A also lange dauert und währendessen der
niedriger- oder gleichpriore Interrupt B sogar zweimal oder mehrmals
kommt, dann geht einer oder mehrere dieser Interrupts B "verloren". Weil
ein bereits gesetztes Flag ja nicht nochmals gesetzt werden kann.
Feivel schrieb:> In diesem Fall könnte man sagen:>> ISRx läuft...>> ISRy mit niederer Prio läuft ein -> ISRy wird in einen "Puffer"> gespeichert und abgearbeitet nachdem ISRx fertig ist.
Ja.
>> ISRy mit höherer Prio läuft ein -> ISRx wird unterbrochen und ISRy wird> bearbeitet, nachdem ISRy fertig ist, fängt:> - ISRx von vorne an?
Nein, sie wurde ja nur unterbrochen.
> - ISRx wird ab Unterbrechung abgearbeitet?
Ja.
> - ISRx wird nicht weiter behandelt?
Nein, sie wird an der unterbrochenen Stelle fortgesetzt. So wie es jeder
Interrupt mit dem "Hauptprogramm" auch macht:
Hauptprogramm läuft...
ISRy mit läuft ein -> Hauptprogramm wird unterbrochen und ISRy wird
bearbeitet, nachdem ISRy fertig ist, wird das unterbrochene
Hauptprogramm an der selben Stelle fortgesetzt.
So kennst du das ja auch mit 1 Interrupt:
Hauptprogramm: Du liegst auf dem Sofa und liest ein Buch.
Interrupt 1: Dein Magen knurrt und du schmierst dir eine Butterstulle.
Wenn dir geschmiert ist, legst du dich wieder aufs Sofa un liest weiter.
Und dann mit 2 Interrupts:
Hauptprogramm: Du liegst auf dem Sofa und liest ein Buch.
Interrupt 1: Dein Magen knurrt und du schmierst dir eine Butterstulle.
Kaum ist die Brotscheibe heruntergeschnitten...
Interrupt 2: ...klingelt der Postbote an der Haustür. Du gehst dorthin,
holst den Brief ab und dann:
a) legst du dich aufs Sofa?
b) schneidest du nochmal ein Scheibe Brot ab?
c) schmierst du die Butter aufs Brot und gehst dann wieder zum Sofa?
BTW:
Da "läuft nix ein" und "der Puffer" ist ein einzelnes Bit (=Flag)
Super, vielen Dank für die Antwort.
Also kann ich es mir so vorstellen:
- Ein Interrupt wird bearbeitet (Interruptflag ist gesetzt)
- ISR mit gleicher oder niederer Prio tritt auf, wird in diesem Moment
nicht bearbeitet, weil Interruptflag bereits gesetzt, erst wenn nach
Abarbeitung des laufenden ISR wieder ein Interrupt eingeht, wird dieses
wieder bearbeitet.
- Sollte aber während der Abarbeitung einer laufenden ISR ein Interrupt
mit höherer Prio kommen, wird die aktuelle ISR an Stelle x unterbrochen
und nach Beendigung des ISR mit der höherern Prio an Stelle x wieder
fortgeführt.
Die Firma dankt (keine IT Firma :P)
Feivel schrieb:> Also kann ich es mir so vorstellen:> - Ein Interrupt wird bearbeitet (Interruptflag ist gesetzt)
Jede Interruptquelle (Timer, Counter, SPI, SIO, IO,...) hat ein eigenes
Interruptflag. Aber eben nur eines. Es kann also nur 1 Interrupt pro
Interruptquelle "gemerkt" werden.
Feivel schrieb:> [...]> - ISR mit gleicher oder niederer Prio tritt auf, wird in diesem Moment> nicht bearbeitet, weil Interruptflag bereits gesetzt, erst wenn nach> Abarbeitung des laufenden ISR wieder ein Interrupt eingeht, wird dieses> wieder bearbeitet.> [...]
Nein. Das ist so nicht korrekt, jedenfalls nicht allgemein.
In der Regel, wird der Interrupt mit der niedrigeren Priorität zwar
nicht sofort abgearbeitet, aber er wird auch nicht ignoriert, als wenn
er nie stattgefunden hätte.
Sobald der Interrupt mit der höheren Priorität fertig ist, wird der
Interrupt mit der niedrigeren Priorität bearbeitet. Das auslösende
Ereignis kann durchaus auch während der Bearbeitung des Interrupts mit
der höheren Priorität auftreten.
Ich vermute, Du bist zu diesem Schluss wegen der Bemerkung über den
Puffer gekommen. Es wurde gesagt, das so ein Puffer nicht existiert.
Aber es wurde auch gesagt, dass ein bzw. das entsprechende Flag gesetzt
wird. Dieses Flag ist der von Dir gedacht "Puffer". Nur das das Wort
"Puffer" dafür nicht verwendet wird.
Als Puffer werden Speicherbereiche bezeichnet in denen mehrere, und
unter Umständen mehrwertige Anwendungs-Daten gespeichert werden. Im
Gegensatz dazu sind die Interrupt-Flags keine Anwendungsdaten. Etwas
abstrakter gesehen, mag man diese Flags durchaus als "Puffer" ansehen,
aber das ist einfach unüblich.
Theor schrieb:> Etwas abstrakter gesehen, mag man diese Flags durchaus als "Puffer"> ansehen, aber das ist einfach unüblich.
richtig, denn so ein "Puffer" führt zum falschen Bild mit einem "Stapel
mit Interruptanforderungen": jeder eintreffende Interrupt kommt auf
einen Stapel und wird später abgearbeitet. Und wenn (weil z.B. der
höchstpriore Interrupt durch einen Programmierfehler 10ms dauert) ein
IO-Interrupt 5 mal kommt, dann wird der hinterher 5 mal abgearbeitet.
Und das ist eben nicht der Fall. Wie angemerkt, ist das kein "Puffer",
sondern eher so ein "Flag" wie bei amerikanischen Briefkästen: wenn der
Postbote montags kommt, dann klappt er die Fahne hoch. Wenn ich im
Urlaub bin und er am Dienstag und am Mittwoch nochmal kommt, dann ist
die Fahne schon oben und das wars. Wenn ich dann am Mittwoch abend
heimkomme, dann sehe ich nur 1 einzige hochgeklappte Fahne und weiß
nicht, wie oft der Postbote da war.
> Aufenthalt in der ISR so kurz, dass in der Zeit kein zweiter Interrupt> einlaufen kann... ;-)
Das klingt wie ein Aphorismus mit dem sich AVR-User die Welt schoen
denken. :-)
Die mangelhaften Interruptfaehigkeiten, also keine Priorisierung und vor
allem keine moegliche Einflussnahme auf die Priorisierung ueber vom User
vergebbare Level war fuer mich einer der wesentlichen Gruende warum ich
vor 15Jahren von AVRs auf M16C umgestiegen bin.
Olaf
Lothar M. schrieb:> Feivel schrieb:>> Im Falle das die Priorisierung niedriger ist, ich nehme an, dass der>> aktuelle Prozess fortgeführt wird, bis dieser beendet ist, der neue>> Interrupt wird dann in einen Puffer geschrieben und danach bearbeitet.> Das gilt auch für den Fall, dass die Priorität gleich ist.> AVR-Controller haben z.B. nur 1 Interruptpriorität.
Das ist doch Bullshit. Natürlich haben AVRs Interruptprioritäten.
Einfach mal ins Datenblatt schauen, auch wenn das mühselig ist...
Z.B. ATmega328:
"The interrupts have priority in accordance with their interrupt vector
osition. The lower the interrupt vector address, the higher the
priority."
Wäre ja noch schöner, wenn der Controller jedes Mal würfeln müsste, wenn
Interrupts gleichzeitig auftreten.
honk schrieb:> Wäre ja noch schöner, wenn der Controller jedes Mal würfeln müsste, wenn> Interrupts gleichzeitig auftreten.
Es trifft aber nicht auf die Frage des TE, denn er fragt:
Feivel schrieb:> Angenommen ein Programm befindet sich gerade in einer ISR...
Da sind wir schon in der ISR, denn Fall "was passiert wenn
zeitgleicht..." kam nicht.
Also ist deine Antwort nicht falsch, Lothars aber auch nicht
hinsichtlich der Fragestellung des TE.
@ honk (Gast)
>> Das gilt auch für den Fall, dass die Priorität gleich ist.>> AVR-Controller haben z.B. nur 1 Interruptpriorität.>Das ist doch Bullshit. Natürlich haben AVRs Interruptprioritäten.>Einfach mal ins Datenblatt schauen, auch wenn das mühselig ist...>Z.B. ATmega328:>"The interrupts have priority in accordance with their interrupt vector>osition. The lower the interrupt vector address, the higher the>priority."
AVRs haben von Haus aus aber keine unterbrechbaren ISRs. Wenn man die
WIRKLICH braucht, muss man das per Software nachbilden.
Die C2000 (PICCOLO) von TI haben das auch nicht.
>Wäre ja noch schöner, wenn der Controller jedes Mal würfeln müsste, wenn>Interrupts gleichzeitig auftreten.
Tut er nicht, aber die Priorität der Interrupts greift beim AVR nur,
wenn mehrere Interrupts aktiv sind und zur Bearbeitung anstehen.
Verkettete (unterbrechbare) Interrupts sind das nicht.
Falk B. schrieb:> Tut er nicht, aber die Priorität der Interrupts greift beim AVR nur,> wenn mehrere Interrupts aktiv sind und zur Bearbeitung anstehen.> Verkettete (unterbrechbare) Interrupts sind das nicht.
Das ist schon klar. Nichtsdestotrotz hat er Prioritäten, insofern muss
man diese falsche Aussage richtigstellen.
Olaf schrieb:> Die mangelhaften Interruptfaehigkeiten, also keine Priorisierung und vor> allem keine moegliche Einflussnahme auf die Priorisierung ueber vom User> vergebbare Level war fuer mich einer der wesentlichen Gruende warum ich> vor 15Jahren von AVRs auf M16C umgestiegen bin.
In Software lässt sich das zumindest teilweise umgehen. Daher taugt der
AVR auch für viele Anwendungszwecke, in denen verschiedene
Interrupttypen gebraucht werden. Und falls doch mal nicht, dann gab es
ja noch die guten alten 8051er ;)
Ingo L. schrieb:> Also ist deine Antwort nicht falsch, Lothars aber auch nicht> hinsichtlich der Fragestellung des TE.
Nichts für ungut, aber Lothar schreibt:
"AVR-Controller haben z.B. nur 1 Interruptpriorität."
Und das ist schlichtweg falsch, egal wie die Fragestellung war.
honk schrieb:> Das ist doch Bullshit.
Immer ein Kraftwort zur Hand.
> Natürlich haben AVRs Interruptprioritäten.
Das sind keine Interruptprioritäten in dem Sinn, wie sie hier
diskutiert werden.
Denke einfach beim AVR als Inrterrupt-Level und schon hast du nur 1
einzigen: wenn schon ein Interrrupt läuft, kann keine höher priorisierte
Interruptquelle diesen Interrupt unterbrechen.
honk schrieb:> "AVR-Controller haben z.B. nur 1 Interruptpriorität."> Und das ist schlichtweg falsch, egal wie die Fragestellung war.
Ja, dann bitte ich hiermit in aller Form um Entschuldigung und
korrigiere diese grundlegend falsche Behauptung dahingehend:
AVR-Controller haben z.B. nur 1 Interruptlevel.
Ich habe gestern auch mal "Schraubenzieher" gesagt. Auch das möchte ich
hiermit zum "Schraubendreher" korrigieren.
Olaf schrieb:> Das klingt wie ein Aphorismus mit dem sich AVR-User die Welt schoen> denken. :-)
Diese Denkweise macht im Grunde das Leben einfach: man muss sich nicht
mit irgendwelchen die Unterbrechung unterbrechenden Unterbrechungen
herumschlagen... ;-)
> Die mangelhaften Interruptfaehigkeiten, also keine Priorisierung und vor> allem keine moegliche Einflussnahme auf die Priorisierung ueber vom User> vergebbare Level war fuer mich einer der wesentlichen Gruende warum ich> vor 15Jahren von AVRs auf M16C umgestiegen bin.
Die STM32 ARM-Prozessoren bieten da auch viele Möglichkeiten. Und wenn
man dann noch die DMY dazunimmt, dann wirds erst richtig lustig.
Feivel schrieb:> nachdem ISRy fertig ist, fängt:> - ISRx von vorne an?> - ISRx wird ab Unterbrechung abgearbeitet?> - ISRx wird nicht weiter behandelt?
Es gibt nur eins davon, das sinnvoll und logisch ist.
Lothar M. schrieb:> ie bei amerikanischen Briefkästen: wenn der> Postbote montags kommt, dann klappt er die Fahne hoch.
Eigentlich klappt man die Fahne hoch, damit der Briefträger sieht, dass
er ne Sendung mitnehmen soll.
Auch beim AVR kann eine laufende ISR durch weitere Interupts
unterbrochen werden.
Dazu muss nur in der ISR per SEI-Befehl das Interupt-Enable Flag wieder
gesetzt werden. Dann kann jeder anstehende oder zukünftig auftretende
Interrupt die ISR unterbrechen. Ja, auch niedriger priorisierte.
Die Priorisierung wirkt sich beim AVR nur auch die Reihenfolge
gleichzeitig anstehender Interupts aus.
Natürlich sollte der Programmierer, wie eigentlich immer, wissen was er
tut.
Mfg Willi
Lothar M. schrieb:> Immer ein Kraftwort zur Hand.
Naja, so ist es halt schön prägnant.
>> Natürlich haben AVRs Interruptprioritäten.> Das sind keine Interruptprioritäten in dem Sinn, wie sie /hier/> diskutiert werden.> Denke einfach beim AVR als Inrterrupt-Level und schon hast du nur 1> einzigen: wenn schon ein Interrrupt läuft, kann keine höher priorisierte> Interruptquelle diesen Interrupt unterbrechen.
Das ist mir schon klar, nur könnte das auch ein unbedarfter lesen und
dann versteht er es falsch. Also warum nicht gleich korrekt schreiben.
> Ich habe gestern auch mal "Schraubenzieher" gesagt. Auch das möchte ich> hiermit zum "Schraubendreher" korrigieren.
Also ich bin dafür seinerzeit im Praktikum vom Lehrwerkstattsleiter rund
gemacht worden ;)
Hubertus schrieb:> Lothar M. schrieb:>> ie bei amerikanischen Briefkästen: wenn der>> Postbote montags kommt, dann klappt er die Fahne hoch.>> Eigentlich klappt man die Fahne hoch, damit der Briefträger sieht, dass> er ne Sendung mitnehmen soll.
So kenne ich es auch aus meiner Zeit drüben.
honk schrieb:>> Eigentlich klappt man die Fahne hoch, damit der Briefträger sieht, dass>> er ne Sendung mitnehmen soll.> So kenne ich es auch aus meiner Zeit drüben.
Blöd, das kann man natürlich nicht so einfach auf einen µC übertragen.
Da muss ich mir ein anderes Beispiel ausdenken... ;-)
Lothar M. schrieb:> Wenn ich dann am Mittwoch abend> heimkomme, dann sehe ich nur 1 einzige hochgeklappte Fahne und weiß> nicht, wie oft der Postbote da war.
Hallo Feivel und in die Runde,
mittlerweile habe ich ja auch dazu gelernt, dass man etwas kompliziert
machen kann und auch straight forward.
Ich versuche einmal wiederzugeben, wie es bei meinem kleinen Prozessor
abläuft:
Sobald die Peripherie den Bedarf nach abarbeiten einer Service Routine
signalisiert, wird ein entsprechendes Flag gesetzt. Sofern das Global
Interrupt Enable Flag gesetzt ist, pushed der Prozessor Status und Code
auf dem Stack und springt in die ISR. Gleichzeitig wird das Global
Interrupt Flag zurück genommen. Damit sind weitere ISR-Ausführungen
blockiert und werden erst einmal keine weiteren ISR angesprungen.
Natürlich könnte ich bei Eintritt in die erste ISR das Flag wieder
setzen und die Blockade aufheben. Damit würde, sobald wieder ein
Interrupt ausgelöst wird in die nächste ISR gesprungen werden, mit push
von Codeadresse und Status, usw. Aber das Globale Flag fasse ich nicht
an! Der Code in der ersten (einzigen ISR) wird abgearbeitet. Nun gibt es
einige Interrupt Vektoren (ISR-Adressen), die sich unterschiedliche
Interrupt-Quellen teilen. Ich muss bei diesen bei Eintritt innerhalb der
ISR verzweigen und vor dem Exit der ISR prüfen, ob nicht vielleicht noch
ein anderer weiterer Grund zu dieser ISR geführt hat. Das auch, falls
zufällig während abarbeiten des Codes ein weiterer Interrupt zur selben
Vektoradresse aufgetreten ist. ...oder auch falls der selbe Grund das
Flag erneut gesetzt hat, während die ISR abgearbeitet wurde. (Das kommt
z.B. bei Capture/Compare Funktionen vor, ... wenn man nicht aufpasst
oder falsch denkt. Auch passiert das, wenn mehre I/O-Pins gleichzeitig
geändert werden und das so programmiert ist. Dann muss ich für jeden Pin
entsprechend Code abarbeiten. ... bedeutet keinerlei Einschränkung,
sondern Flexibilität.)
Sobald der Prozessor die ISR verlässt, holt er sich die Adresse für den
Code außerhalb der ISR und das Statusregister vom Stack zurück und
setzt seine ursprüngliche Bearbeitung weiter fort und zwar mit dem
Globalen Interrupt Flag, das beim IRET wieder gesetzt wurde (erfolgt
automatisch über Wiederherstellung des Stausregisters über das POP).
Sind jetzt zwischenzeitlich andere Interrupt Quellen zu anderen
Vektoradressen zu anderen ISR aufgetreten, werden die in der Reihenfolge
der Priorität angesprungen.
Eigentlich ist dieses Verfahren plausibel, einfach, logisch und somit
straight forward, beim MSP430.
Bei Fragen, bitte fragen.
Weiterhin Happy Coding und Gruß
Bernd
Willi schrieb:> Dazu muss nur in der ISR per SEI-Befehl das Interupt-Enable Flag wieder> gesetzt werden.
Wer das einmal versucht hat, versucht es in der Regel nie wieder.
Fast alle außer den Timerinterrupts löschen ihr Flag nicht automatisch,
d.h. ein SEI bewirkt eine Rekursion bis zum Stacküberlauf. Und selbst
beim Timerinterrupt ist man nicht vorm Stacküberlauf sicher, wenn das
Intervall zu kurz gewählt ist. SEI in Interrupts ist ein ziemlich
sicherer Weg, sich ein Bein zu stellen.
Es hat schon seine Berechtigung, warum viele andere MC-Hersteller
Interruptlevel in Hardware implementieren.
honk schrieb:> Das ist schon klar. Nichtsdestotrotz hat er Prioritäten, insofern muss> man diese falsche Aussage richtigstellen.
Im heute üblichen Verständnis von Interruptsystemen wird der Begriff von
Prioritäten als vom System her verschachtelbare und unterbrechbare
Interrupts mit Prioritäten verstanden. Und zwar auch dann, wenn man
nicht alle diese Worte mitschleppt.
Dass man den AVRs nachhelfen kann, indem man Interrupts in ISRs freigibt
und die Prioritäten über kreative Nutzung der Interrupt-Enables
rudimentär nachbildet, ändert nichts am üblichen Verständnis von
Interruptsystemen.
Da die Prioritäten von AVRs eine völlig andere Baustelle sind,
eigentlich nur einen auf weissem Rauschen basierenden Zufallsgenerator
ersetzen, ist eine Betonung von deren Existenz eher irreführend als
hilfreich (lies: es geht kaum anders als so wie bei den AVRs).
NB: Es gibt Systeme, die dieser Sprachregelung entsprechend grenzwertig
sind. So haben ARM7 Cores eigentlich nur 2 Interrupt-Prioritäten, und
das von ARM definierte Interruptsystem tut sich mit Verschachtelung
etwas schwer. Viele ARM7 µCs besitzen aber dennoch einen zusätzlichen
Interrupt-Controller, der mit Klimmzügen in der ISR für verschachtelbare
und unterbrechbare Interrupts mit Prioritäten genutzt werden kann.
Peter D. schrieb:> Feivel schrieb:>> nachdem ISRy fertig ist, fängt:>> - ISRx von vorne an?>> - ISRx wird ab Unterbrechung abgearbeitet?>> - ISRx wird nicht weiter behandelt?>> Es gibt nur eins davon, das sinnvoll und logisch ist.
Man kann auch unkompliziert antworten:
UNTERBRECHUNG heißt danach an der Stelle der Unterbrechung weitermachen.
Eine ISR wird nie WÄHREND der Abarbeitung des OP-Codes aufgerufen! D.h.
beim Interrupt wird erst der aktuelle Code fertig gemacht und dann
verzweigt und bei Rückkehr weitergemacht, nichts wiederholt oder
übersprungen.
Auch hier gibt es Möglichkeiten die Rücksprungadresse beim Verlassen der
ISR zu verändern. Das würde aber über einen EXPLIZITEN Code innerhalb
der ISR und befummeln des Stack erfolgen. Das machen nur die
Programmierer, die es unbedingt wollen und ggf. mit Schmerzen leben
können.
Gruß
Bernd
Bernd B. schrieb:> Eine ISR wird nie WÄHREND der Abarbeitung des OP-Codes aufgerufen!
Zumindest ist das beim AVR nicht so. Tatsächlich gibt es diverse
Architekturen, die bei einer anstehenden Interrupt-Anforderung eine
Unterbrechung von bestimmten Befehlen mit längerer Laufzeit vorsehen.
Beispielsweise unterbrechen Befehle mit interner Schleife wie LDIR (Z80)
oder MOVS (x86) und erledigen den verbleibenden Rest danach.
Manche Cores mit Fokus auf Mikrocontroller brechen im Interesse kurzer
Interrupt-Latenz komplexe Befehle auch einfach ab und wiederholen die
Ausführung danach vollständig.
A. K. schrieb:> Manche Cores mit Fokus auf Mikrocontroller brechen im Interesse kurzer> Interrupt-Latenz komplexe Befehle auch einfach ab und wiederholen die> Ausführung danach vollständig.
Hast du da eine Architektur dafür? Das sind aber dann hoffentlich nur
"interne" Befehle, die keine Statusflags ändern...
A. K. schrieb:> honk schrieb:>> Das ist schon klar. Nichtsdestotrotz hat er Prioritäten, insofern muss>> man diese falsche Aussage richtigstellen.>> Im heute üblichen Verständnis von Interruptsystemen wird der Begriff von> Prioritäten als vom System her verschachtelbare und unterbrechbare> Interrupts mit Prioritäten verstanden. Und zwar auch dann, wenn man> nicht alle diese Worte mitschleppt.
Auch das ist klar.
Problematisch ist halt nur, dass in den Atmel-Datenblättern das Wort
Interruptpriorität eindeutig definiert ist, und zwar eben nicht so im
"üblichen" Sinne.
Lothar M. schrieb:> Hast du da eine Architektur dafür?
Die ARMv7-M Architektur der Cortex-Mx erlaubt beides:
"In the base ARMv7-M architecture the exception-continuable instructions
are LDM, LDMDB, STM, STMDB, POP, and PUSH.
[...]
Alternatively, the processor can abandon the execution of a Load
Multiple or Store Multiple instruction on taking an exception, and
restart the instruction processing, from the start of the instruction,
on returning from the exception."
A. K. schrieb:> Lothar M. schrieb:>> Hast du da eine Architektur dafür?>> Die ARMv7-M Architektur der Cortex-Mx erlaubt beides:>> "In the base ARMv7-M architecture the exception-continuable instructions> are LDM, LDMDB, STM, STMDB, POP, and PUSH.> [...]> Alternatively, the processor can abandon the execution of a Load> Multiple or Store Multiple instruction on taking an exception, and> restart the instruction processing, from the start of the instruction,> on returning from the exception."
Und nicht mehr alternativ ist es bei SDIV/UDIV, die in jedem Fall neu
ausgeführt werden.
Lothar M. schrieb:> Das sind aber dann hoffentlich nur "interne" Befehle,> die keine Statusflags ändern...
Abbrechbare oder unterbrechbare Befehle haben bisweilen eben deshalb
Einschränkungen in der Kombination der Register, um damit keine Probleme
zu bekommen.
Bei Architekturen mit Unterstützung virtuellen Speichers ist es
allgemein üblich, dass Befehle abgebrochen und wiederholt werden. Nur
Ausnahmen wie 68010 und 68020 verwendeten unterbrechbaren Microcode
dafür, und das auch nur gezwungenermassen.
Der Trick besteht darin, unwiderrufliche Veränderungen erst dann
durchzuführen, wenn der Fall nicht mehr auftreten kann. Was bei Out Of
Order Architekturen nicht weiter schwierig ist.
Das betrifft zwar üblicherweise nur spezielle synchrone Exceptions und
keine Interrupts, aber das Prinzip bleibt gleich und liesse sich auch
auf asynchrone Exceptions wie Interrupts anwenden.
A. K. schrieb:> Zumindest ist das beim AVR nicht so. Tatsächlich gibt es diverse> Architekturen, die bei einer anstehenden Interrupt-Anforderung eine> Unterbrechung von bestimmten Befehlen mit längerer Laufzeit vorsehen.> Beispielsweise unterbrechen Befehle mit interner Schleife wie LDIR (Z80)> oder MOVS (x86) und erledigen den verbleibenden Rest danach.
... da haben wir sie wieder, die Farbe des Bartes vom Kaiser!
Smiley!
Bernd
Anhang:
http://www.worldofspectrum.org/Z80.html
Here's an example of block shift:
1
Here's an example of block shift:
2
3
LD DE,0000h
4
LD HL,4000h
5
LD BC,0100h
6
LDIR
Can you see how this works? Basically 100h bytes of data starting at
4000h are copied to 0000h through to 0100h. Block shift is useful in a
text editor for example. You might want to delete a character and then
shift everything else down in memory. Block shift will do that quickly
and easily. You can think of it as a copy instruction.
Hubertus schrieb:> Beim AVR sind wimre alle Interrupts gleich priorisiert und können sich> somit nicht unterbrechen.
Das stimmt doch nicht.
Jedem Programmierer steht es frei, in seiner ISR gleich zu Anfang
Interrupts wieder frei zu geben, so dass auch ein anderer IRQ zum Zuge
kommen kann. Das setzt allerdings etwas Umsicht bei der Formulierung der
ISR voraus.
Peter D. schrieb:> Fast alle außer den Timerinterrupts löschen ihr Flag nicht automatisch,
Es stimmt, dass es solche Interupts gibt, aber es stimmt sicher nicht,
dass es "fast alle" wären. Tatsächlich sind es nämlich nur ganze drei:
2x USART (RXC und UDRE) und 1x TWI (TWINT).
Richtig ist also: bei fast allen Interrupts wird das Flag automatisch
gelöscht.
Nochmal zu Verdeutlichung: Der Mega644P z.B. hat 30 Interruptvektoren.
Nur 3 davon löschen nicht automatisch das auslösende IRQ-Flag, das sind
exakt 10%.
"Fast alle"? Lächerlich.
Du gibst mir 90% deines Einkommens, sollte ja kein Problem sein, da du
ja "fast alles" behalten darfst...
Nun gut. Wir wissen alle, dass es da eine ganze Reihe verschiedener
Varianten gibt. Da können wir uns noch Tage damit vergnügen uns
gegenseitig mit noch einer Geschmacksrichtung zu "überraschen" oder die
Vorzüge dieses oder jenes Systems zu preisen.
Es sprechen allerdings ein oder zwei Anhaltspunkte dafür, dass der TO
lediglich eine Frage im Unterricht beantworten, bzw. ein Referat halten
muss. Und dafür wurden ihm die wesentlichen Punkte schon erklärt, denke
ich.
c-hater schrieb:> Richtig ist also: bei fast allen Interrupts wird das Flag automatisch> gelöscht.
Wobei das spezifisch für AVRs gilt. Andere Controller, andere Sitten.
A. K. schrieb:> Wobei das spezifisch für AVRs gilt. Andere Controller, andere Sitten.
Natürlich, keine Frage.
Der Trick ist halt immer derselbe: man muß schlicht wissen, was man tut.
Und die Grundlage dafür ist solides Faktenwissen über die jeweilige
Zielarchitektur. Und offensichtliche Falschaussagen können nunmal nix
dazu beitragen, solches Grundlagenwissen zu schaffen, auch dann nicht,
wenn sie nur ein bestimmte Architektur falsch beschreiben. Deswegen muss
man ihnen einfach widersprechen.
Peter D. schrieb:> Willi schrieb:>> Dazu muss nur in der ISR per SEI-Befehl das Interupt-Enable Flag wieder>> gesetzt werden.>> Wer das einmal versucht hat, versucht es in der Regel nie wieder.> Fast alle außer den Timerinterrupts löschen ihr Flag nicht automatisch,> d.h. ein SEI bewirkt eine Rekursion bis zum Stacküberlauf. Und selbst> beim Timerinterrupt ist man nicht vorm Stacküberlauf sicher, wenn das> Intervall zu kurz gewählt ist. SEI in Interrupts ist ein ziemlich> sicherer Weg, sich ein Bein zu stellen.
Genau solche Aussagen führen dazu, dass Interupts hier immer wie eine
Art Mysterium behandelt werden. Das Freigeben von weiteren Interrupts
ist der einzig mögliche und durchaus zulässige Weg, verschachtelte
Interrupts beim AVR zu realisieren. Jeder neue Interrupt setzt das
INT-Flag wieder zurück und sperrt damit weitere Interrupts. Deshalb gibt
es nicht automatisch eine Rekursion. Das ist alles vorherseh- und
beherrschbar. Du beschreibst es so, als kämen irgendwelche Interrupts
heimlich und unerwartet um die Ecke geschlichen. Aber das hat man doch
alles selbst programmiert, und sollte man im Griff haben. Und wenn das
"Intervall zu kurz ist", dann ist das einfach ein Programmierfehler. Und
nichts Überraschendes oder Geheimnisvolles.
Anstatt sich hinter sochen Aussagen oder der hier häufig verbreiteten
Falschmeldung "ISR sollen IMMER so kurz wie möglich sein" zu verstecken,
macht es mehr Sinn, sich mit dem Datenblatt des Controllers auseinander
zu setzen, um wirklich zu verstehen, was bei Interrupts abläuft. Dann
kann man sie auch ohne "geheimnisvolle Fallen" sinnvoll einsetzen, und
damit die Leistungsfähigkeit des AVR auch nutzen.
Feuer frei und Grüsse
Willi
Willi schrieb:> Aber das hat man doch> alles selbst programmiert, und sollte man im Griff haben.
Falsch. Das gilt nämlich leider NICHT für Interrupts aus externen
Quellen. Ganz sicher jedenfalls nicht für diejenigen, die das Potential
haben, schneller Interrupts auszulösen, als man sie selbst im Idealfall
einer sinnvollen Konfiguration und mit optimiertem Assembler in der ISR
behandeln könnte.
Und das sind tatsächlich einige: INTx, PCINTx, ICPx, ACI z.B.
Darauf hat nichtmal der allerbeste Assemblerprogrammierer irgendeinen
Einfluss. DoS über einen wildgewordenen Interrupteingang ist also immer
möglich. Das Problem ist nur durch drei Ansätze lösbar
1) Das kann nicht passieren. (Sprich: man stellt sicher, das die
abzufragende/zu beobachtende Peripherie sowas niemals liefern würde)
2) Durch zusatzliche Hardware (Tiefpässe), die die maximale
Interruptrate zuverlässig auf vertretbare Werte absenken kann.
3) durch Verzicht auf Interrupts aus dieser Quelle und Ersatz durch
Polling.
Ja, da stimme ich dir zu, das externe INTs womöglich völlig asynchron
und häufiger als einem lieb ist, auftreten können. Das wird dann
schwierig.
Einige mögliche Lösungen hast du ja schon angedeutet.
Mir geht es aber darum, das auch solche externe Interruptquellen vorher
bekannt sind. Ihre womöglich unschönen Eigenschaften sind nicht
unvorhersehbar und überraschend. Da muss man sich eben informieren, mit
was da zu rechnen ist, und sich ein Konzept überlegen, wie und ob man
damit klarkommt.
Der Fall, das man gar nicht weiss was da kommt, und mit allem klarkommen
muss, was auch immer es ist, entspricht wohl nicht der Praxis.
MfG Willi
c-hater schrieb:> 1) ...>> 2) ...>> 3) ...
und
Willi schrieb:> häufiger als einem lieb ist, auftreten können. Das wird dann> schwierig.
es gibt auch noch die Möglichkeit, das Interrupt Enable Bit für die
entsprechende Hardware in der ISR zurückzusetzen:
(x feuert Interrupt)
-> Eintritt in die ISR, global Interrupt disabled
- Interrupt disable für Peripherie (x)
- global Interrupt enable
-> (jetzt können andere Quellen nested Interrupts auslösen, x aber
nicht)
- ISR code für (x) ausführen
- globalen Interrup disablen
- ggf. Interrupt-Flag (x) löschen
- Interrupt enable für Peripherie (x)
<- Return from Interrupt (dabei wird der globale Interrupt enabled)
Thomas E. schrieb:> es gibt auch noch die Möglichkeit, das Interrupt Enable Bit für die> entsprechende Hardware in der ISR zurückzusetzen:> (x feuert Interrupt)> -> Eintritt in die ISR, global Interrupt disabled> - Interrupt disable für Peripherie (x)> - global Interrupt enable> -> (jetzt können andere Quellen nested Interrupts auslösen, x aber> nicht)> - ISR code für (x) ausführen> - globalen Interrup disablen> - ggf. Interrupt-Flag (x) löschen> - Interrupt enable für Peripherie (x)> <- Return from Interrupt (dabei wird der globale Interrupt enabled)
Ja richtig, sowas kann man machen.
Das gesamte Interruptsystem des AVR steht komplett unter Kontrolle des
Programmierers.
Da passiert nichts unvorhersehbares oder geheimnisvolles.
So muss es ja auch sein, die Designer des AVR waren doch keine Anfänger.
Und nochmal: Die AVR Interrupts sind unterbrechbar. Wenn man das will.
MfG Willi