E3930 GPIO mit Linux

In meinem Intel Atom Kraftwerk wurde ein neuer Reaktor ans Netz angeschlossen. Und zwar ein Intel Atom E3930 im Supermicro A2SAV-2C-L Mainboard.

Denn seit 3 Jahren arbeitet dessen größerer Bruder E3940 als Server bei mir und deshalb wagte nie ich sein “spezielles” Feature auszuprobieren.
Beide Boards haben einen 10-Pin Header, über den 8 GPIO Kontakte frei nach außen geleitet sind.


WARNUNG: Wer Pins am Mainboard kurzschließt kann das Board zerstören. Also bitte meine beschriebenen Schritte NICHT nachmachen bzw. nur mit größter Sorgfalt auf eigene Gefahr probieren.


Angefangen hatte es furchtbar, denn die Lieferung des Boards war ein Alptraum, und ich hatte die Hoffnung schon aufgegeben es zu erhalten.
Warum sind “einige” Paketdienste in der Lage die Päckchen in einen Shop zu bringen und darüber zu informieren und andere geben es irgend jemandem im Wohnblock und finden nicht einmal die Zeit, eine Benachrichtigung an den eigentlichen Empfänger abzusetzen?
Naja … am Ende mit einigem Herumsuchen hatte ich das Board dann doch in meinen Händen.

Mainboard A2SAV-2C-L

Schon eine Woche zuvor hatte ich mit der Suche im Netz begonnen und gehofft, etwas über die GPIO Ansteuerung zu finden. Doch leider Fehlanzeige.

Im Mainboard-Handbuch stehen die absoluten Adressen der Pins zwar beschrieben, doch wenn man keinen Kernel-Treiber schreibt, hilft einem das nicht. Die Frage war:

Wie kommt man im User-Mode da dran?

Linux sysfs löst alle Probleme

Wenn Linux eines wirklich gut kann, dann ist es: alles in Dateipfade abbilden.

Wenn wir die intern zugeordneten GPIO Pin Nummern kennen und root Rechte haben, wird die Sache einfach:

  • Man schreibt die GPIO Nummer in die virtuelle Datei /sys/class/gpio/export und Linux legt darauf ein Unterverzeichnis mit weiteren “Steuerdateien” an, die den Pin konfigurieren und Bits hinein- und herausschreiben.
    z.B.: echo "123" > /sys/class/gpio/export
  • Im GPIO-Verzeichnis (z.B.: /sys/class/gpio/gpio123) liegen die Dateien direction und value, die man ebenfalls Beschreiben oder Auslesen kann.
  • Wenn man entweder in oder out in die direction Datei schreibt, schaltet man den Pin entweder auf Input oder Output, also Stromfluss lesen, oder Strom ein/ausschalten.
    z.B.: echo "in" > /sys/class/gpio/gpio123/direction
    oder: echo "out" > /sys/class/gpio/gpio123/direction
  • In die value Datei kann man jetzt entweder die Zahlen 1 oder 0 hineinschreiben um einen Output-Pin auf high oder low zu schalten, was in der Regel 3.3 oder 0 Volt bedeutet.
    echo "0" > /sys/class/gpio/gpio123/value
    Oder man liest die Datei und erhält 1 oder 0, wenn eine Spannung am Pin anliegt.
    cat /sys/class/gpio/gpio123/value
  • Braucht man den Pin nicht mehr, schreibt man seine Nummer in die Datei /sys/class/gpio/unexport und Linux entfernt das virtuelle Unterverzeichnis wieder.

Diese Prozedur ist beim Raspberry PI und all seinen ARM Geschwistern bestens bekannt. Doch ob sie auch bei X86 Mainboards klappt, wusste ich bisher nicht.

A2SAV-2C-L GPIO Header

Ärgerlich ist, dass man wenig bis gar keine Infos zu diesem GPIO Header findet (oder vielleicht suche ich falsch…). Denn ich konnte nicht herausfinden, wie sich die 8 Pins am Mainboard in die Linux GPIO Nummern abbilden.

GPIO Pins

Nach dem Hochfahren von Linux (Debian 11) lieferten alle GPIO Pins gemäß Messung gegen Ground etwa 1.8 V.

Im /sys/class/gpio findet man 4 “Chip” Geräte als Verzeichnisse, und die Dateien label, base (Start-Nummer) und ngpio (Nummern-Anzahl ab Start) geben folgende Infos preis:

/sys/class/gpio label base ngpio
gpiochip267 INT3452:03 267 43
gpiochip310 INT3452:02 310 47
gpiochip357 INT3452:01 357 77
gpiochip434 INT3452:00 434 78

Wir haben also 4 GPIO Bänke, die GPIO PINs ab der Nummer 267 bereitstellen und bis einschließlich zur Nummer 511 reichen.

Also habe ich mir ein kleines Script geschrieben, das bei 267 startend immer 10 Pins auf out und low schaltet. Parallel dazu habe ich immer per Multimeter die Spannung am Pin gemessen.

Und nach ein paar Iterationen kam ich bei den Pin-Nummern 318 bis 325 an, die offenbar meinen Mainboard Pins zugeordnet waren.

Die folgende Tabelle zeigt den Pin-Header von oben nach unten, wenn das Mainboard so liegt, dass “oben” LAN, USB und Displayanschlüsse liegen:

Nummer Links Rechts Nummer
- 3.3 V 0 V -
325 GP0 GP4 321
324 GP1 GP5 320
323 GP2 GP6 319
322 GP3 GP7 318

Input geht, aber keine Output-Spannung möglich

Spannung lesen funktioniert, denn mit

1echo "318" > /sys/class/gpio/export
2echo "in" > /sys/class/gpio/gpio318/direction
3cat /sys/class/gpio/gpio318/value

sieht man, ob der rechte untere Pin mit Ground verbunden ist, denn dann liefert value eine 0. Ist er nicht verbunden oder gegen 3.3 Volt gezogen, sehen wir 1.

Damit lässt sich schon ein Taster abfragen, der den Pin mit Ground verbindet. Drückt jemand darauf, sieht man das an der 0, ansonsten kommt immer 1.

Im Output Modus wird der Pin mit Ground verbunden. Leider schaltet er aber nicht auf Spannung um, wenn man eine 1 in value schreibt.
Der Pin ist also immer low, wenn er als Output-Pin betrieben wird.

Das schränkt den Handlungsspielraum natürlich stark ein.
Aber eine Sache bekommt man trotzdem hin:

Man nehme eine blaue LED, die 3.3 Volt verträgt (oder eine schwächere mit Vorwiederstand) und verbindet damit einen GPIO Pin mit 3.3 V auf POWER. Wenn man jetzt zwischen Input und Output Modus umschaltet, geht die LED an und aus, denn im Output low Modus fließt Strom mit 3.3 Volt vom POWER Pin zum GPIO Pin.
Schaltet man aber auf Input, fließt Strom mit 1.8 Volt, was die blaue LED sprichwörtlich kalt lässt.
Es fließt also immer Strom durch die Leuchtdiode, nur im Input-Modus ist er zu schwach um gesehen zu werden.

Nutzt man eine niedriger betreibbare rote LED im Input-Modus, kann man erkennen, dass auch die 1.8 Volt ein ganz schwaches kleines Lichtpünktchen auslösen.

Vorsicht, Reboot möglich

Nur als kleine Warnung am Rande:
Ich habe auch weitere Pins mal auf 0 gesetzt und irgendwo ab Nr. 340 löste mein Mainboard einen Reboot aus. Zwischen 360 und 511 passierte nichts Bemerkbares mehr.

Entweder liegt da so um Nr. 350 eine Verbindung zum Power oder Reset-Button oder eine andere Funktion löst den Reboot des Systems aus.
Man lernt jedenfalls daraus:

Wer irgendwelche unbekannten Pins abklopft, kann böse Überraschungen erleben. Also immer alles vor dem Experiment sichern!

Fazit

Also, diese Spielerei hat mir viel Spaß gemacht. Ohne Infos und Dokus wurden die Funktionen geschwind “reverse engineered” und zumindest ein paar Anwendungsmöglichkeiten festgestellt.

Tatsächlich könnte man sich mit der LED eine primitive Anzeige basteln. z.B.: ein Ping jede Minute und wenn die Gegenseite erreichbar ist, leuchtet die LED, andernfalls nicht, oder gerne auch umgekehrt.

GPIO Pins am X86 PC Mainboard sollten aus meiner Sicht überall Pflicht sein. Viele Intel CPUs und Chipsätze bringen dieses Feature mit, nur leider sind so gut wie nie Pins am Mainboard nach außen gelegt.

In diesem Fall muss ich SuperMicro loben, weil sie zumindest ein paar Boards mit dieser genialen Option ausgestattet haben.