Raspberry Pi Kernel kompilieren (Cross-Compiler)
Der Raspberry Pi bietet bei einer Vielzahl von Projekten enorme Flexibilität, wer allerdings Unterstützung für spezielle Hardware benötigt stößt mit dem Standard Kernel schell an die Grenze des machbaren. Ein gutes Beispiel wann die Erstellung eines eigenen Kernels notwendig wird ist mein Google Kalender Projekt. Hier war es, um den Touch Controller ansprechen zu können, notwendig den passenden Treiber im Kernel bereitzustellen. Da ich, um damals den Zeitaufwand gering zu halten, eine externe Anleitung verwendet hatte wollte ich euch hier nochmal eine kompletten Guide zum Erstellen des Kernels zur Verfügung stellen. Das Problem beim Kompilieren des Kernels ist die fehlende Power am Raspberry Pi, das Kompilieren des Kernel dauert über 12 Stunden. Daher nutzen wir in diesem Tutorial die Möglichkeiten des „Cross Compiler“, ein Coss-Compiler erzeugt Code für eine andere Plattform. Also erzeugen wir an unserem Windows Desktop Rechner mit x64 bzw x86 Architektur den Kernel für den RasPi mit ARM Architektur in weniger als einer Stunde in einem mit Virtual Box virtualisierten Ubuntu System. Falls ihr euch mit dem Thema Kernel noch nicht beschäftigt habt gibt es auf kernelnewbies.org noch einige gute Informationen.
Inhaltsverzeichnis
Vorbereitung Cross Compiler Umgebung
Für euer Ubuntu Entwicklungssystem und zum Erstellen des Kernels auf dem System benötigen wir folgende Software. – Virtual Box zum Ausführen des Compiler Systems als Virtuelle Maschine – Ubuntu 14 in der x64 Variante als ISO Image – Einen Internetzugang Wer richtige Hardware zur Verfügung hat kann Ubuntu ndort installieren, da ich keinen Rechner übrig habe löse ich das Problem anhand eines virtuellen Ubuntu Systems auf meinem Windows Desktop Rechner. Für das Kompiler-System sollten mindestens 30GB Festplatten Platz und zum Beschleunigen des Compiler möglichst viel CPU Power zur Verfügung stehen. Ubuntu benötigt mindestens 512MB Arbeitsspeicher.
Erstellen des Kompiler-Systems
Nachdem ihr Virtual Box zur Virtualisierung eures Kompiler-Systems auf eurem Windows Desktop installiert habt erstellen wir eine neue Virtuelle Maschine (VM). Im Virtual Box Startbildschirm klickt ihr zum Erstellen einer neuen VM auf „Neu“
Dann vergeben wir einen Namen für das System, wichtig hier ist das „Ubuntu 64Bit“ als Betriebssystem ausgewählt wird
Ich vergebe meinem Cross-Kompiler System 1024MB Arbeitsspeicher da mein Desktio massig RAM zur Verfügung hat, mindestens solltet ihr jedoch 512MB vergeben.
Dann erzeugen wir eine neue virtuelle Festplatte mit dem Dateityp VDI
Da ich nicht möchte das direkt aller Speicher, obwohl er in der VM nicht verwendet wird, auf meiner Festplatte reserviert wird wähle ich „dynamisch alloziert“ (etwas langsamer als die feste Größe).
Dann wählen wir einen Speicherort für die Datei der virtuellen Festplatte und geben als maximal nutzbare Größe 60GB an.
Nach Abschluss der Einrichtung der VM möchten wir dieser noch etwas mehr CPU Power zuweißen, die VMs haben im Standard immer nur eine CPU. Da viele Anwendungen und Systeme, so auch der Kompiler, vom Multithreading profitieren sollte der VM mindestens eine weitere CPU zugeteilt werden. Das Funktioniert über Rechtsklick im Startbildschirm auf „Ändern“. Da mein Desktop massig Power zur Verfügung hat habe ich meiner VM 4 CPUs zugewiesen.
Das wir später über das Netzwerk Dateien mit unserem RasPi und/oder unserem Windows Desktop austauschen können stellen wir das Netzwerk in den Einstellungen in den „Netzwerkbrücken“ Modus (Bridge), somit erhält eure VM eine IP-Adresse von eurem Router und verhält sich wie jedes andere System im Netzwerk.
Somit sind erstmal alle wichtigen Einstellungen für unser Crosskompiler System getätigt.
Installation von Ubuntu
Die Virtuelle Maschine haben wir nun erstellt und können darauf das Betriebssystem Ubuntu installieren. Bitte stellt sicher das ihr das 64Bit Image von der Ubuntu Webseite heruntergeladen habt. Zur Installation via ISO Image müssen wir über „Ändern“ der VM noch das Image als virtuelle CD in das CD-Laufwerk des Systems einlegen. Klickt unter „Massenspeicher“ auf euer virtuelles CD-Laufwerk und wählt rechts über den Button „Datei für virtuelles CD/DVD-Medium auswählen…“ und gebt den Pfad zu der heruntergeladenen ISO-Datei von Ubuntu an.
Jetzt könnt ihr via „Rechtsklick“ > „Starten“ eure erstellte VM starten. Da wir das ISO File als virtuelle CD eingelegt haben startet die Installation von Ubuntu automatisch. Durch einen Klick auf „Install Ubuntu“ innerhalb der VM werden wir durch die Installation geführt. Soweit ich hier keine abweichenden Angaben mache habe ich die Standardeinstellungen verwendet.
Den Installer lassen wir direkt die aktuellen Updates und Patches für Ubuntu aus dem Netz laden, dann müssen wir uns später nicht darum kümmern.
Das Keyboard Layout habe ich, um nicht unnötig Probleme beim Tippen zu haben, auf Deutsch geändert.
Ubuntu richtet standardmäßig einen Benutzer für uns ein. Ich habe hier meine Benutzerdaten eingetragen und auf „Login automatically“ umgestellt.
Das Kopieren der Systemdateien von der virtuellen CD in die virtuelle Maschine dauert nun etwas. Nachdem die Installation abgeschlossen ist und ihr auf Restart geklickt habt müsst ihr im Konsolenfenster noch einmal das Entfernen der CD (Virtual Box entfernt die automatisch) mit „Enter“ bestätigen.
Einrichtung des Betriebssystems
Es ist enorm wichtig das die „Virtual Box Guest Additions“ installiert werden. Diese enthalten alle wichtigen Treiber und Software sodass unser Ubuntu System auch schnell und zuverlässig läuft. Das mache ich immer als erstes. Im Fenster der VM Klickt ihr auf Geräte und dann auf „Medium mit Gastererweiterungen einlegen“
Da das Ubuntu System automatisch auf dem Desktop landet (Login automatically) erkennt es sofort das ein Datenträger mit Autoplay Funktion eingelegt wurde und fragt uns ob wir die Installation starten wollen, das bestätigen wir mit „Run“ und geben nach Aufforderung unser Passwort ein.
Die Installation ist, sobald „Press Return to close…..“ in der Konsole des Ubuntu Systems angezeigt wird, abgeschlossen. Wir bestätigen das durch „Enter“ und starten das System einmal neu (Rechts oben unter „Shutdown“). Nun haben wir ein lauffähiges Ubuntu System, auch die Grafikausgabe sollte nach der Installation der Guest Additions zum Arbeiten taugen. Wer sich auf dem Windows Desktop zurecht findet wird auch mit der Ubuntu Oberfläche keine Schwierigkeiten haben.
Kernel für den Raspberry Pi kompilieren
Für alle weiteren Schritte benötigen wir ein Terminal, das findet sich über das Ubuntu Startmenü mit der Suche nach „Terminal“. Der Kernel Build läuft in mehreren Schritten ab, als erstes müssen wir uns jedoch die notwendige Software und den Quellcode besorgen.
- Vorbereitungen
- Kernel bereinigen
- Kernel konfigurieren
- Kernel kompilieren
- Kernel installieren
Vorbereitungen
Wir installieren „git core“ zum Herunterladen der Kernel Sourcen aus dem GitHub Repository und den GCC 4.7 GNU Kompiler im Basispaket (ca. 80MB). Zusätzlich benötigen wir „ncurses“ für das grafische Menu in welchem wir die im Kernel enthaltenen Komponenten zusammenstellen und die Build Essentials.
1 2 3 4 |
sudo apt-get install git-core sudo apt-get install gcc-4.7-arm-linux-gnueabi sudo apt-get install build-essential sudo apt-get install ncurses-dev |
Dann holen wir uns via git die Cross-Compiler Tools und die Sourcen des Kernels auf das System ins Home unseres bei der Installation angelegten Benutzers, das sind circa 1GB an Daten.
1 2 3 4 5 |
mkdir -p ~/src cd ~/src git init git clone git://github.com/raspberrypi/tools.git git clone --depth 1 git://github.com/raspberrypi/linux.git |
Um sicher zu stellen das wir auch die momentan aktuelle Kernel Version 3.12.y verwenden laden wir noch die aktuelle Version unter Angabe der Versionsnummern via Git runter (ca. 900 MB).
1 2 3 4 5 6 |
cd ~/src mkdir -p linux-3.12.y cd linux-3.12.y git init git fetch git://github.com/raspberrypi/linux.git rpi-3.12.y:refs/remotes/origin/rpi-3.12.y git checkout refs/remotes/origin/rpi-3.12.y |
Aufräumen
Nun haben wir die Build Tools und den notwendigen Quellcode heruntergeladen und starten mit ein Aufräumen. make mrproper räumt uns erstmal alle Konfigurationen und erstellten Files auf sodass wir „sauber“ starten können.
1 2 |
cd ~/src/linux-3.12.y make mrproper |
Kernel Konfiguration
Nach dem Aufräumen können wir durch die Konfiguration bestimmen welche Komponente unser Kernel enthält, da wir üblicherweise der Einfachheit halber immer den Umfang des Standard Raspian Kernels mit unseren zusätzlich benötigten Komponenten kompilieren möchte kopieren wir einfach die vorhandene Kernel Konfiguration von unserem Raspberry Pi oder verwenden später „bcmrpi_defconfig“ und sparen uns das kopieren der Konfiguration. Wir melden uns hierzu vie SSH auf dem RasPi und erstellen einen Dump der Konfiguration. Im Normalfall hat die Datei den Namen „.config“ da in meinem Pi Home aber zufällig schon ein Ordner „.config“ liegt habe ich die Ausgabedatei in „.RasPiConfig“ umgeleitet.
1 |
sudo zcat /proc/config.gz > .RasPiConfig |
Die Datei „.RasPiConfig“ muss nun vom Raspberry Pi in das Verzeichnis „~/src/linux/“ auf unserem Ubuntu System. Am einfachsten erledigen wir das via SCP, hierzu müssen wir auf unserem Ubuntu System allerdings noch SSH installieren und das System einmal neu starten. Das Terminal auf dem Ubuntu Desktop geht übrigens mit dem Shortcut „STRG+ALT+T“ oder über das Start Menu auf.
1 2 |
sudo apt-get install openssh-server sudo reboot |
Wenn der SSH-Server installiert wurde führen wir auf unserem RasPi folgenden Befehl aus um die Konfiguration zum Ubuntu zu übertragen. Mein Ubuntu hat die IP-Adresse 192.168.178.32 und ich habe den Benutzer raspberrytips bei der Installation angelegt. Diese Infos müsst ihr im Befehl unten natürlich durch eure IP-Adresse (ifconfig im Ubuntu Terminal eingeben um diese anzuzeigen) und euren Benutzer, den ihr bei der Installation erstellt habt, austauschen.
1 2 |
cd ~ scp -rv .RasPiConfig [email protected]:/home/raspberrytips/src/linux/.config |
Da unsere Konfigurationsdatei vom RasPi vermutlich von einer älteren Kernel Version stammt (kann am RasPi via uname -a überprüft werden) müssen wir diese noch auf die aktuelle Version anpassen. Das erledigt make für uns. Mit dem Parameter „olddefconfig“ verwendet der Kompiler died kopierte .config Datei. Wer das nicht möchte kann auf diese Schritte verzichten und eine neue Konfiguration mit „menuconfig“ grafisch durchführen oder nachträglich via „menuconfig“ zusätzliche Komponenten hinzufügen. Als weitere Alternative kann auch eine Standard Konfiguration via Parameter „bcmrpi_defconfig“ erstellt und dann via „menuconfig“ angepasst werden.
1 2 |
cd ~/src/linux-3.12.y make ARCH=arm CROSS_COMPILE=~/src/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- olddefconfig |
Für meinen Touch Screen aus dem Google Calendar Projekt habe ich zum Beispiel nach Verwendung des Parameters „menuconfig“ im der grafischen Konfiguration unter „Device Drivers->Input Device Support->TouchScreens>USB Touchscreen Driver“ die kompletten Treiber ausgewählt und die Konfiguration gespeichert. Wer Probleme mit der Übernahme der Konfiguration hat kann evtl. noch mit der Option „silentoldconfig“ sein Glück versuchen oder doch via „bcmrpi_defconfig“ die Standard Konfiguration als Basis verwenden.
Kernel Kompilieren
Nachdem wir nun die Konfiguration erstellt haben können wir den Kernel kompilieren. Abhängig von der Power der VM dauert das gerne mal eine Stunde, wer der VM mehrere CPUs zugewiesen hat kann den Vorgang durch das Ergänzen von „-j <Anzahl CPUs>“ beschleunigen (Parallelisierung), ich habe 4 CPUs und daher 4 angegeben. Das Erstellen dauert bei mir nur circa 20-30 Minuten.
1 2 3 4 5 |
cd ~/src/linux-3.12.y/ make -j 4 ARCH=arm CROSS_COMPILE=~/src/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- mkdir /tmp/modules make ARCH=arm CROSS_COMPILE=~/src/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- INSTALL_MOD_PATH=/tmp/modules modules_install |
Die zweite Zeile erstellt uns den Kernel via make, dieser landet dann in „~/src/linux-3.12.y/arch/arm/boot/Image“ . Da wir die kompilierten Kernel Module ebenfalls benötigen sammeln wir diese nach dem Erstellen unter /tmp/modules ein.
Kernel Installieren
Nachdem wir den Kernel erstellt und die Module eingesammelt haben können wir diesen auf dem Raspberry Pi installieren. Erstellt bitte vorher zur Sicherheit via Win32 Disk Imager ein komplettes Image Backup eures Systems. Der Kernel und die Modules müssen nun vom Ubuntu System auf den laufenden RasPi übertragen werden, wer die Systeme im selben Netz betreibt kann das via rsync tun (die Ubuntu VM muss dazu im Netz gebridged werden). Wer die Möglichkeit nicht hat muss den umständlichen Weg über den Virtual Box Geteilten Ordner oder ähnliche Hilfsmittel gehen. Um Daten via Rsync kopieren zu können benötigen wir zunächst das Root Passwort unseres RasPi. Da uns dieses nicht bekannt ist melden wir uns wie gewohnt über SSH als pi an und führen folgende Befehle zum Einstellen eines Passwortes aus.
1 2 |
sudo su - passwd |
Dann öffnen wir auf unserem Ubuntu System wieder ein Terminal und führen „rsync“ aus. Rsync kopiert den Kernel und die Module über das Netzwerk zum Raspberry Pi. Da ich eine Fritzbox habe ist mein RasPi immer mit dem Namen „raspberrypi“ im Heimnetzwerk zu erreichen, falls ihr das nicht habt benötigt ihr die IP-Adresse eures RasPi. Diese könnt ihr über den Befehl „ifconfig“ am RasPi herausfinden und im Befehl unten den Hostname „raspberrypi“ mit der IP-Adresse, ersetzen.
1 2 3 |
cd ~/src/linux-3.12.y rsync arch/arm/boot/Image root@raspberrypi:/boot/kernel_3.12.y.img rsync -avz /tmp/modules/ root@raspberrypi:/ |
Da jetzt die Module und die Kernel File auf dem Raspberry Pi vorhanden sind muss er noch wissen das er den neuen Kernel verwenden soll bzw. wo dieser liegt . Um den RasPi mit dem neuen Kernel zu starten muss die Datei /boot/config.txt angepasst werden.
1 |
sudo nano /boot/config.txt |
Dort editieren oder erstellen wir folgenden Eintrag und speicher die Datei mit „STRG+X“ und „Y“
1 |
kernel=kernel-3.12.y.img |
Da vermutlich die Firmware auf eurem RasPi auch veraltet ist sollte diese noch aktualisiert werden.
1 2 |
sudo rpi-update sudo reboot |
Wenn alles geklappt hat bootet dar RasPi mit dem neuen Kernel, das können wir über das Kommando „uname -a“ kontrollieren. Der Befehl gibt euch die Version und den Zeitpunkt der Erstellung aus. Falls etwas nicht klappt könnt ihr durch das Zurücksetzen eurer Anpassungen in der config.txt den alten Kernel verwenden.