mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Stack beschummeln? - need help


Autor: Danny P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Zusammen!

Kurze Frage:
Ich möchte am Ende des Interrupthandlers Timer0 nicht nur mit "reti"
dahin springen wo der Interrupt ausgelöst wurde, sondern an ein
bestimmte Programmpunkt viel weiter davor.
Kann/muss ich einfach mit "pop Akku" den Stack um einen zurücksetzen
(wurde ja mit dem Interruptsprung auch erhöht) und dann einfach mit
"rjmp Start" an meinen Punkt springen?
Oder handel ich mir mit sowas Probleme ein? Gibs elegantere
Möglichkeiten?

thx & greetz
Danny

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nö, denn das entspricht einem ret, du brauchst aber reti.
Es geht aber anderst: Mir 2x pop den Stack verringern und mit 2x push
die neue Sprungadresse laden.

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In Interruptroutinen am Stack herummanipulieren, das ist sehr
gefährlich. Viel Spaß bei der Fehlersuche.
Ich wüßte auch keinen Grund, so etwas zu machen - Interrupts und
Unterprogramme sind eigentlich dafür da, daß sie ausgeführt werden,
ohne den Ablauf des übrigen Codes zu stören.
Denk mal z.B. über ein Flag nach, das in Deiner Hauptschleife abgefragt
wird.

Autor: Danny P. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, es geht darum das ich Daten synchron Empfange und den Takt
(fallende Flanke) nicht über ein ext.Interrupt abfrage, sondern einfach
mit "warte bis high" - "warte bis low". Ist sicher wenig
professionell aber ich hab entschieden das es vom Programm her in
diesem Fall einfacher ist.
Falls der Empfänger nun aber mal ausser Takt fällt soll per Timer das
"warten" unterbrochen werden. Würd ich den Stack nun nicht
manipulieren würde ich nach dem "reti" im Interrupthandler ja wieder
in der Warteschleife hängen...

thx & greetz
Danny

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gabs schon mal nen thrad zu, such mal nach

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, der war von von mir...
Der Fehler lag am Ende woanderst, bzw. am Assembler, der Byte und Word
Adressen gleichsetzt.
Mit einem 8051 habe ich das schon oft genug gemacht, das geht
wunderbar.

Außerdem ist das überhaupt nicht gefährlich wenn man das in Assembler
in einem Interupt macht. Es gibt ja nichts, das den Interrupt
verändert, und wenn doch, das würde auch im normalen Betrieb den Stack
verhauen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Mit einem 8051 habe ich das schon oft genug gemacht, das geht
wunderbar."

Wohl kaum !

Ohne ein RETI kannst Du beim 8051 nie wieder einen Interrupt
ausführen.


"Außerdem ist das überhaupt nicht gefährlich".

Na aber und ob. Du holst doch nur die Returnadresse vom Stack, was da
sonst noch so auf dem Stack liegt (Unterfunktionsreturnadressen, Daten)
davon hast Du nicht die geringste Ahnung.

D.h. Dein Stack läuft Dir irgendwann völlig aus dem Ruder.

Die einzige Möglichkeit ist, man springt ins Main zurück und dort wird
der Stack komplett neu initialisiert. Und beim 8051 mußt Du auch noch
bis zu 4 Dummy-RETIs machen (eins je Interruptlevel).


Peter

Autor: Winfried (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ein Vorgehen macht durchaus Sinn, wenn man es bedacht anwendet. Und
davon wurde auch z.B. in Heimcomputerzeiten viel Gebrauch gemacht.

Ich hatte letztens so einen Fall, wo ich es auch brauchte. Leider lässt
sich beim ATtiny 12 kein Stack manipulieren. Das Hauptprogramm musste in
einer sehr kurzen Schleife einen Pin toggeln, mehr nicht. Da war aber
keine Zeit, noch Bits abzufragen. Per Timerinterrupt sollte dann diese
Schleife umgeschaltet werden zu einer anderen, die etwas länger oder
kürzer läuft. Um ein unterschiedliches Tastverhältnis zu erreichen.

Also: Sagt niemals nie, aber man sollte schon mit Bedacht sowas
einsetzen. Oft gibt es bessere Lösungen.

Winfried

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bevor hier wieder die selbe Diskussion losgeht wie letzes mal:
a) es funktioniert einwandfrei !
b) ich lösche die Rücksprungadresse (=die letzen beiden Bytes auf dem
Stack) mit 2x POP
c) ich schreibe die neue Rücksprungadresse mit 2x push in den Stack
d) dann kommt ein reti
e) Bei einem Interrupt werden nur Adressen übergeben und keine Daten,
außerdem müssen die Adressen die letzen Daten auf dem Stack sein, denn
nach dem Interrupt befindet sich das Programm ja schon im Interrupt. In
C geht das nicht so leicht, denn man weiß nie was der Compiler macht,
aber in Assembler geht das problemlos.

Autor: Dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
man könnte auch den stack mit 2x pop befreien und dann mit nem rjmp und
sei weitermachen, dann braucht man keinen push der zeitraubend ist.

so: stimmt das eigentlich dass der µC durch ein falsches programm
abrauchen kann? z.b. stack-overflow?

dave

Autor: andré (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"so: stimmt das eigentlich dass der µC durch ein falsches programm
abrauchen kann? z.b. stack-overflow?"

Nein, es stimmt nicht. Allein durch falsche Software wirst du keinen µC
kleinkriegen.

mfg

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"a) es funktioniert einwandfrei !"

Aber nur, wenn Du absolut unstrukturierten Spaghettikode verzapfst, der
keinerlei Unterfunktionen aufruft und keinerlei Daten pusht.

Denn nur dann weißt Du, daß nur die Returnadresse auf dem Stack liegt
und kannst diese löschen.

Bei strukturierten Programmen, die Unterfunktionen verwenden liegen da
noch ne Menge anderer Returnadressen und Daten drauf, je nach
Unterfunktionstiefe und die bleiben dann als Müll liegen.


Beispiel:

Funktion A ruft Funktion B auf, die 2 Register puscht, dann kommt ein
Interrupt C.
Dieser entfernt die Returnadresse zu B und springt wieder nach A.
Ergo die Returnadresse zu A und die 2 gepuschten Register bleiben
liegen.
Beim nächsten Interrupt dann wieder das gleiche usw. bis der Stack
überläuft.


Peter

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Funktion A ruft Funktion B auf, die 2 Register puscht, dann kommt ein
>Interrupt C.
Der Interrupt legt seine Rücksprungadresse auf den Stack.
Und solange der Interrupt nicht durch einen anderen unterbrochen wird
(zumindest nicht in dem Teil, wo der Stack manipuliert wird) passiert
nichts !

>Dieser entfernt die Returnadresse zu B und springt wieder nach A.
>Ergo die Returnadresse zu A und die 2 gepuschten Register bleiben
>liegen.
Nein ! Sonst würde das normale reti ja auch die Adresse von B
löschen...
>Beim nächsten Interrupt dann wieder das gleiche usw. bis der Stack
überläuft.
Nö, oder wie kommtst du bei folgender Rechnnung zu einem anderen
Ergebnis als Stack(nachher)= Stack(vorher)?
Stack(nachher)= Stack(vorher)+2*(-1)+2*(+1)
-1=pop
+1=push


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Benedikt,

kehrt der Interrupt normal zurück, so tut er dies zu Funktion B, die er
ja unterbrochen hat. Diese wiederum popt die gesicherten Register wieder
und kehrt dann zu A zurück.

Geht der Interrupt aber direkt zu A, bleiben notgedrungen 4 Byte (ein
Call + 2 Datenbyte) auf dem Stack liegen.

Man kann aber auch nicht 6 Byte entfernen, da man ja nicht weiß, wo man
unterbrochen hat, ob in B oder B bzw. in B vor oder nach dem Puschen.

Im Interrupt können also bezogen auf Funktion A: 2, 4, 5 oder 6 Byte im
Stack liegen.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups ein Dreckfuhler, richtig:

... ob in A oder B bzw. in B vor oder nach dem Puschen.


Peter

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, stimmt.
Wenn man aber keine Unterprogramme verwendet dann geht es, (ansonsten
macht es ja auch wenig Sinn, zurück ins Hauptprogramm zu springen...

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann bastel mal einen halbwegs komplexen code in asm ohne
unterprogramme. es ist schoon schwer genug mit welchen da ordnung und
übersicht zu halten...

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das geht schon, kommt immer darauf an was das Programm machen soll.
Ich habe mehrere Programme, die komplett ohne per call aufegerufene
Unterprogramme auskommen. Alles läuft über Interrupts (mit
Stackmanipulation) und rjmp. Ist ein Videogenerator.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum einfach, wenns auch kompliziert geht?

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.