用树莓派3B学习Linux驱动开发---内核编译

环境介绍

最近在学习ARM Linux驱动开发,由于手头的ARM开发板版本太老,和教程里用的驱动内核相差太多,于式打算用树莓派3B来进行学习。
要用树莓派开发内核,就必须先让树莓派跑上自己编译的内核,否则insmod会执行失败
教程介绍了如何交叉编译树莓派3B内核并运行ko模块,本教程不再使用虚拟机,而是使用win10的WSL搭配vscode进行开发
硬件:WIN10电脑 、树莓派

WSL安装

参考:win10安装WSL
注意:我安装的是Ubuntu18.4,使用的是WSL1,WSL1完全够用。当然WSL2也是可以的。

安装VSCode

很简单,下载安装就行了,然后安装Remote WSL插件,喜欢折腾的朋友可以再装几个插件。
主要是配置方面需要介绍,文章后面会进行补充。

连接树莓派

连接树莓的方法多种多样,有树莓派的朋友应该都会吧。我采用的是ssh的方式,树莓派通过wifi连接路由器,电脑也是通过wifi连接同一个路由器。

  1. 树莓派系统烧录: 资源下载
  2. 连接SSH
    树莓派默认是关闭SSH的,打开方法:烧录好后在boot目录下新建一个SSH文件
为树莓派安装sz、rz

开发过程中需要频繁地在PC和树莓派间传输文件,传输方法也很多,这里使用sz和rz
树莓派安装sz,rz
使用方法:

#这些命令都在树莓派执行
sz ~/test.txt	#将树莓派的文件发送到PC
rz -y 	#将PC的文件拷贝到当前目录,-y表示覆盖已存在的文件

下载内核源码与工具

  1. 查看当前树莓派内核版本uanme -a
    在这里插入图片描述

  2. 下载对应版本的内核,比如我的是4.19.97
    内核源码下载地址
    注意:这里有很多版本,一定要选对版本,否则编译后可能开不了机
    在这里插入图片描述
    如何找到自己版本内核呢?可以看树莓派官网的raspberrypi OS的release note 点这里打开
    比如我的是4.19.79,可以看出日期是2020-02-13和2020-02-05
    在这里插入图片描述
    下载对应的代码即可
    在这里插入图片描述
    下载前可以看下Makefile的log是不是对的
    在这里插入图片描述

  3. 下载交叉编译工具 下载地址

配置交叉编译环境

  1. 打开wsl,把内核源码和工具拷贝到wsl中
    #WSL可以直接访问windows的磁盘,/mnt/d 代表D盘
    cp /mnt/d/Download/linux-raspberrypi-kernel_1.20200205-1.zip  ./
    cp /mnt/d/Download/infinitystar-raspberrypi-tools-master.zip  ./
    #解压
    mkdir linux-4.19
    unzip -d linux-4.19 linux-raspberrypi-kernel_1.20200205-1.zip 
    mkdir tools
    unzip -d tools infinitystar-raspberrypi-tools-master.zip
    
  2. 配置交叉编译环境
    ~/tools/raspberrypi-tools/arm-bcm2708目录下有几个交叉编译工具,我们使用的WSL是64位的,所以使用gcc-linaro-arm-linux-gnueabihf-raspbian-x64
    vi ~/.bashrc
    #再最后一行添加如下内容
    export PATH=$PATH:/root/tools/raspberrypi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
    #重新运行一遍.bashrc,使配置生效
    source ~/.bashrc
    #查看是否配置成功
    arm-linux-gnueabihf-gcc -v
    
  3. 下载一些依赖( 这是我从其它教程里抄的,不一定全,大家编译出错以后百度一下,一般很容易搜到少了哪个依赖 )
    sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev 
    

编译内核

  1. 进入内核源码目录,修改Makefile

    这一步的作用:我们在make后需要带上两个参数 如:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- ,这两个参数最后传递给Makefile,如果我们在Makefile中直接写死,就可以直接输入make就行了。

修改Makefile
2. 从树莓派获取config文件

内核编译执行make menuconfig时会默认读取.config文件,里面配置了内核会编译哪些模块,不编译哪些模块

#在树莓派上执行
sudo modprobe configs
zcat /proc/config.gz > board.config
sz board.config
#在WSL上执行
cd ~/linux-4.19/linux-raspberrypi-kernel_1.20200205-1/
cp /mnt/d/xxx/board.config ./
cp board.config .config
  1. 执行make menuconfig并重新保存.config

    虽然已经有了.config文件,但最好还是执行下make menuconfig,然后重新保存一下(原因我也不清楚。。。)

    这一步和下一步一般第一次编译都会出错,原因是系统有些东西没有安装,百度很容易找到答案

  2. 编译内核

    KERNEL=kernel7
    make -j4
    
  3. 拷贝内核到树莓派

    #生成树莓派可用的kernel镜像
    ./scripts/mkknlimg arch/arm/boot/zImage kernel7.img
    #把kernel7.img拷贝到树莓派的/boot下即可
    
  4. 树莓派重启后uname -a看下日期,如果没问题的话应该已经是自己编译的内核了

用VSCode编译内核驱动

  1. 先写个驱动小demo
  • Makefile文件
    KERNELDIR := /root/linux-4.19/linux-raspberrypi-kernel_1.20200205-1
    CURRENT_PATH := $(shell pwd)
    obj-m := led.o
    build: kernel_modules
    kernel_modules:
    	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
    clean:
    	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
    
  • led.c文件
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>

#define MYDEV_NAME "LedTest"

struct led_dev
{
    struct cdev dev;
    struct class *class; 
    struct device *device;
    dev_t devid;
    int major;
    int minor;
    
};


static int led_open(struct inode *inode, struct file *file)
{
    return 0;
}

static int led_release(struct inode *inode, struct file *filp)
{
    return 0;
}

ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    return 0;
}

ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    return 0;
}

static const struct file_operations led_fops = {
	.read		=	led_read,
	.write		=	led_write,
	.open		=	led_open,
	.release	=	led_release,
	.owner		=	THIS_MODULE,
};

struct led_dev my_dev;


static int __init led_init(void)
{
    int ret = 0;
    printk("led_init\n");
    /*  设备号分配  */
    if(my_dev.major){   //给定主设备号
        my_dev.devid = MKDEV(my_dev.major,0);
        ret = register_chrdev_region(my_dev.devid,1,MYDEV_NAME);
    }else{  //没有指定主设备号
        ret = alloc_chrdev_region(&my_dev.devid,0,1,MYDEV_NAME);
    }
    if(ret < 0){
        printk("register char dev failed!\n");
        return -1;
    }
    my_dev.major = MAJOR(my_dev.devid);
    my_dev.minor = MINOR(my_dev.devid);
    printk("register chardev major:%d minor:%d\n", my_dev.major, my_dev.minor);
    /*  创建字符设备  */
    cdev_init(&my_dev.dev, &led_fops);
    ret = cdev_add(&my_dev.dev, my_dev.devid, 1);
    if(ret){
        unregister_chrdev_region(my_dev.devid, 1);
    }
    /*  创建设备节点  */
    my_dev.class = class_create(THIS_MODULE, MYDEV_NAME);
    if(IS_ERR(my_dev.class)){
        return PTR_ERR(my_dev.class);
    }
    my_dev.device = device_create(my_dev.class,NULL,my_dev.devid,NULL,MYDEV_NAME);
    if(IS_ERR(my_dev.device)){
        return PTR_ERR(my_dev.device);
    }

    return 0;
}

static void __exit led_exit(void)
{
    printk("led_exit\n");
    cdev_del(&my_dev.dev);
    unregister_chrdev_region(my_dev.devid, 1);
    device_destroy(my_dev.class,my_dev.devid);
    class_destroy(my_dev.class);
    return;
}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("LIUJIANHUA");
  1. 打开VSCode,点击左下角图标,选择WSL
    在这里插入图片描述
  2. 用VSCode打开自己驱动的文件夹
    WSL系统路径:C:\Users\liujh\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\root
  3. VSCode配置
    打开后会显示很多头文件找不到,编写代码的时候也不会有补全,使用下面的配置方法可以解决大部分问题。
    文件:驱动代码路径/.vscode/Settings.json
	{
	"editor.insertSpaces": false,
	"editor.renderWhitespace": "all",
	"C_Cpp.default.includePath": [
		"/root/linux-4.19/linux-raspberrypi-kernel_1.20200205-1/include",
		"/root/linux-4.19/linux-raspberrypi-kernel_1.20200205-1/include/uapi",
		"/root/linux-4.19/linux-raspberrypi-kernel_1.20200205-1/arch/arm/include",
		"/root/linux-4.19/linux-raspberrypi-kernel_1.20200205-1/arch/arm/include/generated",
	],
	"C_Cpp.default.defines": [
		"__KERNEL__",
	]
}

另外还可以直接再VSCODE中打开一个WSL终端,非常方便。
在这里插入图片描述

树莓派4B的内核开发可以按照以下步骤进行: 1. 首先,下载内核源码。可以使用以下命令克隆树莓派Linux内核源码库: ``` git clone --depth=1 https://github.com/raspberrypi/linux --branch rpi-5.4.y ``` 这将下载最新的树莓派Linux内核源码。 2. 安装所需的依赖项。使用以下命令安装所需的软件包: ``` sudo apt install raspberrypi-kernel-headers sudo apt install git bc bison flex libssl-dev make ``` 这将安装所需的内核头文件和其他开发工具。 3. 进入内核源码目录并进行配置。使用以下命令进入内核源码目录: ``` cd linux ``` 然后,使用以下命令配置内核: ``` KERNEL=kernel7l make bcm2711_defconfig ``` 这将使用默认配置文件进行内核配置。 4. 编译内核并安装。使用以下命令编译内核和模块: ``` make -j4 zImage modules dtbs ``` 然后,使用以下命令安装内核模块: ``` sudo make modules_install ``` 接下来,将设备树二进制文件复制到/boot/目录: ``` 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/ ``` 最后,将编译生成的内核映像复制到/boot/目录: ``` sudo cp arch/arm/boot/zImage /boot/$KERNEL.img ``` 5. 重新启动树莓派。使用以下命令重新启动树莓派: ``` sudo reboot -f ``` 这样,你就完成了树莓派4B的内核开发过程。请注意,这只是一个简单的概述,具体的步骤可能会因为不同的环境和需求而有所不同。建议在进行内核开发之前仔细阅读相关文档和指南。 #### 引用[.reference_title] - *1* [树莓派4B内核驱动开发(二)本地编译内核](https://blog.csdn.net/wuspeng/article/details/114040075)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [树莓派 4B 本地编译内核](https://blog.csdn.net/zhoutaopower/article/details/119416771)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值