Forum: Mikrocontroller und Digitale Elektronik gestartete TWI Übertragung ohne Reset rücksetzen


von Thomas Frosch (Gast)


Lesenswert?

Ich betreibe seit einiger Zeit ein Multimaster TWI System. Dieses 
funktioniert auch recht gut. Allerdings passiert es ab und zu 
(wahrscheinlich durch einen Wackelkontakt) wenn der 1. Master senden 
will dass er bei folgenden Status stehen bleibt:

TWI_REP_START  0x10  // 16 Repeated START has been transmitted
TWI_MTX_ADR_NACK  0x20  // 32 SLA+W has been tramsmitted and NACK 
received

Der 2.Master bekommt davon aber nichts mit, bei ihm ist der letzte 
Status der einer komplett abgeschlossenen Übertragung. Ich kann auch 
wieder eine Übertragung durch den 2. Master anstoßen die den 1. dann 
wieder in normale Funktion versetzt. Dabei sind allerdings 2 
Übertragungen notwendig, die erste versteht der 1.Master noch nicht geht 
da aber in den normalen Zustand. Bei der zweiten Übertragung läuft 
wieder alles normal.

Nun die Frage.

Wie kann ich den 1. Master sagen er soll wieder in den Grundzustand 
gehen. Ohne den µC zu reseten, so dass er für Empfang und Senden wieder 
bereit ist? Mir kommt es so vor als würde er ein Stop vom 2. Master 
benötigen um wieder normal zu laufen. Doch es soll unabhängig vom 2. 
Master laufen.

Die Lösung Wackelkontakt beseitigen ist ausgeschlossen, es soll ein 
System werden, dass Übertragungsschwierigkeiten erkennt.

Danke schon mal im voraus!!

von Peter D. (peda)


Lesenswert?

Thomas Frosch schrieb:
> TWI_REP_START  0x10  // 16 Repeated START has been transmitted
> TWI_MTX_ADR_NACK  0x20  // 32 SLA+W has been tramsmitted and NACK
> received

Dann bist Du immer noch der aktive Master, der den Bus belegt.
Du mußt ein STOP senden.

Generell sollte man auf alle Interrupts, die unerwartet sind, ein STOP 
senden.
Ist man der aktive Master, gibt man damit den Bus frei.
Ist man ein Slave, wird das Stop nur intern ausgewertet, d.h. der Slave 
wechselt in den nicht adressierten Zustand.


Peter

von Thomas Frosch (Gast)


Lesenswert?

Dass habe ich schon von anfang an so implementiert. Doch der Fehler 
tritt trotzdem auf. Selbst wenn ich im nachhinein per PC über uart dem 
µC sag er soll einfach mal so ein Stop senden (egal ob Stop mit oder 
ohne ACK) bleibt er dabei.

Gibt es noch andere Möglichkeiten?

Wenn ich den Bus belege warum kann dann der 2.Master trotzdem eine 
Übertragung starten? Weil er gar nicht mitbekommen hat dass der Bus 
belegt ist?

von Peter D. (peda)


Lesenswert?

Ich vermute mal, es geht um AVRs.

Da ist Multimaster ne äußerst komplizierte Sache, da das I2C der AVRs 
einen schweren Bug hat:

http://www.robotroom.com/Atmel-AVR-TWI-I2C-Multi-Master-Problem.html


Ich rate davon ab, AVRs als Multimaster zu verwenden.


Peter

von Thomas Frosch (Gast)


Lesenswert?

Ja das habe ich auch schon mal gelesen. Verstehe ich das richtig, sein 
Workaround besteht darin nach dem Senden/Empfangen einfach zu prüfen ob 
SCL und SDA beide längere Zeit High sind und lässt erst dann wieder ein 
Senden zu wenn diese Zeit abgelaufen ist?

von Peter D. (peda)


Lesenswert?

Ich bin mir nicht sicher, ob das allein hilft.
Ich habe 2 Timeouts eingebaut:

1.
Wenn man als Master STOP sendet und es nicht von selber rückgesetzt 
wird.
2.
Wenn der SDA-Pin konstant auf Low bleibt (Test per Flankeninterrupt).

Dann wird das I2C für ne Weile disabled und neu initialisiert.

Zusätzlich testet der Master, wenn er senden will, ob SDA/SCL für 50µs 
auf high bleiben und erst dann wird das START-Bit gesetzt.

Ist also ganz schön aufwendig (externer Interrupt, Timerinterrupt, 
Warteschleife).


Peter

von Thomas Frosch (Gast)


Lesenswert?

Wie testest du den 1. Fall also er sendet stop aber setzt sich nicht 
zurück. Also wie testest du, dass er sich nicht zurück gesetzt hat?

Und das mit dem Neu initialisieren geht ganz einfach mit den standard 
initialisierungsschritten? Oder muss ich irgend ein Bit vorher 
ausschalten, etwas warten und dann wieder ganz normal initialisieren?

Wäre für mich ein super Workaround.

von Peter D. (peda)


Lesenswert?

Thomas Frosch schrieb:
> Wie testest du den 1. Fall also er sendet stop aber setzt sich nicht
> zurück. Also wie testest du, dass er sich nicht zurück gesetzt hat?

Ich hab nen Timerinterrupt der alle 1ms aufgerufen wird und verschiedene 
Sachen macht.

Wenn also nach 1ms immer nocht STOP gesetzt ist, disabled er das I2C und 
ruft I2C_init auf.

Und wenn nach 1ms kein Flankeninterruptbit gesetzt ist, aber SDA = 0, 
dann auch.
Ich hab damals noch nen ATmega8 benutzt, d.h. kein Pin-Change-Interrupt 
und hab dann nen Draht von SDA nach INT0 gepatcht.

Es scheint zu gehen, aber man hat eben manchmal 1..2ms den I2C blockiert 
und muß ein Retry machen.

Ich hab mir den Code nochmal angeguckt und warscheinlich nen Fehler 
entdeckt:
Nach den 50µs wird das Startbit gesetzt aber nicht zurückt, wenn der 
andere Master schneller ist.
Ich sollte besser das Starbit nach 10µs zurücksetzen. Dann könnten die 
beiden Timeouts vielleicht überflüssig sein.
Aber es läuft so und never touch a running system.


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
Noch kein Account? Hier anmelden.