Hallo Forum, ich möchte gerne nach Ausführung des Interrupts nicht an die Stelle des Aufrufes sondern an eine genau definierte Stelle springen. Wie kann ich das machen? Einfach die ISR nicht mit reti beenden? Grüße Stefan
Ja, aber du musst natuerlich den Stackpointer korrigieren, d.h. ihn um zwei erhoehen. Sven
... Einfach die ISR nicht mit reti beenden? ... - Alte Rücksprungadresse vom Stack holen und verwerfen. - Neue Rücksprungadresse auf dem Stack ablegen. - RETI ausführen
Stefan schrieb: > ich möchte gerne nach Ausführung des Interrupts nicht an die Stelle des > Aufrufes sondern an eine genau definierte Stelle springen. Du solltest dich unbedingt fragen, warum Andere das nicht brauchen!! Ich vermute, dass du irgendwo Murks im Softwarekonzept gebaut hast und jetzt drumrum basteln willst... :-/
Vielen Dank für die Antworten, damit ist mir weitergeholfen!! Lothar Miller schrieb: > Du solltest dich unbedingt fragen, warum Andere das nicht brauchen!! > Ich vermute, dass du irgendwo Murks im Softwarekonzept gebaut hast und > jetzt drumrum basteln willst... :-/ Das kann natürlich sein ;-)....
in der isr flag setzen und nach dem reti auswerten und zum ziel springen
Martin schrieb: > - Alte Rücksprungadresse vom Stack holen und verwerfen. > - Neue Rücksprungadresse auf dem Stack ablegen. > - RETI ausführen - Stackpointer auf Anfang setzen (resp. Ende des SRAMs) - rjmp ausführen... Den Rest des Stacks kann danach eh keiner mehr brauchen. Alternativ könnte man auch einfach vor dem reti ein sei ausführen, dann ein call zur gewünschten Funktion, welche dann mit ret zurückkehrt (ebenso wie der Interrupt) also so:
1 | int: |
2 | . |
3 | . |
4 | . |
5 | sei |
6 | call meineWunschFunktion |
7 | ret |
8 | |
9 | meineWunschFunktion: |
10 | . |
11 | . |
12 | . |
13 | ret |
Dann kehrt das Programm nachdem die Funktion ausgeführt wurde wieder an den Ursprung zurück wo der Interrupt die andere Arbeit unterbrach. Trotzdem kaputt das Konzept ;)
Stefan schrieb: > ich möchte gerne nach Ausführung des Interrupts nicht an die Stelle des > Aufrufes sondern an eine genau definierte Stelle springen. Solche Fragen kommen ausnahmslos von absoluten Programmieranfängern. Das Problem ist, daß sie kein Konzept erstellen, wie das Programm ablaufen soll, sondern einfach drauflos programmieren. Ein Interrupt ist für Kontextwechsel weder gedacht noch geeignet, sowas macht man im Main-Kontext mit einer Statemachine. Im Gegenteil, ein Interrupt macht Sachen so, daß der Main-Kontext gerade nicht gestört wird. Ein Interrupt weiß nämlich nicht, wo er gerade das Main unterbricht und damit auch nicht, was gerade alles auf dem Stack liegt. Simples Beispiel, eine Uhrenfunktion hat gerade die Minute auf 60 hochgezählt und will sie im nächsten Schritt auf 0 setzen. Nun kommt Dein Killer-Interrupt aber dazwischen, bricht die Funktion ab und dann zeigt Deine Uhr lustig 60..255 Minuten an und geht 4h,16min nach. Deshalb gibt es auch in Hochsprachen keinerlei Konstrukt, so etwas zu machen. Und die Compilerbauer sind keine dummen Jungs, die überlegen sich genau, welche Werkzeuge nötig sind und welche man besser garnicht erst implementiert, weil sie nur Chaos anrichten würden. Peter
Peter Dannegger schrieb: > bricht die Funktion ab und dann > zeigt Deine Uhr lustig 60..255 Minuten an und geht 4h,16min nach. Sooo schlimm geht die Uhr übrigens nicht nach, sondern nur 3 Stunden und 15 Minuten, weil sie ja in den ersten 60 Minuten (0..59) richtig ging... ;-)
Eine andere, vermutlich saubere Lösung: In der Int-Routine ein flag setzen, wenn das Abbruchkriterium für die Routine erfüllt ist. Dann den Int brav mit Reti beenden. In der Grundroutine eine Abfrage des flag einbauen und entsprechend reagieren.
Diese Idee schreit ja schon nach einem Stack-Overflow! Die einzige "sinnvolle" Anwendung würde mir im Bereich der Sicherheitstechnik einfallen. Wenn das System den sicheren Zustand einnehmen soll und anschließend nur durch einen Hardware-Reset zurück gesetzt werden kann. Aber selbst dann würde ich in der ISR mittels CALL die Safety-Funktion aufrufen und nicht den Stack manipulieren.
ich habe hier auch eine Anwendung bei der ich aus dem Interrupt anders als üblich zurückspringen muss: ich bekomme über ein Protokoll Daten bei deren Empfang ich schlicht keine Zeit habe noch etwas anderes zu tun (wie z.B. ein vom Timeout-Interrupt gesetztes Flag abzufragen) Funktioniert einwandfrei weil der einzige Interrupt nur beim Aufruf der Empfangsroutine freigegeben wird, ich also genau weiß dass er nur in dieser Routine kommen kann. Hängt die Übertragung dann kommt der Interrupt, ich manipuliere den Stack, schalte den Interrupt aus und das Programm springt an die Stelle zurück, an der die Empfangsroutine aufgerufen wurde. Natürlich ist das nicht sauber, denn man muss aufpassen wenn man Änderungen an der ISR oder der Empfangsroutine vornimmt, denn dann ist der Stackaufbau anders oder auch wenn man eine neue Compilerversion verwendet. Wenn man nur Assembler verwendet hat man das Problem natürlich nicht. Aber wenn man weiß was man da angerichtet hat, das entsprechend notiert, dann ist die Lösung besser als gar keine Lösung, bzw. eine Lösung mit anderem Prozessor, anderem Board usw.
Peter Dannegger schrieb: > Solche Fragen kommen ausnahmslos von absoluten Programmieranfängern. Stimmt wohl, aber nur, weil ein Profi diese Frage nicht mehr zu stellen braucht. > Ein Interrupt ist für Kontextwechsel weder gedacht noch geeignet, sowas Ich löse darüber z.B. den Taskwechsel bei Multitaskingsystemen. (Zugegeben - dabei wechsele ich den kompletten Stack). Aber: Jemand der diese Frage stellen muß, ist noch nicht bereit für solche Schweinereien. Gruß Jobst
Jobst M. schrieb: > Ich löse darüber z.B. den Taskwechsel bei Multitaskingsystemen. > (Zugegeben - dabei wechsele ich den kompletten Stack). Genau!! dazu wurde dies schon 1975 beim ersten Unix auf der PDP-11 benutzt. Ist eben was für Gurus. Dazu brauchts nicht mal einen Interrupt - eigenen Stack aufbauen und dann Funktion mit RETI verlassen.
Bernd schrieb: > Aber wenn man weiß was man da angerichtet hat, das entsprechend notiert, > dann ist die Lösung besser als gar keine Lösung, bzw. eine Lösung mit > anderem Prozessor, anderem Board usw. Oftmals verbeißen sich Anfänger aber auch in einen Lösungsweg und überlegen keinen weiteren Ansatz. Daß die CPU wirklich nicht genug Leistung für eine saubere Lösung haben soll, glaube ich erst, wenn ich die Aufgabe sehe. 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.