Forum: Mikrocontroller und Digitale Elektronik Befehlszeiger AVR


von M. Н. (Gast)


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.

von Sven P. (Gast)


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

von M. Н. (Gast)


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.

von spess53 (Gast)


Lesenswert?

Hi

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

Nein. Das ist eine 'Word'-Adresse.

MfG Spess

von M. Н. (Gast)


Lesenswert?

ok dann ist alles klar.

Danke

von Peter D. (peda)


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

von avrfreak (Gast)


Lesenswert?

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

von Frank M. (aktenasche)


Lesenswert?

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

von Vuvuzelatus (Gast)


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

von spess53 (Gast)


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

von Oliver (Gast)


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

von Purzel H. (hacky)


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.

von bbb (Gast)


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

von spess53 (Gast)


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

von Vlad T. (vlad_tepesch)


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.

von spess53 (Gast)


Angehängte Dateien:

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

von Karl H. (kbuchegg)


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.

von spess53 (Gast)


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

von Karl H. (kbuchegg)


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.

von Läubi .. (laeubi) Benutzerseite


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.

von spess53 (Gast)


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

von Läubi .. (laeubi) Benutzerseite


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

von Andreas F. (aferber)


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

von Andreas F. (aferber)


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

von oldmax (Gast)


Lesenswert?

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

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.