PCIE-XPDMA-SGDMA调试笔记

    xiaoxiao2022-07-07  492

    声明:所有文章属于个人在工作中所记下和搜集的笔记,不得转载

    参考的手册地址: a). Xilinx PCIe axi memory mapped手册地址链接:https://china.xilinx.com/support/documentation/ip_documentation/axi_pcie/v2_8/pg055-axi-bridge-pcie.pdf b). xapp1171文档PCI Express Endpoint-DMA Initiator Subsystem手册地址链接: https://www.xilinx.com/support/documentation/application_notes/xapp1171-pcie-central-dma-subsystem.pdf c)AXI Central Direct Memory Access (CDMA) 手册地址链接: https://china.xilinx.com/support/documentation/ip_documentation/axi_cdma/v4_1/pg034-axi-cdma.pdf d)关于CDMA可以参考我的这篇博客: https://blog.csdn.net/Real003/article/details/90054993 e)关于PCIE Memory Mapped可以参考我的这篇博客: https://blog.csdn.net/Real003/article/details/90045800 f)关于xapp1171源码工程恢复的方法可以参考我的这篇博客: https://blog.csdn.net/Real003/article/details/90186337

    最近刚刚调试完PCIE memory mapped IP,从接到任务到完成这个驱动的编写,花了差不多两周,不容易啊,这两周都是天天加班在调试,趁热打铁,赶紧记录一下调试笔记,不然过几个月估计就忘得一干二净了。。。。

    从设计思路开始讲起吧,首先肯定是先去下载Xilinx PCIe axi memory mapped手册,把手册看一遍,提炼出来重点,以及网上搜索一些与PCIe axi memory mapped相关的资料,网上资料真的不多啊,看到网上有说需要与CDMA IP配合一起使用,Xilinx官网也给了一个测试例子xapp1171,按照xapp1171文档里的步骤创建好工程后,数据始终都没收到啊,只能进行PIO操作,DMA怎么也没有工作起来,也真的是琢磨了好几天。后来得到了大神的指点,才最终解决了这些问题,我觉得好的东西还是可以写出来分享一下的,这样可以帮助别人减少很多的调试时间,下面开始我的设计步骤:

    首先参照xapp1171用Block模块搭建好工程,或者用xapp1171工程脚本恢复工程,这一步可以参考我上面中提到的博客,搭建开的Block框图如下: 去掉DDR3模块,引入了两个AXI_M接口:pcie_data_m_axi用来读写DMA数据,pcie_pio_m_axi用来读写驱动外部寄存器。 axi_cma模块勾选上Enable Scatter Gather,读写数据位宽64,地址位宽32 AXI Interconnect模块选择3个Slave和6个Master,需要注意的是:M01_AXI是用来配置PCIE CTL的,所以它的M01_ACLK时钟必须连PCIE的axi_ctl_aclk_out,其它时钟可以全部连axi_aclk_out; AXI Memory Mapped To PCI Express模块: PCIEBAR2AXIBAR勾选BAR0,映射基地址为:0x8100_0000,128kilobytes够用了(0x8102_0000); AXIBAR2PCIEBAR勾选BAR0,BAR1,映射基地址BAR0为:0xa000_0000,用来存放描述符,BAR1为:0xc000_0000,用来存放数据; bram数据位宽64bit,4k地址深度就可以了。 在添加AXI总线接口的时候Frequency填:125000000,CLK Domain填:design_1_axi_pcie_1_0_axi_aclk_out

    关于地址分配: 地址分配可以参考XAPP1171文档的P7页的配置,我这里是根据它的配置做了适当的修改: 从上面的地址配置表可以分析出: 1).PCIE的Master端只做寄存器配置的工作,完成往bram中存储BAR1数据对应的RC端的物理地址;完成对PCIE的BAR0对应的RC端的物理地址配置;完成CDMA的寄存器配置;完成通过PIO_M_AXI接口读写外部寄存器; 2)CDMA的M_AXI端即axi_cdma->data端根据SG端口读取的描述符完成数据搬移;将bram存储的BAR1地址搬移到pcie的控制寄存器中;将BAR1中的数据与pcie_data_m_axi中的数据来回搬动以实现读写功能; 3)CDMA的M_AXI_SG端即axi_cdma->data_sg端在PCIE的Master端配置完CDMA寄存器后开始从BAR0读取描述符;

    Excluded Address Segment中的地址可以Include Segment进去,没有什么影响,我这样分开只是为了更加明确在interconnect中每个Master真正需要控制哪些slave。

    关于描述符 上图是描述符的格式由8个32bit字对其,由SA和DA的数据地址决定DMA从哪里把数据搬运到哪里,如果SA对应的是AXI interconnet模块的BAR1地址,DA对应的是用户端M_AXI地址,则实现PCIE的写操作;如果SA对应的是AXI interconnet模块用户端M_AXI地址,DA对应的是BAR1地址,则实现PCIE的读操作;具体详细的可以参考:https://blog.csdn.net/Real003/article/details/90054993

    工作流程: 工作流程与xapp1171的15页中提到的一样: 首先配置寄存器:关于详细的寄存器描述请参考pg055和pg034; PCIEBAR2AXIBAR0=0x8100_0000

    1).PCIEBAR2AXIBAR0+0X0000_C000 数据:0x0000_0004;配置CDMA的寄存器,对CDMA复位 2).PCIEBAR2AXIBAR0+0X0000_C000 数据:0x0000_7008;配置CDMA的寄存器,开启DMA传输完成中断,错误中断,启用SG模式 3).RC端创建描述符,获得描述的偏移物理地址,将描述符的物理地址通过下面两个寄存器告诉PCIE,Bar0用于存描述符; 4).PCIEBAR2AXIBAR0+0X0000_8208 数据:0x0000_0001;配置PCIE的寄存器,bar0映射的RC端的高32位物理地址(该值根据实际情况修改) 5).PCIEBAR2AXIBAR0+0X0000_820c 数据:0x0000_0000;配置PCIE的寄存器,bar0映射的RC端的低32位物理地址(该值根据实际情况修改) 6).PCIEBAR2AXIBAR0+0X0000_0000~ 0X0000_7fff 数据:往bram中写入数据,表示每一个描述符的起始地址在BAR1中映射到RC端所对应的物理地址; 7).PCIEBAR2AXIBAR0+0X0000_c008 数据:0x8080_0000;配置CDMA的寄存器,写入CDMA开始工作后从SG端口向BAR0开始读取的描述符的起始地址指针 8).PCIEBAR2AXIBAR0+0X0000_c010 数据:0x8080_0040;配置CDMA的寄存器,写入CDMA开始工作后从SG端口向BAR0开始读取的描述符的最后一个地址指针。(该值根据实际情况修改) 9).写入第八步的寄存器后CDMA工作开始,直到读取到上面设置的最后描述符指针,完成数据搬移动作后,停止。 10).PCIEBAR2AXIBAR0+0X0000_C004 数据:0x0000_7000;如果启用了中断,中断发生后需要清除中断。 上图是下app1171中工作流程的例子,我也是看了好多遍才看懂这个图,我这里稍微解释一下: 上面第9步开始工作后,CDMA的SG端口根据第7步设置的寄存器数据,从AXI地址0x8080_0000开始读取八个数据,AXI地址0x8080_0000映射到RC端的物理地址是0x00000001_00000000;这个物理地址映射我们在第四第五步进行了配置,有可能你的RC端并不是这个地址,那么你只需要配置成你的地址就可以了。读出来的描述符如上图中的描述符,这些描述符都是在第三步中由RC端写入它的物理地址中的,我们这里使用SG端口通过BAR0的地址映射,读取过来进行使用。 读出来的第一个描述符SA为0x8100_0000,DA为0x8100_8210,表示下一步会通过CDMA的M_AXI端读取bram中的数据,写入地址为0x8100_8210,对应BAR1高位映射的物理地址。 第二个描述符表示从BAR1中读取64k字节的数据写入DDR; 第三个描述符表示从bram中读取一个BAR1的物理映射地址,下发给PCIE的控制寄存器; 第四个描述符表示从DDR中读取64K字节的数据,送入BAR1。 下图这个引入了完成状态标志,一般用在最后一个描述符。

    封装后的Block生成HDL Wrapper后如下: 注意reset_logic_mmcm_locked_in作为连接PCIE的复位引脚要做同步输入处理,这个在pg055的p41页中有讲到,具体可以参考我的另一篇博客:https://blog.csdn.net/Real003/article/details/90045800 如果与PCIE驱动对接的不是AXI接口,可以将AXI_M总线时序转换为其它的,比如视频时序、标准的FIFO时序等,这个还是比较容易的。 我的系统是G2X2经过测试PIO寄存器读速率为12.806Mbps,写速率为306.223Mbps,当然这个测试速率并不可靠,因为还参杂了其它用户逻辑,由于项目时间吹得紧原因DMA读写数据速率没测。

    这个PCIE驱动的开发整个调试过程还是不算太难的,主要是在几个地方卡了一些时间: a).一是地址的分配,之前一直没搞懂为什么要这么分配,导致我完全照搬XAPP1171的配置,无法正确读取出BAR0、BAR1中的数据,手册反复看了好几遍才明白,所以你们在使用的时候,地址分配和寄存器配置数据下发需要根据实际情况做修改才能跑起来,当然整个Block的框架是没有问题; b).二是我调试的系统RC端存在字对其的问题,往地址尾数[3:0]是0x4或者0xc写数据的时候EP端收到的数据跑到高32bit去了,之前一直没发现,而CDMA和PCIE的寄存器配置的总线数据位宽是32位的,导致了高32bit数据的失效; c).三是CDMA设置了中断打开,在中断触发后,一定要进行对应位的写1清零,不然会导致下一个DMA数据没法传输;

    7.疑问: a).另外就是一直没搞明白 在PCIE IP中设置的AXIBAR2PCIEBAR 的BAR1、BAR2设置的偏移地址与通过PCIE CTL端口配置的寄存器0x18、0x1c、0x24、0x28有何联系,是不是BAR1、BAR2设置的偏移地址可以随便设置,只要正确配置0x18、0x1c、0x24、0x28就可以了 ? b).该工程只使用了两个BAR和一个CDMA,一个BAR用来作为描述符通道,另外一个BAR用来作为DM数据通道,只能实现半双工通信,是否可以再开启多个BAR和增加多个CDMA来实现更高速率的传输 ?

    最新回复(0)