Hallo.
Ich habe folgende Situation: Innerhalb einer Interrupt-Routine werden
verschiedene Dinge getestet. Liegt ein Fehler vor möchte ich eine
Funtkion error_function () aufrufen und dann die Interrupt-Routine
vorzeitig verlassen.
ISR (UART_RX_vect) {
if (Bedingung1) {
error_function ();
HIER INTERRUPT VERLASSEN
}
// ...
if (Bedingung2) {
error_function ();
HIER INTERRUPT VERLASSEN
}
// ...
}
Bei einer normalen Funktion könnte man einfach return verwenden. Für
Interrupts gäbe es ja reti(), doch dann würde der von AVR GCC generierte
Epilog (SREG und Register wiederherstellen) nicht aufgerufen werden...
Gibt es eine Möglichkeit aus der Routine heraus direkt den Epilog
aufzurufen? Oder habt ihr andere Lösungsvorschläge?
Vielen Dank für eure Hilfe!
Oliver
An sich ist es überhaupt keine gute Idee im Interrupt Funktionen
aufzurufen. Setze in der ISR Variablen und prüfe sie in main. Dann
stellt sich das Problem auch nicht.
Aber wenn es denn unbedingt sein muss, dann verknüpfe die Bedingungen
mit "oder".
A. K. schrieb:>> Bei einer normalen Funktion könnte man einfach return verwenden.>> Hier auch.
Auch wieder richtig. Wie kommst Du darauf, kein return benutzen zu
können?
Napfkuchen schrieb:> An sich ist es überhaupt keine gute Idee im Interrupt Funktionen> aufzurufen.
Sehe ich anders. Sicher, wer seinen halben Programmcode in Interrupts
verballert, der hat garantiert etwas falsch gemacht. Ansonsten ist es
Abwägung, inwieweit man Dinge direkt in der ISR erledigt. Manches geht
nur dort, und bloss des Dogmas wegen verkrampft zu programmieren ist
auch nicht sinnvoll.
> dann verknüpfe die Bedingungen mit "oder".
In diesem Beispiel sicher, aber das könnte der Vereinfachung geschuldet
sein.
A. K. schrieb:> Sehe ich anders.
Aha. Und?
Es ist sicher auch nicht sinnvoll, an solch einer Stelle eine Diskussion
darüber anzufangen. Wenn ich sage, das man nicht ohne Fallschirm aus
einem Flugzeug springen sollte, dann ist das die Antwort auf die Frage
"wie man ohne Fallschirm aus dem Flugzeug springt". Das man, wenn das
Flugzeug auf dem Boden steht, dennoch ohne Gefahr aus dem Flugzeug
springen kann, weiss der ausgebildete Fallschirmspringer aber keiner der
so fragt. (Na gut, das Beispiel ist nicht so schön, aber dem Sinne nach
gilt es für Programmierer).
Genau dieses Argument hier:
A. K. schrieb:> In diesem Beispiel sicher, aber das könnte der Vereinfachung geschuldet> sein.
spricht nach meiner Ansicht, dafür, das der Fragesteller nicht in der
Lage war sein Problem (ob es nun eines war, spielt dabei keine Rolle)
selbst mit trivialen Mitteln zu lösen, also ein Anfänger ist.
Meinen Hinweis finde ich darüber hinaus in solchen Fällen und in denen,
bei denen der Code der aufgerufenen Funktion unbekannt ist, sinnvoll.
Die Formulierung "überhaupt keine gute Idee" hat zugegebenermaßen den
Odem eines Dogmas. Mit dem Nachsatz, "Aber wenn es denn unbedingt sein
muss ..." meinte ich meine Aussage hinreichend relativiert zu haben, so
das sogar ein Anfänger erkennen konnte, das es sich eben nicht um eine
strikte Regel handelt.
A. K. schrieb:> Nur kann ich an seinem Code oben nichts frevelhaftes der Marke "ohne> Fallschirm aus dem Flugzeug springen" erkennen.
Um in dem Beispiel zu bleiben: Du siehst seinen Rücken und kannst keinen
"Buckel" erkennen. Hat er den Fallschirm nun vor der Brust unter dem
Hosenboden oder garkeinen?
Vielen Dank für die Antworten. Das Funktionsaufrufe in Interrupts
problematisch sind weiss ich schon, und ich habe mir auch bereits
überlegt das ganze mit Flags zu machen, die dann in main überprüft
werden.
Problematisch ist jedoch, dass sobald der UART einen Interrupt auslöst
(sprich ein byte empfängt), relativ viel code möglichst schnell
ausgeführt werden muss. In main würde es unter Umständen zu lange
dauern, bis die Hauptschleife durch ist und das nächste Mal die Flags
geprüft werden.
Einfach return einzusetzten muss ich mal ausprobieren. Ich dachte, das
geht nicht, da es sich bei ISR (UART_RX_vect) nicht um eine C-Funktion
im eigentlichen Sinn handelt. ISR ist ja eigentlich ein Makro...
Oliver schrieb:> Einfach return einzusetzten muss ich mal ausprobieren. Ich dachte, das> geht nicht, da es sich bei ISR (UART_RX_vect) nicht um eine C-Funktion> im eigentlichen Sinn handelt. ISR ist ja eigentlich ein Makro...>
Wenn Du Dir das Makro anschaust, wirst Du feststellen, daß da nur ein
paar zusätzliche Funktionsattribute gesetzt werden und das ganze
ansonsten eine (fast) normale C-Funktion ist.
Im Endeffekt sieht das dann etwa so aus:
Oliver schrieb:> Einfach return einzusetzten muss ich mal ausprobieren. Ich dachte, das> geht nicht, da es sich bei ISR (UART_RX_vect) nicht um eine C-Funktion> im eigentlichen Sinn handelt. ISR ist ja eigentlich ein Makro...
Das ist aber nicht dein Problem.
Dafür gibt es einen Compiler, der die Unterschiede kennt.
Oliver schrieb:> Für> Interrupts gäbe es ja reti()
Ja das ist die beste Methode, Programme abstürzen zu lassen.
Stürzt noch besser ab, als die sleep_mode() Fallgrube.
Das war auch wirklich ne saublöde Idee von den AVR-GCC-Entwicklern, das
reti() Macro dem unbedarften Nutzer als direkte Fallgrube zugänglich zu
machen.
Nimm "return;" und gut is.
Peter