Ubuntu 16.04 (x64)下从源代码为Raspberry Pi Zero W编译实时内核

首先参考 Ubuntu 16.04 (x64)树莓派B+ (Raspberry Pi B+)源代码编译 保证能够成功编译标准内核的源代码,然后切换到实时内核分支,并执行如下编译命令:

$ export PATH=$PATH:~/rpi/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

$ cd ~/rpi/rpi-linux/
 
$ git checkout rpi-4.14.y-rt

$ git reset --hard

$ KERNEL=kernel
 
$ make clean

$ make mrproper

$ rm -rf .config

#调整内核切换频率,增加实时性
$ sed -i '$a\CONFIG_HZ_1000=y' arch/arm/configs/bcmrpi_defconfig

#Raspberry Pi Zero W的CPU是BCM2835
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs -j8
 
$ mkdir rt_kernel
 
$ make modules_install ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=./rt_kernel -j8

$ make dtbs_install ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_DTBS_PATH=./rt_kernel -j8

$ ./scripts/mkknlimg ./arch/arm/boot/zImage ./rt_kernel/kernel.img
安装编译好的内核

Ubuntu下面,SD卡会自动挂载,默认挂载到了/media/目录下面,如果是使用NOOBS安装的话,系统目录是固定的,执行如下命令拷贝到目标SD卡上面

$ cd ~/rpi/rpi-linux

#备份需要修改的文件
$ mv /media/`whoami`/boot/kernel.img /media/`whoami`/boot/kernel_old.img

$ mv /media/`whoami`/boot/overlays /media/`whoami`/boot/overlays.old

#拷贝内核
$ cp rt_kernel/kernel.img /media/`whoami`/boot/kernel.img

#拷贝硬件配置
$ cp rt_kernel/bcm2835*.dtb /media/`whoami`/boot/

#拷贝overlays
$ cp -r rt_kernel/overlays /media/`whoami`/boot/

#拷贝内核模块
$ sudo cp -r rt_kernel/lib/modules/* /media/`whoami`/rootfs/lib/modules/

#卸载设备
$ sudo umount -A -R -a /media/`whoami`/boot
借助编译环境,单独编译内核模块

有时,我们需要单独编译新下载的内核驱动,这个时候,就可以使用如下的方式进行单独内核模块的编译。

下面,我们以ASIX AX88772系列的USB有线网卡驱动的编译为例:

$ export PATH=$PATH:~/rpi/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

$ cd ~/rpi/rpi-linux

# wget https://www.mobibrw.com/wp-content/uploads/2018/09/AX88772C_772B_772A_760_772_178_LINUX_DRIVER_v4.22.0_Source.tar.bz2

$ wget http://www.asix.com.tw/FrootAttach/driver/AX88772C_772B_772A_760_772_178_LINUX_DRIVER_v4.22.0_Source.tar.bz2

$ tar xvf AX88772C_772B_772A_760_772_178_LINUX_DRIVER_v4.22.0_Source.tar.bz2

$ cd AX88772C_772B_772A_760_772_178_LINUX_DRIVER_v4.22.0_Source

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C ../ M=`pwd`

#当前目录下就会生成 asix.ko 这个内核模块,生成的内核模块拷贝到指定的目录即可正常工作
解决已知问题

使用上面的命令安装完成内核后,目前(2018.09.26)遇到的问题为,当插入ASIX AX88772系列的USB有线网卡之后,会导致内核崩溃,启动失败。

设备信息如下:

Bus 001 Device 034: ID 0b95:7720 ASIX Electronics Corp. AX88772

初步怀疑是USB设备的驱动依赖关系不正确导致内核崩溃。

目前的临时解决方法为要求设备启动时候优先加载USB设备相关的驱动,而不是等到网卡插入的时候再去加载。

也就是在/boot/config.txt文件尾部新增加一行dtoverlay=dwc2。这段代码本来是为树莓派通过USB访问网络的虚拟网卡准备的(是的,你没看错,树莓派本身可以不借助网卡直接通过USB接口跟电脑共享方式上网,不过需要设置一堆东西,最简单的还是外接真正的USB网卡)。我们加载这个模块,但是并不使用这个功能,造成的结果就是重新调整了模块加载顺序,规避了后续的问题。

$ sed -i '$a\\ndtoverlay=dwc2' /media/`whoami`/boot/config.txt

上述修改后,依旧存在动态插拔网卡,设备会重启的问题,不过已经不影响正常使用。

参考链接