Linux Kernel-Module kompilieren

So erstellen Sie Treiber für den Raspberry Pi selbst

09.01.2015 von Thorsten Eggeling
Nicht jede Hardware funktioniert von Haus aus unter Linux. Ein passender Treiber lässt sich jedoch auch für den Raspberry Pi erstellen, wenn der Quelltext vorhanden ist, lässt sich das fehlende Kernel-Modul nachrüsten.

Der Raspberry Pi lässt sich über die USB-Ports erweitern, etwa um Festplatten, Drucker oder WLAN-Adapter zu nutzen. Aber nicht alle USB-Geräte funktionieren auf Anhieb. Voraussetzung ist ein passendes Modul für den Linux-Kernel, und gerade für neuere Geräte fehlt manchmal die Unterstützung. Wenn der Treiber-Quellcode für Linux verfügbar ist, lässt sich das fehlende Kernel-Modul nachrüsten. Im Unterschied zum PC mit Intel/AMD-Prozessor gelten beim Raspberry allerdings einige Besonderheiten.

Der Artikel bezieht sich auf Raspbian, ein Debian-basiertes Linux für Raspberry Pi, Pi Modell B+ und Pi 2 Modell B. Das Prinzip gilt aber für jedes Linux-System, gleich ob auf Raspberry Pi oder PC. Der Artikel erklärt exemplarisch die Installation des Kernel-Moduls für den verbreiteten WLAN-USB-Stick TP-Link AC600 T2U (TL-WDN5200). Die Vorgehensweise ist jedoch für alle Kernel-Module ähnlich.

1. Linux-Kernel, Geräte & Module

Der Linux-Kernel stellt Schnittstellen zur Hardware zur Verfügung, koordiniert den Start von Programmen und die Zuweisung von Prozessorzeit. Er bildet das eigentliche Betriebssystem. Alles andere sind letztlich nur Hilfsprogramme etwa zur Darstellung der grafischen Oberfläche.

In den Kernel direkt integriert sind wichtige Treiber etwa für Festplattenadapter und Dateisysteme. Was sonst noch nötig ist, wird als Modul nachgeladen. Das geschieht zuerst beim Linux-Start über eine Datei mit dem Basissystem, die der Kernel in eine Ramdisk lädt. Weitere Module, etwa für USB-Geräte, lädt der Kernel automatisch, sobald er ein neues Gerät erkennt. Dazu ermittelt er die eindeutige Geräte-ID und sieht nach, ob ein Modul dafür zuständig ist. Das Modul wird dann initialisiert, und die neue Hardware ist einsatzbereit.

Wenn kein passendes Modul im Linux-Kernel enthalten ist, lässt es sich nachinstallieren. In der Regel steht dafür der Quelltext zur Verfügung, mit dem Sie selbst das Modul kompilieren müssen. Wer Kernel-Module aus dem Quelltext erzeugen möchte, benötigt keine Programmierkenntnisse, jedoch ist ein souveräner Umgang mit der Kommandozeile und den nötigen Tools erforderlich.

Bei Quelltextmodulen handelt sich oft um Treiber, die relativ neu und noch nicht ausreichend getestet sind. Es gibt also keine Garantie, dass ein selbst erstelltes Modul auch einwandfrei arbeitet.

2. Informationen zum USB-Gerät ermitteln

Manchmal liegt es gar nicht am Treiber – für den AVM-WLAN-Stick fehlt nur die Firmware.

WLAN-USB-Adapter und TV-Sticks funktionieren manchmal nicht, weil die nötige Firmware-Datei fehlt. Sehen Sie sich daher die letzten Protokolleinträge an, direkt nachdem Sie das USB-Gerät verbunden haben:

dmesg

Wiederholen Sie dmesg mehrmals, weil es manchmal etwas dauert, bis der Kernel das Gerät entdeckt hat. Erscheinen nur Infos wie „new high-speed USB device“, ist kein passendes Modul vorhanden. Erscheint hingegen „Direct firmware load failed“, dann fehlt nur die Firmware. In der Regel findet sich auch ein Hinweis, wie die Firmware-Datei heißt, etwa „carl9170-1.fw“ für einen Fritz WLAN-N-Adapter von AVM. In diesem Fall suchen Sie über die folgende Befehlszeile nach Firmware-Paketen:

apt-cache search firmware

Installieren Sie dann beispielsweise ein Paket nach, das viele Firmware-Dateien für verbreitete WLAN-Adapter enthält:

apt-get install firmware-linux

Weitere Firmware-Pakete finden Sie etwa unter den Namen „firmware-brcm80211“, „firmware-realtek“ und „firmware-ralink“.

Suche nach Kernel-Modulen: Wenn das Kernel-Modul fehlt, ermitteln Sie zuerst die Geräte-ID:

lsub

In der Ausgabe sehen Sie die eindeutigen USB-IDs und die Bezeichnungen. Letztere müssen nicht unbedingt mit der Modellbezeichnung übereinstimmen. Oft stehen hier nur die Namen der Chipsatz-Hersteller, etwa „Ralink Technology, Corp.“ oder „Atheros Communications“.

Hardware-Datenbanken helfen, den Chipsatz eines WLAN-USB-Sticks zu ermitteln.

Die Internet-Suche nach einer USB-ID wie „148f:761a“ führt dann meist auf Seiten mit weiteren Informationen und Erfahrungen anderer Linux-Nutzer. Sie können auch direkt in Linux-Hardware-Datenbanken wie https://wikidevi.com, https://de.opensuse.org/Portal:Hardware oder http://wiki.ubuntuusers.de suchen. Auf diese Weise bekommen Sie den verwendeten Chipsatz und den Hersteller heraus.

Es ist möglich, dass bisher noch niemand das gewünschte Gerät unter Linux zur Mitarbeit überreden konnte. Oder Sie finden Erfolgsgeschichten mit konkreten Anleitungen.

Für unsere Beispiel-Hardware TP-Link AC600 T2U stoßen Sie auf die Software-Quellen vom taiwanischen Chiphersteller Mediatek, der 2011 den Hersteller Ralink übernommen hat. Der Original-Quelltext lässt sich jedoch nicht ohne Weiteres für aktuelle Kernel-Versionen kompilieren.

Außerdem enthält die Konfiguration keine USB-IDs für Geräte, die man in Deutschland kaufen kann. Der Treiber funktioniert auch mit den WLAN-Sticks Cisco Linksys AE6000 und Asus AC600, nicht jedoch mit dem AVM-Stick AC 430, obwohl in diesem der gleiche Chipsatz steckt (MT7610U).

3. Kernel-und Compiler-Versionen für Raspberry Pi

Versions-Check: Ermitteln, welche Linux-Kernel-Version auf dem Raspberry Pi installiert ist.

Der Kernel-Quellcode und die Compiler-Version müssen exakt zu dem Kernel passen, der auf Ihrem Gerät läuft – sonst lässt sich das Modul später nicht laden. Informationen zum Kernel erhalten Sie auf jedem Linux-System über die folgenden Terminal-Kommandos:

uname -a cat /proc/version gcc --version

Die Ausgabe bei einem Raspberry Pi sehen Sie in der Abbildung. Die Kernel-Version ist „3.18.11+“, und im Gerät steckt eine ARMv6l-CPU. Ein Raspberry PI 2 würde hier „3.18.11-v7+“ und „armv7l“ melden. In der Ausgabe von „cat /proc/version“ sehen Sie, dass der Kernel mit dem Compiler GCC Version 4.8.3 20140303 und crosstool-NG linaro-1.13.1+bzr2650 erstellt wurde. Die Version des installierten Compilers gcc 4.6.3 passt allerdings nicht zum Kernel (-> Punkt 7).

Die Angabe „crosstool-NG“ ist eine Besonderheit bei Raspbian, denn der Kernel wird nicht auf einem Raspbian-System kompiliert, sondern unter einem anderen Linux. Der Raspberry Pi ist nämlich zu langsam für so aufwendige Projekte wie den Linux-Kernel. Deshalb kommt ein Crosscompiler zu Einsatz (-> Punkt 4). Damit ist es möglich, Programme auf einem leistungsfähigeren PC mit x86_64-CPU (Intel/AMD) für ein Gerät mit ARM-Prozessor zu erstellen. Grundsätzlich ist es aber möglich, Kernel-Module auch unter Raspbian zu erstellen. Zumindest beim neuen Raspberry Pi 2 reicht die Leistung gerade mal so aus.

4. Entwicklungsumgebung unter Linux einrichten

Damit sich Kernel-Module unter Ubuntu erstellen lassen, sind Zusatz-Tools erforderlich.

Für ein neues Kernel-Modul benötigen Sie den Quellcode des Linux-Kernels, den Quellcode des gewünschten Moduls und Werkzeuge für die Kernel-beziehungsweise Software-Entwicklung. Wir haben als Entwicklungssystem Ubuntu 14.04 LTS verwendet. Im Prinzip geht auch jedes andere Linux. Sie müssen dann aber die Bezeichnungen der nötigen Pakete selbst herausfinden. Wenn Sie Ubuntu nicht auf Ihrem PC installiert haben, ist auch die Entwicklung in einer virtuellen Maschine möglich. Um Ihnen die Arbeit zu vereinfachen, haben wir alle nötigen Befehle im Script „raspi_crosstools.sh“ versammelt. Im Folgenden erläutern wir die einzelnen Schritte, die das Script ausführt, damit Sie bei Bedarf selbst Anpassungen vornehmen können.

Entpacken Sie die ZIP-Datei unter Ubuntu direkt in Ihr Home-Verzeichnis, und machen Sie das Shell-Script mit

chmod 755 raspi_crosstools.sh

ausführbar. Stellen Sie sicher, dass Ihr Raspberry Pi über SSH erreichbar ist. Dazu tippen Sie im Terminal-Fenster folgende Zeile ein:

ssh pi@[IP-Adresse]

„[IP-Adresse]“ ersetzen Sie durch die tatsächliche IP oder den Host-Namen des Raspberry Pi. Geben Sie das Kennwort ein, und beenden Sie die Verbindung wieder mitexit. Öffnen Sie „raspi_crosstools.sh“ in einem Editor. Tragen Sie unter „Konfiguration“ hinter die kommentierten Variablen Benutzernamen, Kennwort und IP-Adresse für den Raspberry Pi ein. Speichern Sie die Datei und starten Sie das Script im Terminal-Fenster mit

./raspi_crosstools.sh

Das Script installiert – sofern nötig –zuerst Pakete über die Zeilen

sudo apt-get update sudo apt-get install git build-es sential lftp

nach. Dann erstellt es das Arbeitsverzeichnis „raspi_cross“ in Ihrem Home-Verzeichnis.

5. Quellcode herunterladen und kompilieren

Infos zum installierten Kernel stehen in der Datei „changelog.Debian.gz“.

Der Quellcode des Raspberry-Kernels ist unter https://github.com/raspberrypi/linux zu finden. Allerdings befindet sich dieser in ständiger Entwicklung: Sie können die aktuellen Dateien nicht einfach verwenden, weil der installierte Kernel älter ist als die Entwickler-Version. Welcher Kernel zum Einsatz kommt, steht bei Raspbian in der Datei „/usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz“ hinter „firmware as of“. Dabei handelt es sich um eine Prüfsumme („Hash“). Mit dieser lässt sich dann die Download-Adresse für den Kernel-Quellcode bestimmen. Das Script „raspi_crosstools.sh“ lädt dazu in der Funktion „get_files_from_raspi()“ die Datei von Ihrem Raspberry Pi und speichert das Ergebnis in der Variablen „KERNEL_HASH“. Außerdem holt es sich die Konfigurationsdatei für den Kernel aus „/proc/config.gz“ und ermittelt aus dieser, ob der Kernel für das Modell Pi oder Pi 2 erstellt wurde. Diese Information ist für die korrekte Download-Adresse der Datei „Module.symvers“ erforderlich, ohne die sich Kernel-Module nicht bauen lassen.

Im nächsten Schritt lädt das Script den Kernel-Quellcode, den Cross-Compiler und den Treiber-Quellcode über das Tool git herunter. Das geschieht per „git checkout“ beziehungsweise „git clone“. Nach diesen Vorbereitungen setzt das Script einige Umgebungsvariablen, damit sich der Cross-Compiler nutzen lässt:

export CCPREFIX=$WORKDIR/tools/arm-bcm2708/gcc-linaro-arm-li nux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- export ARCH=arm export CROSS_COMPILE=${CCPREFIX}

Für die Vorbereitung des Raspbian-Kernels genügen diese drei Zeilen:

make oldconfig make prepare make scripts

Danach kompiliert das Script den Treiber aus dem Verzeichnis „mt7610u_wifi_sta_v3002_dpo_ 20130916/os/linux/“. Der Quellcode enthält gegenüber dem Original-Treiber einige Anpassungen für den Raspberry Pi und neuere Kernel. Wenn Sie einen anderen Treiber erstellen möchten, passen Sie das Script an. Sorgen Sie dafür, dass die Angaben im Block „Treiber compilieren“ auf das gewünschte Verzeichnis verweisen.


6. Neuen Treiber auf dem Raspberry Pi einrichten

Im letzten Schritt kopiert das Script „raspi_crosstools.sh“ in der Unterroutine „put_file_to_raspi()“ die Treiberdatei „mt7650u_sta.ko“ per sftp nach „/home/pi“ auf den Raspberry. Hier finden Sie jetzt außerdem das Script „install_driver.sh“, das Sie mit den folgenden zwei Zeilen ausführbar machen und starten:

chmod 755 install_driver.sh sudo ./install_driver.sh

Das Script kopiert die Treiberdatei beim Raspberry Pi 2 nach „/lib/modules/3.18.11-v7+“ sowie die Konfigurationsdatei nach „/etc/Wireless/RT2870STA/RT2870STA.dat“. Darin sind einige Einstellungen enthalten, die die Arbeitsweise des WLAN-Adapters beeinflussen. In der Regel müssen Sie hier nichts ändern ( Informationen zu möglichen Optionen).Bei Bedarf verwenden Sie das Script „un-install_driver.sh“ für die Deinstallation.

Abschließend richten Sie das WLAN ein wie im -> Kasten „Raspbian: WLAN konfigurieren“ beschrieben.

7. Treiber auf dem Raspberry Pi kompilieren

Kernel-Module lassen sich auch direkt auf dem Raspberry Pi kompilieren. Aufgrund der geringen Rechenleistung dauert das allerdings deutlich länger als auf dem PC. Neben den passenden Kernel-Quellen muss zurzeit der Compiler gcc in der Version 4.8.3 oder höher vorhanden sein. In den Standard-Paketquellen gibt es aber nur eine ältere Version. Sie können jedoch gcc 4.8.4 aus dem Repositorium von Debian 8 („Jessie“) verwenden.

Das Verfahren birgt allerdings gewisse Risiken, weil man Paketquellen eigentlich nicht mischen sollte. Bei unseren Tests gab es keine Auffälligkeiten, Sie sollten aber zur Sicherheit ein Backup des Systems erstellen.

Laden Sie das vorbereite Script herunter, und entpacken Sie es in Ihr Home-Verzeichnis auf dem Raspberry. Machen Sie es ausführbar, und starten Sie es:

chmod 755 raspi_kernel_source.sh sudo ./raspi_kernel_source.sh

Wird eine ältere gcc-Version als 4.8.3 gefunden, passt das Script die Paketquellen an und aktualisiert gcc und andere Entwicklungs-Tools. Anschließend wählen Sie gcc 4.8 als Standard-gcc aus.

Danach installiert das Script das Tool rpi-source und startet es. Darüber erfolgt der Download der Kernel-Quellen in das Verzeichnis „root“. Im Home-Verzeichnis „/home/pi“ führen Sie danach für den Mediatek-Treiber die folgenden vier Befehlszeilen aus:

git clone https://github.com/My ria-de/mt7610u_wifi_sta_v3002_dpo_20130916.git cd mt7610u_wifi_sta_v3002_dpo_20130916 make sudo make install

Die Befehlszeilen sind auch als Kommentar in der Datei „raspi_kernel_source.sh“ enthalten. Damit ist das Kernel-Modul installiert, und Sie richten das WLAN ein, wie im -> Kasten „Raspbian: WLAN konfigurieren“ beschrieben. Abschließend entfernen Sie die Datei „/etc/apt/sources.list.d/jessie_for_gcc.list“, damit apt nicht aktuellere Pakete aus dem Jessie-Repositorium installiert.

Raspbian: WLAN konfigurieren

Inhalt von „/etc/network/interfaces“ für das Interface „ra0“ ändern und WLAN-Verbindung herstellen.

Damit das WLAN funktioniert, passen Sie die Datei „/etc/network/interfaces“ an. Hier sind bereits auskommentierte Einträge enthalten, die sich auf das Interface wlan0 beziehen. Ersetzen Sie „wlan0“ durch „ra0“, und entfernen Sie die Kommentarzeichen („#“). Der Abschnitt sieht dann so aus:

auto ra0 allow-hotplug ra0 iface ra0 inet manual wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Starten Sie den Raspberry Pi neu. Nach einem Klick auf das Netzwerk-Icon in der Leiste am oberen Bildschirmrand wählen Sie das gewünschte WLAN, tippen den WPA-Schlüssel ein, und die Verbindung wird hergestellt.

(PC-Welt/ad)