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".
1 | ISR (UART_RX_vect) { |
2 | |
3 | if ((Bedingung1) || (Bedingung2)) { |
4 | error_function (); |
5 | // HIER INTERRUPT VERLASSEN nicht mehr notwendig
|
6 | }
|
7 | else { |
8 | // ...
|
9 | }
|
10 | }
|
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.
Nur kann ich an seinem Code oben nichts frevelhaftes der Marke "ohne Fallschirm aus dem Flugzeug springen" erkennen.
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:
1 | void __vector_9(void) __attribute__ ((signal, used, externally_visible)); |
2 | void __vector_9(void) |
3 | {
|
4 | // ...
|
5 | }
|
Wobei die Zahl am Ende des Namens ('9') die Interruptnummer ist.
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.