Appearance
5. Kernel Compilen
Linux Kernel
Der Linux kernel wird vom Kernel Team über git
verwaltet. Versionen und das Repository sind unter https://www.kernel.org/ ersichtlich.
Für das Raspberry Pi existiert ein eigenes Git Repository https://github.com/raspberrypi/linux, in welchem die Raspberry Pi foundation ihren eigenen vom Vanilla abgeleiteten Kernel zur Verfügung stellt. Allgemein gilt: weil der Kernel unter GPL lizenziert ist, muss der Source Code des Kernels inklusive allen Änderungen für User unter der GPL verfügbar sein.
Für unsere Versuche basieren wir auf dem LTS Release Branch rpi-6.6.y
.
Frage
Welchen Kernel haben wir mit Buildroot verwendet? Kann dies im laufenden Betrieb des Targets ermittelt werden?
Toolchain aufsetzen
In Buildroot haben wir den Kernel bereits mit der Toolchain (von Buildroot heruntergeladen) kompiliert und auf die Bootpartition deployt.
Produkte des Kernels sind:
- self extracting Kernel Image
zImage
(je nach Bootloader z.T.uImage
) - Kernelmodule welche nicht statisch gelinkt sind (
*.ko
) - Device Tree Binding
.dtb
für das Raspberry Pi - Device Tree Overlays für peripherie
*.dto
.
Um den Kernel für das Target kompilieren zu können, hat Buildroot für uns die passende Toolchain verwendet.
Wir laden nun einen aktuellen Release der arm
Toolchain für unser Hostsystem und das Linux Arm 32 Target herunter.
Besuchen Sie hierfür https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads und suchen Sie die passende Toolchain aus. Welche wird wohl am besten zu unserem Target passen?
Auswahl für die Versuche
Verwenden Sie arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz
.
Entpacken Sie die Toolchain im Downloads folder und erstellen Sie einen Symbolischen link mit ln
auf den Folder
Wechseln zuerst Sie in das Verzeichnis ~/embedded-linux
. Validieren Sie, dass die Toolchain arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz
im Ordner ~/Downloads
heruntergeladen worden ist.
bash
# symbolic link auf die toolchain im working directory
ln -s ~/Downloads/<hier-das-toolchain-directory>
# ls -al sollte nun einen symbolischen link auf die toolchain zeigen
ls -al
Probleme beim Kompilieren
Es kann sein, dass mit einer sehr aktuellen Toolchain Probleme beim Compilen entstehen, wie z.B.
drivers/media/i2c/msp3400-driver.c:421:17: internal compiler error: Illegal instruction
421 | msp3400c_set_carrier(client, MSP_CARRIER(10.7),
Hier ein Beispiel eines Fehlers mit gcc-arm-11.2-2022.02-x86_64-arm-none-linux-gnueabihf
. https://community.arm.com/support-forums/f/compilers-and-libraries-forum/52623/gcc-11-2-arm-none-eabi-internal-compiler-error-illegal-instruction/176970
Environment Variablen setzen
Für das Compilen müssen noch folgende Variablen gesetzt sein: ARCH=arm
und CROSS_COMPILE
soll den ganzen Prefix von ARM-gcc
inklusive absolutem Pfad beinhalten.
In unserem Fall wäre das /home/$USER/embedded-linux/toolchain/bin/arm-none-linux-gnueabihf-
. Wichtig ist das -
am Ende des Pfades.
Mit export können die Variablen ins environment aufgenommen werden. Führen Sie also im Terminal aus:
export CROSS_COMPILE=/home/$USER/embedded-linux/toolchain/bin/arm-none-linux-gnueabihf-
und export ARCH=arm
.
Kontrollieren Sie ob die Pfade stimmen mit
bash
echo $CROSS_COMPILE
echo $ARCH
Achtung: neues Terminal
Sobald Sie das Terminal verlassen gehen die Variablen verloren!
Sie können dieses Setup allerdings auch in einem Shell Script (z.B. envsetup.sh
) durchführen. Damit die Änderungen am Environment auch ausserhalb des Scripts übernommen werden, müssen Sie dieses allerdings mit source
aufrufen.
bash
#!/usr/bin/bash
# file envsetup.sh
export ARCH=arm
export CROSS_COMPILE=<toolchain-prefix>
bash
# env aufsetzen mit
source envsetup.sh
# alternativ mit
. envsetup.sh
Setup Testen
Falls alles geklappt hat wird dieser Command ARM GCC aufrufen:
bash
${CROSS_COMPILE}gcc -v
Kernel Sources via git herunterladen
Wir laden die Kernel Sources von dem Raspberry Pi git repository herunter. Mit git clone
können wir entweder den ganzen Tree mit der ganzen Kernel History herunterladen oder alternativ nur den aktuellen branch verwenden:
Wechseln Sie ins Verzeichnis ~/embedded-linux
. Verwenden Sie für <branch>
rpi-6.6.y
bash
# linux-rpi: lokales verzeichnis
git clone --depth 1 --single-branch --branch <branch> https://github.com/raspberrypi/linux.git linux-rpi
Kernel kompilieren
Ein typischer Vorgang für das kompilieren und deployen eines Kernels sieht so aus:
- Kernel herunterladen
- Toolchain einreichten
- ggf. Kernel patchen
- Board
defconfig
nach.config
kopieren. - Menuconfig ausführen und Treiber auswählen mit
make menuconfig
make zImage
make modules
make dtbs
zImage
unddtb
kopieren und Bootloader konfigurieren für neues image..ko
modules ins RFS kopieren unter entsprechendem Folder.- DT Overlays in die Boot Partition kopieren und Bootloader konfigurieren.
Menuconfig
Wechseln Sie in das Verzeichnis des Kernel Sources embedded-linux/linux-rpi
.
Zuerst laden wir die defconfig
für unseren SoC:
bash
make bcm2711_defconfig
Installieren Sie noch folgende Pakete:
sudo apt install libmpc-dev \
flex bison openssl libssl-dev
Für den Moment patchen wir den Kernel nicht und selektieren neu IIO
Treiber und linken dies statisch dem Kernel hinzu (in menuconfig
mit [*]
).
Führen Sie make menuconfig
aus um die Menuconfig zu starten.
XZ komprimierte Module
Suchen Sie in der Config nach der Option MODULE_COMPRESS_XZ
und setzen Sie diese auf n
.
Wechseln Sie ins Verzeichnis des Kernels und suchen Sie mit ?
nach IIO und aktivieren Sie die Treiber für den Pressure Sensor und Humidity Sensor, den Sie hier finden https://pinout.xyz/pinout/sense_hat. Verwenden Sie wieder ?
in der menuconfig
um die Sensormodelle zu finden.
Verlassen Sie das Menü und speichern Sie die Config.
Compile
Kompilieren Sie den Kernel mit make zImage dtbs modules
.
Das kompilieren wird eine Zeit dauern. Als Referenz auf einem 16 Thread Ryzen CPU dauert es ca 10 Minuten mit 15 Threads.
Mit -j15
können so bei make
mehrere Threads verwendet werden. Um die Zeit zu messen können Sie mit time
den make
Command aufrufen:
bash
# -jX: X am besten Anzahl Threads der CPU - 1
time make -j15 zImage dtbs modules
Deploy
Kopieren Sie die Produkte des Kernels an die entsprechenden Orte auf dem Target
Source | Partition | Destination | |
---|---|---|---|
arch/arm/boot/zImage | Kernel | Boot | zImage |
arch/arm/boot/dts/broadcom/bcm2711-rpi-4-b.dtb | Device Tree Blob | Boot | bcm2711-rpi-4-b.dtb |
arch/arm/boot/dts/overlays/*.dtb* | Overlay Tree | Boot | overlays |
*.ko | Kernelmodule | RFS | /lib/modules/** |
Für die Kernelmodule *.ko
verwenden wir make
, da auch Unterverzeichnissen erstellt werden:
bash
# Pfad für rootfs ggf. anpassen
sudo make ARCH=arm INSTALL_MOD_PATH=/media/$USER/rootfs/ modules_install
Nach dem kopieren können Sie die SD-Karte unmounten und das Raspberry Pi neu starten. Kontrollieren Sie mit cat /proc/version
, dass Sie den neuen Kernel richtig installiert haben.