mikrocontroller.net

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


Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sven (Gast)
Datum:

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

Sven

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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... :-/

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)....

Autor: Prof. Dr. Delay (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in der isr flag setzen und nach dem reti auswerten und zum ziel springen

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
int:
.
.
.
sei
call meineWunschFunktion
ret

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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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... 
;-)

Autor: Peter R. (pnu)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jobst M. (jobstens-de)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfgang R. (portside)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.