Forum: Compiler & IDEs global interrupts in einer ISR dauerhaft deaktivieren


von Peter O. (cpo)


Lesenswert?

Der Wert von SREG wird ja vor der ISR in einem Register gesichert, 
danach die global interrupts deaktiviert. Ber Verlassen der ISR wird 
SREG wieder hergestellt. (AVR-GCC)

Wie kann ich erreichen, dass vor der ISR aktivierte gloabl interrupts in
der ISR deaktiviert werden und nach der ISR dauerhaft deaktiviert 
bleiben.

Die Variante mit void interrupt_vect(void) ist keine Lösung, da die 
erste
Instruktion in der Procedure dann bereits sei ist und keine Zeit bleibt 
mit cli die global interrupts zu deaktivieren.

von Andreas K. (a-k)


Lesenswert?

Du musst das gerettete SREG finden und dort das I Bit löschen. Ist aber 
abgrundtief hässlich und wahrscheinlich der falsche Ansatz.

von Matthias L. (Gast)


Lesenswert?

Indem du die in den einzelnen Registern alle ausschaltest.

von Peter O. (cpo)


Lesenswert?

Ich denke auch. Das genutzte Register für das SREG wird in meinem 
Projekt nicht immer das Selbe sein. Trotzdem danke für den Gedanken.

von Peter O. (cpo)


Lesenswert?

Matthias Lipinsky wrote:
> Indem du die in den einzelnen Registern alle ausschaltest.

Das Manipulieren aller Register hätte doch Chaos zur Folge. Ich verstehe 
das nicht ganz, Matthias.

So sieht der erste Teil des Compilats der ISR aus:
1
@000000D2: __vector_33
2
417:      {
3
+000000D2:   921F        PUSH    R1               Push register on stack
4
+000000D3:   920F        PUSH    R0               Push register on stack
5
+000000D4:   B60F        IN      R0,0x3F          In from I/O location
6
+000000D5:   920F        PUSH    R0               Push register on stack
7
+000000D6:   2411        CLR     R1               Clear Register
8
+000000D7:   930F        PUSH    R16              Push register on stack
9
+000000D8:   931F        PUSH    R17              Push register on stack
10
+000000D9:   932F        PUSH    R18              Push register on stack
11
+000000DA:   933F        PUSH    R19              Push register on stack
12
+000000DB:   934F        PUSH    R20              Push register on stack
13
+000000DC:   935F        PUSH    R21              Push register on stack
14
+000000DD:   936F        PUSH    R22              Push register on stack
15
+000000DE:   937F        PUSH    R23              Push register on stack
16
+000000DF:   938F        PUSH    R24              Push register on stack
17
+000000E0:   939F        PUSH    R25              Push register on stack
18
+000000E1:   93AF        PUSH    R26              Push register on stack
19
+000000E2:   93BF        PUSH    R27              Push register on stack
20
+000000E3:   93EF        PUSH    R30              Push register on stack
21
+000000E4:   93FF        PUSH    R31              Push register on stack
22
425:      rout_timer_stop();                      //Timer1 abschalten

Anweisung 3:
1
 IN R0,0x3F
... lädt das SREG in R0. Ich arbeite mit einem ATMega128. Wird das SREG 
im Bedarfsfall immer in R0 gesichert? Habe dazu im Datenblatt nichts 
gefunden.

von Matthias L. (Gast)


Lesenswert?

>Ich verstehe das nicht ganz, Matthias.

Ich meine, wenn du irgendwelche ISRs aktiviert hast, kannst du die auch 
wieder deaktivieren, IM selben Register:
TIMSK, UCSR..

Ich meine die INDIVIDUELLEN Bits zum Freischalten der entsprechenden 
Ints.

von Peter O. (cpo)


Lesenswert?

Das ist tatsächlich der Punkt den ich umgehen will.  Es handelt sich 
hier praktisch um den TWI_vect.

Sobald ich den Vektor wieder lösche wird automatisch die Taktleitung 
(SCL) und damit der I²C-Bus wieder freigegeben. Ich versuche jedoch den 
Takt zu stretchen. Und die notwendigen TWI-Maßnahmen außerhalb der ISR 
abzuarbeiten.

Wenn das alles nichts hilft werde ich wohl die Taktleitung mit einem 
anderen PIN so lange auf low halten bis halt alles berechnet wurde.

von Matthias L. (Gast)


Lesenswert?

>Das ist tatsächlich der Punkt den ich umgehen will.
Hm. Aber das mit dem Gefrickel im SREG ist keine saubere Lösung.

>Takt zu stretchen.
Das muss auch so gehen.
in einem I2C-Sniffer von peda hat er das auch mal gemacht.
gucks dir mal an, vielleicht findest du raus wies geht
(ich habs mir nicht im Detail angesehen)
Beitrag "I2C (TWI) Sniffer mit AVR"

von Peter D. (peda)


Lesenswert?

Peter Oelsner wrote:
> Das ist tatsächlich der Punkt den ich umgehen will.  Es handelt sich
> hier praktisch um den TWI_vect.

Und warum sollen dann sämtliche anderen Interrupts darunter leiden 
müssen?

Besser also nur den TWI-Interrupt disablen, das ist dann auch sauber.

Was dann aber der Master dazu sagt, wenn er Däumchen drehen muß, ist ne 
andere Sache. Lange sollte man ihn daher nicht warten lassen.

In größeren I2C-Netzen wird oft mit Timeout gearbeitet, d.h. wenn der 
Master merkt, daß der Bus für länger als 1ms hängt, denkt er daß sich 
was verklemmt hat, verabschiedet sich vom Bus und versucht ihn wieder 
neu zu initialisieren.

Ist der Slave für längere Zeit beschäftigt, nimmt man daher besser ne 
andere Methode:
Der Slave sendet einfach NACK auf seine Adresse, stellt sich also tot. 
Der Master merkt das und versucht es dann später nochmal und kann 
inzwischen was anderes machen.

Die I2C-EEPROM 24Cxx machen das z.B. so.


Peter

von Johannes M. (johnny-m)


Lesenswert?

Andreas Kaiser wrote:
> Du musst das gerettete SREG finden und dort das I Bit löschen. Ist aber
> abgrundtief hässlich und wahrscheinlich der falsche Ansatz.
Das bringt nur im Normalfall (also bei einem normalen Interrupt Handler 
in C) überhaupt nichts, weil das gerettete SREG erstens an der Stelle 
des I-Bits immer eine Null enthält (schließlich wird es erst gerettet, 
wenn der Interrupt-Vektor bereits angesprungen wurde, und zu dem 
Zeitpunkt ist I bereits durch die Hardware gelöscht worden) und weil 
zweitens nach dem Wiederherstellen des SREG das I-Bit sowieso 
automatisch durch die Hardware wieder gesetzt wird (nämlich beim 
Rücksprung mit reti). Das Einzige, was man da machen kann, ist ein ret 
anstelle von reti am Ende des Interrupt Handlers, was in C geht, wenn 
man den Interrupt Handler als naked deklariert. In dem Fall muss man 
allerdings für alle Registersicherungen selber sorgen!

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.