Forum: Mikrocontroller und Digitale Elektronik Interrupt Problem


von Ralf A (Gast)


Angehängte Dateien:

Lesenswert?

Hi
Ich habe den Quellcode im Anhang geschrieben, der auch soweit
funktioniert, jedoch nur wenn das "sei" im Label sek steht.
Die Aufgabe des Codes ist nach jedem Timer0 Overflow Interrupt einen
Zähler zu erhöhen und wenn dieser den Wert 31 hat einen weiteren Zähler
um eins erhöhen (dies geschieht immer so nach ca. 1 sekunde)
Wenn ich dass besagte "sei" entferne funktioniert der Code für exakt
eine Sekunde, danach nicht mehr. Wenn das "sei" an dieser Stelle ist
funktioniert der Code einwandfrei.
Was bewirkt das "sei" an dieser Stelle?

Ich freue mich auf eure Hilfe

von TravelRec. (Gast)


Lesenswert?

Sichere mal Dein SREG, bevor Du die eigentliche
Interrupt-Service-Routine ausführst, nach der ISR mußt Du´s wieder
rücksichern. Also:

 in   Temp, SREG
 push Temp
.....
.....
 pop  Temp
 out  SREG, Temp
 reti

von arc (Gast)


Lesenswert?

Weil im sek Teil direkt (ohne reti) in die Endlosschleife gesprungen
wird, was zum einen dazu führt das es irgendwann garantiert zu einem
Stackoverflow kommt, zum anderen wird (ohne reti) das globale
Interruptflag nicht autom. gesetzt.

von Hannes L. (hannes)


Lesenswert?

In dem Fall, wo du "sek" anspringst, beendest du deine ISR nicht mehr
mit "reti". Das hat einerseits den Effekt, dass das I-Flag im SREG
nicht wieder gesetzt wird und dadurch kein Interrupt mehr abgearbeitet
wird.

Dein "sei" täuscht nur vor, dass es funktioniert, aber dein Stack
läuft über, weil kein RETI erreicht wird, dass die Rücksprungadresse
des Int-Aufrufs wieder vom Stack nimmt.

Du musst deine ISR so schreiben, dass sie immer mit RETI beendet wird.
Der Übersichtlichkeit halber nimmt man dazu immer das selbe RETI. Denn
wenn das Programm etwas größer wird (wenn es eine Mainloop bekommt),
dann musst du in der ISR noch das SREG sichern und ggf lokale Variablen
beschaffen, indem du Registerinhalte vorübergehend auf Stack legst (PUSH
/ POP). Der Stack muss dabei immer ausgewogen sein, jedes PUSH braucht
sein POP, jedes (R)Call sein RET und jeder Int-Aufruf sein RETI.

Falls du mal übern Zaun schaun willst, dann schau mal hier:
www.hanneslux.de/avr

...

von Ralf A (Gast)


Lesenswert?

Danke für die schnelle Hilfe!

Das Problem mit dem Stapelüberlauf habe ich verstanden, nur sehe ich
das irgendwie bei der simulation im Studio nicht?
Ich sehe auch keine Möglichkeit, wie ich dass umgehen kann (Ich bin
totaler neuling)

 in   Temp, SREG
 push Temp
.....
.....
 pop  Temp
 out  SREG, Temp
 reti

Wie kann mir das Helfen?

von TravelRec. (Gast)


Lesenswert?

Dieses Fragment sollte in jeder ISR (Interruptserviceroutine) stehen,
für die Pünktchen setzt Du den eigenlichen Code ein, den die ISR
abarbeiten soll. Verwendest Du dann in der ISR auch noch andere
Variablen, die Du auch im Hauptprogramm benutzt, so mußt Du diese
anfangs auch push-en und am Ende der ISR wieder pop-en, damit nach dem
Interrupt alles so ist, wie es vorher war.

von Ralf A (Gast)


Lesenswert?

ok und wie mach ich das wenn ich wie in meinem Code ohne reti aus der
ISR rausspringe? dann hab ich ja dennoch dass gleiche Problem wenn ich
dass richtig verstanden habe.

von TravelRec. (Gast)


Lesenswert?

Das darfst Du nicht! RETI ist IMMER das letzte, was eine ISR ausführen
muß! Wenn Du aus der ISR ´raus willst, mußt Du immer noch die ganzen
POP-s und das RETI ausführen lassen, sonst raucht Dein Stack ab!

von Ralf A (Gast)


Lesenswert?

So hab jetzt was in der ISR geändert, und kann es jetzt simulieren.
Is da jetzt noch ein Stackproblem?
Ich glaube, dass es jetzt ok sein müsste.

von Ralf A (Gast)


Angehängte Dateien:

Lesenswert?

Hab den Code vergessen ;-)

von Hannes L. (hannes)


Lesenswert?

Warum schaust du bei der Simulation nich einfach mal deinem Stackpointer
zu? Der wird doch nicht zum Spaß im Workspace, I/O angezeigt.

...

von Ralf A (Gast)


Lesenswert?

ich sehe da nur nen Stackmonitor, bei dem hinter jedem Eintrag immer
disabled steht

von H.joachim S. (crazy_horse)


Lesenswert?

in   Temp, SREG
 push Temp
.....
.....
 pop  Temp
 out  SREG, Temp
 reti

Das ist natürlich Quark :-), es sei denn, Temp wird ausschliesslich in
ISRs verwendet.
Vollständig muss es so aussehen:
 push Temp
 in   Temp, SREG
 push Temp
.....
.....
 pop  Temp
 out  SREG, Temp
 pop Temp
reti

Ich habe immer gerne ein eigenes Register für die SREG-Sicherung
benutzt.

.def sreg_bak=R2

ISR:
in sreg_bak, SREG
.
.
out SREG, sreg_bak
reti

Das bietet sich an, wenn man noch freie Register hat oder es auf
kürzeste Interrupt-Laufzeit ankommt. Bei den RAM-losen Typen geht es
nur so.

von Ralf A (Gast)


Lesenswert?

ok hab ihn gefunden ;-) und ihm zugesehen und es verstanden.
Also vielen Dank für eure Hilfe

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.