博客
关于我
树莓派4B Linux的底层驱动编写体验
阅读量:390 次
发布时间:2019-03-05

本文共 3132 字,大约阅读时间需要 10 分钟。

一、编写前的准备工作

在开始编写驱动程序之前,需要完成以下几项准备工作:

  • 确认内核版本一致性

    确保树莓派上的内核版本与虚拟机中的Linux内核版本保持一致。内核版本不一致将导致驱动无法正确安装。

  • 确保交叉编译工具的存在

    虚拟机中需要预先安装交叉编译工具,这些工具将用于将驱动程序编译为树莓派所需的机器码(binaries)。

  • 确定交叉编译参数

    • 对于树莓派4,交叉编译驱动模块时,使用参数KERNEL=kernel7l
    • 对于树莓派2、3代,使用参数KERNEL=kernel7
  • 二、驱动程序编写

    驱动程序的编写基于标准的Linux内核模块框架,以下是详细步骤:

    1. 构建file_operations结构体

    驱动程序的核心是定义一个符合Linux内核规范的文件操作接口。以下是file_operations结构体的定义示例:

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    static int Test_open(struct inode *inode, struct file *file) { printk("pin4_open\n"); return 0;}static ssize_t Test_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { printk("pin4_write\n"); return 0;}static struct file_operations pin4_fops = { .owner = THIS_MODULE, .open = Test_open, .write = Test_write,};

    注意事项:

    • 使用static关键字是为了避免函数名冲突,确保在内核环境中不会出现命名冲突。
    • 每个函数都需要打印相关信息以确认驱动的功能实现。

    2. 编写初始化函数

    初始化函数负责将驱动注册到内核中,创建设备节点等。以下是初始化函数的实现示例:

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    static struct class *Test_class;static struct device *Test_dev;static dev_t devno;static int major = 240; // 设备主号static int minor = 0; // 设备次号static char *module_name = "test"; // 驱动名称static int Test_open(struct inode *inode, struct file *file) { printk("Test_open\n"); return 0;}static ssize_t Test_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { printk("Test_write\n"); return 0;}static struct file_operations Test_fops = { .owner = THIS_MODULE, .open = Test_open, .write = Test_write,};int __init Test_dev_init(void) { int ret; devno = MKDEV(major, minor); ret = register_chrdev(major, module_name, &Test_fops); Test_class = class_create(THIS_MODULE, "Test_class"); Test_dev = device_create(&Test_class, NULL, devno, NULL, module_name); return 0;}

    注意事项:

    • MKDEV宏用于创建设备号,register_chrdev函数用于将设备注册到内核中。
    • class_createdevice_create函数分别用于创建设备类和设备节点。

    3. 编写剩余内容

    驱动程序的退出函数负责卸载设备和释放资源:

    void __exit Test_exit(void) {    device_destroy(Test_class, devno);    class_destroy(Test_class);    unregister_chrdev(major, module_name);}module_init(Test_dev_init);module_exit(Test_exit);MODULE_LICENSE("GPL v2");

    三、驱动模块的编译

    完成驱动程序编写后,需要按照以下步骤进行编译:

  • 将驱动文件放置在内核文件系统的/drivers/char/目录下:

    cp Test.c /home/.../drivers/char/
  • 修改Makefile文件,将驱动源文件添加到编译列表中:

    obj-m += test.o
  • 在内核文件根目录下,执行编译命令(以树莓派4为例):

    ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make -j4 modules
  • 编译完成后,检查并修复可能的错误(如语法错误或缺少分号等),重新编译。

  • 四、驱动模块的安装

  • 将编译生成的驱动模块文件复制到树莓派上:

    scp drivers/char/xxx.ko pi@
    <树莓派ip地址>
    :/home/xxx/
  • 在树莓派上安装驱动:

    sudo insmod xxx.kosudo chmod 666 /dev/xxx
  • 注意事项:

    • 驱动名称需要全小写,且不能与其他模块的设备号冲突。
    • 如果安装后发现/dev/xxx节点不存在,请检查设备号是否正确,并确保设备号唯一。

    五、驱动测试

    编写一个简单的用户空间测试程序来验证驱动功能:

    #include 
    #include
    #include
    #include
    int main() { int fd; int cmd = 1; fd = open("/dev/test", O_RDWR); if (fd < 0) { perror("open failed"); return -1; } fd = write(fd, &cmd, sizeof(int)); return 0;}

    测试命令:

    ./test_program

    查看内核日志:

    使用dmesg命令查看驱动安装和运行时的内核打印信息:

    dmesg

    转载地址:http://stlwz.baihongyu.com/

    你可能感兴趣的文章
    OpenCV保证输入图像为三通道
    查看>>
    OpenCV入门教程(非常详细)从零基础入门到精通,看完这一篇就够了
    查看>>
    opencv图像分割2-GMM
    查看>>
    opencv图像分割3-分水岭方法
    查看>>
    opencv图像切割1-KMeans方法
    查看>>
    OpenCV图像处理篇之阈值操作函数
    查看>>
    opencv图像特征融合-seamlessClone
    查看>>
    OpenCV图像的深浅拷贝
    查看>>
    OpenCV在Google Colboratory中不起作用
    查看>>
    OpenCV学习(13) 细化算法(1)(转)
    查看>>
    OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
    查看>>
    OpenCV学堂 | CV开发者必须懂的9种距离度量方法,内含欧氏距离、切比雪夫距离等(建议收藏)
    查看>>
    OpenCV学堂 | OpenCV中支持的人脸检测方法整理与汇总
    查看>>
    OpenCV学堂 | OpenCV案例 | 基于轮廓分析对象提取
    查看>>
    OpenCV学堂 | YOLOv8与YOLO11自定义数据集迁移学习效果对比
    查看>>
    OpenCV学堂 | YOLOv8官方团队宣布YOLOv11 发布了
    查看>>
    OpenCV学堂 | YOLOv8实战 | 荧光显微镜细胞图像检测
    查看>>
    OpenCV学堂 | 汇总 | 深度学习图像去模糊技术与模型
    查看>>
    OpenCV安装
    查看>>
    OpenCV官方文档 理解k - means聚类
    查看>>