Forum: Projekte & Code TWI-Multi-Master für ATMEGA in C


von Michael S. (Gast)


Angehängte Dateien:

Lesenswert?

TWI-Multi-Master für ATMEGA in C

Der TWI-Bus wird in der Regel als "Single-Master-Bus" zentralistisch von 
einem einzelnen Master regiert, der um sich herum passive Slaves 
beschäftigt.

Der Multi-Master-Bus erlaubt dagegen den hierarchiefreien Betrieb 
mehrere gleichberechtigter Master an einem gemeinsamen Bus mit der 
Möglichkeit, dass jeder mit jedem direkt kommunizieren kann.
Und zusätzliche Slaves dürfen sich die Master natürlich auch halten.

Diese Freiheit will erkauft werden:
Es muss sichergestellt sein, dass zu jedem Zeitpunkt immer nur ein 
einziger Master eine Transaktion startet und ausführt.

Da ich im Netz bisher keine fertige Lösung für einen Multi-Master 
gefunden habe, habe ich hier einen eigenen Versuch gestartet.

Er baut auf dem TWI-Master und dem TWI-Slave der Atmel AppNotes auf, die 
ich neulich durchforstet und für meine eigene Verwendung vereinheitlicht 
habe:

Beitrag "Re: TWI-Master für ATMEGA in C (ohne TWI-Start/Stop, ACK/NACK)"

Der Programmcode ist in der zip-Datei beigefügt, eine ausführliche 
Beschreibung - auch der Tests - gibts in der Readme.pdf.


mfg

Michael S.

von Peter D. (peda)


Lesenswert?

Michael S. schrieb:
> Diese Freiheit will erkauft werden:
> Es muss sichergestellt sein, dass zu jedem Zeitpunkt immer nur ein
> einziger Master eine Transaktion startet und ausführt.

Das liegt aber nicht am I2-Bus, sondern an Atmel. Deren AVR und 8051 
hängen sich auf, wenn 2 Master zugleich versuchen zu senden.

Die I2C-Spezifikation ermöglicht natürlich das gleichzeitige Senden, ein 
Master verliert die Arbitration und kann es später versuchen. Ansonsten 
wäre der Status "Arbitration lost" ja völlig sinnlos.

Mit den NXP/Philips 8051-ern (P87C751, P80C562, P89C668) hat das auch 
super geklappt, bis sie eingestellt wurden. Der Multimaster-I2C 
funktionierte auf Anhieb und exakt nach den Beispielen in den 
Application Notes.

Den P89C668 habe ich durch den AT89C51RE2 ersetzt und schon hing der 
Bus.
Als Würg-Äraund mache ich folgendes. Sobald er die Arbitration verliert, 
wird das HW-I2C disabled und wieder enabled. Anderenfalls erzeugt er 
nach dem Stop des gewinnende Mastes wirre Impulse und kann nie mehr 
senden.

Beim Ersatz des P87C751 durch den ATmega8 gab es ähnliche Probleme, der 
ausgeflippte Master hielt SDA für immer auf Low.

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

Es ist daher überhaupt nicht verwunderlich, daß es von Atmel keine 
I2C-Multimaster Codebeispiele gibt. Dann hätten sie ja merken müssen, 
daß es nicht geht.


Mit einen funktionierenden I2C wäre Multimaster natürlich ne feine 
Sache. Niemand muß auf den anderen Rücksicht nehmen oder einen ihn 
ständig pollen.


Peter

von Michael S. (Gast)


Lesenswert?

Peter Dannegger schrieb:

>> Es muss sichergestellt sein, dass zu jedem Zeitpunkt immer nur ein
>> einziger Master eine Transaktion startet und ausführt.

Diese Aussage hätte ich besser formulieren können:
Es muss sichergestellt sein, dass - wenn mehrere Master zeitgleich eine 
Transaktion starten - dieser Konflikt aufgelöst wird und nur einer von 
ihnen den Bus übernimmt.

> Das liegt aber nicht am I2-Bus, sondern an Atmel. Deren AVR und 8051
> hängen sich auf, wenn 2 Master zugleich versuchen zu senden.

Diese Aussage kann ich zumindest für den ATMEGA48 nicht bestätigen.

Ich habe in allen meinen Tests drei Master gleichzeitig gestartet.
Es gab nie grundsätzliche Probleme, niemand hat sich aufgehängt.

Oder sollte an meinen Testbedingungen etwas nicht stimmen?

Einige Schwierigkeiten hatte ich nur nach einem Repeated Start.
Aber auch das war mit einem "Workaround" (pollen von SCL vor dem Setzen 
von TWEA) lösbar.

Im Übrigen soll es ja von BASCOM und bei der Arduino-Fraktion 
Bibliotheken für den Multimaster geben - ein Zeichen dafür, dass es 
nicht grundsätzlich nicht funktioniert.

Michael S.

von Michael L. (michaelx)


Lesenswert?

Hallo.

Mit Verwunderung lese ich über derlei Probleme bei AVRs mit 
Multi-Master-I2C.
Das hätte ich nicht gedacht, zumal die Specs von Philips diesbezüglich 
doch recht einfach und eindeutig sind.

Michael S. schrieb:
> Im Übrigen soll es ja von BASCOM und bei der Arduino-Fraktion
> Bibliotheken für den Multimaster geben - ein Zeichen dafür, dass es
> nicht grundsätzlich nicht funktioniert.

Bin mir nicht ganz sicher, aber ich meine gelesen zu haben, dass deren 
I2C "nur" in SW läuft, weil/um auf beliebigen I/O laufen zu können.

Vlt. kann das mal ein Experte aus der BASCOM und Arduino-Fraktion 
verifizieren.

Grüße.

von Peter D. (peda)


Lesenswert?

Michael S. schrieb:
> Ich habe in allen meinen Tests drei Master gleichzeitig gestartet.
> Es gab nie grundsätzliche Probleme, niemand hat sich aufgehängt.

Vieleicht hast Du nur Glück gehabt oder der Traffic ist zu gering.
Ich habe 6 I2C-Teilnehmer, die sich pausenlos unterhalten und der Fehler 
trat manchmal erst nach einer Stunde auf. Das Debuggen war daher sehr 
langwierig.
Das I2C läuft völlig im Interrupt, das Main wertet nur die Pakete aus 
und erzeugt neue Pakete. Der I2C kommt dadurch nie zur Ruhe.

In dem Link von David Cook ist auch sehr schön zu sehen, wie SDA am Ende 
dauerhaft auf low bleibt.
Und er verwendet den ATMega168, also muß der ATMega48 den Bug auch 
haben.


Peter

von Michael S. (Gast)


Lesenswert?

Peter Dannegger schrieb:

> In dem Link von David Cook ist auch sehr schön zu sehen, wie SDA am Ende
> dauerhaft auf low bleibt.

Ich habe mir den Beitrag von David Cook angeschaut.

Er erkennt folgendes Problem:

Nach einem TWI-Stop nimmt der Master an, der Bus sei frei - und 
übersieht dabei, dass er bereits wieder durch einen anderen Masters 
belegt ist.
Er sendet einfach drauf los ...

Sein Workaround:

Nach einem Stop wird in der ISR per Software geprüft, ob der Bus 
wirklich frei ist.

Rein zufällig habe ich eine ähnlich wirkende Prüfung eingebaut:

Bevor ein TWI-Start (TWEA) gesendet wird, polle ich per Software für 
einige Microsekunden SCL.
Nur wenn SCL ständig HIGH ist, wird TWEA gesetzt, wenn nicht, dann wird 
gewartet.


Folgende Beobachtung hat diese Warteschleife/Prüfung erforderlich 
gemacht:

Um eine Transaktion zu starten wird das Bit TWEA gesetzt (ein TWI-Start 
angefordert).
Die Hardware wartet auch brav, bis der Bus frei ist, erst dann wird die 
Start-Condition auf den Bus gegeben.

Aber während der gesamten Wartezeit reagiert die TWI-Hardware nicht als 
Slave:
offenbar kann sie zu diesem Zeitpunkt nur den Bus testen.

Wird nun dieser wartende Master als Slave adressiert, dann antwortet er 
nicht (bzw. mit NACK) - es kommt keine Verbindung zustande.

Folgerung: Auf jedem Master darf erst dann das Bit TWEA gesetzt werden, 
wenn der Bus wirklich frei ist.

Ich werde das Testszenario von David Cook bei Gelegenheit mal 
durchspielen.


Michael S.

von Peter S. (psavr)


Lesenswert?

>Rein zufällig habe ich eine ähnlich wirkende Prüfung eingebaut:
>
>Bevor ein TWI-Start (TWEA) gesendet wird, polle ich per Software für
>einige Microsekunden SCL.
>Nur wenn SCL ständig HIGH ist, wird TWEA gesetzt, wenn nicht, dann wird
>gewartet.

Damit kannst Du nicht verhindern, dass zwei Master gleichzeitig 
loslegen.

von Michael S. (Gast)


Lesenswert?

Peter S. schrieb:
> Damit kannst Du nicht verhindern, dass zwei Master gleichzeitig
> loslegen.

Völlig klar. Verhindern kann man es grundsätzlich nicht.

Aber die Wahrscheinlichkeit reduzieren.

Und einen besseren Vorschlag hat David Cook auch nicht.

Im Gegenteil - wenn ich es richtig verstehe, dann hat er sogar in einer 
ISR eine Warteschleife eingebaut.

Michael S.

von Peter D. (peda)


Lesenswert?

Michael S. schrieb:
> Nach einem TWI-Stop nimmt der Master an, der Bus sei frei - und
> übersieht dabei, dass er bereits wieder durch einen anderen Masters
> belegt ist.
> Er sendet einfach drauf los ...

Das ist nur einer der Bugs. Ist nicht schön, aber er bewirkt nicht das 
Hängen.
Wenn ein Master sendet und ein anderer sendet etwas später, weil er das 
Start nicht mitbekommen hat, kommt es zur Kollision. D.h. beide kriegen 
das Ereignis "Arbitration lost" oder "Bus Error". Beide können also 
drauf reagieren und später nochmal senden.

Ich habe das natürlich auch versucht, d.h. der Master, der STOP sendet, 
verläßt nicht erst den Interrupt, sondern pollt bis STOP vorbei ist und 
löscht sofort das Interruptflag.
Es hat aber garnichts gebracht, die Bus-Hänger waren vielleicht ein 
bischen seltener.


Da ich ja schon einen über viele Jahre funktionierenden Code mit 
NXP-Chips hatte, war es auch einfach, ihn auf Atmel anzupassen. 
Softwaremäßig ist er ja identisch (gleiche Bits, Register und Zustände) 
aber leider nicht harwaremäßig. Daher wußte ich auch recht schnell, daß 
es kein Softwarefehler sein kann.

Beim AVR war noch eine Fallgrube, daß das Interruptflag nicht unabhängig 
von den anderen Bits gelöscht werden kann. Ich mußte daher noch ein 
Schattenregister anlegen, damit das Flag wirklich erst am Ende des 
Interrupthandlers gelöscht wird. Beim 8051 kann man die Bits ja einzeln 
setzen, da gibt es dieses Problem nicht.


Peter

von Michael S. (Gast)


Lesenswert?

Peter S. schrieb:
> Damit kannst Du nicht verhindern, dass zwei Master gleichzeitig
> loslegen.

Und noch ein Gedanke dazu:

Wenn die Software einen freien Bus erkennt, können unmittelbar DANACH 
immer noch mehrere Master gleichzeitig starten. Klar.
Das stellt aber an sich kein Problem dar.

Denn es folgt ja noch die Prüfung durch die TWI-Hardware (entweder 
wartet der Master, weil er einen besetzten Bus erkennt oder es gibt 
einen Arbitrierungsfehler).


Im dümmsten Falle schlägt danach ein Repeated Start fehl (das Problem 
sollte meine Warteschleife lösen).

Aber die Schwierigkeite, über die David Cook berichtet, sollten nicht 
auftreten.

Theoretisch.


Michael S.

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.