Hallo Arno,
On 05/09/2017 12:52 PM, Arno Steffens wrote:
Mh, hab noch gesehen, es gibt unabhängig von bits/word
(was ja eh nicht hilft, wenn Adresse und Daten unterschiedlich sind) noch
__u8 tx_nbits;
__u8 rx_nbits;
Hab damit aber nicht weiter rumgespielt.
Weiss aus dem Stehgreif nicht, was das macht.
>> Ich pussele halt die Adresse, RW-Bit und Daten
so in einen Buffer, dass es passt.
>> Kommen halt am Ende ein paar Takte mehr.
>> Sende 4x8bit für den Inhalt von 9+1+16. Aber das scheint kein Problem zu sein.
Ja, solche Probleme werden in der Regel immer erst relevant, wenn die
ersten 1000 Geräte im Feld sind :-)
uah, ich weiß,
Gewalt ist keine Lösung, aber der Hardware-Entwickler ...
Ja, das war auch mein Gedanke, wtf....
Wie alt ist denn das Gerät, über das wir da reden? Ich finde, wenn es
jünger als 20 Jahre ist, gibt es keine Entschuldigung für so ein Design.
Zwar gibt es
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
aber ich sehe nur eine Reaktion auf die Änderung des Write modes ?!?
Wenn wir mal einen Hardware-Bug ausschließen: Was schreibst Du denn in
mode rein? Für die erste Sequenz muss da CPOL=0 + CPHA=0 (also mode=0)
und für die zweite Sequenz CPOL=0 + CPHA=1 (also mode=1) einstellt sein.
Zunächst hatte ich gar keinen Mode gesetzt, aber 0 scheint default.
Den Effekt am Oszi kann ich natürlich nur für den Write-Teil sehen. Und da ist
"0" richtig.
Mit eins bekomme ich die korrekten Daten zurück. (Es gibt ein Register mit Adresse 0, da
ist es egal ob mit Mode 0 oder 1 geschrieben wird. Daher weiß ich das) Bei allen anderen
Adressen werden diese natürlich falsch übermittelt, so das ich die richtige Daten zur
falschen Adresse bekomme :(
Das kriegst Du nur hin, wenn Dein Treiber die
Verwendung von
struct spi_ioc_transfer::cs_change unterstützt und selbst dann ist das
hacky.
Ich hatte da diesen kurzen Hoffnungsschimmer und hab im spi_ioc_transfer struct auch die
.cs_change = 1
gesetzt, aber leider ohne Effekt. SPI_IOC_RD_MODE wird ignoriert.
Ist es das was du meinst?
Die Fehlerbehandlung im spi-Framework ist bescheiden, deswegen wird das
cs_change vielleicht ignoriert. Lesen ginge ungefähr so:
/* transfer address, keeping CS active at the end */
transfer.cs_change = 1;
transfer.bits_per_word = 10;
transfer.len = 1;
ioctl(..., &transfer);
/* switch mode */
mode = 1
ioctl(fd, SPI_IOC_WR_MODE, &mode);
/* read datum */
transfer.cs_change = 0;
transfer.bits_per_word = 16;
transfer.len = 1;
ioctl(..., &transfer);
Vermutlich ist es einfacher das Protokoll mit gpio-bitbanging zu
implementiern als einen spi-Treiber dazuzubekommen, das so zu machen,
wie es muss.
Uwe