Der I2C-Bus wird auf einem Single-Master-Single-Slave-System blockiert

Ich habe versucht, eine I2C-Treiberfunktion zum Lesen von Daten von einem Näherungssensor (Cypress CY8CMBR3102) zu entwickeln, und anfangs hat die Funktion sehr gut und erfolgreich funktioniert. Aber während der Slave kontinuierlich Daten vom Gerät liest, hält der Slave die SDA-Leitung niedrig und das Busarbitrierungs-Flag wird in der MCU (NXP MKE04Z64) gesetzt. Dadurch wird jede weitere Kommunikation blockiert.

Ich habe den folgenden Fix in meinem Code ausprobiert, aber es hat nicht funktioniert.

  • Jedes Mal, wenn ich vom Gerät lesen möchte, behalte ich die I2C-Pins als GPIOs und überprüfe den Pegel im Datenbus.

  • Das I2C-Modul wird nur aktiviert, wenn der Datenbus im High-Zustand ist.

  • Wenn der Bus niedrig gehalten wird, wird der SCL-Pin als GPIO getaktet, bis SDA vom Slave freigegeben wird.

Als ich den obigen Fix im Gerät getestet habe, bleibt der Code in der Schleife hängen, in der ich den SCL-Pin takte, bis SDA wieder hoch wird. Das bedeutet, dass das Takten von SCL nicht dazu beiträgt, den Bus vom Slave freizugeben.

Wenn ich jedoch den Slave ausstecke oder einen Power-Reset durchführe, wird der Bus freigegeben, da der Slave zurückgesetzt wird.

Ich kann die Ursache für dieses Problem immer noch nicht finden. Ich habe die Leitungen mit einem DSO überwacht und kein nennenswertes Rauschen in den Leitungen gefunden.

1. Was könnte der mögliche Grund für diese Bussperre sein?

2. Wie kann man erkennen und wiederherstellen, wenn der Bus gesperrt ist?

Die Details unseres Setups sind wie folgt:

-> Einzelner Master - Einzelner Slave

-> Meister - NXP MKE04Z64 Arm Cortex M0+

-> Slave - Cypress CY8CMBR3102 Capsense Näherungsregler

-> 400KHz I2C-Takt

-> MCU-Pins sind Open-Drain mit 4,7 K externen Pull-ups.

-> Master und Slave sind in getrennten Platinen mit einem 6cm langen Draht verbunden.

Außerdem legt das Datenblatt Wert auf die Funktion "Kein Bus-Stalling oder Clock-Stretching während Transaktionen", was bedeutet, dass der Sensor reibungslos funktionieren sollte ... wenn der Master sich natürlich an die Regeln hält. Es enthält umfangreiche Informationen zu den Timing-Anforderungen. Haben Sie alle Richtlinien befolgt? Insbesondere "busfreie Zeit" und eine Möglichkeit für das Gerät, beim Übergang zwischen Zuständen NACK zu antworten.
Ja, ich habe die Firmware gemäß den Anweisungen im Datenblatt erstellt. Ich schätze, der Slave wird nicht einmal ACK geben, wenn es ein Timing-Problem mit dem System gibt. Der Slave reagiert einige Zeit nach dem Einschalten sehr gut. Der Zeitpunkt, zu dem der Bus gesperrt wird, ist völlig zufällig. Das kann nach einer Minute, einer Stunde passieren oder sogar auf unbestimmte Zeit ohne Probleme laufen. Ich kenne die Ursache immer noch nicht.
Sie müssen entweder einen Pfad haben, um einen Hardware-Reset des Peripheriegeräts durchzuführen (falls dies überhaupt möglich ist), oder Sie müssen die Bedingungen identifizieren, die dies verursachen, und sie vermeiden. Eine Art automatisiertes Fuzzing in Kombination mit einem Test für diesen hängengebliebenen Zustand könnte sich lohnen, um zu sehen, ob Sie eine wiederholbare Ursache finden können. Suchen Sie auch nach bekannten Fehlern und wenden Sie sich an die Anwendungstechniker des Anbieters. Wenn möglich, wählen Sie nicht blockierende Modi, in denen Sie eine Messung auslösen und später zurückkommen, um die Ergebnisse abzufragen, anstatt diese zu verzögern, bis Sie fertig sind.
Wie funktioniert "kontinuierliches Lesen von Daten"? Sie können Daten nicht unbegrenzt lesen. Irgendwann müssen Sie die Stoppbedingung senden und den Datenzeiger zurücksetzen. Und am wichtigsten ist, dass jede Operation mit der Adresse beginnen und die Startbedingung wiederholen muss, bis der Slave bestätigt. Die meisten MCU-Firmware-Bibliotheken, die ich gesehen habe, unterstützen dieses Verhalten nicht standardmäßig. Schließlich sollten Sie die HI-Funktion verwenden, um den Sensor nur bei Bedarf zu lesen und nicht immer wieder dieselben Daten abzufragen.
@Maple Mit "Kontinuierliches Lesen von Daten" meinte ich, dass ich die Lesesequenz mehrmals mit den richtigen START- und STOP-Bedingungen und -Timings ausführe. Lassen Sie mich die HI-Funktion überprüfen, die Sie erzählen.
@ChrisStratton Du hast Recht, die einzige Option, die mir bleibt, ist, die Kontrolle über die Stromversorgung des Slaves zu übernehmen, um einen Power-Reset durchzuführen, wenn er blockiert ist. Aber ich glaube nicht, dass es eine zuverlässige Methode ist, sie in einem kommerziellen Produkt zu implementieren. Ich habe eine Beschwerde beim Cypress-Support registriert. Lassen Sie mich sehen, ob ich eine andere Methode anwenden kann, als Daten immer wieder abzufragen.
Beachten Sie, dass das Ausschalten des Slaves allein wahrscheinlich nicht funktioniert - Sie müssen auch beide I2C-Leitungen gleichzeitig auf Low nehmen, um zu verhindern, dass Strom durch die Uhr vom Pullup-Widerstand austritt, der den Chip ausreichend mit Strom versorgt, um den problematischen Zustand beizubehalten. Und Sie müssen sicherstellen, dass sich alle Versorgungsfilterkappen tatsächlich vollständig entladen und nicht nur auf etwa 0,8 V abfallen, wo die Stromaufnahme auf Null fällt, ohne dass der Zustand unbedingt gelöscht wird.

Antworten (1)

Sieht so aus, als hätte dies etwas mit meiner Master- MCU (NXP MKE04Z64) zu tun . Ich habe etwas tiefer in die alten NXP-Foren gegraben und herausgefunden, dass viele Leute das gleiche Problem der I2C-Bus-Sperrung bei den MCUs der Kinetis E-Serie hatten und NXP noch nicht darauf reagiert hat. Vielleicht stimmt etwas mit dem Chipdesign nicht. Ich habe versucht, denselben Slave mit GPIO-Bit-Banging zu versehen, anstatt das I2C-Modul zu verwenden, und das Problem wurde gelöst. Ich habe auch versucht, denselben Slave von einer anderen MCU aus zu fahren, wo es sehr gut funktioniert hat.