RaspberryPi4B树莓派4B,Linux5.4本地编译驱
从下载Linux源码到编译更新系统,以及安装自己的驱动,整个流程全在树莓派上完成,不需要借助PC机。
本人的树莓派Linux版本是5.4.51-v7l+,最新Linux版本是5.4.61-v7l+,因此直接下载GitHub的源码编译更新系统。
安装更新之前 更新系统之后主要参考官方文档:Kernel building
在Raspberry Pi上,首先安装最新版本的Raspberry Pi OS。 然后启动树莓派,然后登录,确保能联网更新软件。
准备工作
首先安装Git和构建依赖项
sudo apt install git bc bison flex libssl-dev make
在树莓派上新建一个文件夹来存储Linux源码,例如:/home/pi/work
最好确保是否要使用最新的Linux版本,请访问github并检查最新的版本是什么:
查看最新的版本号如果想要下载最新的源码,在终端中输入:
获取最新源码git clone --depth=1 https://github.com/raspberrypi/linux
选择其他版本的Linux源码
上面的git clone命令省略--depth = 1将下载整个存储库,包括所有分支的完整历史记录,但这会花费更长的时间并占用更多的存储空间。
要下载其他分支,请使用--branch选项:(其中<branch>是要下载的分支的名称)
git clone --depth=1 --branch <branch> https://github.com/raspberrypi/linux
请参阅原始GitHub存储库以获取有关可用分支的信息。
至此,你已经获得了Linux源码。
内核配置
一般根据不同树莓派版本使用默认配置
首先,根据您的Raspberry Pi版本,通过运行以下命令来准备默认配置:
Raspberry Pi 1,Pi Zero,Pi Zero W和Compute Module默认构建配置
cd linux
KERNEL=kernel
make bcmrpi_defconfig
Raspberry Pi 2,Pi 3,Pi 3+和Compute Module 3默认构建配置
cd linux
KERNEL=kernel7
make bcm2709_defconfig
Raspberry Pi 4默认构建配置
树莓派4B的默认配置cd linux
KERNEL=kernel7l # 请用复制粘贴的方式,这里是的l是L的小写
make bcm2711_defconfig
Linux源码编译
根据使用的Pi型号,此步骤可能需要很长时间:
make -j4 zImage modules dtbs
注意:在Raspberry Pi 2/3/4上,-j4标志在所有四个内核之间分配工作,加快了编译速度。
更新系统内核(可选)
安装内核,模块和设备树;(可选)
sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm/boot/zImage /boot/$KERNEL.img
然后重新启动系统。
如果内核更新失败(系统还是之前的版本)或者想保留之前的内核(每次启动后都可以更改内核版本):
回到linux目录:
sudo cp arch/arm/boot/zImage /boot/kernel-my.img # 将新内核命名为kernel-my.img
修改config.txt,请用管理员身份运行:
sudo nano /boot/config.txt # 修改启动配置文件
在config.txt文件中添加一行:
修改启动配置文件kernel=kernel-my.img
然后,重启系统。
通过dmsg命令查看启动信息:
Linux启动信息测试驱动编写
写一个简单的驱动文件example.c:
# example.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/uaccess.h>
int __init example_init(void) //真实入口
{
printk("init the module example\n"); // 内核的打印函数 和printf类似
return 0;
}
void __exit example_exit(void)
{
printk("the example module is uninstalled\n"); // 内核的打印函数 和printf类似
}
module_init(example_init); //入口 内核加载该驱动的时候 这个宏会被调用
module_exit(example_exit);
MODULE_LICENSE("GPL");
写一个简单的Makefile:
# Makefile
ifneq ($(KERNELRELEASE),)
$(MODULE_NAME)-y := example.o
obj-m := example.o
else
KDIR := /home/pi/work/linux ### 这个目录需要和你下载并编译的Linux源码的目录一致
PWD := $(shell pwd)
all:
make -C $(KDIR) M:=$(PWD) modules
clean:
rm *.o *.ko *.mod.c *.mod modules.order Module.symvers
endif
编译驱动,然后通过insmod安装驱动:
编译驱动并安装使用rmmod卸载驱动:
卸载驱动通过dmesg查看printk的信息, 可以看到,驱动成功的安装和卸载:
查看驱动的注册信息其他
如果编译Linux源码之后没有更新系统,直接编译安装驱动可能并不能成功。
如图所示,树莓派系统是5.4.51,而下载的Linux源码是5.4.61,驱动安装失败。
Linux版本不匹配驱动安装失败