Forum: Mikrocontroller und Digitale Elektronik [AVR ASSEMBLER] ISR ohne RETI beenden?


von Stefan (Gast)


Lesenswert?

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

von Sven (Gast)


Lesenswert?

Ja, aber du musst natuerlich den Stackpointer korrigieren, d.h. ihn um 
zwei erhoehen.

Sven

von Martin (Gast)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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... :-/

von Stefan (Gast)


Lesenswert?

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

von Prof. Dr. Delay (Gast)


Lesenswert?

in der isr flag setzen und nach dem reti auswerten und zum ziel springen

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

von Peter R. (pnu)


Lesenswert?

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.

von Fabian (Gast)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

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.

von Jobst M. (jobstens-de)


Lesenswert?

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

von Wolfgang R. (portside)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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
Noch kein Account? Hier anmelden.