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.
Du musst das gerettete SREG finden und dort das I Bit löschen. Ist aber abgrundtief hässlich und wahrscheinlich der falsche Ansatz.
Indem du die in den einzelnen Registern alle ausschaltest.
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.
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.
>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.
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.
>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"
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.