Try   HackMD

在 WSL2 上 Compile Raspberry Pi 4B 的 Kernel

Topic: Modified OV5647 CMOS Camera

Ref1: Raspberry Pi Documentation
Ref2: Raspberry Pi GitHub
Ref3: Applying Patches To The Linux Kernel

Cross-Compiling the Kernel

安裝必要的編譯套件 && Toolchain

所需的依賴項

$ sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev -y

Toolchain

32 位元 Kernel

$ sudo apt install crossbuild-essential-armhf -y

64 位元 Kernel

$ sudo apt install crossbuild-essential-arm64 -y

下載 kernel source

$ cd < path > $ git clone git@github.com:raspberrypi/linux.git -b < branch name >

Build Source

32 位元 configs

For Raspberry Pi 1, Zero and Zero W, and Raspberry Pi Compute Module 1:

$ cd linux $ KERNEL=kernel $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig

For Raspberry Pi 2, 3, 3+ and Zero 2 W, and Raspberry Pi Compute Modules 3 and 3+:

$ cd linux $ KERNEL=kernel7 $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

For Raspberry Pi 4 and 400, and Raspberry Pi Compute Module 4:

$ cd linux $ KERNEL=kernel7l $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig

64 位元 configs

For Raspberry Pi 3, 3+, 4, 400 and Zero 2 W, and Raspberry Pi Compute Modules 3, 3+ and 4:

$ cd linux $ KERNEL=kernel8 $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig

For Raspberry Pi 5:

$ cd linux $ KERNEL=kernel_2712 $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2712_defconfig
Note:

標準的 bcm2711_defconfig 基於的核心 (kernel8.img) 也可以在 Raspberry Pi 5 上使用。不過為了獲得最佳效能,您應該使用 kernel_2712.img,但對於需要 4KB 頁面大小的情況,則應使用 kernel8.img (kernel=kernel8.img)

Customising the Kernel Version Using LOCALVERSION

除了核心配置變更之外,您可能還想調整 LOCALVERSION 以確保新核心不會收到與上游核心相同的版本字串。 這不僅表明您在 uname 的輸出中運行自己的內核,也確保 /lib/modules 中的現有模組不會被覆蓋。

為此,請更改 .config 中的以下行:

CONFIG_LOCALVERSION="-v8-Edward_Kernel"

Build with Configs

For all 32-bit Builds

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

For all 64-bit Builds

Note:

Note the difference between Image target between 32 and 64-bit.

$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs

Installing Kernel to SDCard

Ref4: Windows Mount Linux Partition in WSL 掛載 存取 Linux USB SD Card 隨身碟 EXT4
Ref5: 編譯 替換 Windows WSL Kernel 方法 步驟

使用 USBIPD 來掛載 USB Drive/ SD Card

列出目前 USB bus 狀態

PS C:\Users\EdwardWu> usbipd list Connected: BUSID VID:PID DEVICE STATE 1-3 13d3:56ff Integrated Camera Not shared 2-2 03f0:028e USB 輸入裝置 Not shared 2-3 27c6:5503 Goodix fingerprint Not shared 2-4 8087:0032 Intel(R) Wireless Bluetooth(R) Not shared 3-1 0b95:1790 ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter #3 Not shared 3-3 05e3:0749 USB Mass Storage Device Not shared

Allow Share USB bus 3-3

PS C:\Users\EdwardWu> usbipd bind -b 3-3 PS C:\Users\EdwardWu> usbipd list Connected: BUSID VID:PID DEVICE STATE 1-3 13d3:56ff Integrated Camera Not shared 2-1 2109:2817 Generic USB Hub Not shared 2-2 03f0:028e USB 輸入裝置 Not shared 2-3 27c6:5503 Goodix fingerprint Not shared 2-4 8087:0032 Intel(R) Wireless Bluetooth(R) Not shared 3-1 0b95:1790 ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter #3 Not shared 3-3 05e3:0749 USB Mass Storage Device Shared

向 WSL 轉送 usb bus 3-3 device

PS C:\Users\EdwardWu> usbipd attach --wsl --busid 3-3 usbipd: info: Using WSL distribution 'Ubuntu-22.04' to attach; the device will be available in all WSL 2 distributions. usbipd: info: Using IP address 172.19.112.1 to reach the host.

關閉 WSL

PS C:\Users\EdwardWu> wsl --shutdown

列出 USB 裝置

PS C:\Users\EdwardWu> usbipd list Connected: BUSID VID:PID DEVICE STATE 1-3 13d3:56ff Integrated Camera Not shared 2-2 03f0:028e USB 輸入裝置 Not shared 2-3 27c6:5503 Goodix fingerprint Not shared 2-4 8087:0032 Intel(R) Wireless Bluetooth(R) Not shared 3-1 0b95:1790 ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter #3 Not shared 3-3 05e3:0749 USB Mass Storage Device Attached

移除 USB bus 3-3

PS C:\Users\EdwardWu> usbipd detach --busid 3-3

將 Raspberry Pi 4B 的 SDCard 分割區掛載到資料夾

$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 389.8M 1 disk sdb 8:16 0 3G 0 disk [SWAP] sdc 8:32 0 256G 0 disk /mnt/wslg/distro /
$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 389.8M 1 disk sdb 8:16 0 3G 0 disk [SWAP] sdc 8:32 0 256G 0 disk /mnt/wslg/distro / sdd 8:48 1 0B 0 disk sde 8:64 1 59.5G 0 disk ├─sde1 8:65 1 512M 0 part └─sde2 8:66 1 59G 0 part

掛載分割區

您應該根據您的設定適當調整磁碟代號,例如,如果您的 SD 卡顯示為 而 /dev/sdc 不是 /dev/sdb。

$ sudo mount /dev/sde1 ../mnt/fat32 $ sudo mount /dev/sde2 ../mnt/ext4
$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 389.8M 1 disk sdb 8:16 0 3G 0 disk [SWAP] sdc 8:32 0 256G 0 disk /mnt/wslg/distro / sdd 8:48 1 0B 0 disk sde 8:64 1 59.5G 0 disk ├─sde1 8:65 1 512M 0 part /home/edwardwu/rpi-kernel/mnt/fat32 └─sde2 8:66 1 59G 0 part /home/edwardwu/rpi-kernel/mnt/ext4

Install the Kernel Modules

$ sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=../mnt/ext4 modules_install

備份原先的 Kernel

$ sudo cp ../mnt/fat32/kernel8.img ../mnt/fat32/kernel8-backup.img

Copy Kernel & Device Tree blobs

$ sudo cp arch/arm64/boot/Image ../mnt/fat32/kernel8.img $ sudo cp arch/arm64/boot/dts/broadcom/*.dtb ../mnt/fat32/ $ sudo cp arch/arm64/boot/dts/overlays/*.dtb* ../mnt/fat32/overlays/ $ sudo cp arch/arm64/boot/dts/overlays/README ../mnt/fat32/overlays/

移除掛載分割區

$ sudo umount ../mnt/fat32 $ sudo umount ../mnt/ext4

測試鏡頭

libcamera-hello

拍照

libcamera-jpeg -o test.jpg

Build Script

#!/bin/bash # 定義 kernel tree 的路徑 LINUX_DIR="/home/edwardwu/rpi-kernel/linux" echo "選擇要編譯的 Raspberry Pi 版本:" echo "1. Raspberry Pi 4" echo "2. Raspberry Pi 5" read -p "請輸入選擇 (1 或 2): " choice # 提問是否需要執行 make clean read -p "是否需要執行 make clean? (y/n): " clean_choice start_time=$(date +%s) # 記錄開始時間 case $choice in 1) echo "正在編譯 Raspberry Pi 4 的 Kernel..." cd $LINUX_DIR if [ "$clean_choice" == "y" ]; then echo "正在執行 make clean..." make clean -j$(nproc) fi KERNEL=kernel8 #CONFIG_LOCALVERSION="-v8-Edward_Kernel" make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig sed -i 's/CONFIG_LOCALVERSION="-v8"/CONFIG_LOCALVERSION="-v8-Edward_Kernel"/' .config make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs | tee ../build.log cd - ;; 2) echo "正在編譯 Raspberry Pi 5 的 Kernel..." cd $LINUX_DIR if [ "$clean_choice" == "y" ]; then echo "正在執行 make clean..." make clean -j$(nproc) fi KERNEL=kernel_2712 #CONFIG_LOCALVERSION="-v2712-Edward_Kernel" make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2712_defconfig sed -i 's/CONFIG_LOCALVERSION="-v8-16k"/CONFIG_LOCALVERSION="-v2712-Edward_Kernel"/' .config make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs cd - ;; *) echo "無效的選擇" ;; esac end_time=$(date +%s) # 記錄結束時間 elapsed=$((end_time - start_time)) # 計算總耗時 minutes=$((elapsed / 60)) seconds=$((elapsed % 60)) echo "編譯完成,總耗時: ${minutes}分鐘 ${seconds}秒"

Install Script

#!/bin/bash :<<comment Reference: https://hackmd.io/9f2GysWvR5eA1Y_t56Vtmw?view#Installing-Kernel-to-SDCard comment # 定義掛載點目錄 MOUNT_POINT="/home/edwardwu/rpi-kernel/mnt" # 定義 kernel tree 的路徑 LINUX_DIR="/home/edwardwu/rpi-kernel/linux" # 顯示選單 echo "選擇要刷入的 Raspberry Pi 版本:" echo "1. Raspberry Pi 4" echo "2. Raspberry Pi 5" read -p "請輸入選擇 (1 或 2): " choice # 根據選擇設置 kernel 和 device tree blobs 的目標路徑 if [ "$choice" -eq 1 ]; then KERNEL_IMG="kernel8.img" DEVICE="Raspberry Pi 4" elif [ "$choice" -eq 2 ]; then KERNEL_IMG="kernel_2712.img" DEVICE="Raspberry Pi 5" else echo "無效的選擇,請輸入 1 或 2." exit 1 fi echo "檢查 SD 卡是否已掛載到 WSL..." lsblk # 檢查是否有可掛載的 SD 卡分割區 if lsblk | grep -q 'sde'; then echo "找到 SD 卡分割區,準備掛載..." else echo "未找到 SD 卡分割區,請確認 SD 卡已正確插入並重試。" exit 1 fi # 建立掛載目錄 # mkdir -p $MOUNT_POINT/fat32 # mkdir -p $MOUNT_POINT/ext4 # 掛載分割區 echo "掛載 FAT32 分割區到 $MOUNT_POINT/fat32" sudo mount /dev/sde1 $MOUNT_POINT/fat32 echo "掛載 EXT4 分割區到 $MOUNT_POINT/ext4" sudo mount /dev/sde2 $MOUNT_POINT/ext4 # 檢查掛載是否成功 mount | grep sde start_time=$(date +%s) # 記錄開始時間 # 安裝 kernel 模組 echo "安裝 kernel 模組..." cd $LINUX_DIR pwd sudo env PATH="$PATH" make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=$MOUNT_POINT/ext4 modules_install cd $LINUX_DIR/../ pwd # 複製 Kernel 和 Device Tree blobs echo "複製 Kernel 和 Device Tree blobs..." sudo cp $LINUX_DIR/arch/arm64/boot/Image $MOUNT_POINT/fat32/$KERNEL_IMG sudo cp $LINUX_DIR/arch/arm64/boot/dts/broadcom/*.dtb $MOUNT_POINT/fat32/ sudo cp $LINUX_DIR/arch/arm64/boot/dts/overlays/*.dtb* $MOUNT_POINT/fat32/overlays/ sudo cp $LINUX_DIR/arch/arm64/boot/dts/overlays/README $MOUNT_POINT/fat32/overlays/ # 移除掛載 echo "移除掛載分割區..." sudo umount $MOUNT_POINT/fat32 sudo umount $MOUNT_POINT/ext4 # 計算總耗時 end_time=$(date +%s) # 記錄結束時間 elapsed=$((end_time - start_time)) # 計算總耗時 minutes=$((elapsed / 60)) seconds=$((elapsed % 60)) echo "刷寫完畢,總耗時: ${minutes}分鐘 ${seconds}秒" # 輸出完成訊息 echo "已經完成 $DEVICE kernel 的刷寫"

Finally !!