当前位置:首页 > 基于FPGA的PCIE接口设计
基于FPGA的PCIE接口设计
由图可以看出,下发的fig为线性数,fig_vld在数据有效时为高电平
(2)PCIE中断板上时序图
PCIE的中断主要由PCIE_interrupt_n_final和PCIE_interrupt_assert_n两条信号线决定,PCIE_interrupt_n_final决定是否有中断信号,PCIE_interrupt_assert_n决定是产生中断还是清除中断。每次当PCIE_interrupt_n_final由1跳变到0时为该时刻会产生或清除中断,此时对应PCIE_interrupt_assert_n的高低来判断具体是哪种中断操作。当PCIE_interrupt_assert_n为低电平时为产生中断,当PCIE_interrupt_assert_n为高电平时为清除中断。Int_mode = 1说明此时的中断为参数中断
21
基于FPGA的PCIE接口设计
产生中断的时序图
清除中断的时序图
22
基于FPGA的PCIE接口设计
第五章 基于中断方式的DMA传输设计
5.1 什么是DMA
直接存储器访问(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许某些计算机内部的硬件子系统(电脑外设),可以独立地直接读写系统存储器,而不需绕道中央处理器(CPU)。在同等程度的处理器负担下,DMA是一种快速的数据传送方式。很多硬件的系统会使用DMA,包含硬盘控制器、绘图显卡、网卡和声卡。DMA 是所有现代计算机的重要特色,他允许不同速度的硬件设备来沟通,而不需要依于中央处理器的大量中断 负载。否则,中央处理器 需要从 来源 把每一片段的数据复制到 暂存器,然后把他们再次写回到新的地方。在这个时间中,中央处理器 对于其他的工作来说就无法使用。DMA 传输重要地将一个存储器区从一个设备复制到另外一个。当中央处理器初始化这个传输动作,传输动作本身是由 DMA 控制器 来实行和完成。典型的例子就是移动一个外部存储器的区块到芯片内部更快的存储器去。像是这样的操作并没有让处理器工作拖延,反而可以被重新调度去处理其他的工作。DMA 传输对于高性能 嵌入式系统 算法和网络是很重要的。举个例子,个人计算机的ISA DMA 控制器拥有 8个 DMA 通道,其中的 7 个通道是可以让计算机的中央处理器所利用。每一个 DMA 通道有一个 16位 地址暂存器和一个 16 比特 计数暂存器。要初始化数据传输时,设备驱动程序一起设置 DMA 通道的地址和计数暂存器,以及数据传输的方向,读取或写入。然后指示 DMA 硬件开始这个传输动作。当传输退出的时候,设备就会以中断的方式通知中央处理器。\分散-收集\(Scatter-gather)DMA 允许在一次单一的 DMA 处理中传输数据到多个存储器区域。相当于把多个简单的 DMA 要求串在一起。再一求;DACK 意为 DMA 确认。这些符号一般在有 DMA 功能的计算机系统硬件概要上可以看到。他们表示了介于 中央处理器 和 DMA 控制器之间的电子信号传输线路。
DMA 会导致缓存一致性问题。想像中央处理器带有缓存与外部存储器的情况,DMA 的运作则是去访问外部存储器,当中央处理器访问外部存储器某个地址的时候,暂时先将新的值写入缓存中,但并未将外部存储器的数据更新,若在缓存中的数据尚 未更新到外部存储器前发生了 DMA,则 DMA 过程将会读取到未更新的数据。相同的,如果外部设备写入新的值到外部存储器内,则中央处理器若访问缓存时则会访问到尚未更新的数据。这些问题可以用两种方法来解决:
1)高速缓存同调系统(Cache-coherent system):以硬件方法来完成,当外部设备写入存储器时以一个信号来通知缓存控制器某存储器地址的值已经过期或是应该重新更新数据。
2)非同调系统(Non-coherent system):以软件方法来完成,操作系统必须确认缓存读取时,DMA 程序已经开始或是禁止 DMA 发生。第二种的方法会造成 DMA 的系统负担。
5.2软件界面设计与关键部分代码说明
软件基于Visual C++的MFC编程语言设计,MFC语言主要设计上位机软件的总体框架,上位机的驱动程序使用windriver提供的API函数即可,该上位机程序主要实现的功能是对PCIE设备的关闭与打开,存储文件位置的选取以及DMA传输中对PCIE卡的控制功能。
设计的软件界面如图1所示
23
基于FPGA的PCIE接口设计
图1 上位机软件总体框架
上位机包括对PCIE卡控制的若干个按钮,采集状态的显示以及不同状态的文本显示。 主要的功能按钮包括“打开设备”按钮,“开始采集”按钮和“停止采集”按钮。其中最主要的功能是开始采集的按钮,以下将对该段代码作解释,其他按钮的代码部分详情见附件。
采集功能的关键部分代码如下 bsize=1024*1024;
file.Open(Pointer->filepath,CFile::modeCreate|CFile::modeReadWrite|CFile::typeBinary,NULL); Pointer->mydriver.CompleteFlag=0; Pointer->StopFlag=0;
Pointer->timer=CTime::GetCurrentTime();
s1.Format(\开始传输\\r\\n\,
Pointer->timer.GetHour(),Pointer->timer.GetMinute(),Pointer->timer.GetSecond());
Pointer->log=s1+Pointer->log;
Pointer->SetDlgItemText(IDC_EDIT2,Pointer->log); t=clock(); while(TRUE) {
Pointer->mydriver.AddWrite32(0,REG_DMACST, 2); while (TRUE)
24
共分享92篇相关文档