Zweiter SPI Chipselect für den Orange-Pi Zero



Vor kurzem habe ich versucht, ein TPM-Modul von Infineon das für den Raspberry-Pi entwickelt ist auf dem Orange-Pi Zero zum Laufen zu bekommen. Der Chipselect des TPM-Moduls ist hart verdrahted mit dem Chipselect 1 (mit einem 0 Ω Widerstand der auf ein vorgesehenes Lötpad umgelötet werden könnte um den Chipselect 0 zu verwenden).

Der Orange-Pi hat das gleiche Anschlussschema wie der Raspberry-Pi aber verwendet SPI-1 (statt SPI-0 auf dem Raspi) auf den Anschlüssen 19 (MOSI), 21 (MISO), 23 (CLK) und 24 (CS-0, der von der Hardware unterstützte Chipselect). Chipselect CS-1, der auf dem Raspi ein nativer vom SPI-Controller unterstützter Chipselect ist, ist ein normaler GPIO (PA10) auf dem Orange-Pi Zero. Der SPI-Treiber für den H2 Allwinner Prozessor im Linux-Kernel sollte eigentlich normale GPIOs als zusätzliche Chip-Selects verwenden können. Das hat in meinem Fall nicht funktioniert.

Ich habe also zuerst versucht rauszufinden, ob irgendwas mit meiner Device-Tree Konfiguration nicht stimmt oder ob ich einen zusätzlichen Fix für die SPI-Initialisierung brauch. Diese Suche ist in einer Diskussion im Armbian Forum dokumentiert. Es hat sich dann herausgestellt, dass meine Device-Tree Konfiguration OK war, der folgende Ausschnitt zeigt ein Device-Tree Overlay das ich derzeit verwende um den GPIO PA10 vom Orange-Pi Zero als zweiten Chipselect CS1 zu verwenden:

// Enable CS1 on SPI1 for the orange pi zero
/dts-v1/;
/plugin/;

/ {
    fragment@0 {
        target = <&pio>;
        __overlay__ {
            spi1_cs1: spi1_cs1 {
                pins = "PA10";
                function = "gpio_out";
                output-high;
            };
        };
    };

    fragment@1 {
        target = <&spi1>;
        __overlay__ {
            status = "okay";
            pinctrl-names = "default", "default";
            pinctrl-1 = <&spi1_cs1>;
            /* PA10 GPIO_ACTIVE_HIGH (last 0) */
            cs-gpios = <0>, <&pio 0 10 0>;
        };
    };
};

Aber in der Praxis wird die Taktleitung (CLK) des SPI-Bus auf High gesetzt bevor der SPI-Transfer gestartet wird. Dies sieht man im folgenden Oszilloskop Bildschirmabzug für den eingebauten Chipselect CS0:

/wp-content/uploads/2019/native-cs0.bmp

Die Taktleitung (Blau) geht auf High bevor der Transfer startet und dann auf Low sobald der Chipselect (Gelb) auf Low geht. Der Chipselect ist Aktiv Low, die Daten auf MISO/MOSI, nicht gezeigt im Oszilloskop-Bild, werden bei Taktleitung High abgetastet. Das kann einige Geräte verwirren sollte aber in den meisten Fällen funktionieren.

Das Bild schaut anders aus wenn man den zweiten Chipselect CS1 verwendet. In diesem Fall geht der Takt (Blau) auch auf High bevor der Transfer startet aber geht nicht auf Low wenn der Chipselect (Gelb) auf Low geht. Das ist ein Problem weil Takt auf High bedeutet dass der SPI Slave den Bus (MOSI) an diesem Punkt abtastet. Dadurch werden alle übertragenen Bits um ein Bit nach rechts geshiftet und der SPI Slave empfängt nur Müll.

/wp-content/uploads/2019/additional_cs1.bmp

Als ich das gesehen habe, habe ich mich an einen Patch auf der SUNXI spidev Seite erinnert, der das Problem fixt, dass die Taktleitung auf High geht bevor der SPI-Transfer startet (Siehe am Ende dieser Seite unter der Überschrift "HIGH on SCK line right before transfer"). Also habe ich den Patch eingespielt.

Im nächsten Oszilloskop-Bild – CS1 wieder in Gelb und Takt in Blau – sieht man dass die Taktleitung nicht vor dem Transfer auf High geht. Von dem Verhalten von CS0 (dem nativen Chipselect) habe ich kein Oszilloskop-Bild gemacht, weil CS0 dauern auf Low bleibt: Er ist auf Low bevor der SPI Bus initialisiert wird und bleibt auf Low sobald der Transfer startet. Der Wackler der Taktleitung vor dem Transfer wie im ersten Oszilloskop-Bild vor Anwendung des Patches zeigt sich nicht mehr.

/wp-content/uploads/2019/working_cs1.bmp

Ich habe vor den Original-Autor des Patches auf der SUNXI spidev Seite zu überzeugen, diesen Patch auf der Kernel Mailingliste zu posten, weil ohne diesen Patch der zweite Chipselect nicht funktioniert. Falls mir das nicht gelingt (bis jetzt habe ich keine Antwort bekommen) werde ich selbst versucht, den Patch in den Kernel zu bekommen.