Hallo zusammen,
ich habe mal eine grundsätzliche Frage.
Ich arbeite mit einem MSP430FR5729 und spreche über I2C zwei Devices an.
Hin und wieder bricht der Bus "zufällig" zusammen und keine
Kommunikation ist dann mehr möglich. Der MSP430 hängt dann meist in
folgender Zeile:
1
while(UCB0CTL1&UCTXSTP);// Ensure stop condition got sent
Klar, ich könnte diese Zeile sinnvoller gestalten mit einem Zähler drum
herum und/oder einem Watchdog als zusätzliche Sicherheit.
Aber was kann denn grundsätzlich die Ursache für diesen plötzlichen
Bus-Crash sein?
Da solltest du mal mit einem Oszilloskop oder einem Logic-Analyzer
nachschauen, wie die Signale kurz vor und beim "crash" aussehen.
Vermutlich hält einer der Slaves die Clock low (clock stretching) und
lässt sie nicht wieder los.
Für eine gewisse Zeit ist dies zulässig, wenn ein Slave z.B.
signalisieren möchte, dass er z.Zt. busy ist.
Er sollte den Bus natürlich nicht dauerhaft blockieren.
Michael schrieb:> Klar, ich könnte diese Zeile sinnvoller gestalten mit einem Zähler drum> herum und/oder einem Watchdog als zusätzliche Sicherheit.
Das nützt aber dem Bus nichts, falls einer der Slaves Mist baut.
Michael schrieb:> Hin und wieder bricht der Bus "zufällig" zusammen und keine> Kommunikation ist dann mehr möglich. Der MSP430 hängt dann meist in> folgender Zeile:> while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got> sent>
Da hätte ich vermutlich eine Lösung:
Beitrag "I2C hängt sich auf"
mfg klaus
Vlt. hilft dir das:
Ich hatte auch mal das Problem, dass sich der I2C-Bus aufhängt und ich
quasi an selber Stelle fest saß. Trat immer sporadisch auf. Bis ich das
einmal reproduzieren konnte und da hatte ich einen Page-Write-Zugriff
versucht (also quasi mehrere Bytes nacheinander ab Page-Startadresse
schreiben), hab aber dann kein einziges Daten-Byte geschickt. Also
Start, alle Vorbereitungen zum Schreiben und dann die Stop-Condition.
Das EEPROM hat dann den Bus blockiert und nicht mehr hergegeben, also
Spannung weg und wieder dran und schon liefs wieder bis zur nächsten
Runde.
War einfach ein vergessenes -1 bei der Berechnung der Anzahl zu
schreibender Pages. Hat niemand gemerkt, bis ein Datenblock genau am
Ende einer Page zuende war... lief schon Jahre in Serie bis dieser
EEPROM-Code von mir in meine Software eingebaut wurde ;-)
Hallo zusammen,
danke für zahlreichen Tipps. Bisher bekämpfe ich das Problem mit Hilfe
eines Watchdogs, die Ursache habe ich dennoch noch nicht gefunden.
Gruß
Hallo,
hast Du Dir den von mir aufgezeigten Thread durchgelesen? Im Kern geht
es dabei um einen erweiterten I2C-INIT. Der löst gewisse Blockaden. In
Deinem Fall kann es allerdings noch eine andere Ursache sein.
mfg Klaus
Wenn man für I2C-Master keine Interrupts benutzt, sondern eh wartet,
kann man das auch ganz bequem per Bit-Banging machen. Dann kann sich
nichts aufhängen und mehr Code ist es auch nicht.
Peter D. schrieb:> Wenn man für I2C-Master keine Interrupts benutzt, sondern eh wartet,> kann man das auch ganz bequem per Bit-Banging machen. Dann kann sich> nichts aufhängen und mehr Code ist es auch nicht.
Nur, wenn der Code nicht in Ordnung ist.
Beim TO versucht der Master ein STOP auf den Bus zu legen und den
Zustand der Leitungen dahingegen zu überprüfen. Auf dem Bus kommt aber
kein Stop an (IMHO weil SDA vom Slave festgehalten wird), das
entsprechende Controlerbit wird daher nicht gesetzt.
Wenn man die Überprüfung, ob auf dem Bus ein STOP angekommen ist, im
eigenen Code nicht macht, sondern nur eine Bitzeit wartet, hängt der
BitBang Code nicht, und es sieht erstmal gut aus. Man könnte sich aber
bei Verwendung der HW auch die Abfrage des Bits im Controler sparen und
einfach eine Bitzeit warten. Dann läuft das Programm ebenfalls weiter.
Der Bus hängt in beiden Fällen, man merkts nur später. Ein LA würde es
einem gleich zeigen und wenn man Glück hat, auch seit wann er schon
hängt. Da ist der wirkliche Bug.
Einen Slave kann man abschießen, mit eigenem Code oder mit Hilfe der
Hardware. Vielfach reicht es, das letzte Byte eines Reads nicht mit NAK
zu quitieren oder einen Read in der Mitte eines Bytes im Debugger
abzuwürgen und den Code neu zu starten. Oder es ist so ein "Page
Problem" wie bei Sascha.
MfG Klaus
Einen blockierenden Slave kann man ganz einfach mit Bit-Banging lösen.
Man testet vor jedem Start, ob SDA high ist und erzeugt bei Bedarf bis
zu 9 SCL-Takte.
Soweit mir bekannt, hat aber kein Hardware-I2C eine solche Funktion.
Daneben gibt es HW-I2C, die sich auch ganz von selber aufhängen können,
weil sie einen Bug haben. Z.B. bei den ATmega AVRs reicht es schon, wenn
noch ein Master am Bus hängt, d.h. man Multimaster-I2C benutzen will.
Peter D. schrieb:> Daneben gibt es HW-I2C, die sich auch ganz von selber aufhängen können,> weil sie einen Bug haben. Z.B. bei den ATmega AVRs reicht es schon, wenn> noch ein Master am Bus hängt, d.h. man Multimaster-I2C benutzen will.
Die TWI-Logik der AVRs hat meines Wissens nach keine diesbezüglichen
Fehler.
Weder sind solche in irgendwelchen errata beschrieben noch konnte ich
jemals selber welche feststellen.
Kann es mal sein, dass einfach DU den doch recht ausführlichen Teil
des DB zum Thema TWI-MM nicht vollständig gelesen hast oder nicht alle
dort ausführlich beschriebenen Restriktionen im Code aller beteiligten
Master korrekt umgesetzt hast?
Als da im Wesentlichen sind:
1) Wann darf ich überhaupt nicht senden...
2) Was muß ich tun, wenn ich einen Konflikt mit einem anderen Master
bemerke...
3) Welche Grundbedingungen gibt es dafür, dass ich diesen Konflikt
überhaupt zuverlässig bemerken KANN...
...und genau darum würde es helfen, mit einem entsprechenden Analyzer
auf den Bus zu gucken, um herauszufinden was kurz vor dem Fehlerfall
passiert ist, und warum die Stop-Condition nicht stattfindet (ob SDA
oder SCL auf low gehalten wird).
Eventuell sind ja auch einfach die Pegel grottig, oder die Pull-Ups
stimmen nicht, oder das Timing ist kaputt.
Daher auch besser zusätzlich mit einem Oszilloskop angucken.
c-hater schrieb:> Weder sind solche in irgendwelchen errata beschrieben noch konnte ich> jemals selber welche feststellen.
Z.B. hier:
http://www.robotroom.com/Atmel-AVR-TWI-I2C-Multi-Master-Problem.html
Alle dort beschriebenen Fehler konnte ich reproduzieren.
Vermutlich hat Atmel die Multimasterfunktion nie getestet.
Da Philips/NXP seine 8051 mit I2C eingestampft hat, wollte ich ein Gerät
auf AVR umrüsten. Schon bei nur einem neuen AVR-Modul krachte es.
Als Lösung hab ich dann letztendlich ein Timeout aufsetzen müssen, das
bei den 3 Fehlern das klemmende TWI kurz disabled, enabled und den
vergeigten Transfer wiederholt. Ist nicht schön, aber es geht nicht
anders.
Die alten Philips/NXP liefen völlig ohne Timeout stabil.
Formal sieht das AVR-TWI wie von Philips abgekupfert aus (gleiche
Register, Bits, States), ich konnte also den C-Code vom 8051 übernehmen.
Bloß bei der Hardware sind Atmel eben die besagten 3 Fehler passiert und
niemand hats geprüft.
Die Atmel 8051 mit I2C haben übrigens die gleichen Fehler, wie die AVRs.
Und da ist es eindeutig der Atmel, da ich ja den gleichen Code und den
gleichen Compiler (Keil C51) wie beim Philips 8051 benutzt habe.
c-hater schrieb:> 1) Wann darf ich überhaupt nicht senden...
Theoretisch kann ich immer senden, da jeder Multimaster den Bus
überwachen muß und somit das Stop eines anderen erkennt.
Die Startbedingung darf das HW-I2C erst nach dem Erkennen eines Stop und
der vorgeschriebenen Wartezeit auf den Bus legen, bzw. sofort, falls der
Bus bereits idle ist.
Praktisch kann ich das Startbit beim Philips 8051 jederzeit setzen.
c-hater schrieb:> 2) Was muß ich tun, wenn ich einen Konflikt mit einem anderen Master> bemerke...
Theoretisch muß ich nur die Arbitration-Lost States behandeln.
Praktisch klappt das aber nur beim Philips 8051 zu 100% zuverlässig.
c-hater schrieb:> 3) Welche Grundbedingungen gibt es dafür, dass ich diesen Konflikt> überhaupt zuverlässig bemerken KANN...
Alle HW-I2C müssen einfach nur den von Philips definierten I2C-Standard
einhalten.
Peter D. schrieb:> c-hater schrieb:>> 3) Welche Grundbedingungen gibt es dafür, dass ich diesen Konflikt>> überhaupt zuverlässig bemerken KANN...>> Alle HW-I2C müssen einfach nur den von Philips definierten I2C-Standard> einhalten.
Wenn ich das mal noch erleben dürfte... ;-)
Peter D. schrieb:>> 1) Wann darf ich überhaupt nicht senden...>> Theoretisch kann ich immer senden
Das DB sagt hingegen:
Note that arbitration is not allowed between:
• A REPEATED START condition and a data bit.
• A STOP condition and a data bit.
• A REPEATED START and a STOP condition.
It is the user software’s responsibility to ensure that these illegal
arbitration conditions never occur. This implies that in multi-master
systems, all data transfers must use the same composition of SLA+R/W and
data packets. In other words: All transmissions must contain the same
number of data packets, otherwise the result of the arbitration is
undefined.
>> 2) Was muß ich tun, wenn ich einen Konflikt mit einem anderen Master>> bemerke...>> Theoretisch muß ich nur die Arbitration-Lost States behandeln.
Das DB sagt hingegen:
When a contending master discovers that it has lost the arbitration
process, it should immediately switch to Slave mode to check whether it
is being addressed by the winning master.
> Alle HW-I2C müssen einfach nur den von Philips definierten I2C-Standard> einhalten.
Es gibt Sachen, die nicht explizit im Standard stehen müssen, weil sie
sich aus der Logik der Sache selber zwingend ergeben.
c-hater schrieb:> Note that arbitration is not allowed between:> • A REPEATED START condition and a data bit.> • A STOP condition and a data bit.> • A REPEATED START and a STOP condition.
Schau Dir mal den Standard an. Das meint nur, daß dort kein Unterschied
festgestellt werden kann.
Die Arbitration kann man nur verlieren, wenn man ein Datenbit 1 sendet,
aber auf dem Bus Datenbit 0 liest.
Da die Master nicht hellsehen können, ist es natürlich möglich und
erlaubt, daß 2 Master gleichzeitig ein Start senden. Sie können sogar
die gleiche Slaveadresse senden ohne die Arbitration zu verlieren. Und
auch das ist natürlich erlaubt.
c-hater schrieb:> All transmissions must contain the same> number of data packets, otherwise the result of the arbitration is> undefined.
Das meint wiederum nur, daß nicht einer Daten und der andere Stop senden
kann, wenn bisher die Daten identisch waren, also die Arbitration noch
nicht entschieden. Das ergibt sich aber auch klar aus dem Standard.
Ich sichere das dadurch ab, daß das erste Datenbyte die Masteradresse
ist, d.h. spätestens danach ist die Arbitration entschieden.
c-hater schrieb:> When a contending master discovers that it has lost the arbitration> process, it should immediately switch to Slave mode to check whether it> is being addressed by the winning master.
Genau das mache ich doch, ich halte mich genau an den Philips
Beispielcode.
Der unterlegene und adressierte Master muß danach in den State 0x68
gehen (Arbitration lost in SLA+R/W as Master; own SLA+W has been
received; ACK has been returned).
c-hater schrieb:> Es gibt Sachen, die nicht explizit im Standard stehen müssen, weil sie> sich aus der Logik der Sache selber zwingend ergeben.
Da bin ich voll d’accord, aber Atmel hat das leider verpennt.
Ich hatte mich sehr gründlich mit I2C beschäftigt, eh ich das Gerät
entwickelt habe. Und auch der Philips Beispielcode war allererste Sahne,
der lief auf Anhieb einwandfrei.
Der Ärger ging erst mit den Atmels los.
Man findet von Atmel auch nur Single-Master Beispiel Code und keinen für
Multi-Master. Das hätte mich eigentlich schon warnen sollen.
Peter D. schrieb:> c-hater schrieb:>> Note that arbitration is not allowed between:>> • A REPEATED START condition and a data bit.>> • A STOP condition and a data bit.>> • A REPEATED START and a STOP condition.>> Schau Dir mal den Standard an. Das meint nur, daß dort kein Unterschied> festgestellt werden kann.> Die Arbitration kann man nur verlieren, wenn man ein Datenbit 1 sendet,> aber auf dem Bus Datenbit 0 liest.
In der Rev 03 von 2007 steht folgendes:
There is an undefined condition if the arbitration procedure is still in
progress at the moment when one master sends a repeated START or a STOP
condition while the other master is still sending data. In other words,
the following combinations result in an
undefined condition:
• Master 1 sends a repeated START condition and master 2 sends a data
bit.
• Master 1 sends a STOP condition and master 2 sends a data bit.
• Master 1 sends a repeated START condition and master 2 sends a STOP
condition.
>> Da die Master nicht hellsehen können, ist es natürlich möglich und> erlaubt, daß 2 Master gleichzeitig ein Start senden. Sie können sogar> die gleiche Slaveadresse senden ohne die Arbitration zu verlieren. Und> auch das ist natürlich erlaubt.>> c-hater schrieb:>> All transmissions must contain the same>> number of data packets, otherwise the result of the arbitration is>> undefined.>> Das meint wiederum nur, daß nicht einer Daten und der andere Stop senden> kann, wenn bisher die Daten identisch waren, also die Arbitration noch> nicht entschieden. Das ergibt sich aber auch klar aus dem Standard.
Das es unter obigen Bedingungen nicht entscheiderbar ist, wird im
ursprünglichen Standard (von 2000) nicht erwähnt. War den Verfassern
eventuell auch nicht bewusst.
> Ich sichere das dadurch ab, daß das erste Datenbyte die Masteradresse> ist, d.h. spätestens danach ist die Arbitration entschieden.
Defintiv best Praxis.
Bei einem reinem Messageprotokoll wie bei robotroom kann man auch anders
dafür sorgen, z.B. feste Länge, oder die Länge geht aus den Daten am
Anfang hervor (z.B. Längenbyte) und niemals implizit durch die STOP
Condition.
>> c-hater schrieb:>> When a contending master discovers that it has lost the arbitration>> process, it should immediately switch to Slave mode to check whether it>> is being addressed by the winning master.>> Genau das mache ich doch, ich halte mich genau an den Philips> Beispielcode.> Der unterlegene und adressierte Master muß danach in den State 0x68> gehen (Arbitration lost in SLA+R/W as Master; own SLA+W has been> received; ACK has been returned).>> c-hater schrieb:>> Es gibt Sachen, die nicht explizit im Standard stehen müssen, weil sie>> sich aus der Logik der Sache selber zwingend ergeben.>> Da bin ich voll d’accord, aber Atmel hat das leider verpennt.
Wenn Grenzfälle im Standard nicht diskutiert werden, passiert sowas
nunmal. Atmel sind nicht der einzigen die Bockmist machen.
>> Ich hatte mich sehr gründlich mit I2C beschäftigt, eh ich das Gerät> entwickelt habe. Und auch der Philips Beispielcode war allererste Sahne,> der lief auf Anhieb einwandfrei.> Der Ärger ging erst mit den Atmels los.> Man findet von Atmel auch nur Single-Master Beispiel Code und keinen für> Multi-Master. Das hätte mich eigentlich schon warnen sollen.
Der Fehler ist vermutlich, dass der Atmel Multi-Master beim Senden nicht
die START/STOP/REPEATET START auf dem BUS selbst monitored, sondern erst
wenn man den STOP Status des Masters bestätigt damit wieder anfängt. Das
gibt halt eine übles Wettrennen.
Dieser Bug liegt aber nicht an Unklarheiten im Standard, sondern hat
wirklich jemand gepennt. Sowas passiert gerne wenn die Spec Schreiber,
Hardware Leute, Software Leute nicht vom Anfang an miteinander reden.
(auch schon erlebt).
Software: Da stimmt was nicht, die Hardware ist buggy.
Hardare: Steht so in der Spec.
Spec Schreiber: Kann man nicht mehr ändern wegen vorgeschrieben
Prozeduren (ISO und so)
Hallo zusammen,
nach langen Stunden vor dem Oszilloskop habe ich herausfinden können,
dass im Fehlerfall die Spannung auf dem I2C Bus um ca. 1 Volt abfällt.
Der MSP430 erkennt dann keine gültige Stop Bedingung mehr und hängt sich
an beschriebener Code-Zeile auf.
Nach weiteren herumsuchen habe ich dann herausgefunden, dass sich ein
Slave Device über die I2C Leitungen mit Strom versorgt, da dessen
Versorgungsspannung im Fehlerfall einbricht.
Nun die spannende Frage: Warum?
Ich halte euch auf dem Laufenden.
Grüße
Michael schrieb:> nach langen Stunden vor dem Oszilloskop habe ich herausfinden können,> dass im Fehlerfall die Spannung auf dem I2C Bus um ca. 1 Volt abfällt.
AHA.
Ersmal messen ist immer gut ;-)
Um was für ein Slave-Device handelt es sich denn?
Hallo,
das blöde ist, dass der Fehler zufällig auftaucht und nicht
reproduzierbar ist. Von daher war ich froh, überhaupt mal was messen zu
können.
Es handelt sich um einen Beschleunigungssensor.