mikrocontroller.net

Forum: PC-Programmierung Probleme mit Linux i2c-Treiber


Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich habe schon seit längerem eine Steuerung in Betrieb. Dabei nutze ich 
den i2C-Bus der VGA Schnittstelle eines alten Laptops um damit einige 
ATmegas anzusteuern. Der Code auf den ATmegas ist simple. Sie fungieren 
eigentlich als reiner Port-Expander.

Nun habe ich den Laptop durch einen NanoPi NEO mit der aktuellen armbian 
Version ersetzt.

Grundsätzlich funktioniert ist, es scheint aber Probleme beim Schreiben 
auf den Bus zu geben. in einer Schleife mit Delay, schreibe ich jetzt 
schon extra jeden Schaltbefehl 7 mal auf den Bus, damit wenigstens ein 
Befehl durchkommt.


Vom Kernel bekomme ich auch Fehlermeldungen, die ich nicht deuten kann:
sudo tail -f /var/log/kern.log
Jun 11 19:56:15 localhost kernel: [ 3591.273849] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
Jun 11 19:56:17 localhost kernel: [ 3593.354024] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0
Jun 11 19:56:19 localhost kernel: [ 3595.346987] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x41, flags: 0x0
Jun 11 19:56:46 localhost kernel: [ 3622.906724] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x10, flags: 0x0
Jun 11 19:57:23 localhost kernel: [ 3659.840450] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x10, flags: 0x0
Jun 11 19:57:31 localhost kernel: [ 3668.019921] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x10, flags: 0x0
Jun 11 20:06:26 localhost kernel: [ 4202.894321] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x41, flags: 0x0
Jun 11 20:07:38 localhost kernel: [ 4274.869937] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x41, flags: 0x0
Jun 11 20:09:15 localhost kernel: [ 4371.666878] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x41, flags: 0x0
Jun 11 20:09:39 localhost kernel: [ 4395.481057] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x41, flags: 0x0
Jun 11 20:25:01 localhost kernel: [ 5317.437496] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x41, flags: 0x0
Jun 11 21:20:43 localhost kernel: [ 8659.838023] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x10, flags: 0x0
Jun 11 21:24:45 localhost kernel: [ 8901.569019] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x41, flags: 0x0
Jun 12 08:33:43 localhost kernel: [49041.355650] i2c i2c-0: mv64xxx_i2c_fsm: Ctlr Error -- state: 0x2, status: 0x0, addr: 0x10, flags: 0x0
i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: 10 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: 30 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- 41 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                      

ich habe zwar das passende c-File gefunden, welches die Meldung 
generiert:

https://github.com/spotify/linux/blob/master/drive...

aber scheinbar wird hier state 0x2 nicht interpretiert. Leider habe ich 
auch kein Oszi, um mich dem Problem von der Hardwareseite zu nähern.

Vielleicht habt ihr ja einen guten Überblick über die Funktionsweise des 
Kernels an der Stelle? Über Tips würde ich mich jedenfalls sehr freuen.

Vielen Dank

Ralf

: Verschoben durch Moderator
Autor: i3c (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pull-Ups nicht vergessen?

Kleinere Bitrate mal versucht?

Autor: Md M. (Firma: Potilatormanufaktur) (mdma)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ralf schrieb:
> Leider habe ich
> auch kein Oszi, um mich dem Problem von der Hardwareseite zu nähern

Falls du große Ausgaben scheust, ist vielleicht so ein 
5-Euro-Logic-Analyzer von ebay drin. Ich hab mir auch sowas zugelegt 
(das etwas teuerer DSLogic), weil ich mit I2C und SPI Probleme hatte. 
Hat mir sehr viel Nerv erspart.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
i3c schrieb:
> Pull-Ups nicht vergessen?
>
> Kleinere Bitrate mal versucht?

Pull-Ups habe ich...wenn die fehlen, dann hängt auch i2cdetect, dass 
kenne ich schon.

Bitrate kann ich bei armbian offenbar nur durch Kernel-Kompilieren 
ändern. Davor scheue ich mich noch.

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Raspi hat eine Hardwarefehler, der macht das clock streching falsch.
(Das fällt bei i2c-ICs nicht auf, die sind schnell genug)
Benutzt der ATmega clock streching?

Um das zu umgehen gibt es reine Softwareimplementation von i2c.

Und ja, mit einem Logic-Analyzer kann man das debuggen.

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bastler schrieb:
> Der Raspi hat eine Hardwarefehler, der macht das clock streching falsch.

Hier wird ein NanoPi Neo verwendet, der verwendet einen Allwinner H3.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bastler schrieb:
> Der Raspi hat eine Hardwarefehler, der macht das clock streching falsch.
> (Das fällt bei i2c-ICs nicht auf, die sind schnell genug)
> Benutzt der ATmega clock streching?

Von dem Raspi-Problem habe ich gelesen, aber ich verwende ja einen 
Nanopi Neo (Allwinner H3 Chip). Ob es dort auch dieses Clock-Stretching 
Problem gibt weiß ich nicht. ABER, so wie ich es verstehe verzögert der 
ATmega nur, bis man das TWI-Register leer macht. Ich übertrage aber nur 
gelegentlich mal ein Byte um ein Relais zu schalten...und auf den Atmels 
ist nur der TWI-Interrupt aktiv. Entsprechend springt er dort auch 
direkt rein....ich kann es mir kaum vorstellen.

Der Kernel-Treiber will mir ja sogar etwas mitteilen, ich kann es nur 
noch nicht deuten.:-)

Autor: Sven B. (scummos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Zweifel würde ich einfach mal in den Code vom Treiber kucken, evtl. 
auch extra Debug-Meldungen einfügen. Wenn wirklich unklar ist was 
passiert, ist das das einzige systematische Vorgehen.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven B. schrieb:
> Im Zweifel würde ich einfach mal in den Code vom Treiber kucken, evtl.
> auch extra Debug-Meldungen einfügen. Wenn wirklich unklar ist was
> passiert, ist das das einzige systematische Vorgehen.

Ich glaube, wenigstens zwischen den Zeilen habe ich durchblicken lassen, 
dass ich an dieser Stelle (so tief drin im Kernel) an meine Grenzen 
stoße und daher hier um Unterstützung bitte.

Autor: Georg A. (georga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man sich den Treibercode anschaut, kommt die Meldung dann, wenn 
keiner der "normalen" Zustände des I2C-Controllers auftaucht, in dem 
Fall 0. Und das ist laut Doku MV64XXX_I2C_STATUS_BUS_ERR. Fälle wie 
Ack/No Ack sind da schon raus, also ist das was eher selteneres. Laut 
state (2) passiert das bei WAITING_FOR_START_COND. Das Ding verreckt 
also schon vor/beim Abschicken der Start-Condition. Könnte auf einen 
pegelmässig kaputten Bus hindeuten, evtl. durch die Geschwindigkeit. 
Schau doch mal, ob du die im Device-Tree kleiner drehen kannst:

https://www.kernel.org/doc/Documentation/devicetre...

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Georg A. schrieb:
> Laut
> state (2) passiert das bei WAITING_FOR_START_COND.

Ralf schrieb:
> mv64xxx: I2C bus locked,

Der regelgerechte Ablauf beim Erzeugen einer Start-Condition ist: Warte 
auf Bus idle, dann erzeuge Start. Und "idle" heißt, SDA und SCL high. 
Das könnten sowohl Pegelprobleme als auch ein verklemmter Slave sein.

Ralf schrieb:
> Dabei nutze ich
> den i2C-Bus der VGA Schnittstelle eines alten Laptops um damit einige
> ATmegas anzusteuern.

Es ist auch gut denkbar, daß ein (softwaremäßig) kaputter Slave an einem 
Master funktioniert hat, mit einem anderen aber nicht klar kommt. Die 
PC-internen I2C Busse sind IMHO auch SMB, haben also TTL-Pegel 
(0,4V/2,0V) und einen Timeout.

MfG Klaus

Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ralf

könnte es ein Problem sein, dass die eine Seite mit 5V Pegel und die 
andere Seite mit 3.3V Pegel o.ä. arbeitet?

MfG Jan

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jan schrieb:
> könnte es ein Problem sein, dass die eine Seite mit 5V Pegel und die
> andere Seite mit 3.3V Pegel o.ä. arbeitet?

In der Tat sind die Atmels mit 5V versorgt, aber ich habe extra einen 
dieser kleinen Pegelwandler verbaut.

Die Pegel im Ruhezustand stimmen auch, das habe ich mit dem Multimeter 
überprüft.

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte mal so ähnliche Probleme...
Da mit einem Scope am Bus alles funktionierte, habe ich mich am Kopf 
gekratzt und ein bisschen Kapazität an beide Leitungen geklemmt, was 
dann auch tatsächlich das Problem behoben hat.
Einer der Chips am Bus hatte wohl eine etwas abweichende 
i2c-Implementierung.

Autor: bingo (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Schau Dir mal die Impulse mit dem Oszi an, evtl. sind die Pullups zu 
gross und damit die Flanken zu flach.

Autor: Md M. (Firma: Potilatormanufaktur) (mdma)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bingo schrieb:
> Schau Dir mal die Impulse mit dem Oszi an

Youtube-Video "Hallo McFly jemand zuhause"

SCNR :)

: Bearbeitet durch User
Autor: Ralf (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

die Antwort von Gregor & Klaus haben mir weitergeholfen, den Treiber 
etwas besser zu verstehen....vielen Dank dafür. Jetzt tauchen allerdings 
noch mehr Fragen auf. :-)

Kurze Rekapitulation:

Es beginnt wohl damit, dass in der Interrupt-Routine des Treibers das 
Statusregister des Chips ausgelesen wird und die Statemachine in 
mv64xxx_i2c_fsm() aufgerufen:

static irqreturn_t
mv64xxx_i2c_intr(int irq, void *dev_id)
{
...
   {
    status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS);
    mv64xxx_i2c_fsm(drv_data, status);
    
...    
  }
...
  return rc;
}


Der Wert von Status ist 0x00, deswegen läuft die Switch-Anweisung in den 
Default und meldet einen Fehler. Status 0x00 ist laut Allwinner 
Datenblatt "Bus-Error"

Nun stimmen die Register des Treibers aber nicht 100% mit dem Datenblatt 
überein. Der Treiber erwartet das Status Register auf Adresse 0x0c, 
während das Datenblatt des Chips die Adresse 0x10 benennt (siehe 
Anhang). Ist das evtl. ein Problem?

Den Hinweis mit dem Device Tree bekomme ich noch nicht umgesetzt. Dafür 
fehlt mir noch der Ansatz. Ich verstehe es aber richtig, dass der Kernel 
dafür nicht kompiliert werden muss?

Vielen Dank

Autor: Sven B. (scummos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um den Device Tree zu ändern musst du den Kernel nicht neu übersetzen, 
nein. Mir wäre aber gar nicht bekannt, dass Linux auf x86 standardmäßig 
überhaupt einen Device Tree benutzt?!

Die Register sehen völlig unterschiedlich aus. Bist du sicher, dass das 
der richtige Chip ist? Dann gibt es vermutlich verschiedene Varianten 
davon oder so, dieser Treiber mit den Register-Offsets wird deinen Chip 
jedenfalls keinesfalls korrekt ansteuern.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven B. schrieb:
> Um den Device Tree zu ändern musst du den Kernel nicht neu übersetzen,
> nein. Mir wäre aber gar nicht bekannt, dass Linux auf x86 standardmäßig
> überhaupt einen Device Tree benutzt?!

Ist armbian ein x86 Build?

Sven B. schrieb:
> Die Register sehen völlig unterschiedlich aus. Bist du sicher, dass das
> der richtige Chip ist? Dann gibt es vermutlich verschiedene Varianten
> davon oder so, dieser Treiber mit den Register-Offsets wird deinen Chip
> jedenfalls keinesfalls korrekt ansteuern.

Evtl. wird der Treiber für armbian auch abgeändert? Ich tue mir mit der 
Linux-Struktur echt schwer.
Das Repository von armbian ist hier zu finden:

https://github.com/armbian/build

allerdings finde ich darin den besagten Linux Treiber 
(drivers/i2c/busses/i2c-mv64xxx.c) nicht.

Autor: Sven B. (scummos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, ne, sorry ist es nicht, ist arm. Ich bin nochmal hochgescrollt und 
las was von altem Notebook, bis zu dem Punkt dass es jetzt was anderes 
ist bin ich nicht mehr gekommen.

Das verlinkte Repo ist ein Build-System. Da ist der Linux-Tree nicht 
drin. Der wird wahrscheinlich von irgendeinem Skript in diesem 
Repository heruntergeladen.

Autor: Georg A. (georga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachdem Treiber bei so PCI-losen Chips ja "per Definition" geladen 
werden, kann es evtl. sein, dass der mv* der falsche Treiber ist. Ich 
finde beim H3 oft einen sunxi-ng-Treiber erwähnt. Bist du sicher, dass 
du die richtige Distribution oder so hast?

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.