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
... 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 ;-)....
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