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