Guten Morgen,
eigentlich ein ganz einfache Sache die ich machen möchte. Ich möchte das
ein Interrupt beim reti nicht da weiter macht wo er her gekommen ist,
sondern das alle Rücksprungandressen gelöscht werden ( Stack leeren??? )
und an einem anderen Label zurück springen.
Beispiel:
1
.INCLUDE "m88def.inc"
2
3
.def Dummy1 = r16
4
5
.equ F_CPU = 8000000 ; Systemtakt in Hz
6
7
.org 0x000 ; kommt ganz an den Anfang des Speichers
8
rjmp RESET ; Interruptvektoren überspringen und zum Hauptprogramm
Das Programm rennt in Loop_1 (0x002A) soweit ok. Nun kommt einen
fallende Flanke an INT1, das Programm springt zu Wechsel. Auch das ist
OK, nun kommt es an reti und springt wieder zurück nach Loop_1 (0x002A)
doch ich möchte das es zu Loop_2 springt (0x002B) und alle anderen
Rücksprungadressen vergisst (rcall, reti, Pop, etc)
Mir ist ganz klar das man jene Entscheidungen im Loop_1 treffen sollte
darum geht es aber hier gerade nicht. Meine Frage bezieht sich darauf
wie ich den Stack zurücksetzen kann und eventuell die neue
Rücksprungadresse eintragen.
Reicht es einfach:
Bei AVR kenne ich mich nicht aus, aber es wird sein, wie bei den meisten
anderen Architekturen. Die Register werden auf den Stack gesichert.
Schau wo auf dem Stack die Adresse liegt und ändere diese.
Auf anderen Prozessoren ist dies z.B. SP und SP-1 (StackPointer), dort
liegt die 16bit Adresse.
Hi
>Aber ansonsten ist dagegen nix zu sagen?
Ich würde so etwas nur in sehr, sehr überschaubaren Programmen anwenden.
Ansonsten mußt du mit mehr oder weniger lustigen Nebeneffekten rechnen.
MfG Spess
und noch was kürzer:
Wechsel:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,Low(RAMEND)
out SPL,r16
rjmp zieladresse
Zieladresse:
sei
.
.
Empfehlen würde ich es auch nicht, es geht auch "sauber".
Bei einem Programm, dass im Grunde genommen nichts macht, mag das ganze
ja gehen. Vor allem in Assembler.
Stack zurücksetzen und jmp xxx. Das ist alles.
... aber eigentlich ist es ja recht sinnvoll, wenn eine beliebige
Sequenz unterbrochen wird, die Arbeit an der UNTERBRECHUNGSSTELLE wieder
aufzunehmen.
In diesem Falle dient der Stack sozusagen als Gedächtnis.
Auch ist der Prozessorstatus danach in unbedingt definiert. Ein bisschen
von der Unterbrechung, ein bisschen von der Unterbrechung selbst.
Holger P. schrieb:> Aber ansonsten ist dagegen nix zu sagen?
Doch viel.
Das ist ne Lösung nur für den Eintagsprogrammierer.
Wenn Du aber länger programmieren willst und die Programme größer
werden, schießt Du Dir damit irgendwann ins Knie.
Holger P. schrieb:> Soll eine Art eigene Watchdog geben.
Was gefällt Dir an dem richtigen Watchdog nicht?
So ein quatsch. Aus Performance-Gründen war genau dieses ein sehr
beliebtes Mittel in der 8bit Ära.
Aber ich weiss schon, alles was alt ist, ist Mist. Auch wenn man seine
Tricks überblickt, kommentiert und genau durchdenkt.
Peter Dannegger schrieb:> Was gefällt Dir an dem richtigen Watchdog nicht?
Nun das ich nach einer bestimmten Zeit eine Bestimmte Routine anspringen
möchte und kein Reset ausführen.
Ich bin in einer schleife gefangen die bei Normalfall verlassen wird.
Aber im nicht normalen Fall würde sich mein kleiner Mega halt in dieser
Schleife aufhängen.
Also dachte ich einen Timer gestartet, da die schleife nach 0,5Sekunden
eigentlich beendet sein müsste. Ist dieses nicht der Fall so setzt der
Timer ein, Fehlermeldung wird ausgegeben und ab zu meinem Main.
Nils Stec schrieb:> So ein quatsch. Aus Performance-Gründen war genau dieses ein sehr> beliebtes Mittel in der 8bit Ära.>> Aber ich weiss schon, alles was alt ist, ist Mist. Auch wenn man seine> Tricks überblickt, kommentiert und genau durchdenkt.
Irgendwie verstehe ich die Aussage nicht so richtig.
Hi
>Nun das ich nach einer bestimmten Zeit eine Bestimmte Routine anspringen>möchte und kein Reset ausführen.
Ob der interne Watchdog einen Reset auslöst kann konfiguriert werden. Es
sind auch noch Interrupt und Interrupt mit nachfolgendem Reset möglich.
Außerdem kann beim Progammstart abgefragt werden, was den Reset
ausgelöst hat. Steht im Register MCUSR.
>Ich bin in einer schleife gefangen die bei Normalfall verlassen wird.>Aber im nicht normalen Fall würde sich mein kleiner Mega halt in dieser>Schleife aufhängen.>Also dachte ich einen Timer gestartet, da die schleife nach 0,5Sekunden>eigentlich beendet sein müsste. Ist dieses nicht der Fall so setzt der>Timer ein, Fehlermeldung wird ausgegeben und ab zu meinem Main.
Dann einfach einen Timer starten, der nach den 0,5s ein Flag setzt. Das
wird abgefragt und entsprechend gehandelt.
Ich habe den Watchdog in 15 Jahren mit AVRs noch nicht einmal gebraucht.
MfG Spess
spess53 schrieb:> Dann einfach einen Timer starten, der nach den 0,5s ein Flag setzt. Das>> wird abgefragt und entsprechend gehandelt.
Ja das war auch am Anfang meine Idee, doch habe ich in der Schleife
dafür keine Zeit mehr. Hatte ich schon versucht und das Timing war im
A.....
Hi
>Ja das war auch am Anfang meine Idee, doch habe ich in der Schleife>dafür keine Zeit mehr. Hatte ich schon versucht und das Timing war im>A.....
Als Flag kannst du z.B. auch das T-Flag in SREG nehmen. Dann langt ein
zusätzliches brtc oder brts um deine Schleife zu verlassen.
MfG Spess
spess53 schrieb:> Hi>>>Ja das war auch am Anfang meine Idee, doch habe ich in der Schleife>>dafür keine Zeit mehr. Hatte ich schon versucht und das Timing war im>>A.....>> Als Flag kannst du z.B. auch das T-Flag in SREG nehmen. Dann langt ein> zusätzliches brtc oder brts um deine Schleife zu verlassen.>> MfG Spess
Richtig das T-Flag hatte ich auch gefunden. Doch kostet mich auch die
brtc bzw. brts zu viel Zeit.
Holger P. schrieb:> Richtig das T-Flag hatte ich auch gefunden. Doch kostet mich auch die> brtc bzw. brts zu viel Zeit.
Zeig mal Code.
Irgendwie kommt mir das spanisch vor, wenn du einerseits eine Schleife
mit einem Timeout beenden willst, es aber auf der anderen Seite auf
jeden Taktzyklus ankommt.
Es gibt natürlich solche Fälle, bei denen es tatsächlich auf jeden
Taktzyklus ankommt, aber im Regelfall (wir reden hier immerhin über
Mykro-Sekunden) ist das kein Problem.
> Also dachte ich einen Timer gestartet, da die schleife nach> 0,5Sekunden eigentlich beendet sein müsste. Ist dieses nicht> der Fall so setzt der Timer ein, Fehlermeldung wird ausgegeben> und ab zu meinem Main.
Noch ein Grund mehr da geordnet aus der Schleife auszusteigen und hinter
sich aufzuräumen.
>Ich bin in einer schleife gefangen
Soso. Dann könnte es aber auch sein, dass Dein Problem ganz woanders
liegt als in Deinem Unwissen darüber, wie man den Stack verbiegt,
nämlich hier:
Was ist das für eine Schleife, die Deinen ATmega gefangennimmt? Muss sie
das unbedingt tun und wenn ja: Aus welchem Grund?
>Richtig das T-Flag hatte ich auch gefunden. Doch kostet mich auch die>brtc bzw. brts zu viel Zeit.
Diese Schleife muss etwas ganz Besonderes sein.
Holger P. schrieb:> Wo oder wie könnte ich das verkürzen?
warum nicht den Pinchage interrupt dafür verwenden und dann ein flag
setzen. auf diesen kannst du dann warten.
Oder ist es wichtig das du "sofort" nach dem low etwas machst?
Hi,
Holger P. schrieb:> ich möchte das es zu Loop_2 springt (0x002B) und alle anderen> Rücksprungadressen vergisst (rcall, reti, Pop, etc)
...wenn du den Stack eh löschst, brauchst du am Ende deiner ISR auch
kein reti. Das reti restauriert ja nur den P.C. mit der, beim Aufruf der
ISR auf den Stack gelegten, Adresse.
Das ist aber dirty coding...
loop_1:
rjmp loop_1
Loop_2:
rjmp loop_2
Wechsel:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,Low(RAMEND)
out SPL,r16
rjmp loop_2
Falls ich dich richtig verstanden habe...
Mike
Peter II schrieb:> Holger P. schrieb:>> Wo oder wie könnte ich das verkürzen?>> warum nicht den Pinchage interrupt dafür verwenden und dann ein flag> setzen. auf diesen kannst du dann warten.>> Oder ist es wichtig das du "sofort" nach dem low etwas machst?
Dieses habe ich auch schon versucht. Zum einen sind es 8 Signale die ich
hintereinander abfragen möchte. ( zu wenig Interrupt beim Mega88 ) und
zum anderen kostet mich das zu viel Zeit.
Ich habe 8 Signalleitungen die alle mal ganz kurz low werden. Es ist
alles OK wenn diese innerhalb von 0,5Sek mal low waren.
Also habe ich 8 von diesen Schleifen hintereinander gebaut.
Also
1. Taster wird gedrückt
2. Alle 8 Leitung auf low testen.
3. waren alle Leitung mal low alles OK
Klappt so auch 100% nur wenn mal eine Leitung defekt ist oder ???? so
würde ich aus diesem Test nie wieder zurück kommen. Deswegen ein Timer
1Sek vor den Schleifen starten. und nach den Schleifen wieder anhalten.
Schlägt der Timer zu so Fehlermeldung und ab wieder zum Main.
Diese Schleife ist exakt genauso schnell, wird aber verlassen sobald das
T-Flag gesetzt ist:
1
clt
2
Wait_Start_1:
3
sbic PIND,PIND2 ; Überspringe den nächsten Befehl, fals Bit 2 in PIND low ist
4
brtc Wait_Start_1 ; T=0 --> loopen, T wird beim Timeout in der Timer-ISR gesetzt
>Ein brbs kostet mich 631Hz was bei dieser Aufgabenstellung...
Solche Aufgabenstellungen sind (natürlich) nicht ausgeschlossen, aber in
der Praxis selten.
bzw. reti noch dran, damit den Compiler nicht mault. das reti wird ja
nicht ausgeführt, bei diesem rumgehopse in die Schleifen. aber sauber
geht anders... ;-)
Holger P. schrieb:> Ich habe 8 Signalleitungen die alle mal ganz kurz low werden.
Was ist 'ganz kurz'?
> nAlso> 1. Taster wird gedrückt
Das Wort 'Taster' ignorier ich jetzt mal.
spess53 schrieb:> Hi>>>Ein brbs kostet mich 631Hz was bei dieser Aufgabenstellung dazu führt>>das ich diesen kurzen low Impuls nicht immer sicher erkenne.>> Nein. ...> clt> ...>> Wait_Start_1:> sbic PIND,PIND2> brtc Wait_Start_1> brts Main> ...>> Interrupt:> set> reti> Das kostet dich lediglich einen Takt nach der Schleife wenn ein Inpuls> erkannt wurde.>> MfG Spess
Jou aber springt man nun nicht immer in Main?
Sollte Pin Low sein geht es weiter mit dem nächsten Pin dabei so wenig
Zeit wie es geht zu verlieren.
Aber ich werde es mal versuchen. Danke
Karl Heinz Buchegger schrieb:> Holger P. schrieb:>>> Ich habe 8 Signalleitungen die alle mal ganz kurz low werden.>> Was ist 'ganz kurz'?>>>> nAlso>> 1. Taster wird gedrückt>> Das Wort 'Taster' ignorier ich jetzt mal.
Der Taster ist lediglich zum starten der Prüfung gedacht.
Holger P. schrieb:> ALLES OK
Das bedeutet aber auch, dass deine Low-Pulse in genau der richtigen
Reihenfolge kommen müssen.
Davon war aber bei
> . waren alle Leitung mal low alles OK
noch nicht die Rede.
Und es erklärt immer noch nicht, wo diese ultrkurzen Pulse eigentlich
herkommen.
Würde es was helfen, alle 8 Eingänge gemeinsam parallel abzufragen?
ldi r16, 0xFF
loop:
in r17, PIND
and r16, r17
brne loop ; noch nicht auf allen eine 0 gesehen
die Schleife ist zwar ein wenig länger aber dafür ist die Reihenfolge
egal.
Aber der wichtigste Punkt scheint mir immer noch zu sein: wo kommen die
Pulse her bzw. machst du dir hier nicht eigentlich selbst ein Problem.
Hi
>Jou aber springt man nun nicht immer in Main?
Nein. Nur wenn das T-Flag gesetzt ist (Timeout) springt er aus der
Schleife und mit brts in deine Main oder wo du sonst hin willst. Ist das
T-Flag nicht gesetzt wird 'brts Main' ignoriert.
MfG Spess
Karl Heinz Buchegger schrieb:> Aber der wichtigste Punkt scheint mir immer noch zu sein: wo kommen die>> Pulse her bzw. machst du dir hier nicht eigentlich selbst ein Problem.
Das ganze Problem aufzuzeigen wäre echt Arbeit. Nehmen wir doch mal an
es ist so wie ich es sage. Also das Problem ist so wie hier getippt.
Deswegen bin ich ja auf die Idee mit dem Stack gekommen.
spess53 schrieb:> Hi>>>Jou aber springt man nun nicht immer in Main?>> Nein. Nur wenn das T-Flag gesetzt ist (Timeout) springt er aus der> Schleife und mit brts in deine Main oder wo du sonst hin willst. Ist das> T-Flag nicht gesetzt wird 'brts Main' ignoriert.>> MfG Spess
Aja eben habe ich es verstanden. Das werde ich mal versuchen ob mich der
eine Takt nicht killt.
Aber sieht so oder so nicht schlecht aus und vor allem wieder was
gelernt.
Hi
>Aja eben habe ich es verstanden. Das werde ich mal versuchen ob mich der>eine Takt nicht killt.
Den Sprung zur Main brauchst du nur nach
>Wait_Start_8:> sbic PIND,PIND7> rjmp Wait_Start_8
Die Teile davor werden mit gesetztem T-Flag einfach durchlaufen.
Allerdings ist die Variante von Karl-Heinz eleganter. Wie lang sind die
Impulse und mit welchem Takt läuft dein Controller?
MfG Spess
Holger P. schrieb:> Das ganze Problem aufzuzeigen wäre echt Arbeit. Nehmen wir doch mal an> es ist so wie ich es sage. Also das Problem ist so wie hier getippt.
ich steh nicht auf Rätselraten,
andere scheinbar schon
spess53 schrieb:> Wie lang sind die> Impulse und mit welchem Takt läuft dein Controller?
Das will er ja nicht sagen.
Mein Bauch sagt trotzdem, dass er das 'falsche Problem' löst.
Und sei es nur, dass er einen ungeeigneten Controller nimmt um
Nano-sekunden Pulse festzustellen, bzw. dort auf Software setzt wo
eigentlich schon Hardware angebracht wäre.
Aber ist ok. Des Menschen Wille ist sein Himmelreich.