基于PCIE4C的数据传输(三)——使用遗留中断与MSI中断

ops/2024/10/19 7:31:28/

   本文继续基于PCIE4C IP核实现主机(RHEL 8.9)与FPGA(Xilinx Ultrascale+HBM VCU128开发板)间DMA数据传输时的中断控制。本文分为三个部分:FPGA设计、驱动程序设计、上板测试。

FPGA设计

   基于PCIE4C的数据传输(二)——DMA一文实现了主机与FPGA间通过PCIe进行DMA数据传输:主机通过将DMA相关描述字段写入FPGA指定地址后,由FPGA工作进行批量的数据搬运,主机会每隔一段时间T后通过PCIe访问FPGA指定地址的DMA工作状态字段判断DMA是否完成。

   上述判断DMA是否完成的过程存在可以优化的地方,若主机等待时间T较小,主机通过PCIe访问FPGA指定地址的方式会占用CPU、PCIe总线的资源;若主机等待时间T较大,则会影响DMA传输的效率。为此,本文尝试使用中断解决该问题。

   PCIe协议中共存在三种中断方式:遗留中断(Legacy Interrupt)、MSI中断、MSIX中断。其功能按顺序越来越多,本文介绍PCIE4C提供的专用遗留中断与MSI中断接口的使用方式。

IP核配置及相关引脚说明

   遗留中断与MSI中断的配置需要进行如下配置,其中遗留中断继承自PCI协议,包括四个中断引脚INTA、INTB、INTC、INTD,每个PCIe设备只能使用1个中断引脚,这里均配置为INTA。MSI中断引入了中断向量的概念,个人认为相当于为每个PCIe设备引入了32个中断,本文仅使用1个中断,故配置为1 vector。

图片

   在完成上述配置后,IP核会引出pcie4_cfg_interrupt、pcie4_cfg_msi两组引脚,可结合手册相关章节使用。

   对于遗留中断,主要会用到如下四个信号,cfg_interrupt_int与cfg_interrupt_pending信号的四个比特由低到高对应INTA-D,由于配置选择INTA,因此这里只能使用0比特位。在cfg_interrupt_int与cfg_interrupt_pending信号拉高后,PCIE4C核会产生ASSERT_INTA的TLP报文给主机。在确认主机收到该报文后,cfg_interrupt_sent首次拉高。在经过一段合适的时间后(本文选择32个时钟周期),cfg_interrupt_int与cfg_interrupt_pending信号同时拉低,PCIE4C核会产生DEASSERT_INTA的TLP报文给主机,在确认主机收到该报文后,cfg_interrupt_sent二次拉高。中断过程结束。

图片

   由于遗留中断在主机启用MSI/MSIX中断后可以关闭,PCIE4C IP核提供了cfg_function_status信号用于告知用户逻辑遗留中断是否被启用。

   对于MSI中断,主要用到信号如下。

图片

FPGA代码实现

   根据上述描述,可写出FPGA相关代码,在每次DMA操作结束后,通过调用中断产生模块产生一个合适的中断。

图片

   状态机如下:

    always @(*) begincase (fsm_r)RESET: beginif (rst) beginfsm_s = RESET;end else beginfsm_s = IDLE;endendIDLE: beginif (irq_valid & irq_ready) begincase ({cfg_interrupt_msi_enable, cfg_interrupt_msix_enable})2'b00: begin    // legacy INTxif (|(irq_func)) beginfsm_s = SEND_LEGACY_INTR;end else beginfsm_s = IDLE;endend2'b01: begin    // MSI-Xif (|(irq_func & cfg_interrupt_msix_enable)) beginfsm_s = SEND_MSIX_INTR;end else beginfsm_s = IDLE;endend2'b10,          // MSI2'b11: begin    // illegal, but msiif (|(irq_func & cfg_interrupt_msi_enable)) beginfsm_s = SEND_MSI_INTR;end else beginfsm_s = IDLE;endendendcaseend else beginfsm_s = IDLE;endendSEND_LEGACY_INTR: beginif (cfg_interrupt_sent) begin fsm_s = WAIT_LEGACY_INTR;end else beginfsm_s=  SEND_LEGACY_INTR;endendWAIT_LEGACY_INTR: beginif (cfg_interrupt_sent) begin fsm_s = IDLE;end else beginfsm_s = WAIT_LEGACY_INTR;endendSEND_MSI_INTR: beginfsm_s = WAIT_MSI_INTR;endWAIT_MSI_INTR: beginif (cfg_interrupt_msi_sent | cfg_interrupt_msi_fail) begin fsm_s = IDLE;end else beginfsm_s = WAIT_MSI_INTR;endenddefault: fsm_s = RESET;endcaseend

驱动程序设计

   本文基于linux(RHEL8.9)开发,驱动程序的设计依然可参考Kernel.org关于PCI驱动的介绍,对于遗留中断向量号的获取,可参考StackOverflow。

   对于遗留中断,可以采用如下方式使用:

            printk("start create legacy interrupt");// pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &pcieirq);pcieirq = dev->irq; free_irq(pcieirq, (void*)legacy_irq_handler);                                                   // clear exist pending interrupt (if any)ret = request_irq(pcieirq, legacy_irq_handler, 0, "test_driver", (void*)legacy_irq_handler);    // associate handler and enable irqif (ret != 0) { printk("cannot register irq %d", ret);goto irq_alloc_err; }printk("finish create legacy interrupt");

   对于MSI中断,可以使用如下方式使用:

            printk("start create msi interrupt");ret = pci_alloc_irq_vectors(dev, MIN_VEC_NUM, MAX_VEC_NUM, PCI_IRQ_MSI); // allocate specific amount of interruptsif (ret < MIN_VEC_NUM) { // real allocated interrupts amountprintk("cannot register enough irq %d", ret);goto irq_alloc_err; }pcieirq = pci_irq_vector(dev, 0); // get IRQ numberfree_irq(pcieirq, (void*)legacy_irq_handler);                                                   // clear exist pending interrupt (if any)ret = request_irq(pcieirq, legacy_irq_handler, 0, "test_driver", (void*)legacy_irq_handler);    // associate handler and enable irqif (ret != 0) { printk("cannot register irq %d", ret);goto irq_alloc_err; }printk("finish create msi interrupt");

上板测试

   对于遗留中断,每次DMA传输完成后产生波形如下:

图片

   在驱动侧,相关输出如下:

图片

图片

工程代码

   完整代码可于同名公众号回复PCIE4C_IRQ获取。


http://www.ppmy.cn/ops/24379.html

相关文章

前端页面单元测试最佳策略:全面涵盖逻辑、组件、流程、UI及性能优化测试,全面保障软件应用的质量

页面级别的测试要求我们从更宏观的角度审视应用&#xff0c;不仅关注单个组件的正确性&#xff0c;还要确保组件间的协作无误&#xff0c;以及用户在应用中的完整体验。通过集成测试、E2E测试和场景测试&#xff0c;我们可以更全面地覆盖应用的各种使用情况&#xff0c;提高软件…

elementPlus treeselect相关问题

<el-tree-selectplaceholder"请选择业务代码":props"{ label: transactionName, value: transactionCode }"v-model"item.transactionCode"node-key"id":data"transactionList":default-expanded-keys"[item.transa…

AI视频教程下载:用ChatGPT做SEO的终极教程

ChatGPT是由OpenAI开发的一款尖端人工智能&#xff0c;它已经彻底改变了我们进行搜索引擎优化&#xff08;SEO&#xff09;的方式。其先进的语言处理能力使其成为增强网站内容、提高搜索引擎排名和显著提升在线可见性的宝贵工具。 这个全面的课程旨在为你提供使用ChatGPT进行SE…

开源代码分享(26)-考虑预测不确定性的综合能源调度优化

参考文献&#xff1a; [1]崔杨,周慧娟,仲悟之,等.考虑源荷两侧不确定性的含风电电力系统低碳调度[J].电力自动化设备,2020,40(11):85-93.DOI:10.16081/j.epae.202009019. 1.基本原理 考虑碳交易机制能够有效提高风电消纳量&#xff0c;但是随着风电并网容量的增大&#xff0c…

【STM32 IIC通信与温湿度传感器AHT20(I2C_AHT20)】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 最终效果展示AHT20温湿度传感器&#xff08;I2C_AHT20&#xff09; 1、工程配置2、代码如果您发现文章有错误请与我留言&#xff0c;感谢 最终效果展示 详细讲解视频…

Linux如何redis清空缓存

通过命令清空缓存 登录redis redis-cli -h 127.0.0.1 -p 6379# 如果有密码需要下面这一步 auth 你的密码出现ok表示登录成功 查看所有key keys * 清空整个Redis服务器的数据 flushall

Vue+ElementUI实现文件照片音频视频预览

1. 需求是点击预览按钮 根据文件名的后缀去实现预览 2. 具体实现代码及逻辑 1.预览弹框 <el-dialog:visible.sync"visibleFile"width"40%":close-on-click-modal"false"close"cancelHandler":append-to-body"true">…

足球滚球数据分析靠谱吗?能不能通过大模型去实时预测?

足球滚球数据分析在一定程度上是靠谱的&#xff0c;但并非绝对可靠。滚球数据分析主要依赖于大量的历史数据、实时比赛数据以及相关的统计模型来预测比赛结果。这些数据可以包括球队的实力对比、球员状态、比赛进程、进球趋势、控球率变化等多个方面。 通过深入分析和挖掘这些数…