mikrocontroller.net

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


Autor: Peter Oelsner (cpo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas K. (a-k)
Datum:

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

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Indem du die in den einzelnen Registern alle ausschaltest.

Autor: Peter Oelsner (cpo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Oelsner (cpo)
Datum:

Bewertung
0 lesenswert
nicht 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:
@000000D2: __vector_33
417:      {
+000000D2:   921F        PUSH    R1               Push register on stack
+000000D3:   920F        PUSH    R0               Push register on stack
+000000D4:   B60F        IN      R0,0x3F          In from I/O location
+000000D5:   920F        PUSH    R0               Push register on stack
+000000D6:   2411        CLR     R1               Clear Register
+000000D7:   930F        PUSH    R16              Push register on stack
+000000D8:   931F        PUSH    R17              Push register on stack
+000000D9:   932F        PUSH    R18              Push register on stack
+000000DA:   933F        PUSH    R19              Push register on stack
+000000DB:   934F        PUSH    R20              Push register on stack
+000000DC:   935F        PUSH    R21              Push register on stack
+000000DD:   936F        PUSH    R22              Push register on stack
+000000DE:   937F        PUSH    R23              Push register on stack
+000000DF:   938F        PUSH    R24              Push register on stack
+000000E0:   939F        PUSH    R25              Push register on stack
+000000E1:   93AF        PUSH    R26              Push register on stack
+000000E2:   93BF        PUSH    R27              Push register on stack
+000000E3:   93EF        PUSH    R30              Push register on stack
+000000E4:   93FF        PUSH    R31              Push register on stack
425:      rout_timer_stop();                      //Timer1 abschalten 

Anweisung 3:
 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Oelsner (cpo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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!

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.