目录
前言
1验证成功的流程
1.1环境准备:
1.11PC:VM下Ubuntu18.04 版本:
1.12树莓派版本:
1.13树莓派内核下载
1.14虚拟机VM Ubuntu 交叉编译工具链安装
1.15虚拟机VM Ubuntu 安装交叉编译所需的依赖项
1.2交叉编译内核:
1.21config文件选择
1.22构建源和设备文件
1.23编译
1.3树莓派内核替换:
1.31识别U盘
1.32挂载U盘
1.33安装modules
1.34移植编译的内核
2交叉编译驱动
2.1准备工作
2.2驱动编译
2.3驱动加载
2.4驱动程序的测试
3遇到的问题
3.1 VM虚拟机上使用高本交叉编译工具链导致的不匹配
3.2没有替换内核的情况下,inmod加载驱动模块时遇到的问题编辑
3.3insmod xxx.ko 内核报错undefined reference to `__stack_chk_guard'
记录在PC-VM虚拟机进行树莓派4b内核&驱动的交叉编译,内核移植,驱动加载测试验证过程
先描述验证成功的方式,后期在描述遇到的问题
Linux ubuntu 5.4.0-146-generic #163~18.04.1-Ubuntu SMP Mon Mar 20 15:02:59 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
树莓派官方烧录工具下载链接:Raspberry Pi OS – Raspberry Pi
当前树莓派官方Raspberry Pi OS(32-bit)内核版本信息:
Linux raspberrypi 5.15.84-v7l+ #1613 SMP Thu Jan 5 12:01:26 GMT 2023 armv7l GNU/Linux
下载地址:GitHub - raspberrypi/linux at rpi-5.14.y
我选择的是rpi-5.14.y 内核版本 (后面说的源码树目录,指 linux-rpi-5.14.y)
在我使用的Ubuntu1系统中,可以直接输入:
sudo apt-get install gcc-arm-linux-gnueabihf
注意:该交叉编译工具链是应对32位树莓派系统
安装好后,检查交叉编译工具链的版本
可以看到 版本是7.5.0 (也避免了手动在~/.bashrc 配置环境变量的步骤)
注意:如果直接去下载高版本的包,解压安装,之后交叉编译的文件一般会出现glibc库相关的问题,非常麻烦,这个放到后面问题说
sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev
树莓派4的工程是bcm2711_defconfig
cd linux-rpi-5.14.y #进入内核文件夹
KERNEL=kernel7l #指定kernel 树莓派4b 32位系统的内核文件是kernel7l
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make bcm2711_defconfig #构建源
生成 .config 文件
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make zImage modules dtbs
编译成功后,在源码树目录会生成vmlinux文件
我们的目标zImage镜像文件在 ./arch/arm/boot
打包zImage成为树莓派可用的xxx.img 文件格式
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
注意:这里会遇到一个问题-- 在linux-rpi-5.14.y中,mkknlimg 打包工具已经被废除。我的解决方法是 下载低版本的linux-rpi-4.14.y,将其中./scripts 文件夹内的mkknlimg拷贝到linux-rpi-5.14.y/scripts 内即可使用
打包陈成功后,在源码树目录下生成目标文件kernel_new.img
将烧录好树莓派系统的SD卡,插入电脑,并且选择虚拟机读取读卡器。
dmesg
通过dmesg 可以查看虚拟机内核信息,已经识别到SD卡
同时也可以在/dev 下查看到设备文件
# 位置 Desktop
mkdir data-fat data-ext4
#挂载U盘,U盘有两个分区,fat ext4
sudo mount /dev/sdb1 data-fat #一个fat分区,是boot相关的内容,kernel的img
sudo mount /dev/sdb2 data-ext4 #一个是ext4分区,也就是系统的根目录分区
设备驱动文件,如果不安装的话,很多外设识别不了,例如 hdmi、usb、io等等
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make INSTALL_MOD_PATH=/home/hans/Desktop/data-ext4 modules_install
首先备份老的内核文件
cp /home/pi/Desktop/data-fat/kernel7l.img kernel7lBak.img
其次,将虚拟机上打包好的kernel_new.img 拷贝到data-fat路径下,并命名位kernel7l.img
cp /home/hans/Desktop/linux-rpi-5.14.y/kernel_new.img /home/hans/Desktop/data-fat/kernel7l.img
cp arch/arm/boot/dts/.*dtb* /home/hans/Desktop/data-fat
cp arch/arm/boot/dts/overlays/.*dtb* /home/hans/Desktop/data-fat/overlays/
取出SD卡,插入树莓派启动
输入 uname -r 或者 uname -a 查看内核版本信息
可以看到内核已经替换成了5.14版本
至此内核替换完毕
编写好一份驱动文件(module_name = "pin4"),一份驱动测试文件
在驱动文件中,通过printk,在内核打印调试信息,以确定驱动文件加载后,正常运行
驱动文件中调试信息如下:
在驱动文件中,成功调用pin4_open 和 pin4_write ,会在内核打印出对应的调试信息
驱动测试文件(调用open、write)
在源码树目录中,将驱动文件拷贝到 ./driver/char ,修改char路径中的Makefile文件
我用的是以模块的方式加载驱动(非config形式)
在Makefile文件中,新增 obj-m += pin4_driver2.o (放在哪个路径下,就修改哪个路径下的Makefile)
返回源码树目录,执行
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make modules
在源码树目录下生成 xxxx.ko文件
同时,虚拟机上交叉编译好驱动测试文件,并将其拷贝到树莓派
在树莓派上执行以下指令加载驱动模块
sudo insmod pin4_driver.ko # 内核驱动装载
注意:此时pin4 一般用户没有读写权限,若调用open/write/read api去打开pin4 文件,会提示没权限
给pin4设备文件加上权限
sudo chmod 666 /dev/pin4
同时我们也可以通过lsmod 指令查看内核是否已经起了驱动程序
运行驱动测试文件,进行测试,可以看到pin4文件被打开
通过dmesg ,查看内核打印中,是否有驱动对应的pin4_open pin4_write 调用成功后打印的调试信息
成共打印出调试信息
至此,驱动程序的交叉编译,加载运行,测试完毕
一开始下载安装的是11.2版本的交叉编译工具链,编译好程序后,拷贝到树莓派当中运行,会出现libc相关的不兼容问题
然后就开始各种折腾升级glibc库
首先遇到就是升级的时候各种下载依赖包的问题
其次,升级完成后,libc.so.6建立新的软连接时,系统指令不生效
最后,以上问题解决后,报错:
symbol lookup error: ./libc.so.6: undefined symbol: __nptl_set_robust_list_avail, version GLIBC_PRIVATE
折腾一阵后,放弃
原因:Makefile里设置kernel源码的路径错误,没有和当前的内核版本一致,导致版本验证不通过,无法安装(比如我虚拟机上编译驱动的内核包时 5.14,树莓派内核是5.15 这个时候KDIR就对不上)
修改Makefile 中的KDIR 路径
通过insmod 指令加载 驱动ko文件, 报错:unknown symbol in module
通过 dmesg 查看内核打印信息,发现内核报错 undefined reference to `__stack_chk_guard'
这个原因是因为启用了Stack Guard堆栈保护,经过测试,不管是交叉编译驱动模块,还是在树莓派本地进行编译驱动模块。都会报错
解决办法:
在源码树目录的 Makefile 文件中,找到KBUILD_CFLAGS
新增:KBUILD_CFLAGS += -fno-stack-protector // 禁用堆栈保护
再重新编译驱动编译驱动模块,生成 ko文件。在树莓派上。用新生成的ko文件,可以正常加载
上述仅记录自己玩树莓派的过程,如果哪里不对,大家一笑而过
如果有大佬告知正确升级glibc库的方式,感激不尽