树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证

目录

前言

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内核&驱动的交叉编译,内核移植,驱动加载测试验证过程

先描述验证成功的方式,后期在描述遇到的问题

1验证成功的流程

1.1环境准备:

1.11PC:VM下Ubuntu18.04 版本:

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

1.12树莓派版本:

使用官方烧录工具提供的最新32位版本           树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第1张图片

树莓派官方烧录工具下载链接: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

1.13树莓派内核下载

下载地址:GitHub - raspberrypi/linux at rpi-5.14.y

树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第2张图片

我选择的是rpi-5.14.y 内核版本 (后面说的源码树目录,指 linux-rpi-5.14.y)

1.14虚拟机VM Ubuntu 交叉编译工具链安装

在我使用的Ubuntu1系统中,可以直接输入:           

sudo apt-get install gcc-arm-linux-gnueabihf

注意:该交叉编译工具链是应对32位树莓派系统

安装好后,检查交叉编译工具链的版本 

树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第3张图片可以看到 版本是7.5.0 (也避免了手动在~/.bashrc 配置环境变量的步骤)

注意:如果直接去下载高版本的包,解压安装,之后交叉编译的文件一般会出现glibc库相关的问题,非常麻烦,这个放到后面问题说

1.15虚拟机VM Ubuntu 安装交叉编译所需的依赖项

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

1.2交叉编译内核:

1.21config文件选择

树莓派4的工程是bcm2711_defconfig

1.22构建源和设备文件

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 文件 

 1.23编译

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 内即可使用

树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第4张图片

打包陈成功后,在源码树目录下生成目标文件kernel_new.img

1.3树莓派内核替换:

1.31识别U盘

将烧录好树莓派系统的SD卡,插入电脑,并且选择虚拟机读取读卡器。    

dmesg

通过dmesg 可以查看虚拟机内核信息,已经识别到SD卡     

同时也可以在/dev 下查看到设备文件

1.32挂载U盘

# 位置 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分区,也就是系统的根目录分区

1.33安装modules

设备驱动文件,如果不安装的话,很多外设识别不了,例如 hdmi、usb、io等等

sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make INSTALL_MOD_PATH=/home/hans/Desktop/data-ext4 modules_install

1.34移植编译的内核

首先备份老的内核文件

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版本

至此内核替换完毕

2交叉编译驱动

2.1准备工作

编写好一份驱动文件(module_name = "pin4"),一份驱动测试文件

在驱动文件中,通过printk,在内核打印调试信息,以确定驱动文件加载后,正常运行

驱动文件中调试信息如下:

在驱动文件中,成功调用pin4_open 和 pin4_write ,会在内核打印出对应的调试信息树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第5张图片

驱动测试文件(调用open、write)

树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第6张图片

2.2驱动编译

在源码树目录中,将驱动文件拷贝到 ./driver/char ,修改char路径中的Makefile文件

我用的是以模块的方式加载驱动(非config形式)

在Makefile文件中,新增  obj-m  += pin4_driver2.o  (放在哪个路径下,就修改哪个路径下的Makefile)

树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第7张图片

返回源码树目录,执行

ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make modules
		

在源码树目录下生成 xxxx.ko文件

树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第8张图片

拷贝pin4_driver.ko到树莓派中

同时,虚拟机上交叉编译好驱动测试文件,并将其拷贝到树莓派

 2.3驱动加载

可以看到在树莓派的Desktop有以下两个文件

 在树莓派上执行以下指令加载驱动模块

sudo insmod pin4_driver.ko  # 内核驱动装载

 可以看到在 /dev下已经生成了pin4的设备文件

 注意:此时pin4 一般用户没有读写权限,若调用open/write/read api去打开pin4 文件,会提示没权限

给pin4设备文件加上权限

sudo chmod 666 /dev/pin4

同时我们也可以通过lsmod 指令查看内核是否已经起了驱动程序树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第9张图片

 2.4驱动程序的测试

运行驱动测试文件,进行测试,可以看到pin4文件被打开

 通过dmesg ,查看内核打印中,是否有驱动对应的pin4_open pin4_write 调用成功后打印的调试信息

 成共打印出调试信息

至此,驱动程序的交叉编译,加载运行,测试完毕

3遇到的问题

3.1 VM虚拟机上使用高本交叉编译工具链导致的不匹配

        一开始下载安装的是11.2版本的交叉编译工具链,编译好程序后,拷贝到树莓派当中运行,会出现libc相关的不兼容问题

通过指令查看树莓派系统最高支持的glibc,是2.31树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第10张图片

 然后就开始各种折腾升级glibc库

        首先遇到就是升级的时候各种下载依赖包的问题

        其次,升级完成后,libc.so.6建立新的软连接时,系统指令不生效

        最后,以上问题解决后,报错:

                symbol lookup error: ./libc.so.6: undefined symbol: __nptl_set_robust_list_avail, version GLIBC_PRIVATE

       折腾一阵后,放弃

3.2没有替换内核的情况下,inmod加载驱动模块时遇到的问题

 原因:Makefile里设置kernel源码的路径错误,没有和当前的内核版本一致,导致版本验证不通过,无法安装(比如我虚拟机上编译驱动的内核包时 5.14,树莓派内核是5.15 这个时候KDIR就对不上)

修改Makefile 中的KDIR 路径

3.3insmod xxx.ko  内核报错undefined reference to `__stack_chk_guard'

通过insmod 指令加载 驱动ko文件, 报错:unknown symbol in module

通过 dmesg 查看内核打印信息,发现内核报错 undefined reference to `__stack_chk_guard'

这个原因是因为启用了Stack Guard堆栈保护,经过测试,不管是交叉编译驱动模块,还是在树莓派本地进行编译驱动模块。都会报错

解决办法:

在源码树目录的 Makefile 文件中,找到KBUILD_CFLAGS

新增:KBUILD_CFLAGS   += -fno-stack-protector    // 禁用堆栈保护树莓派4B--内核&驱动交叉编译--内核移植--驱动加载验证_第11张图片

再重新编译驱动编译驱动模块,生成 ko文件。在树莓派上。用新生成的ko文件,可以正常加载

上述仅记录自己玩树莓派的过程,如果哪里不对,大家一笑而过

如果有大佬告知正确升级glibc库的方式,感激不尽

你可能感兴趣的:(linux,运维,服务器)