Maßnahmen gegen das Hängen bei SPI/I2C Kommunikation

Gast #6617172
Lesenswert?

Hallo,

Diese Frage zielt darauf, welche allgemeinen Maßnahmen man im 
Werkzeugkoffer haben sollte, wenn man in der Firmware die SPI/I2C 
Kommunikation robuster machen möchte gegenüber Störung (z.b EMV).
Was tut ihr, wenn die Kommunikation z.B in der While-Schleife (gaanz 
schlecht, ich weiß) hängen geblieben ist, weil vom Slave keine Antwort 
kommt?

Der Schaltplan und die Hardware ist hier bei meiner Fragestellung 
zunächst als irrelevant zu betrachten.

Schönen Abend.
Gast #6617175
Lesenswert?

Teddy schrieb:
> Was tut ihr, wenn die Kommunikation z.B in der While-Schleife (gaanz
> schlecht, ich weiß) hängen geblieben ist, weil vom Slave keine Antwort
> kommt?
>
> Der Schaltplan und die Hardware ist hier bei meiner Fragestellung
> zunächst als irrelevant zu betrachten.

Dann viel Glück.
Wenn die Kommunikation in einer while-Schleife hängen bleiben kann, 
fehlt ein Timeout
#6617183
Lesenswert?

Wolfgang schrieb:
> fehlt ein Timeout

Wobei hier kann auch passieren dass sich der HW I2C Baustein sich 
verabschiedet hat. Danach könnte man versuchen den Baustein wenn es geht 
zu reseten. Aus und wieder einschalten könnte helfen. Manchmal aber auch 
nicht, da hilft dann nur der POR :(

Das Thema ist leider nicht so einfach. Wenn man anfängt mit HW 
Bausteinen zu arbeiten dann kann sein dass die sich aufhängen. Wenn man 
dann auf Bit Bang zurückgreift, dann wird man entweder den CPU aufhalten 
müssen damit man sehr schnell etwas schicken kann, oder es wird sehr 
langsam weil man eine State Maschine bauen muss.
Gast #6617184
Lesenswert?

Teddy schrieb:
> Was tut ihr, wenn die Kommunikation z.B in der While-Schleife (gaanz
> schlecht, ich weiß) hängen geblieben ist, weil vom Slave keine Antwort
> kommt?

Ja ja, immer schön die Hardware die voller Macken steckt, mit
Software Patches flicken. Das nennt man professionelles Arbeiten.

Teddy schrieb:
> Der Schaltplan und die Hardware ist hier bei meiner Fragestellung
> zunächst als irrelevant zu betrachten.

Bloss nichts mehr an der Hardware flicken, das könnte nur
schlafende Hunde wecken.
Gast #6617258
Lesenswert?

Andras H. schrieb:
> Wobei hier kann auch passieren dass sich der HW I2C Baustein sich
> verabschiedet hat. Danach könnte man versuchen den Baustein wenn es geht
> zu reseten. Aus und wieder einschalten könnte helfen.

Das hätte aber etwas mit der Hardware zu tun und wurde vom TO als 
irrelevant ausgeschlossen.

Teddy schrieb:
> Der Schaltplan und die Hardware ist hier bei meiner Fragestellung
> zunächst als irrelevant zu betrachten.
Beitrag #6617433 wurde von einem Moderator gelöscht.
Gast #6617473
Lesenswert?

Arduino Fanboy D. schrieb:
> Warum sind while Schleifen schlecht?
> Quasi jeder Prozess, jeder Thread/Task, beinhaltet eine solche
> (endlos)Schleife.
> Sie kann also nicht böse sein, sondern ist eher notwendig.

While-schleifen sind schlecht. Abgesehen von einzelnen Tasks, die extern 
überwacht werden (z.b. GUI, die auf Tasten/Events wartet)

Du meinst vermutlich Endlosschleifen. Das ist etwas anderes. (Wird in C 
eigentlich auch mit for gemacht)

Prinzipiell spricht dann nichts gegen while, wenn sichergestellt ist, 
dass die Schleife wirklich schnell genug verlassen wird. Z.b. warten bis 
transmit des uarts beendet.

Bei I2C-bus nur für interne Signale, ganz sicher nicht das Warten bei 
clockstretching.
Beitrag #6617474 wurde von einem Moderator gelöscht.
#6617853
Lesenswert?

SPI/I2C sind grundlegend unterschiedlich, die kann man nicht in einen 
Topf werfen.

SPI kann nicht hängenbleiben, aber auch keine Übertragungsfehler 
feststellen. Da hilft nur saubere und kurze Verdrahtung, eventuell 
Treiber-ICs (differentiell).

Bei I2C kann sich der Master durch Störungen verklemmen, da hilft 
Timeout mit Disable.
Wurde bei einer Störung oder einem Reset gerade ein Slave als Sender 
adressiert, kann dieser SDA auf low ziehen (0-Bit senden). Da helfen 
dann bis zu 9 Takte auf SCL.
Oder der Slave disabled sich ebenfalls nach einem Timeout, falls er auch 
ein MC ist.

Teddy schrieb:
> weil vom Slave keine Antwort
> kommt?

Dieser Fall ist unmöglich, der Master liest immer was. Er kann nur 
vermuten, daß es Mumpitz ist, wenn er bei I2C 0xFF liest oder bei SPI 
das vorher gesendete Byte.

Sind alle Teilnehmer MCs, dann sollte man ein Protokoll mit CRC 
vorsehen. Ist die CRC falsch, dann liegt ein Fehler vor.
Gast #6622529
Lesenswert?

Das Thema mit hängender I2C Staemachine habe ich hier schon endlos 
durchgekaut. Du brauchst überhaupt keine Timeouts und anderen OverBlow. 
Jede gescheite Anwendung benutzt den Watchdog und der wird zyklisch 
zurück gesetzt. Mit einer Laufzeitanalyse des Codes wird ermittelt wie 
oft er das tun muss. Und hängt es irgendwo kommt der Reset und danach 
werden Bits abgefragt warum er das getan hat. Der HardFault Handler ist 
auch noch eine Option, der Ausrutscher abfangen kann.

Mit Ausrutscher meine ich so ca 1-2 Wochen geht alles gut und dann steht 
alles und auch kein Reset Knopf bringt es mehr ans laufen.

Ich kann dir allerdings gleich sagen, dass bei mir alles nichts geholfen 
hat die I2C wieder in den Tritt zu bringen ausser ON/OFF und zwar bei 
beiden Teilnehmern. Die STM32 haben auch ein spezielles Bit dafür. 
Irgendwelche EEProms oder was es sonst noch gibt können auch stehen 
bleiben wo sie sind und die setzen erst zurück mit ON/OFF.

Meine rabiate Methode ist die, dass ich über einen 3.3V DC/DC Wandler 
mit Enable in der Größe eines Fingernagels alle abklemme per CPU Befehl 
und dann wieder zuschalte. Ruhestrom sind keine 150uA, damit kann ich 
leben.
Gast #6622745
Lesenswert?

Teddy schrieb:
> Diese Frage zielt darauf, welche allgemeinen Maßnahmen man im
> Werkzeugkoffer haben sollte, wenn man in der Firmware die SPI/I2C...
...
> weil vom Slave keine Antwort kommt?

Mal abgesehen vom Clock-Stretching beim I2C, was man entweder im Treiber 
oder im zuständigen I2C-Peripherie-Core zeitlich begrenzt, gibt es die 
Sitation NICHT, daß vom Slave keine Antwort kommt. Stattdessen hast du 
eben kein ACK und das führt nicht zum Hängenbleiben, sondern zum Abbruch 
der Transmission durch den Treiber und Rückgabe eines Fehlercodes oder 
so.

Und was die höheren Schichten der Firmware dann daraus machen, ist eine 
andere Nummer. Das hat dann aber nicht mit "Kommunikation robuster 
machen" zu tun, sondern nur mit "die eigenen Algorithmen robuster 
machen".

W.S.
Gast #6622767
Lesenswert?

Christian J. schrieb:
> Jede gescheite Anwendung benutzt den Watchdog und der wird zyklisch
> zurück gesetzt.

"Jede" würde ich nicht unterschreiben wollen. Es gibt Anwendungen, wo 
ein Neustart nur im äußersten Notfall zulässig ist.

Unabhängig davon hat der Watchdog keinen Einfluss auf die I²C cCients. 
Eine nicht abgeschlossene Transaktion ist nach dem Neustart immer noch 
offen. Ohne weitere Maßnahmen kann das dazu führen, dass der Bus nach 
dem Neustart direkt wieder hängt.

Freitakten ist eine gängige Lösung, die nicht 100% wirkt.

Die Clients kurz Stromlos schalten und den I²C Master resetten (nicht 
den ganzen µC) dürfte immer gehen, denke ich. Nur ist leider auch das 
nicht immer gewollt und möglich.
#6622780
Lesenswert?

W.S. schrieb:
> Mal abgesehen vom Clock-Stretching beim I2C

eben und wenn der Master nicht ewig warten will muss er sich selber eben 
aus dem Wartezustand befreien, er kann dann versuchen eine 
Abbruchsequenz zu senden und wenn das auch nicht hilft muß er eben einen 
Power On Reset auslösen und das geht nur am I2C slave durch 
Stromunterbrechung vom Slave.
#6622801
Lesenswert?

W.S. schrieb:
> Mal abgesehen vom Clock-Stretching beim I2C, was man entweder im Treiber
> oder im zuständigen I2C-Peripherie-Core zeitlich begrenzt, gibt es die
> Sitation NICHT, daß vom Slave keine Antwort kommt.

Wenn ein sich irgendwie verhedderter Slave SCL und/oder SDA low zieht, 
steht der Bus. Da hilft dann nur noch der o.a. Kopfschuß...

Oliver
Beitrag #6622979 wurde von einem Moderator gelöscht.
Beitrag #6622996 wurde von einem Moderator gelöscht.
(Firma: Tamoggemon Holding k.s.) #6623351
Lesenswert?

Oliver S. schrieb:
> W.S. schrieb:
>> Mal abgesehen vom Clock-Stretching beim I2C, was man entweder im Treiber
>> oder im zuständigen I2C-Peripherie-Core zeitlich begrenzt, gibt es die
>> Sitation NICHT, daß vom Slave keine Antwort kommt.
>
> Wenn ein sich irgendwie verhedderter Slave SCL und/oder SDA low zieht,
> steht der Bus. Da hilft dann nur noch der o.a. Kopfschuß...
>
> Oliver

Ich sehe, noch jemand hat HDC2010 Erfahrung
Gast #6623368
Lesenswert?

SPI Clients die hängen hatte ich noch nie, denke auch wenn der SSL High 
ist, sind die vom CHIP Aufbau nicht mehr fähig die Leitungen zu 
blockieren. (Man möge mich korrigieren)

I2C ist eine andere Nummer. Wir haben teilweise I2C Recovery Function 
eingeführt. Nachdem Bus-Hänger schwer zu reproduzieren sind, gibt es 
keine qualitative Aussage bzgl. Nutzen.
https://www.nxp.com/docs/en/application-note/AN10216.pdf
Seite 17 I2C Bus recovery.


Und natürlich jede while mit Abbruchbedingungen über die Zeit und 
Auslassen des Teilnehmers bei Fehler. Bleibt die SDA Leitung wirklich 
down schließe ich mich hier an:
Oliver S. schrieb:
> Da hilft dann nur noch der o.a. Kopfschuß...

Alles Annahmen das du der Master bist.
Gast #6623443
Lesenswert?

Peter D. schrieb:
> Wir produzieren seit 1995 Geräte mit I2C-Bus, die 24/7 laufen.

dito meine Firma (nicht die kleinste) seit geschätzt 1998.

Peter D. schrieb:
> Aber die VCC abklemmen war noch nie notwendig.

dito meine Firma. Wenn "solche Ereignisse" oder ähnliche notwendig
wären, wären I2C Bausteine schon längst aus unseren Geräten ver-
schwunden und intern hätte ein Aufschrei stattgefunden der seines-
gleichen gesucht hätte. Doch lebt I2C bei uns weiterhin.

Daher nochmal mein Zitat:

jo mei schrieb:
> Nur bei beratungsresistenten Teilnehmern im mikrocontroller.net-
> Forum die ihre Hardware selbst und schlecht aufbauen und dann
> jammern dass die Chips sich so mies verhalten.

Hinzuzufügen wäre dass es möglicherweise auch andere beratungs-
resistente Leute gibt die nicht notwendigerweise der mikro-
controller.net-Gemeinde angehören ....
Moderator Persönliche Seite #6623601
Lesenswert?

Peter D. schrieb:
> Wurde bei einer Störung oder einem Reset gerade ein Slave als Sender
> adressiert, kann dieser SDA auf low ziehen (0-Bit senden). Da helfen
> dann bis zu 9 Takte auf SCL.

Diese 9 Takte sind eigentlich fast immer das Patentrezept, wenn der 
I2C-Bus klemmt.

Ich konnte das bei Tests nachvollziehen. Wird der µC mitten in einer 
I2C-Übertragung resettet/ausgeschaltet, dann kann sich der angesprochene 
I2C-Baustein (z.B. eine RTC) dabei aufhängen und SDA auf permanent auf 
low ziehen. Da hilft unter Umständen noch nichtmals ein Power-Off, wenn 
die RTC an einer Batterie hängt. Aber die 9 Takte helfen immer.

Vorgehen (Pseudo-C):
1
bool i2c_reset_bus ()
2
{
3
    uint_fast8_t i;
4
    bool         success = true;
5

6
    if (SDA_is_low ())    // SDA low?
7
    {                     // yes, reset i2c bus
8
        set_SCL_low ();
9
        delay_msec (1);
10

11
        for (idx = 0; idx < 9; idx++)
12
        {
13
            set_SCL_high ();
14
            delay_msec (1);
15

16
            if (SDA_is_high ())  // SDA now high?
17
            {                    // yes, we are ready
18
                break;
19
            }
20

21
            set_SCL_low ();
22
            delay_msec (1);
23
        }
24

25
        set_SCL_high ();
26
        delay_msec (1);
27

28
        if (SDA_is_low ())      // SDA still low
29
        {
30
            success = false;
31
            // log_message ("error: cannot reset I2C bus");
32
        }
33
    }
34

35
    return success;
36
}

Die Delays mit 1 Millisekunde sind nicht fix vorgeschrieben. Sie sollen 
nur verdeutlichen, dass man nach einer neuen Flanke etwas warten sollte.

Dies kann man eigentlich immer prophylaktisch in der i2c_init()-Funktion 
durchführen. Dann ist man auf der sicheren Seite.

EDIT: C-Pseudo-Code nochmals geändert und mit Kommentaren versehen.
#6623640
Lesenswert?

Frank M. schrieb:
> Wird der µC mitten in einer
> I2C-Übertragung resettet/ausgeschaltet, dann kann sich der angesprochene
> I2C-Baustein (z.B. eine RTC) dabei aufhängen.

Das ist eine irreführende Aussage, denn er hängt sich gar nicht auf. Er 
bleibt einfach im Sende 0-Bit stehen, denn er kann ja nicht hellsehen, 
daß der Master resettet wurde.
Der Worst-Case ist, der Slave sendet 9 aufeinanderfolgende 0-Bits (ACK + 
8 Datenbits). Daher die bis zu 9 SCL-Takte, um SDA = 1 zu erhalten und 
das Startbit senden zu können.
Man muß nach jedem Takt prüfen, ob SDA = 1 ist, denn als Slave Receiver 
sendet der Slave nach 9 Takten wieder ein ACK, d.h. 0.

Die ganze Prozedur lang ist aber der Slave im regulären I2C-Modus und 
keinesfalls hängen geblieben oder abgestürzt.
Moderator Persönliche Seite #6623649
Lesenswert?

Peter D. schrieb:
> Das ist eine irreführende Aussage, denn er hängt sich gar nicht auf.

Ja, natürlich, er hat sich nur "augenscheinlich" aufgehängt, weil er 
sich nicht erwartungsgemäß verhält, wenn ich das System einschalte.

Peter D. schrieb:
> Man muß nach jedem Takt prüfen, ob SDA = 1 ist,

Ist in obigem Pseudo-Code auch so drin, siehe "break".
#6623723
Lesenswert?

Mike schrieb:
> https://www.nxp.com/docs/en/application-note/AN10216.pdf
> Seite 17 I2C Bus recovery.

"1 - Send 9 clock pulses on SCL line"

Darin fehlt jedoch das Abfragen nach jedem Takt. D.h. man kann in die 
Slave-Receiver Falle laufen und nach jeweils 9 Takten das nächste ACK 
sehen. Daß dazwischen der Bus frei ist (SDA = 1), merkt man so nicht.
Dieser Fall kann durchaus sehr wahrscheinlich sein, da der I2C-Interrupt 
im ACK-Slot wartet, bis das nächste Byte in den Sendepuffer geschrieben 
wird. Bleibt dann ein höher priorisierter Interrupt oder atomarer Block 
hängen und schlägt der Watchdog zu, dann ist das I2C in genau diesem 
Zustand.
Man verdächtig dann den I2C-Slave, obwohl der Fehler an einer völlig 
anderen Stelle passiert.

Trick 17 wäre natürlich:
- SDA abfragen
- SCL 10* takten // above 9 but not multiples of 9
- SDA abfragen

Damit wäre man asynchron zum ACK-Slot und der Leser kratzt sich verdutzt 
am Kopf.
Gast #6623776
Lesenswert?

Frank M. schrieb:
> Diese 9 Takte sind eigentlich fast immer das Patentrezept, wenn der
> I2C-Bus klemmt.

Die stehen schon seit 20 Jahren in einer Appnote von Microchip drin 
glaube ich. Gewirkt haben sie bei mir aber nicht auf einem AVR. Lag 
vielleicht auch daran, dass sich der Hang-Up Zustand nicht künstlich 
erzeugen liess und die Routine nur aus dem Kopf geschrieben war in der 
Hoffnung, dass sie "wirkt".
Die Hänger traten eh nur alle 1-2 Wochen auf oder auch mal nicht. Beim 
STM2 ist das ja eine Mords-Umschalterei, bevor aus einem I2C Pin wieder 
ein I/O Pin wird und das Ganze wieder zurück.

Ich gebe zu, dass ich irgendwann aufgehört habe darüber nach zu denken 
und die Holzhammer-Methode des Abschaltens der Slaves gewählt habe, da 
ich nur den Master unter voller Kontrolle habe.

PS: Watchdog ist bei sicherheitsrelevanter Software in gelber Ware 
absolute Pflicht, sogar ein externer. Es kann jederzeit ein Bit oder 
irgendwas kippen. Und das System muss genau da wieder aufsetzen wo es 
aufgehört hat.
(Firma: Tamoggemon Holding k.s.) #6623791
Lesenswert?

jo mei schrieb:
> Peter D. schrieb:

> dito meine Firma. Wenn "solche Ereignisse" oder ähnliche notwendig
> wären, wären I2C Bausteine schon längst aus unseren Geräten ver-
> schwunden und intern hätte ein Aufschrei stattgefunden der seines-
> gleichen gesucht hätte. Doch lebt I2C bei uns weiterhin.
>

Hallo,
wenn ich kleine Flügelchen am Hintern hätte, wäre ich eine Yak40. Leider 
bin ich aber nur ein rassischer Halbaraber.

Die Sensorbausteine kommen allzu oft aus der Anwendung und du kannst sie 
nicht aussuchen. Wenn du es kannst, ich beneide dich. Ich kann es leider 
nicht...zumindest in dieser Applikation nicht.

lg
th
#6623799
Lesenswert?

Christian J. schrieb:
> Lag
> vielleicht auch daran, dass sich der Hang-Up Zustand nicht künstlich
> erzeugen liess und die Routine nur aus dem Kopf geschrieben war in der
> Hoffnung, dass sie "wirkt".

Beim AVR ist das sehr einfach zu simulieren, da er genau in den 
kritischen ACK-Slots auf den Interrupt wartet. Man muß also nur eine 
Endlosschleife einfügen und auf den Watchdog warten.
Die Endlosschleife wird dann z.B. per UART-Befehl oder Taster 
getriggert.
Die UART gibt dann nach dem Watchdogreset aus, wie oft SCL getaktet 
werden mußte. Als Slave reicht ein einfacher PCF8574.

Aber es ist schon ein Armutszeugnis, daß über viele Jahrzehnte es noch 
kein MC-Hersteller geschafft hat, sowas in den I2C-Controller zu 
integrieren. Man könnte es automatisch vor jedem Startbefehl aufrufen.
#6623860
Lesenswert?

Peter D. schrieb:
> Aber es ist schon ein Armutszeugnis, daß über viele Jahrzehnte es noch
> kein MC-Hersteller geschafft hat, sowas in den I2C-Controller zu
> integrieren.

Vielleicht ist das eine Charaktersache, weil man damit ja nicht das 
eigentliche Problem beseitigt ;) Man könnte nämlich auch am anderen Ende 
ansetzen:
Es ist eine Schande, dass es Port-Expander ohne Reset-Pin gibt und 
ausgerechnet solche besonders beliebt sind.
Es ist eine Schande, dass eine RTC das I2C-Interface im Batteriebetrieb 
nicht abschaltet.
Es ist eine Schande, dass es so wenig I2C-Peripherie mit integriertem 
Time-Out gibt. Ausgerechnet Maxim baut eine RTC mit I2C-Time-Out (und 
5ppm MEMS-Oszillator!), MAX31343. Aber die kennt natürlich wieder 
niemand :(
#6624145
Lesenswert?

Bauform B. schrieb:
> Vielleicht ist das eine Charaktersache, weil man damit ja nicht das
> eigentliche Problem beseitigt ;)

Das Problem ist eigentlich nur, daß man I2C nicht verstanden hat.
Es liegt kein Fehler vor, sondern der Master wurde innerhalb eines 
Transfers resettet oder hat durch Leitungsstörungen die Arbitration 
verloren. Daher sollte auch der Master gefälligst den Slave wieder 
deadressieren, denn der Slave ist völlig unschuldig. Er verhält sich nur 
streng nach dem I2C-Standard. Daß der Standard kein Timeout definiert, 
mag nicht jedem gefallen, läßt sich aber nachträglich nicht mehr ändern.
Es hat dafür den Vorteil, daß es keine Maximalzeiten gibt, d.h. man kann 
I2C zu Fuß debuggen und keine Task muß auf I2C Rücksicht nehmen.

Bauform B. schrieb:
> Ausgerechnet Maxim baut eine RTC mit I2C-Time-Out

Dazu muß aber SCL >35ms auf low gehalten werden. Also muß man doch 
wieder das I2C disablen und mit den Pins spielen. Da mache ich lieber 9 
Takte, das geht bedeutend schneller.
Gast #6624346
Lesenswert?

Stefan ⛄ F. schrieb:
> Wer ist "er"?

Der IC (integrierte Schaltkreis), der in 99.9% der Fälle 
fälschlicherweise verantwortlich gemacht wird, abgestürzt zu sein.


Vielleicht stürzen ja wirklich I2C-ICs ab. Ich kenne das aber auch nur 
so, dass die ersten zig Implementierungen einfach von Unkenntnis geprägt 
sind. Ich habe Clock-Stretching beispielsweise erst nach Jahren 
berücksichtigt. Andere Kollegen kennen das heute noch nicht.
#6624630
Lesenswert?

Daß ein Master nach dem Reset einen adressierten Slave vorfinden kann 
und ihn deadressieren muß, ist ja nun kein großes Ding.

Aber es gibt leider auch buggy I2C-Controller, die als Multimaster so 
richtig Ärger machen. Da sträuben sich einem dann wirklich die Haare.

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

https://community.st.com/s/question/0D50X00009XkgoY/stm32-i2c-multimaster-hardware-bug

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren