2018/8/13

如何編譯 RPi kernel


以下紀錄如何編譯 Raspberry Pi Kernel


查詢 RPi 上安裝的 kernel 版本號碼


$ uname -a
Linux raspberrypi 4.14.34-v7+ #1110 SMP Mon Apr 16 15:18:51 BST 2018 armv7l GNU/Linux

找一台 x86 linux 電腦,以 cross-compile 方式重新編譯 RPi kernel,雖然可以直接在 RPi 編譯,但速度會很慢,因此還是選擇用 cross-compile 方式編譯。


RPi kernel 存放在 git repository 裡面


cd
mkdir raspberry
cd raspberry

確認有安裝 git, 並更新一些套件(需要安裝nss 相關和更新curl)


yum update git
yum update nss nss-util nspr
yum update curl



下載 kernel source


git clone https://github.com/raspberrypi/linux.git

下載 cross-compilers tools


git clone https://github.com/raspberrypi/tools

使用 tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian,設定環境變數 CCPREFIX


export CCPREFIX=/root/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-

${CCPREFIX}gcc -v

在 GitHub 上面的 kernel 有許多不同的 branch,請選擇你想要使用的 branch 來使用。


cd linux
git branch -a

目前版本為


* rpi-4.14.y
  remotes/origin/HEAD -> origin/rpi-4.14.y



由 RPi 取得目前的 kernel 設定,因為 RPi 上沒有 config.gz,用以下指令產生 /proc/config.gz


sudo modprobe configs

將 /proc/config.gz 複製到要編譯 kernel 的機器上的 /root/raspberry/linux 目錄中


cd /root/raspberry/linux
scp pi@192.168.1.15:/proc/config.gz . 
gunzip -c config.gz > .config

用以下指令產生新的 kernel configuration,如果遇到新的功能,就會問你要不要支援


ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig

reset .config 裡面的 debug symbols,Enable the ‘DEBUGINFO’ option and don’t enable the DEBUGINFO_REDUCED option.


grep -v DEBUG_INFO < .config > newconfig 
mv newconfig .config 
ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig



以 menuconfig 微調設定,調整 kernel modules support。


make -j4 ARCH=arm CROSS_COMPILE=${CCPREFIX} menuconfig



編譯 kernel,如果是 multi-core cpu,可加上 -j<amount of cores> 加速編譯


ARCH=arm CROSS_COMPILE=${CCPREFIX} make

如果編譯過程中,有發生 compile error,打開錯誤的 source code,在發生錯誤的 function 前面加上


#pragma GCC optimize("-g0")

編譯完成後,必須檢查 symbols,用以下指令,查看 initutsns.name.release 的值


${CCPREFIX}gdb vmlinux 
print init_uts_ns.name.release

確認 kernel 有包含 symbols 後,將 RPi 需要的 modules 放在 modules 目錄


ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=../modules make modules_install



建立 uncompressed kernel image,並放到 RPi 的 tmp 目錄中


cd <raspberry pi downloads>/tools/mkimage 
./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
scp kernel.img pi@raspberrypi:/tmp

將 modules 目錄,壓縮後,傳送到 RPi 的 tmp 目錄中


cd <raspberry pi downloads>/tools/modules 
tar czf modules.tgz * 
scp modules.tgz pi@raspberrypi:/tmp

最後 ssh 到 RPi,安裝新的 kernel 及 modules


cd / 
sudo mv /tmp/kernel.img /boot/ 
sudo tar xzf /tmp/modules.tgz 
rm /tmp/modules.tgz

reboot RPi


sudo shutdown -r now



以 uname 檢查是否使用了新版的 kernel


uname -r



如果要 debug kernel ,可參考 Preparing Raspberry PI for JTAG Debugging 的說明


References


https://sysprogs.com/VisualKernel/tutorials/raspberry/buildkernel/


https://blog.gtwang.org/iot/raspberry-pi-compile-linux-kernel/


https://www.raspberrypi.com.tw/528/compiling-kernel-for-raspberry-pi/


https://coldnew.github.io/f5873b3f/

沒有留言:

張貼留言