mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Befehlszeiger AVR


Autor: M. H. (bambel2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Ich will, dass ich über einen interrupt etwas ausführe und dann aber 
nicht dorthin zurückspringe wo ich war sondern woanders hin. Hab mir das 
so gedacht ich könnte doch den Befehlszeiger, der beim auslösen des 
interrupts auf dem stack abgespeichert wird, mit pop befehlen "löschen" 
und mit push befehlen einen neuen wert auf den Stack tun. beim reti 
befehl springt er dann zur neuen Adresse.

1.Geht das so?? oder ist es einfacher den zeiger vom Stapel zu holen (2 
mal pop) und am ende des interrupts mit sei die interrupts aktivieren 
und mit ijmp zur adresse in Z springen??
2.Wenn ja in welcher reihenfoge müssen die high und low bytes auf den 
stack??
Danke im voraus.


Gruß M.H.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. H. schrieb:
> 1.Geht das so??
Ja.

> oder ist es einfacher den zeiger vom Stapel zu holen (2
> mal pop) und am ende des interrupts mit sei die interrupts aktivieren
> und mit ijmp zur adresse in Z springen??
Wie du möchtest.

> 2.Wenn ja in welcher reihenfoge müssen die high und low bytes auf den
> stack??
Low zuerst, http://www.avr-asm-tutorial.net/avr_de/testjmp.html

Autor: M. H. (bambel2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok. noch was muss ich nicht low(blabla*2) etc schreiben. Weil wenn ich 
z.B. ein LCD ansteuere und daten aus dem flash hole ( mit lpm) muss ich 
dass doch so machen.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ok. noch was muss ich nicht low(blabla*2) etc schreiben.

Nein. Das ist eine 'Word'-Adresse.

MfG Spess

Autor: M. H. (bambel2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok dann ist alles klar.

Danke

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In C kann man das mit einem longjmp machen.
Bloß hat das 1.000.000 Pferdefüße, sodaß in der Praxis niemand sowas 
macht, der bei Verstand ist.

Sobald Dein Programm auch nur etwas größer als superwinzig wird, weißt 
Du nämlich nicht mehr, welchen Prozeß Du da gerade killst.

Laß es z.B. ein LCD im 4-Bit Mode sein. Du killst es nach dem ersten 
Nibble und fürderhin zeigt es nur noch Bockmist an.

Und so gibt es noch 1.000.000 Beispiele von Tasks, denen man nicht 
einfach die CPU unterm Hintern wegziehen darf.

Die gebräuchliche Methode ist daher, ein Flag zu setzen. Dieses Flag 
signalisiert der gerade aktiven Task, sich geordnet zu beenden und zum 
Main zurück zu kehren. Oder es bewirkt einfach, das Ergebnis des letzten 
Task zu verwerfen.
In der Regel kommt es bei einem Abort nicht auf die ms an, d.h. man läßt 
den aktuellen Task einfach zuende laufen.


Peter

Autor: avrfreak (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vorsicht mit dem Entladen der Rücksprungadresse.
Der ATmega256x hat 3-byte-PC.
Hat mich mal böse erwischt.

Autor: Frank Meier (aktenasche)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm würd ich an deiner Stelle nicht machen, so ein Verhalten wird schnell 
unübersichtlich.

Autor: Vuvuzelatus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich will, dass ich über einen interrupt etwas ausführe und dann aber
>nicht dorthin zurückspringe wo ich war sondern woanders hin.

Nein, Du willst damit ein Problem lösen und glaubst mangels Erfahrung, 
dass dies eine gute Lösung sei. Das ist sie aber sehr wahrscheinlich 
nicht, im Gegenteil. Auf jeden Fall handelst Du Dir mit diesem Konstrukt 
den Albtraum jedes Entwicklers ein, nämlich ein abstruses, unklares 
Programmdesign.

Tipp: Das zugrundeliegende Problem beschreiben und nach der besten 
Lösung dafür fragen :-)

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Warum jetzt noch mal ins gleiche Horn tröten? Wenn man weiß was man 
macht, ist das durchaus legitim. Und diese Aussage resultiert nicht aus 
mangelnder Erfahrung.

MfG Spess

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Wenn man weiß was man
> macht, ist das durchaus legitim.

Die Erfahrung zeigt aber, daß diejenigen, die diese Frage stellen (und 
die kam hier schon öfter), üblicherweise nicht mal ansatzweise wissen, 
was sie da tun.

Oliver

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man weiss, was man macht stellt man die Frage nicht so. Das 
uebliche Vorgehen in dieser Richtung ist einen Scheduler zu schreiben. 
Sonst macht das keinen Sinn.

Autor: bbb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist denn so unwichtig, dass man die Ausführung einfach so abbrechen 
kann? Das bräuchte man dann ja erst gar nicht ausführen ;-)

Die Methode ist auf jeden Fall sehr dreckig/schlecht. Beispielsweise 
braucht das Beschreiben von einer 16-bit Adresse durchaus mehrere CKs

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Die Erfahrung zeigt aber, daß diejenigen, die diese Frage stellen (und
>die kam hier schon öfter), üblicherweise nicht mal ansatzweise wissen,
>was sie da tun.

Richtig. Aber manchmal ist selbst auf die Schn... zu fallen lehrreicher 
als tausend Hinweise.

MfG Spess

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb im Beitrag #1746704
> Warum jetzt noch mal ins gleiche Horn tröten? Wenn man weiß was man
> macht, ist das durchaus legitim.


so lange man nur an irgend einer Stelle außerhalb der ISR was auf den 
Stack packt (und sei es nur durch Funktionsaufrufe), ist das Ganze 
tödlich.
Wenn immer wieder mal weggesprungen ist, bevor der Stack wieder 
abgeräumt wurde, dann ist man irgend wann am Ende des Rams angekommen 
und läuft in einen Adressbereich, bei dem die CPU den den Zugriff mit 
Absturz quittiert.

Autor: spess53 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>so lange man nur an irgend einer Stelle außerhalb der ISR was auf den
>Stack packt (und sei es nur durch Funktionsaufrufe), ist das Ganze
>tödlich.
>Wenn immer wieder mal weggesprungen ist, bevor der Stack wieder
>abgeräumt wurde, dann ist man irgend wann am Ende des Rams angekommen
>und läuft in einen Adressbereich, bei dem die CPU den den Zugriff mit
>Absturz quittiert.

Ach. Allerdings gehört das nicht in die Kategorie 'man weiss, was man 
macht'.
Stackmanipulation ist bei höheren Progrmmiersprachen eigentlich eher die 
Regel. Warum sollte man es in Assembler dann nicht machen. Im Anhang mal 
ein sinnvolles Beispiel.

MfG Spess

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:

> Stackmanipulation ist bei höheren Progrmmiersprachen eigentlich eher die
> Regel.

Das ist jetzt aber eine andere Baustelle

> Warum sollte man es in Assembler dann nicht machen. Im Anhang mal
> ein sinnvolles Beispiel.

Aber selbst dein Beispiel manipuliert nicht die Rücksprungadresse. Die 
lässt man normalerweise tunlichst in Ruhe.


Vuvuzelatus hat es exakt auf den Punkt gebracht.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Aber selbst dein Beispiel manipuliert nicht die Rücksprungadresse. Die
>lässt man normalerweise tunlichst in Ruhe.

Aber selbsverständlich wird die Rücksprungadresse manipuliert. Der 
UP-Aufruf gibt den 'String' der nachfolgenden 'db'-Direktive auf einem 
Display aus und das Programm geht nach dem 'db' weiter

   call print_str
   .db "abcde",0
   und hier geht es weiter

MfG Spess

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Hi
>
>>Aber selbst dein Beispiel manipuliert nicht die Rücksprungadresse. Die
>>lässt man normalerweise tunlichst in Ruhe.
>
> Aber selbsverständlich wird die Rücksprungadresse manipuliert. Der
> UP-Aufruf gibt den 'String' der nachfolgenden 'db'-Direktive auf einem
> Display aus und das Programm geht nach dem 'db' weiter

OK. Das hab ich so übersehen. Hast du recht.

Trotzdem ist dieser Fall nicht mit dem vergleichbar, den der 
Threadersteller im Sinn hatte.

Ein Interrupt returniert dorthin zurück wo er herkam. Nur in ganz 
wenigen Ausnahmefällen kann man davon abgehen (weil zb. ein kompletter 
Systemreset notwendig ist). Und da greift dann etwas, was weiter oben 
schon angesprochen wurde:

Wer weiß was er tut, braucht hier nicht fragen
Wer hier fragen muss, hat noch nicht die Übersicht um zu wissen was er 
sich einhandelt.

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

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Warum sollte man es in Assembler dann nicht machen. Im Anhang mal
> ein sinnvolles Beispiel.
Naja, hier würde es aber auch ein simples pop der Adresse vom Stack 
reichen + ein ijmp am Ende, ganz ohne Stackverbiegung.

Wenn man aus einem Interrupt die Rücksprungadresse verbiegen will gibt 
es eigentlich nur zwei Möglichkeiten:

1) Stackpointer reset (da eh alles im Eimer ist) + rjmp, "Ziel" muß 
dabei ein Codetewil sein der nicht mit ret zurückkehrt...
2) sei + rjmp und das "Ziel" muß eine Funktion sein die per ret 
zurückkehrt.

Fall 2 kann sinnvoll sein, wenn man nach einem Interrupt auf jeden 
Fall eine bestimmte Funktion ausführen will ohne die Interupts weiter zu 
sperren und dann erst wieder an die Ursprüngliche Stelle zurückzukehren. 
Ist aber höchst zweifelhaft, da man sich bei hoher Interruptfrequenz 
zwangsläufig weitere Probleme aufhalst.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Naja, hier würde es aber auch ein simples pop der Adresse vom Stack
>reichen + ein ijmp am Ende, ganz ohne Stackverbiegung.

Damit 'verbiegst' du aber Register. Und genau das soll vermieden werden.

MfG Spess

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

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Damit 'verbiegst' du aber Register. Und genau das soll vermieden werden.
Mist du hast recht... Also in diesem Fall einfach den Z-Pointer als 
Arbeitsregister definieren ;)

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läubi .. schrieb:
> Mist du hast recht... Also in diesem Fall einfach den Z-Pointer als
> Arbeitsregister definieren ;)

Und es hilft bei einem Interrupt genau wie, dass das als 
Scratchregister definiert ist?

Läubi .. schrieb:
> 2) sei + rjmp und das "Ziel" muß eine Funktion sein die per ret
> zurückkehrt.

Und damit hast du dann sauber die Flags zerstört, wenn das in einem 
Interrupt gemacht wird.

Andreas

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eigentlich wie immer, wenn man versucht, besonders "trickreich" zu 
programmieren, es gibt jede Menge Teufel im Detail, die alle Schlange 
stehen, um einem auf den Fuss zu hüpfen.

Es gibt sicher Einzelfälle, wo es mal nicht anders geht (Kontextswitch 
im Scheduler z.B.), ohne wirkliche Not sollte man sowas aber eher nicht 
machen.

Andreas

Autor: oldmax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
Manchmal ist es schön, euren Worten zu lauschen, während der 
Fragesteller längst zum Tagesthema abgewandert ist :)
Gruß oldmax

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.