Hi,
mal eine Fragen zu AVR ATmega Mikrocontrollern:
Ein Timer soll alle 10us einen Interrupt auslösen.
Die Interuptroutine benötigt aber stets 20us bis sie abgearbeitet ist
und geschlossen wird.
Was passiert dann genau?
Viele Grüße,
006
Der Interrupt wird abgearbeitet und der Interrupt, welcher während des
Abarbeiten ausgelöst wird, wird ignoriert.
Es gibt keinen Absturz, aber es passiert nicht das, was du vom Programm
erwartetst.
006 schrieb:> Ein Timer soll alle 10us einen Interrupt auslösen.> Die Interuptroutine benötigt aber stets 20us bis sie abgearbeitet ist> und geschlossen wird.
Dann würde ich effizientere Programmierung und wenn das nichts hilft
einen Schnelleren µC verwenden.
Der µC wird die ganze Zeit in einer ISR sein und hat keine Zeit für die
Ausführung der main();
Das entsprechende Interrupt-Flag wird zwar gesetzt, aber nicht direkt
abgearbeitet. Alle 10µs kommt ein IRQ, alle 20µs ist der Interrupt
fertig. Das Programm arbeitet also nur jeden zweiten IRQ ab. Während der
IRQ nicht direkt ignoriert wird, wird er aber auch nicht abgearbeitet.
Wenn du per sei() am Anfang des Interrupts wieder neue IRQ zulässt wird
der Interrupt immer wieder unterbrochen und es wird niemals einer fertig
abgearbeitet.
> Der µC wird die ganze Zeit in einer ISR sein und hat keine Zeit für die> Ausführung der main();
Doch, die wird schon ausgeführt (sofern der IP sich in der main()
aufhält), aber ziemlich langsam :-)
> Wenn du per sei() am Anfang des Interrupts wieder neue IRQ zulässt wird> der Interrupt immer wieder unterbrochen und es wird niemals einer fertig> abgearbeitet.
..und insbesondere läuft der Stack ratzfatz voll. Also ein gaaanz
schlechte Idee.
Marcel schrieb:> Wenn du per sei() am Anfang des Interrupts wieder neue IRQ zulässt wird> der Interrupt immer wieder unterbrochen und es wird niemals einer fertig> abgearbeitet.
und dann stützt er wirklich ab, dann damit überschreibst du dir nach
einer weile den Stack.
Marcel schrieb:> Wenn du per sei() am Anfang des Interrupts wieder neue IRQ zulässt wird> der Interrupt immer wieder unterbrochen und es wird niemals einer fertig> abgearbeitet.
Abgesehen davon, daß der Stack dann schnell überläuft: Warum läßt man
das in der Architektur zu, einen Interrupt wieder beginnen zu können,
wenn er noch nicht fertig ist? Ich kann es noch gar nicht richtig
glauben.
Bei 8051 ist das doch besser gelöst, und ein Interrupt wird erst
automatisch wieder frei gegeben, wenn er beendet wurde. Zusätzlich ist
noch gewährleistet, daß zwischen zwei Interrupts immer ein einziger
Befehl des Hauptprogrammes noch abgearbeitet wird, damit dieses nicht
ganz stehen bleibt. Dort würden Interrupts einfach nur verschluckt, wenn
die Verarbeitung länger ist als die Interruptintervalle. Daß immer ein
Hauptprogrammbefehl zwischen Interrupts verarbeitet werden muß, war mal
ein Fortschritt zu Zeiten, als 8085 und 8048 und kurz darauf der 8051
entwickelt wurde.
Den pegelgetriggerten Interrupt macht man sich so beim 8051 für einen
Software-Single-Step zu Nutze. Echten Single-Step kann er ja wegen
dynamischem Design nicht.
Ich kenne ATmega nicht, frage einfach nur mal locker in die Runde.
Da läuft überhaupt kein Stack voll.
Wenn ein neuer Interrupt eintrifft, während der µC noch in der ISR ist,
dann wird ein Flag gesetzt, dass ein neuer Interrupt eingetreten ist.
Sobald die aktuelle ISR verlassen wird, wird die ISR direkt wieder neu
gestartet, da ja das Flag gesetzt ist.
Wenn also die Interrupts schneller reinkommen als sie abgearbeitet
werden, wird lediglich die ISR dauerhaft aufgerufen und bekommt so 100%
CPU-Zeit.
Aber da es kein rekursiver Aufruf ist (denn erst nach Verlassen wird die
ISR erneut aufgerufen), läuft da auch nix über - schon gar nicht der
Stack.
Also wie A.K. schon sagte: Kein Absturz.
Ein Elektroniker schrieb:> Abgesehen davon, daß der Stack dann schnell überläuft: Warum läßt man> das in der Architektur zu, einen Interrupt wieder beginnen zu können,> wenn er noch nicht fertig ist? Ich kann es noch gar nicht richtig> glauben.
Standardmäßig passiert das ja nicht. Man kann den Interrupt früher
erlauben, als das System es vorsieht - wenn man genau weiß, was man da
tut.
Deine Frage hört sich an wie: "Warum lässt man bei Autos zu, dass man
sich nicht anschnallt und dann gegen eine Wand fährt? Ich kann es noch
gar nicht richtig glauben."
Ein Elektroniker schrieb:> Abgesehen davon, daß der Stack dann schnell überläuft: Warum läßt man> das in der Architektur zu, einen Interrupt wieder beginnen zu können,> wenn er noch nicht fertig ist?
Sie lsst es von Haus aus nicht zu. Aber sie lässte es zu, dass du dir
mit SEI absichtlich oder versehentlich in den Fuss schiesst.
006 schrieb:> Was passiert dann genau?
Das siehst du am besten, wenn du mal den Simulator anschmeißt. Da kannst
du dir jedes Register angucken, auch den Programm Counter.
A. K. schrieb:> Frank M. schrieb:>> Da läuft überhaupt kein Stack voll.>> Das bezog sich auf die SEI Variante. Dann läuft der sehr wohl voll.
Dann natürlich ja. Aber nicht alles ist sinnvoll, was auch erlaubt ist.
;-)
Ich wollte nur klarstellen, dass im Standardfall (kein frühzeitiges
Interrupt-Enable in der ISR selbst) nichts passieren kann. Wer das
dennoch macht, muss sich über die Konsequenzen im Klaren sein.
Frank M. schrieb:> Wenn also die Interrupts schneller reinkommen als sie abgearbeitet> werden, wird lediglich die ISR dauerhaft aufgerufen und bekommt so 100%> CPU-Zeit.
Scheinbar kann ich beim ATmega dann nicht mit reden. Wenn wirklich
zwischen Interrupts das Hauptprogramm überhaupt nicht mehr läuft, wie
der eine Befehl, der beim 8051 immer zwischen zwei Interrupts
abgearbeitet wird, was man schon 1975 als Mangel erkannte, dann ist das
schlecht.
Allerdings waren diese µC auch noch auf Assembler und kleine Programme
und nicht C optimiert, und mit Abarbeitung komplexerer C-Funktionen in
Main kommt man auch nicht besonders weit, daß das Main-Programm gut
weiter läuft.
Ein Elektroniker schrieb:> Scheinbar kann ich beim ATmega dann nicht mit reden. Wenn wirklich> zwischen Interrupts das Hauptprogramm überhaupt nicht mehr läuft, wie> der eine Befehl, der beim 8051 immer zwischen zwei Interrupts> abgearbeitet wird, was man schon 1975 als Mangel erkannte, dann ist das> schlecht.
Das ist beim AVR genauso.
Wie soll man das sonst lösen? Außerdem gab es 1975 noch gar keinen 8051.
mfg.
Die Cortex Ms hingegen kriegt man auf diese Art stillgelegt. Die sind
darauf optimiert, ISRs möglichst fix abzuarbeiten, und es ist fixer,
direkt von einer ISR in die nächste zu hüpfen, als zweimal den ganzen
Stack-Kram abzuarbeiten.
Ob man das freilich als Nachteil sehen sollte? Wer seine Kiste so baut,
dass sich über eine längere Zeit ISRs dicht an dicht stapeln und im
Hauptprogramm rein garnichts mehr geht, der hat wohl etwas falsch
kalkuliert.
> Abgesehen davon, daß der Stack dann schnell überläuft: Warum läßt man> das in der Architektur zu, einen Interrupt wieder beginnen zu können,> wenn er noch nicht fertig ist? Ich kann es noch gar nicht richtig> glauben.
Weil das eine Voraussetzung für verschachtelte (softwarepriorisierte)
Interrupts ist. Du kannst ja nicht nur Interrupts global sperren,
sondern die auch für jede Quelle einzeln ein- und ausschalten.
> Bei 8051 ist das doch besser gelöst, und ein Interrupt wird erst> automatisch wieder frei gegeben, wenn er beendet wurde.
Das ist auch das normale Verhalten. Für Sonderfälle kann man es aber
auch anders machen - niemand zwingt dich.
Bei den 8 bit PICs ist es ähnlich: Das Interrupt Enable Bit wird beim
Sprung in die ISR gelöscht und dann mit dem RETFIE (Return from
Interrupt Enabele) Befehl wieder gesetzt. Dem Programmierer steht es
natürlich frei das Bit, wenn er es für sinnvoll hält, früher wieder zu
setzen.