首页 > 编程语言 >手把手教你学PCIE(12.2)--开发一个简单的 PCIe 设备驱动程序

手把手教你学PCIE(12.2)--开发一个简单的 PCIe 设备驱动程序

时间:2024-11-01 21:47:22浏览次数:3  
标签:驱动程序 PCIe -- driver dev PCIE static pcie

目录

PCIe 实战实例:开发一个简单的 PCIe 设备驱动程序

目标

环境准备

步骤一:理解 PCIe 基本概念

步骤二:设置开发环境

步骤三:开发 PCIe 设备驱动程序

步骤四:测试和调试驱动程序

步骤五:深入学习和实践

结语


PCIe 实战实例来展示如何开发一个简单的 PCIe 设备驱动程序,该驱动程序将设备注册到内核,并实现基本的读写功能。我们将使用 Linux 内核提供的 PCIe API 来完成这个任务。

PCIe 实战实例:开发一个简单的 PCIe 设备驱动程序

目标
  • 理解 PCIe 设备的基本结构和配置空间。
  • 学习如何编写 PCIe 设备驱动程序。
  • 实现设备的读写功能。
  • 测试和调试驱动程序。
环境准备
  • 硬件:一块支持 PCIe 的开发板或者虚拟机。
  • 软件:Linux 操作系统(推荐 Ubuntu),因为 Linux 内核提供了丰富的 PCIe 支持。
  • 开发工具:GCC 编译器、Make 工具、文本编辑器(如 Vim 或者 VSCode)。
步骤一:理解 PCIe 基本概念
  1. 物理层:PCIe 使用差分信号对传输数据,支持多种链路宽度(如 x1, x4, x8, x16)。
  2. 数据链路层:负责确保数据包的正确传输,包括错误检测和重传机制。
  3. 事务层:处理请求和响应消息,定义了读写操作的协议。
  4. 配置空间:每个 PCIe 设备都有一个唯一的配置空间,用于存储设备信息和控制寄存器。
步骤二:设置开发环境
  1. 安装操作系统:在开发板或虚拟机上安装 Ubuntu。
  2. 安装开发工具:打开终端并运行以下命令来安装必要的开发工具。
     bash 

    深色版本

    sudo apt-get update
    sudo apt-get install build-essential
步骤三:开发 PCIe 设备驱动程序

我们将开发一个简单的 PCIe 设备驱动程序,该驱动程序将设备注册到内核,并提供基本的读写功能。

  1. 创建项目文件夹

     bash 

    深色版本

    mkdir pcie_driver_example
    cd pcie_driver_example
  2. 编写驱动程序代码: 创建一个名为 pcie_driver.c 的文件,并编写以下代码:

     c 

    深色版本

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/pci.h>
    #include <linux/io.h>  // 用于内存映射
    #include <linux/fs.h>  // 用于文件操作
    #include <linux/cdev.h>  // 用于字符设备
    #include <linux/uaccess.h>  // 用于用户空间访问
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Your Name");
    MODULE_DESCRIPTION("A simple PCIe driver with read/write support");
    
    #define DEVICE_NAME "pcie_example"
    #define CLASS_NAME "pcie_class"
    
    static dev_t dev;
    static struct cdev c_dev;
    static struct class *cl;
    static struct pci_dev *pdev;
    static void __iomem *bar0;
    
    static struct pci_device_id pcie_dev_ids[] = {
        { PCI_DEVICE(0x1234, 0x5678) },  // 替换为你设备的Vendor ID和Device ID
        { 0, }  // 表示列表结束
    };
    
    static int pcie_driver_open(struct inode *inode, struct file *file)
    {
        return 0;
    }
    
    static int pcie_driver_close(struct inode *inode, struct file *file)
    {
        return 0;
    }
    
    static ssize_t pcie_driver_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
    {
        unsigned int value = ioread32(bar0);
        if (copy_to_user(buf, &value, sizeof(unsigned int)))
            return -EFAULT;
        return sizeof(unsigned int);
    }
    
    static ssize_t pcie_driver_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
    {
        unsigned int value;
        if (count != sizeof(unsigned int))
            return -EINVAL;
        if (copy_from_user(&value, buf, sizeof(unsigned int)))
            return -EFAULT;
        iowrite32(value, bar0);
        return sizeof(unsigned int);
    }
    
    static struct file_operations fops = {
        .owner = THIS_MODULE,
        .open = pcie_driver_open,
        .release = pcie_driver_close,
        .read = pcie_driver_read,
        .write = pcie_driver_write
    };
    
    static int pcie_driver_probe(struct pci_dev *pdev, const struct pci_device_id *id)
    {
        int ret;
        unsigned long bar0_start, bar0_len;
    
        // 请求PCI资源
        ret = pci_enable_device(pdev);
        if (ret) {
            dev_err(&pdev->dev, "Failed to enable PCI device\n");
            return ret;
        }
    
        // 获取BAR0地址和长度
        bar0_start = pci_resource_start(pdev, 0);
        bar0_len = pci_resource_len(pdev, 0);
    
        // 映射BAR0到内存
        bar0 = ioremap(bar0_start, bar0_len);
        if (!bar0) {
            dev_err(&pdev->dev, "Failed to map BAR0\n");
            pci_disable_device(pdev);
            return -ENOMEM;
        }
    
        // 注册字符设备
        alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
        cdev_init(&c_dev, &fops);
        cdev_add(&c_dev, dev, 1);
    
        cl = class_create(THIS_MODULE, CLASS_NAME);
        if (IS_ERR(cl)) {
            unregister_chrdev_region(dev, 1);
            iounmap(bar0);
            pci_disable_device(pdev);
            return PTR_ERR(cl);
        }
    
        device_create(cl, NULL, dev, NULL, DEVICE_NAME);
    
        printk(KERN_INFO "PCIe Driver: Device Found and Mapped!\n");
        return 0;
    }
    
    static void pcie_driver_remove(struct pci_dev *pdev)
    {
        device_destroy(cl, dev);
        class_destroy(cl);
        cdev_del(&c_dev);
        unregister_chrdev_region(dev, 1);
        iounmap(bar0);
        pci_disable_device(pdev);
        printk(KERN_INFO "PCIe Driver: Device Removed!\n");
    }
    
    static struct pci_driver pcie_driver = {
        .name = "pcie_example_driver",
        .id_table = pcie_dev_ids,
        .probe = pcie_driver_probe,
        .remove = pcie_driver_remove,
    };
    
    static int __init pcie_driver_init(void)
    {
        return pci_register_driver(&pcie_driver);
    }
    
    static void __exit pcie_driver_exit(void)
    {
        pci_unregister_driver(&pcie_driver);
    }
    
    module_init(pcie_driver_init);
    module_exit(pcie_driver_exit);
  3. 编写 Makefile: 在同一目录下创建一个名为 Makefile 的文件,内容如下:

     makefile 

    深色版本

    obj-m += pcie_driver.o
    
    all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    
    clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  4. 编译驱动程序: 在终端中运行以下命令来编译驱动程序:

     bash 

    深色版本

    make
步骤四:测试和调试驱动程序
  1. 加载驱动程序
     bash 

    深色版本

    sudo insmod pcie_driver.ko
  2. 查看内核日志
     bash 

    深色版本

    dmesg | tail
    查看输出确认驱动程序是否成功加载并且找到了设备。
  3. 创建设备节点: 如果设备节点没有自动创建,可以手动创建:
     bash 

    深色版本

    sudo mknod /dev/pcie_example c 240 0
    sudo chmod 666 /dev/pcie_example
  4. 测试读写功能
    • 读取设备寄存器
       bash 

      深色版本

      cat /dev/pcie_example
    • 写入设备寄存器
       bash 

      深色版本

      echo 12345678 > /dev/pcie_example
  5. 卸载驱动程序
     bash 

    深色版本

    sudo rmmod pcie_driver
步骤五:深入学习和实践
  • 学习 PCIe 配置空间:了解如何通过配置空间访问设备属性。
  • 实现 DMA 功能:学习如何使用 Direct Memory Access (DMA) 技术提高数据传输效率。
  • 多设备支持:扩展驱动程序以支持多个相同类型的 PCIe 设备。
  • 性能优化:研究如何优化驱动程序以减少延迟和提高吞吐量。
结语

通过以上步骤,你应该能够建立一个具有读写功能的 PCIe 设备驱动程序,并具备进一步探索 PCIe 技术的基础。PCIe 是一个复杂的领域,涉及到许多底层硬件知识和技术细节,因此持续的学习和实践是非常重要的。

标签:驱动程序,PCIe,--,driver,dev,PCIE,static,pcie
From: https://blog.csdn.net/MHD0815/article/details/143441643

相关文章

  • halo配置踩坑过程小记
    写在最前:​ 终于搞定了最后的一步域名解析配置,其实动态博客的折腾程度也不低于当时的hexo吧,也可能当时的痛苦过程已经忘了。。整理一下思路,记录一下配置过程走过的坑。​ 我是从hexo用了半年想折腾点新玩意儿的,其实hexo配置自动化部署之后也挺方便的,反正都是本地编辑写作,后台啥......
  • 51单片机 3.1独立按键的基本操作
    一、电路图及分析(部分解释参考网络,仅用于学习记录)蓝桥杯单片机的板子将独立按键和矩阵按键结合了起来,通过一个短接片选择使用独立按键还是矩阵按键。首先我们先看原理图的左下角绿色方框所标的地方,这里与我们板子上的短接片所对应,是选择按键工作模式的地方。  如果短......
  • wordpress设置自定义字体
    wordpress设置自定义字体:失败的操作过程:写在最前:试了一天多的引用字体,方法包括但不限于:下载.ttf、.otf格式字体,转化为wotf、wotf2格式,挂在github仓库用CDN引用,得到css链接​ 然后这里填字体名称和CSS链接,试了很久很久,都失败了,不知道是不是字体本身转换的时候出错了。​......
  • Java实验二 分支循环程序设计
    1.编写程序接受用户输入的一个表示月份的整数,若用户输入了从1到12以外的整数则提示“输入有误”,输出对应月份的天数。提示1:可暂不考虑闰年,以2月份为28天来实现提示2:可以使用if或switch实现,体会选择分支的构造packageproject;importjava.util.Scanner;publicclassMont......
  • 数据库基本
    SQL语言分类:DQL:数据查询语言,用于对数据进行查询,例如:selectDML:数据操作语言,对数据进行增加、修改、删除,例如:insert、update、deleteTPL:事务处理语言,对事务进行处理,例如:begintransaction、commit、rollbackDCL:数据控制语言,进行授权与权限回收,例如:grant、revokeDDL:数据定义语......
  • [ACTF2020 新生赛]Include
    链接:https://buuoj.cn/challenges#[ACTF2020新生赛]Include。打开环境后如下,只有一个"tips"的超链接。访问tips,留意传入了"file"参数。接下来,可以尝试下路径穿越:?file=flag.php../../../../../etc/passwd。可以看到,存在路径穿越漏洞,但是通过路径穿越漏洞并没有读取到......
  • 知识图谱毕业设计基于知识图谱的中学生物学习APP系统
    一、项目介绍  基于知识图谱的中学生物学习APP系统是一个集成了现代信息技术与教育教学理念的创新学习平台。该系统通过构建生物学科的知识图谱,将复杂的生物知识点以结构化、可视化的方式呈现给学生,从而提高学习效率,增强学习兴趣。以下是对该系统的详细介绍:基于知识图......
  • 知识图谱毕业设计基于知识图谱的微博可视化与推荐系统
    一、项目介绍  近年来,随着人类进入大数据时代,整个社交媒体平台产生的文本数量呈爆炸式增长。由于海量的中文文本本身存在稀疏性和高维性特点,其语义解释也具有多样性和较强的语境依赖性,这无疑增加了对中文文本准确分类任务的难度。如何利用计算机对海量文本信息进行准确......
  • Visual Studio快捷键
    VS2005代码编辑器的展开和折叠代码确实很方便和实用。以下是展开代码和折叠代码所用到的快捷键,很常用:Ctrl+M+O:折叠所有方法Ctrl+M+M:折叠或者展开当前方法Ctrl+M+L:展开所有方法解决VS2010中工具箱的的不见的问题:按快捷键Ctrl+Alt+X全屏:Shift+Alt+Enter注......
  • 思通数科AI平台引领医疗数据管理变革,高效处理化验单与诊断报告
    思通数科 思通数据 一、系统概述在医疗行业,化验单和诊断报告的数据处理常常面临信息碎片化、数据提取效率低、管理难度大等问题,导致医疗机构在患者信息管理上遇到瓶颈。思通数科AI平台通过开源免费、技术领先的优势,为医疗机构提供了一套高效、智能的化验单和诊断......