Neue Kernel-Module für den Raspberry Pi erstellen

Raspberry Pi Kernel Module erstellen

Nicht jede Hardware wird unter Linux von Haus aus unterstützt. Bei neuen Geräten sind die erforderlichen Kernel-Module (Treiber) noch nicht im Kernel enthalten. Wenn man den Quelltext des gewünschten Treibers im Internet findet, kann man sich die Kernel-Module jedoch selbst erstellen.

Für neue Kernel-Module sind mehrere Voraussetzungen zu erfüllen: Sie benötigen den Quellcode des Kernels, einige Entwicklungs-Tools, wie den Compiler gcc, und natürlich den Quellcode des Treibers. Programmierkenntnisse sind dafür nicht erforderlich, lediglich der souveräne Umgang mit der Kommandozeile.

Update 04.04.2016: Ich habe den Treiber-Quellcode bei Github aktualisiert und Änderungen aus verschiedenen Quellen einfließen lassen. Das erzeugte Kernel-Modul heißt jetzt mt7610u_sta.ko. Die Konfigurationsdatei /etc/Wireless/RT2870STA.dat wird jetzt auch unter neueren Kerneln korrekt eingelesen. Hier ist jetzt „WirelessMode=13“ konfiguriert. Nach meinen Tests funktionieren damit jetzt 2,4 und 5 GHz. Bei 5 GHz wird jedoch die erwartete Geschwindigkeit nicht erreicht (siehe „Netzwerkleistung mit iperf messen“)

Kernel-Quellcode und gcc-Version müssen genau zur Version des auf dem Raspberry Pi laufenden Linux-Kernels passen. Informationen dazu finden Sie über die beiden Befehlszeilen

cat /proc/version
gcc --version

Die erste Zeile gibt beispielsweise folgendes aus:

Linux version 4.1.6-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 – Linaro GCC 2014.03) ) #810 SMP PREEMPT Tue Aug 18 15:32:12 BST 2015

Die Kernel-Version ist hier „4.1.6-v7+“. Außerdem 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 Ausgabe von „gcc –version“ lautet beispielsweise „gcc-4.6“, was dann nicht zum installierten Kernel passen würde.

Die Ausgabe „crosstool-NG“ weist darauf hin, dass der Kernel nicht auf einem Raspberry Pi kompiliert wurde. Dieser wäre auch zu langsam dafür. Stattdessen kam eine Crosscompile-Umgebung zum Einsatz, die sich auf jedem beliebigen Linux-PC einrichten lässt.

Welcher Kernel genau installiert ist, lässt sich über die Datei „/usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz“ ermitteln. Darin steht ein Firmware-Hash-Wert aus dem sich der Kernel-Hash und damit die Download-URL bei https://github.com/raspberrypi/linux.git für diesen Kernel ergibt.

Script zum Erstellen der Kernel-Module verwenden

Um Kernel-Module für den Raspberry Pi zu erstellen, benötigen Sie einen PC mit installiertem Linux. Am einfachsten ist es, Ubuntu 14.04 (32- oder 64-Bit) zu verwenden. Die Entwicklung ist auch in einer virtuellen Maschine möglich, etwa in Virtualbox. Alle nötigen Downloads und Schritte habe ich in einem Script zusammengefasst. Das Script eignet sich für den Raspberry Pi (armv61) und Raspberry Pi 2 (armv71).

Ich erläutere das Verfahren am Beispiel des Kernel Moduls für den WLAN-USB-Stick TP-Link AC900. Wie sich das Kernel-Modul dafür unter und für Ubuntu erstellen lässt, habe ich im Artikel TP-Link Archer T2U AC600 unter Linux nutzen beschrieben.

Im Prinzip funktioniert es so oder ähnlich für jeden Treiber, dessen Quellcode verfügbar ist.

SSH-Verbindung testen: Stellen Sie sicher, dass Sie Ihren Raspberry Pi über ssh erreichen können:

ssh pi@192.168.0.17

Ersetzen Sie die IP-Nummer durch die IP Ihres Raspberry Pi. Bestätigen Sie den Schlüssel mit yes und geben Sie das Passwort ein. Prüfen Sie bei der Gelegenheit, ob die Datei „/proc/config.gz“ vorhanden ist:

zcat /proc/config.gz

Wenn Sie die Fehlermeldungen „gzip: /proc/config.gz: No such file or directory“ erhalten. Starten Sie

sudo modprobe configs

Danach ist „/proc/config.gz“ vorhanden. Beenden Sie die SSH-Verbindung mit exit.

Script vorbereiten: Laden Sie „raspi_crosstools.sh“ herunter (siehe unten auf dieser Seite) und speichern beziehungsweise entpacken Sie die Datei in Ihr Home-Verzeichnis auf dem (Ubuntu-)PC. Machen Sie die Datei mit folgendem Befehl ausführbar:

chmod 755 raspi_crosstools.sh

Öffnen Sie raspi_crosstools.sh in einem Editor. Passen Sie den Abschnitt unterhalb von „Konfiguration“ an. Tragen Sie hinter die Variablen den Benutzernamen („RASPI_USER=“), das Passwort („RASPI_PWD=“) und die IP-Adresse ein („RASPI_IP=“).

Der hinter „USE_THREADS=“ eingetragene Wert „-j4“ bestimmt die Anzahl der Threads, die der Compiler verwenden soll. Bei einem Intel Core i7 können Sie auch „-j8“ eintragen. Das Compilieren geht dann schneller. Bei langsameren CPUs lassen Sie den Wert leer
Starten Sie das Script dann mit

./raspi_crosstools.sh

Script raspberry_cross

In der Regel genügt es hier „Minimal“ zu wählen. Bei Problemen entscheiden Sie sich für „Voll“.

So arbeitet das Script: Das Bash-Script prüft zunächst, ob die nötigen Entwicklerpakete auf dem Linux-System installiert sind und installiert sie bei Bedarf. Danach haben Sie die Wahl, ob Sie eine minimale (schneller) oder volle (langsamer) Kompilation des Kernels wünschen. In der Regel sollte eigentlich eine minimale Konfiguration des Kernels genügen.

Das Problem dabei: Sie benötigen die Datei „Module.symvers“ von github.com/raspberrypi/firmware. Als ich das Script geschrieben habe, lag hier für den Kernel 4.1.6-v7+ noch eine veraltete Version. In diesem Fall müssen Sie „Voll“ wählen. Dabei wird die Datei „Module.symvers“ neu erstellt. Das ist also der sicherere Weg. Mit der falschen „Module.symvers“ verweigert der Kernel des Raspberry Pi später das Modul zu laden. Es erscheint dann eine Fehlermeldung wie „mt7650u_sta: disagrees about version of symbol module_layout“.

Im nächsten Schritt ermittelt das Script, welcher Kernel auf dem Raspberry Pi installiert ist und lädt dann den Quellcode des Kernels herunter. Außerdem werden die Tools für den Cross-Compiler und die Quellen des Treibers heruntergeladen. Alle Dateien landen im Verzeichnis „~/raspi_cross“.

Kernel-Modul auf dem Raspberry Pi installieren: Der Kernel und die Module werden dann kompiliert. Nach Abschluss kopiert das Script das Modul und zwei Bash-Scripte in das Home-Verzeichnis „/home/pi“ auf den Raspberry Pi. Machen Sie install_driver.sh und un-install_driver.sh jeweils mit chmod 755 ausführbar. Mit

sudo ./install_driver.sh

installieren Sie das Modul und mit sudo ./un-install_driver.sh entfernen Sie es wieder. Mit dmesg prüfen Sie, ob der Kernel das Modul korrekt geladen hat.

Script anpassen: Wenn Sie ein anderes Kernel-Modul für den Raspberry Pi erstellen möchten, sind einige Anpassungen im Script nötig. Ändern Sie die Download-Adresse unter dem Kommentar „Treiber herunterladen“ und die Anweisungen unter „Kernel-Modul compilieren“. Passen Sie außerdem den Abschnitt „Dateien auf den Raspi kopieren“ an.

Hinweise: Das Script fragt nicht ab, ober Kernel oder Modul bereits zuvor compiliert wurden. Es startet immer mit einer frischen Konfiguration („make clean“). So ist es sicherer aber es kostet mehr Zeit. Wenn Sie das nicht wünschen, kommentieren Sie beispielsweise den Block unter „Kernel vorbereiten/compilieren“ aus. Dann wird nur das Modul neu erstellt.

Sollte nach einem Update einer neuer Kernel auf dem Raspberry Pi installiert werden, müssen Sie den kompletten Vorgang wiederholen. In diesem Fall löschen Sie das Verzeichnis „raspi_cross“ und starten wieder das Script raspi_crosstools.sh. Es lädt dann die aktuellen, beziehungsweise passenden, Kernel-Quellen herunter und erzeugt ein neues Kernel-Modul.

WLAN auf dem Raspberry Pi einrichten

Prüfen Sie nach erfolgter Modulinstallation auf dem Raspberry Pi mit dem Befehl ifconfig in einem Terminalfenster, ob das Netzwerkgerät vorhanden ist. Im der Ausgabe sollte das Gerät ra0 auftauchen. Suchen Sie nach WLAN-Netzwerken mit folgender Befehlszeile:

sudo iwlist ra0 scan

Tauchen hier Netzwerke mit der Angabe etwa von „Frequency:5.22 GHz“ auf, funktioniert auch 5 GHz.

Die WLAN-Konfiguration erfolgt am einfachsten und zuverlässigsten auf der Kommandozeile in einem Terminalfenster. Ändern sie zunächst mit sudo nano /etc/network/interfaces die Konfiguration der Netzwerk-Geräte. Die Datei kann danach so aussehen:

auto lo
iface lo inet loopback
iface eth0 inet manual

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

Verwenden Sie den Befehl

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Hier tragen Sie zusätzlich beispielsweise folgendes ein:

network={
        ssid="Meine_SSID"
        psk="1234567890"
        key_mgmt=WPA-PSK
}

Die Angaben hinter „ssid=“ und „psk=“ ändern Sie passend für Ihr Netzwerk.

Starten Sie den Raspberry Pi neu (sudo reboot). Die Verbindung zum WLAN-Netzwerk erfolgt jetzt automatisch.

Crosscompile-Script für Raspberry-Pi-Module

Und hier das Script. Fahren Sie mit der Maus in den Script-Block und klicken Sie auf das erste Icon, um das Script im Textmodus zu sehen. Oder laden Sie das Script raspi_crosstools.sh als ZIP-Datei herunter.

#!/bin/bash

#########################
##    Konfiguration    ##
#########################
#
# IP-Adresse, Benutzername und Passwort des Raspberry Pi
# Das Gerät muss über ssh erreichbar sein
# Testen Sie das zuerst mit ssh pi@IP-Adresse
#
RASPI_USER=pi
RASPI_PWD=geheim
RASPI_IP=192.168.0.XX
# beispielsweise 192.168.0.17
# USE_THREADS= #langsame/ältere CPUs
# Beschleunigt das Compilieren bei Multicore-CPUs deutlich
USE_THREADS=-j4 # schnelle/neuere CPUs oder -j8 (schneller)
#
#DRIVERDIR=mt7610u-linksys-ae6000-wifi-fixes
DRIVERDIR=mt7610u_wifi_sta_v3002_dpo_20130916
#########################
## Konfiguration Ende ##
#########################

KERNEL_HASH=
FIRMWARE_HASH=

HOMEDIR=`pwd`
WORKDIR=$HOMEDIR/raspi_cross

if [ `getconf LONG_BIT` = "64" ]
then
    HOSTARCH=64
else
    HOSTARCH=32
fi

#####################################
## Dateien auf den Raspi kopieren ###
#####################################
put_file_to_raspi() {
cd $WORKDIR/$DRIVERDIR/os/linux
if [ -e mt7610u_sta.ko ]
then
echo Kopiere Datei auf den Raspberry Pi
lftp sftp://$RASPI_USER:$RASPI_PWD@$RASPI_IP -e "put mt7610u_sta.ko; bye"
cd $WORKDIR/$DRIVERDIR
lftp sftp://$RASPI_USER:$RASPI_PWD@$RASPI_IP -e "put RT2870STA.dat; bye"
else
echo Fehler. Nicht gefunden: $WORKDIR/$DRIVERDIR/os/linux/mt7610u_sta.ko
exit 1 
fi
cd $WORKDIR
cat<<EOF>${WORKDIR}/un-install_driver.sh
#!/bin/bash
[ \$UID -ne 0 ] && { 
    echo "Fehler: Das Script benötigt root-Rechte."
    echo "Aufruf mit mit sudo $0"
    exit 1
}
OSVERSION=\`uname -r\`
echo Entlade Modul mt7610u_sta
rmmod mt7610u_sta
echo Lösche Modul /lib/modules/\${OSVERSION}/extra/mt7610u_sta.ko
rm /lib/modules/\${OSVERSION}/extra/mt7610u_sta.ko
echo Lösche Konfiguration /etc/Wireless/RT2870STA/RT2870STA.dat
rm /etc/Wireless/RT2870STA/RT2870STA.dat
echo Aktualisiere Module...
depmod -a
echo Sie können das Verzeichnis /etc/Wireless jetzt komplett löschen
echo Fertig!
EOF

cat<<EOF>${WORKDIR}/install_driver.sh
#!/bin/bash
[ \$UID -ne 0 ] && { 
    echo "Fehler: Das Script benötigt root-Rechte."
    echo "Aufruf mit mit sudo \$0"
    exit 1
}
OSVERSION=\`uname -r\`
mkdir -p /etc/Wireless/RT2870STA
mkdir -p /lib/modules/\$OSVERSION/extra
echo Kopiere Modul nach /lib/modules/\${OSVERSION}/extra/mt7610u_sta.ko
cp mt7610u_sta.ko /lib/modules/\${OSVERSION}/extra/mt7610u_sta.ko
echo Kopiere Konfigration nach /etc/Wireless/RT2870STA/RT2870STA.dat
cp RT2870STA.dat /etc/Wireless/RT2870STA/RT2870STA.dat
echo Aktualisiere Module...
depmod -a
echo lade Modul mt7610u_sta.ko
modprobe mt7610u_sta
echo Fertig!
EOF
chmod 755 install_driver.sh
chmod 755 un-install_driver.sh

# Datei uebertragen
echo Kopiere Datei install_driver.sh auf $RASPI_IP
lftp sftp://$RASPI_USER:$RASPI_PWD@$RASPI_IP -e "put install_driver.sh; bye"
lftp sftp://$RASPI_USER:$RASPI_PWD@$RASPI_IP -e "put un-install_driver.sh; bye"
}

# Konfigurations-Dateien vom Raspberry Pi holen
get_files_from_raspi() {
cd $WORKDIR

# Alte Dateien löschen
if [ -e changelog.Debian.gz ]
then
rm changelog.Debian.gz
fi

if [ -e config.gz ]
then
rm config.gz
fi

if [ -e Module.symvers ]
then
rm Module.symvers
fi

echo Download changelog.Debian.gz vom Raspberry Pi $RASPI_IP
lftp sftp://$RASPI_USER:$RASPI_PWD@$RASPI_IP -e "get -e /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz; bye"
FIRMWARE_HASH=$(zgrep "* firmware as of" changelog.Debian.gz | head -1 | awk '{ print $5 }')
echo Firmware-Hash: $FIRMWARE_HASH
#
# hier bei Bedarf einen eigenen Hash-Wert eintragen
# wenn nicht der Standard-Kernel, wie in raspberrypi-bootloader/changelog.Debian.gz
# abgelegt, zum Einsatz kommmt.
# die Hash-Werte sind unter https://github.com/raspberrypi/firmware/commits/ zu finden
# Beispielsweise "kernel: Bump to 4.1.15" unter
# https://github.com/raspberrypi/firmware/commit/22d8c910f4c53118f9cf85c038d7d8e307efc110 
# 
#4.1.15
#FIRMWARE_HASH=c22d8c910f4c53118f9cf85c038d7d8e307efc110
#4.1.20
#FIRMWARE_HASH=37f187cd887f67235f3b84e0a2cd67807196c70f
#7f30737678023b5becaf0e2e012665f71b886a7d

#c37f187cd887f67235f3b84e0a2cd67807196c70f
#FIRMWARE_HASH=4bf906cdd221c4f6815d0da7dda0cd59d25d945b

#3.18.13
#FIRMWARE_HASH=9354845ea5a961f267bcf440f92c9bd21be29b35
#git hash
#3.18.11
#8362c08dfc8dd9e54745b3f1e5e4ff0a1fb30614

echo Hole $FIRMWARE_HASH/
KERNEL_HASH=$(wget https://raw.github.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/git_hash -O -)
echo Kernel-Hash ist: $KERNEL_HASH

echo Download config.gz vom Raspberry Pi $RASPI_IP
lftp sftp://$RASPI_USER:$RASPI_PWD@$RASPI_IP -e "get -e /proc/config.gz; bye"

# Version des Kernels ermittlen (für PI/PI2)
STR=$(zgrep "CONFIG_LOCALVERSION" config.gz | head -1)
LOCALVERSION=${STR#*=} #string part after =
LOCALVERSION="${LOCALVERSION//\"}" #remove quotes
if [ "$LOCALVERSION" == "-v7" ]
then
echo "Raspberry PI 2 gefunden (armv71)"
RASPI_MODEL=armv71
else
echo "Raspberry PI gefunden (armv61)"
RASPI_MODEL=armv61
fi

# hier sollte die Datei Module.symvers für den aktuellen Kernel liegen 
if [ $RASPI_MODEL = armv71 ]
then
echo Download Module7.symvers
wget https://raw.github.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/Module7.symvers -O Module.symvers 
else
echo Download Module.symvers
wget https://raw.github.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/Module.symvers -O Module.symvers 
fi

if [ ! -e changelog.Debian.gz ]
then
echo "Fehler: changelog.Debian.gz nicht gefunden"
return 0
fi

if [ ! -e config.gz ]
then
echo "Fehler: config.gz nicht gefunden"
return 0
fi

return 1
}

##############################
## Das Script startet hier ###
##############################

echo "Prüfe Voraussetzungen..."
if [ ! -d /usr/share/build-essential ]
then
sudo apt-get update
sudo apt-get build-essential
echo "OK" > prep_ok
fi 

#git ?
if [ -z $(which git) ]
then
echo "Installiere git"
sudo apt-get -y install git
fi

# dialog?
if [ -z $(which dialog) ]
then
echo "Installiere dialog"
sudo apt-get -y install dialog
fi

# lftp?
if [ -z $(which lftp) ]
then
echo "Installiere lftp"
sudo apt-get -y install lftp
fi

if [ -z ${RASPI_IP} ]
then
MSG="Die IP-Adresse des Raspberry Pi ist nicht konfiguriert.\n"\
"Bitte öffnen Sie dieses Script zuerste in einem Editor"\
" und passen Sie die Konfiguration an.\n"\
"Abbruch!"

dialog --title "Konfiguration" --msgbox "${MSG}" 10 50
exit 1
fi	

MSG="Dises Script erstellt ein Kernel Modul für den Raspberry Pi.\n"\
"Als Beispiel wird ein Modul für den USB-WLAN-Stick TP-Link AC900 erstellt."\
" Passen Sie zuerst im Script den Abschitt Konfiguration an."\
" Wenn das noch nicht erledigt ist, gehen Sie auf 'Abbrechen'\n"\
"Bei 'Weiter' lädt das Script den zu Ihrem Raspberry Pi passenden Kernel,"\
"einige Tools und den Treiber-Quellcode herunter. Das kann einige Zeit dauern..."

dialog --title "Module erstellen" --yes-label "Weiter" --no-label "Abbrechen" --yesno "${MSG}" 13 60

if [ "$?" != "0" ]
then
echo "Abbruch!"
exit 0
fi	

MSG="Für die Kernel-Module ist die Datei 'Module.symvers' nötig.\n"\
"Die Datei ist auf 'raw.github.com/raspberrypi/firmware' verfügbar."\
" Wenn die Datei heruntergeladen werden soll, wählen Sie 'Minimal'.\n"\
"Manchmal liegt hier aber nicht die aktuelle Datei."\
" Dann schlägt das Laden des Moduls auf dem Rapberry Pi fehl."\
" In diesem Fall müssen Sie Kernel und Module komplett erstellen, wobei die Datei erzeugt wird."\
" Das dauert länger, sollte aber in jedem Fall ein passendes Modul erzeugen."

dialog --title "Modus wählen" --yes-label "Minimal" --no-label "Voll" --yesno "${MSG}" 15 60
if [ "$?" != "0" ]
then
MODE=full
else
MODE=min
fi	

if [ ! -d $WORKDIR ]
then
mkdir $WORKDIR
fi
cd $WORKDIR

# Konfigurations-Dateien vom Raspberry Pi holen
get_files_from_raspi

if [ ! -e config.gz ]
then
MSG="config.gz nicht auf dem Rapberry Pi gefunden.\n"\
"Bitte führen Sie auf dem Gerät zuerst 'modeprobe configs' aus.\n"\
"Prüfen Sie, ob zcat /proc/config.gz den Inhalt der Datei ausgibt.\n"\
"Abbruch!"

dialog --title "config.gz" --msgbox "${MSG}" 10 50
exit 1
fi
echo Kernel-Hash: $KERNEL_HASH

if [ ! -d $WORKDIR/kernel ]
then
echo "Lade Kernel herunter"
git clone https://github.com/raspberrypi/linux.git kernel
echo Checkout Kernel ${KERNEL_HASH}
cd $WORKDIR/kernel
git checkout $KERNEL_HASH
fi
cd $WORKDIR
if [ ! -e kernel/.config ]
then
echo Kopiere .config
gunzip -c config.gz > kernel/.config
fi

if [ ! -d $WORKDIR/tools ]
then
echo "Lade Tools herunter"
git clone https://github.com/raspberrypi/tools
fi 
#########################
# Treiber herunterladen #
#########################
if [ ! -d $WORKDIR/$DRIVERDIR ]
then
echo "Lade Treiber herunter"
git clone -b raspberry https://github.com/Myria-de/$DRIVERDIR.git
fi 

# Crosscompile-Umgebung vorbereiten
if [ $HOSTARCH = 64 ]
then
export CCPREFIX=$WORKDIR/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
else
export CCPREFIX=$WORKDIR/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-
fi

export ARCH=arm
export CROSS_COMPILE=${CCPREFIX}
export KERNEL_SRC=$WORKDIR/kernel
echo "Erstelle Kernel..."
cd $WORKDIR/kernel

if [ -e $WORKDIR/config.gz ]
then
if [ ! -e $WORKDIR/config.gz ] 
then
zcat $WORKDIR/config.gz > $WORKDIR/kernel/.config
fi
else
echo $WORKDIR/config.gz ist nicht vorhanden. Abbruch.
exit 1
fi

if [ -e $WORKDIR/Module.symvers ]
then
cp $WORKDIR/Module.symvers $WORKDIR/kernel/Module.symvers
else
echo $WORKDIR/Module.symvers ist nicht vorhanden. Abbruch.
exit 1
fi

####################################
## Kernel vorbereiten/compilieren ##
####################################
if [ $MODE = "min" ]
then
make oldconfig
make prepare
make scripts
else
make clean
make oldconfig
make prepare
make $USE_THREADS
fi

##############################
## Kernel-Modul compilieren ##
##############################
echo Erstelle Treiber
cd $WORKDIR/$DRIVERDIR
make clean
make $USE_THREADS

if [ -e $WORKDIR/$DRIVERDIR/os/linux/mt7610u_sta.ko ]
then
put_file_to_raspi
else
echo
echo $WORKDIR/$DRIVERDIR/os/linux/mt7610u_sta.ko
echo ist nicht vorhanden.
echo Die Compilation ist fehlgeschlagen.
echo Bitte prüfen Sie Ihre Konfiguration.
fi
echo
echo Fertig!
echo
echo Zusammenfassung/Summary
echo Firmware-Hash: $FIRMWARE_HASH
echo Kernel-Hash: $KERNEL_HASH
echo Raspberry-Modell:$RASPI_MODEL
echo Modul: mt7610u_sta.ko

Netzwerkleistung mit iperf messen

Zuverlässigkeit und Geschwindigkeit Ihres Netzwerkes ermitteln Sie mit Tool iperf. Installieren Sie es auf dem Raspberry Pi und einem anderen PC im Netzwerk in einem Terminalfenster mit

 sudo apt-get install iperf

Starten Sie auf dem Raspberry Pi

iperf -s

Das Tool lauscht nun auf dem TCP-Port 5001. Starten Sie auf einem anderen PC den Test mit dieser Befehlszeile:

iperf -c Server-IP -d 

Ersetzen Sie Server-IP durch die tatsächliche IP-Adresse des Servers. Iperf sendet und empfängt nun zehn Sekunden lang Daten und zeigt anschließend das Ergebnis im Terminal. Der Parameter „-d“ testet simultan den Datendurchsatz in beiden Richtungen. In der Auswertung zeigt der erste Wert die Verbindung vom Client zum Server (Uplink), der zweite den Durchsatz vom Server zum Client.

Die Bedienung von Iperf wird durch das grafische Frontend Jperf erleichtert. Es zeigt die Messergebnisse in einem Diagramm und vermittelt so einen besseren Eindruck von der Transferrate. Jperf benötigt eine Java-Laufzeitumgebung. Installieren Sie diese beispielsweise unter Ubuntu mit folgender Befehlszeile:

sudo apt install default-jre

Laden Sie Jperf über https://www.pcwelt.de/1735757 herunter. Entpacken Sie das ZIP-Archiv und wechseln Sie im Terminalfenster mit cd in das Verzeichnis, in das Sie Jperf entpackt haben. Starten Sie das Tool mit

sh jperf.sh

Wählen Sie die Option „Server“, und klicken Sie auf „Run Iperf!“. Auf einem anderen PC im Netzwerk richten Sie Jperf ebenfalls ein. Hier wählen Sie die Option „Client“ und geben dahinter die IP-Adresse des Servers ein. Hinter „Output Format“ stellen Sie „MBits“ ein. Klicken Sie auf „Run Iperf!“. Das Tool zeigt Ihnen die Text-Ausgabe von iperf an und stellt die Daten in einem Diagramm dar.

Die folgenden Messungen stammen aus einen 2,4- und 5 GHz-WLAN (802.11n), also nicht aus einem Netzwerk mit 802.11ac-Router (zurzeit ist keiner verfügbar).

iperf Ergebnis TP-Link T2U

Übertragungsrate WLAN TP-Link T2U zwischen Raspberry Pi und einem Linux-PC (2,4 GHz, in einem 802.11n-Netzwerk).

jperf TP-Link

Übertragungsrate WLAN TP-Link T2U zwischen Raspberry Pi und einem Linux-PC (5 Ghz, in einem 802.11n-Netzwerk).

Be Sociable, Share!

18 Kommentare

  • Hallo. Ich bekomme beim Kompilieren folgenden Ausgabe.

    make -C ~/raspi_cross/kernel SUBDIRS=/home/falko/pi_crosstool/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux modules
    make[1]: *** /root/raspi_cross/kernel: Datei oder Verzeichnis nicht gefunden. Schluss.
    Makefile:403: die Regel für Ziel „LINUX“ scheiterte
    make: *** [LINUX] Fehler 2
    make: *** Auf noch nicht beendete Prozesse wird gewartet …
    make[1]: Verzeichnis „/home/falko/pi_crosstool/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/tools“ wird verlassen
    /home/falko/pi_crosstool/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/tools/bin2h
    chipset = mt7610u

    /home/falko/pi_crosstool/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux/mt7610u_sta.ko
    ist nicht vorhanden.
    Die Compilation ist fehlgeschlagen.
    Bitte prüfen Sie Ihre Konfiguration.

    Fertig!

    Zusammenfassung/Summary
    Firmware-Hash: 6ba0dabbe76ce02d261cc4658c3484fa12b10385
    Kernel-Hash: be2540e540f5442d7b372208787fb64100af0c54
    Raspberry-Modell:armv61
    Modul: mt7610u_sta.ko

    Gibt es dazu ein Workaround?

    Viele Grüße Falko

  • Vielen Dank für die tolle Anleitung!
    Beim aktuellen Kernel (zumindest für RP2) wurde allerdings ein anderer Compiler genutzt, daher muss Zeile 330 angepasst werden:
    export CCPREFIX=$WORKDIR/tools/arm-bcm2708/gcc-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-

    Aus irgendeinem Grund hat bei mir die install-driver-scripts nicht mit execute-Rechten versehen, daher keine automatische Installation. Ich habe das dann per Hand nachgeholt und schon ging alles.

    Super!
    Danke!

  • Jörg Kohlschmidt

    Hallo,
    Vielen Dank für das Script. Ich habe es probiert, bekomme aber folgenden Fehler:
    Erstelle Kernel…
    /home/kohli/source/raspberry/kernel_module/raspi_cross/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14′ not found (required by /home/kohli/source/raspberry/kernel_module/raspi_cross/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc)
    Was könnte die Ursache sein?
    Ich nehme an, dass die GLIBC 2.14 bei den Crosstools dabei ist, oder? Was kann ich machen, damit es funktioniert?
    Vielen Dank im voraus für Hilfe
    Jörg

  • Ich habe den Treiber für Archer T2U AC600 mit der „Voll“ Version kompiliert. Das Ausführen des intall Skripts ergab Folgendes:
    #########
    sudo ./install_driver.sh
    Kopiere Modul nach /lib/modules/4.1.17-v7+/extra/mt7650u_sta.ko
    Kopiere Konfigration nach /etc/Wireless/RT2870STA/RT2870STA.dat
    Aktualisiere Module…
    lade Modul mt7650u_sta.ko
    Fertig!
    #########

    dmesg liefert nun aber einen Versions-Error:
    #########
    [23941.408726] no file read method
    [23941.408740] Read file „/etc/Wireless/RT2870STA/RT2870STA.dat“ failed(errCode=-1)!
    [23941.408792] 1. Phy Mode = 6
    [23941.408803] 2. Phy Mode = 6
    [23941.408816] NVM is Efuse and its size =1d[1e0-1fc]
    [23941.428533] /home/kim/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux/../../chips/mt76x0.c:2114 assert (pAd->TxPower[choffset].Channel == 36)failed
    [23941.443084] ERROR!!! E2PROM: WRONG VERSION 0x2, should be 1
    [23941.448659] mt76x0_read_tx_alc_info_from_eeprom: EEPROM_MT76x0_TEMPERATURE_OFFSET (0xD1) = 0xf8
    [23941.448678] mt76x0_read_tx_alc_info_from_eeprom: TemperatureOffset = 0xfffffff8
    #########
    Woran könnte das liegen? Ich habe davon leider gar keine Ahnung und fühle mich momentan etwas verloren. 🙁

    • „Read file „/etc/Wireless/RT2870STA/RT2870STA.dat“ failed(errCode=-1)!“

      Ist die Datei denn an diesem Ort vorhanden?

      „ERROR!!! E2PROM: WRONG VERSION 0x2, should be 1“

      Diese Fehlermeldung taucht immer auf, und ist kein Hinweis auf Fehlfunktionen des Treibers.

      • Hallo Thorsten,
        vielen Dank für deine schnelle Antwort und natürlich auch für die Ressourcen, die du hier bereitstellst.

        Die Datei ist vorhanden und hat folgenden Inhalt (gekürzt):
        ######
        #The word of „Default“ must not be removed
        Default
        CountryRegion=5
        CountryRegionABand=7
        CountryCode=DE
        ChannelGeography=1
        SSID=11n-AP
        NetworkType=Infra
        WirelessMode=5
        EfuseBufferMode=0
        Channel=0
        BeaconPeriod=100
        TxPower=100
        (…)
        PMFMFPC=0
        PMFMFPR=0
        PMFSHA256=0
        ######

    • Es gab einige Updates im Quellcode des Treibers, die das Problem bei neueren Kerneln beseitigen sollten. Bitte die aktuelle Version des Scripts von dieser Seite verwenden und darüber den Treiber-Quellcode erneut herunterladen.

  • Thanks for the driver modifications and this post, very helpful!
    Loosely following these, I managed to make the Wifi dongle work on FC22.

    Minor correction:
    The comments for install-script and uninstall-script should exchange their places; of course, no impact, but does ease understanding. Excellent example for bash programming btw.

  • Hallo Thorsten Eggeling

    Danke für die Antwort. Nach langem suchen habe ich im Netz keine so klare Anleitung gefunden, wie Ihre, um Module für neue Hardware in den Raspi einzufügen. Daher habe ich mir das Scrip einmal genauer angesehen, um es zum laufen zu bringen.

    Dabei sind mir ein paar kleine Fehler aufgefallen. Ich bin noch beim überarbeiten, möchte aber fragen ob ich Ihnen meine Verbesserungsvorschläge senden darf?

    Beispiel:
    Zeile 147 : if [ $LOCALVERSION = „-v7″ ]
    muss eigentlich heißen:
    Zeile 147 : if [ $LOCALVERSION = ‚“-v7″‚ ]
    , sonnst wird immer eine RPI und niemals ein RPI2 erkannt, da die Variable bereits „-Zeichen beinhaltet („-v7“).

    Gern sende ich in den nächsten Tagen meine Vorschläge.

    Grüße Eddy

  • Hallo
    Die Prozedur ist bis zum Ende fehlerfrei durchgelaufen. Bein laden des Kernelmodules gab es jedoch einen Fehler:
    ERROR: could not insert ‚mt7650u_sta‘: Exec format error
    in dmesg sieht das dann so aus:
    mt7650u_sta: disagrees about version of symbol module_layout

    Ich benutze auf dem Raspi Kernel: 4.1.15-v7+
    Cross-compiled wurde auf einen: Ubuntu 14.04.3 LTS

    Was kann da schief gelaufen sein?

    Viel Glück fürs neue Jahr wünscht Eddy

    • Das Script hofft darauf, das sowohl im Github-Repository als auch beim Raspi-Kernel alles zusammenpasst. Dem ist aber zurzeit wohl nicht so. In der Datei changelog.Debian.gz steht ein anderer Wert, als er für den Kernel 4.1.15 müsste.

      Die Hash-Werte der Firmware sind unter https://github.com/raspberrypi/firmware/commits/ zu finden. In diesem Fall bei „kernel: Bump to 4.1.15“ und hier der Wert hinter „Commit“.

      Das Problem lässt sich für Kernel 4.1.15 wie folgt lösen (zuerst das bisherige Verzeichnis „raspi_cross“ löschen):

      Im Script über „echo Firmware-Hash: $FIRMWARE_HASH“ folgende Zeile einfügen:

      FIRMWARE_HASH=22d8c910f4c53118f9cf85c038d7d8e307efc110

      Dann das Script starten und nicht „Minimal“ sondern „Voll“ wählen.

      Mit folgender Zeile lässt sich auf dem Raspberry Pi prüfen, für welchen Kernel das Modul kompiliert wurde:

      modinfo mt7650u_sta.ko

      Auch wenn hier der richtige Wert, in diesem Fall „vermagic: 4.1.15-v7+ SMP mod_unload modversions ARMv7“ angezeigt wird, kann das Laden des Moduls trotzdem fehlschlagen. Das wiederum liegt dann an der falschen „Module.symvers“ von Github. Im Modus „Voll“ wird der Kernel komplett kompiliert und dann einen passende „Module.symvers“ erstellt. Das dauert aber etwas länger.

      Ich wünsche ebenfalls ein schönes neues Jahr.

  • Vielen Dank!
    Nun geht es! Super!!!
    Gibt es Hoffnung auf 5 GHz Unterstützung?

    Gruß
    Martin

    • 5 GHz? Das ist merkwürdig. Auf einem Raspberry Pi 2 mit Kernel 4.1.6-v7+ gibt iwlist chan nur 2,4-GHz-Kanäle aus. Auf einem Raspberry Pi mit Kernel 3.18.11 sowie unter Ubuntu (Kernel 3.19.0) funktioniert auch 5 GHz. Da sind wohl längere Forschungsarbeiten nötig. Wahrscheinlich sind zusätzliche Anpassungen für neuere Kernel erforderlich. Mal sehen, was sich da machen lässt. Das kann jedoch einige Zeit dauern, da ich gerade mit anderen Projekten beschäftigt bin.

      Ein Spaß am Rande: Bei einem anderen Stick mit Realtek/Mediatek-Chipsatz und Original-Treiber funktioniert unter Windows 5 GHz nicht, unter Linux dagegen 2,4 und 5 GHz. Man kann wohl grundsätzlich sagen, dass Hardware beziehungsweise Treiber von Mediatek mehr als fragwürdig sind. Andererseits gibt es immerhin einen Quellcode der Treibers und damit eine potentielle Linux-Unterstützung.

  • Danke!
    Ich habe dennoch 2 errors :
    Nr. 1
    ————————-
    LD [M] drivers/media/media.o
    LD drivers/media/usb/built-in.o
    LD drivers/media/built-in.o
    Makefile:947: recipe for target ‚drivers‘ failed
    make: *** [drivers] Error 2
    ———
    wieso findet er das auf einmal nicht?

    und Nr.2
    ————-
    Erstelle Treiber
    cp -f os/linux/Makefile.clean os/linux/Makefile
    make -C os/linux clean
    make[1]: Entering directory ‚/home/martin/src/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux‘
    rm -f ../../common/.*.cmd .*.flags .*.d
    rm -f ../../os/linux/*.o *.ko *.mod.o *.mod.c



    rm -f ../../sta/*.o
    rm -f ../../sta/.*.cmd .*.flags .*.d
    make[1]: Leaving directory ‚/home/martin/src/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux‘
    rm -rf os/linux/Makefile
    make -C tools
    make[1]: Entering directory ‚/home/martin/src/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/tools‘
    gcc -g bin2h.c -o bin2h
    cp -f os/linux/Makefile.6 /home/martin/src/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux/Makefile
    make -C SUBDIRS=/home/martin/src/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux modules
    make[1]: *** SUBDIRS=/home/martin/src/raspi_cross/mt7610u_wifi_sta_v3002_dpo_20130916/os/linux: Datei oder Verzeichnis nicht gefunden. Schluss.
    Makefile:406: recipe for target ‚LINUX‘ failed
    ……..

    Was ist hier passiert?

    Danke für Antworten!
    Gruß

    Martin

    • Mir ist da ein kleiner Fehler unterlaufen. Ich habe Pfadangaben aus dem Makefile entfernt, damit es universell für unterschiedliche Verzeichnisse passt. Die Umgebungsvariablen LINUX_SRC und CROSS_COMPILE_INCLUDE müssen im Script gesetzt werden. Das habe ich vergessen. Jetzt müsste das Script aber funktionieren (wenn ich keine weiteren Fehler eingebaut habe).

      Für den Kernel bei einem Raspberry Pi 2 mit Kernel 4.1.6-v7+ bitte „Voll“ wählen. Die Datei Module.symvers bei github.com zeigt stammt immer noch von Version 4.1.5. Das repariert wohl auch niemand mehr, weil die inzwischen schon ein paar Versionen weiter sind.

  • Hallo,
    vielen Dank für script!

    ist die Zeile 62 so korrekt?

    Gruss

    Martin

    • Zeile 62 ist in Ordnung. Es muss „\$UID“ heißen, damit $UID im über „cat“ generierten Script ankommt und nicht der Inhalt von $UID. Aber Zeile 60 und ein paar andere hatten Fehler. Da hat WordPress die Formatierung geändert. Aber jetzt müsste alles stimmen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.