Hallo zusammen, ich verwende das TWI Interface eines mega128 zusammen mit dem avrgcc. Die TWI ISR ist bisher so deklariert, das sie durch andere Interrupts nicht unterbrochen werden kann. Nun möchte ich aber explizit andere Interrupts während der TWI ISR Ausführung zulassen. Dabei habe ich folgende Probleme: 1.) Wenn ich die TWI ISR durch folgendes avrgcc Macro unterbrechbar mache: void TWI_vect( void ) __attribute__( ( interrupt ) ); Habe ich das Problem, das die TWI ISR in einer Endlosschleife hängen bleibt. D.d. sobald in die TWI ISR gesprungen wird, geht der Controller wohl davon aus das schon wieder ein Interrupt eingetreten ist und springt wieder in die TWI ISR. Das Verhalten scheint mir plausibel da das TWINT Bit auch noch gesetzt ist. 2.) Wenn ich in der TWI ISR explizit den TWI Interrupt deaktiviere ( TWIE = 0 ) und darauf durch sei( ) die globalen Interrupts wieder aktiviere so tritt das Problem von 1.) nicht mehr auf. Die TWI ISR wird auch unterbrechbar. Jedoch überträgt das TWI interface nur noch Müll. Irgendwie komme ich überhaupt nicht weiter. Deshalb meine Frage an euch: Wie bekomme ich es hin, das die TWI ISR des mega128 durch weitere Interrupts unterbrechbar wird ? Habe ich irgendwas übersehen ?!
Edit: Mir ist noch folgendes aufgefallen: Sobald das TWIE Bit auf 0 gesetzt wird, wird implizit auch das TWSR Register auf 0 gesetzt. Das Verhalten ist mir nicht klar ?!
Bei den AVRs sind Interrupts von Haus aus nicht unterbrechbar, das muss man Softwaremäßig lösen (Interrupt-Freigabe mit SEI). Abgesehen davon gibt es noch andere Probleme, z.B. Priorisierung (das können die AVRs ebenfalls nicht). Der Müll könnte auch durch Stack-Probleme zustande kommen - allerdings nur eine Vermutung. Ich würde versuchen, ohne solche Klimmzüge auszukommen. Interrupts allgemein werden so kurz wie möglich gehalten, keine Warteschleifen etc. in Interrupts - wenn man das beherzigt, muss man meist keinen Interrupt unterbrechbar machen.
Deswegen kann man mit dem genannten Macro auch explizit Interrupts in ISR´s freischalten. Das Macro macht nichts anderes wie ein sei am Anfang der ISR zu einzufügen. Bisher hatte ich nie solche Probleme und setze es sehr häufig ein das ISR´s unterbrechbar sind. Nur das TWI Interface scheint sich hier anders zu verhalten.
Tja, bei den AVRs ist es nicht schön gelöst mit den Interruptprioritäten (es gibt sie leider nicht). Und zu allem Übel löschen die Interrupts, die langsam sein dürfen, beim Eintritt nicht ihr Interruptflag (UART, I2C, EEPROM). Ich hab mir daher ne 2.Interruptpriorität in Software gebastelt und zwar mit T0. T0 läuft alle 256 Zyklen über und hält sich selbst an. Damit kann er nicht mehr sich selbst unterbrechen. Er wird aber als ISR_NOBLOCK definiert und ist damit unterbrechbar. Dann pollt er alle low priority Interruptquellen und führt die Handler aus. Und zum Schluß startet er sich wieder. Damit das funktioniert, müssen die high Priority Interrupts kürzer 256 Zyklen sein. Und die low priority Interrupts werden bis zu 256 Zyklen verzögert ausgeführt. Ich hab das für ne 8-Kanal Software-PWM mit UART und I2C benötigt. Funktioniert sogar. Ich hätts ja lieber mit nem 8051 gemacht und mir den ganzen Aufwand gespart, aber die funktional geeigneten NXP LPC9xx sind leider nicht 5V kompatibel. Peter
Ja, so ähnlich habe ich das auch gemacht. Aber das hilft mir jetzt nicht weiter. Keiner eine Idee wie ich die TWI ISR unterbrechbar mache ?
Mario wrote: > Ja, so ähnlich habe ich das auch gemacht. Aber das hilft mir jetzt nicht > weiter. Warum nicht? > Keiner eine Idee wie ich die TWI ISR unterbrechbar mache ? Wenn Dir die Idee nicht gefällt, denk Dir was anderes aus. Ich sage ja nicht, daß dies die einzige Lösung ist. Aber sie funktioniert und ist sauber. Peter P.S.: Man muß einen Timerinterrupt opfern, weil nur diese ihr Flag automatisch löschen und damit das SEI schnellstmöglichst ausgeführt werden kann.
Ich muss unmittelbar auf das TWI Interface reagieren und habe nicht die Zeit eine gewisse Zeit später zu pollen ob ein Interrupt anliegt. Gleichzeitig muss ich auf externe Interrupts horchen und darf dort keinen "verschlucken".
Wenn du den TWI-Interrupt abschaltest, musst du darauf achten, dass du das TWINT-Flag nicht aus versehen löschst, denn dann geht ja das TWI wieder auf Sendung:
1 | //also nicht:
|
2 | TWCR &= ~(1<<TWIE); |
3 | //sondern vl. so (nicht gestestet
|
4 | TWCR &= ~(1<<TWIE)|(1<<TWINT)); |
Wenn das erstmal nach totalem blödsinn klingt, schau(t) noch mal nach wie man (die meisten) Interruptflags löscht... hth. Jörg
Mario wrote: > Ich muss unmittelbar auf das TWI Interface reagieren und habe nicht die > Zeit eine gewisse Zeit später zu pollen ob ein Interrupt anliegt. Ich fürchte, dann hast Du das I2C gründlich mißverstanden. Das I2C wartet immer auf den langsamsten Teilnehmer (SCL-Stretching). Und wenn das HW-I2C richtig implementiert ist, kannst Du das auch nicht verhindern. Ich weiß, daß beim PIC das I2C nicht vollständig implementiert ist. Wenn Du also den AVR mit nem PIC verheiraten willst, hast Du schlechte Karten. I2C von 8051, AVR, ARM7 verstehen sich aber prima (warten aufeinander). Peter
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.